For my application I\'m trying to programmatically pair a bluetooth device. I\'m able to show the pairing dialog for the device I want to pair and I can enter a pincode. Whe
I am using this class to do connection between my client smartphone and the server device:
private class ConnectThread extends Thread
{
private final BluetoothSocket mmSocket;
private final UUID WELL_KNOWN_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
public ConnectThread(BluetoothDevice device)
{
// Use a temporary object that is later assigned to mmSocket,because
// mmSocket is final
BluetoothSocket tmp = null;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try
{
tmp = device.createRfcommSocketToServiceRecord(WELL_KNOWN_UUID);
//This is the trick
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (Exception e)
{
e.printStackTrace();
}
mmSocket = tmp;
}
public void run()
{
DebugLog.i(TAG, "Trying to connect...");
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try
{
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
DebugLog.i(TAG, "Connection stablished");
} catch (IOException connectException)
{
// Unable to connect; close the socket and get out
DebugLog.e(TAG, "Fail to connect!", connectException);
try
{
mmSocket.close();
} catch (IOException closeException)
{
DebugLog.e(TAG, "Fail to close connection", closeException);
}
return;
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel()
{
try
{
mmSocket.close();
} catch (IOException e)
{
}
}
}
First, get the BluetoothDevice object that you want to connect (listing paired devices or discoverying devices). Then do:
ConnectThread ct = new ConnectThread(device);
ct.start();
Because connect() is a blocking call, this connection procedure should always be performed in a thread separate from the main activity thread. See Android Developers for more detailed info.
I've found that using different values for PAIRING_VARIANT_PIN result in different pairing UI behaviours.
See this page: http://code.google.com/p/backport-android-bluetooth/source/browse/trunk/backport-android-bluetooth201/src/backport/android/bluetooth/BluetoothDevice.java?spec=svn67&r=67
I suspect the problem you're having is that both devices are Bluetooth 2.1, in which case a pairing request should result in a 6 digit passkey being displayed on both devices.
The best result I was able to achieve was using PAIRING_VARIANT_PIN = 0. When prompted by my application, I entered pin 1234 and a 6 digit passkey appeared on my target device. The pairing UI finished and that was that.
Either you need to find out how to initiate a Bluetooth 2.1 pairing request, using some other pairing variant or pairing variant pin. Or, you're not catching the result of the activity that's running properly.
Given the amount of time I've been trying to do this, I've decided that my end users will just have to pair using the android settings before using my application.
I managed to auto request a pairing procedure with keyboard featured devices through an app working as a service checking the presence of a specific kind of device and a modified version of the Settings app.
I have to say that I was working on a custom device running Android 4.0.3 without external controls (no back/Home/confirm buttons): pairing a controller on boot complete without any interaction until PIN request was mandatory.
First I created a service starting an activity on boot (with android.intent.action.BOOT_COMPLETED
and android.permission.RECEIVE_BOOT_COMPLETED)
that checks periodically the presence of a 1344 class device (a keyboard, the only way to input data on request) on the onReceive callback:
public void onReceive(Context context, Intent intent)
...
BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
...
if(dev.getBluetoothClass().getDeviceClass() == 1344){...}
Once filtered I choose the first keyboard available and then I pass the BT address to the Settings app:
Intent btSettingsIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
btSettingsIntent.putExtra("btcontroller", dev.getAddress());
startActivityForResult(btSettingsIntent, 1);
The tricky part was looking for the best position to call the pairing process. Using only the
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);
led me to a paring dialog that once closed left me with the device paired, but unusable.
Digging into the classes of com.Android.settings.Bluetooth I found my way through the
createDevicePreference(CachedBluetoothDevice cachedDevice)
in the DeviceListPreferenceFragment.
From there I did compare my previously selected BT address with those available coming up and once successfully matched I call
cachedDevice.startPairing();
I know, it's tricky and requires access to the Android source code, but in a custom environment it works.
I hope this could be helpful.
in addition to my comment, by the way, even if these ACTION types did exist, that's not how you use them. here's an example:
Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
intent.putExtra(EXTRA_DEVICE, device);
int PAIRING_VARIANT_PIN = 272;
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);
sendBroadcast(intent);