I'm creating an app that connects to an Arduino via USB. The connection works fine and I can properly transmit and receive data. My problem is when connecting and disconnecting the USB.
For some reason, everytime I connect or disconnect the Arduino via USB, the BroadcastReceives is called from 2 to 4 times, and sometimes the Arduino just doesn't even connect at all.
My BroadcastReceiver implementation:
public static class ArduinoConnectionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
switch(intent.getAction()) {
case ArduinoConfigurations.ACTION_USB_PERMISSION:
if (intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED)) {
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters.
serialPort.setBaudRate(115200);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(new ArduinoCallback());
Log.d("ARDUINO", "Arduino connected!");
((MainActivity)context).enableButtons(true);
} else
Log.e("ARDUINO", "Port not open, not possible to connect.");
} else
Log.e("ARDUINO", "Port is null, not possible to connect.");
} else
Log.e("ARDUINO", "Permission not granted, not possible to connect.");
break;
case UsbManager.ACTION_USB_DEVICE_ATTACHED:
openConnection((MainActivity)context);
break;
case UsbManager.ACTION_USB_DEVICE_DETACHED:
default:
closeConnection((MainActivity)context);
break;
}
...
Sometimes it also throws:
exception in UsbManager.openDevice
java.lang.IllegalArgumentException: device /dev/bus/usb/003/012 does not exist or is restricted
at android.os.Parcel.readException(Parcel.java:1688)
at android.os.Parcel.readException(Parcel.java:1637)
at android.hardware.usb.IUsbManager$Stub$Proxy.openDevice(IUsbManager.java:411)
at android.hardware.usb.UsbManager.openDevice(UsbManager.java:330)
...
and
Error on connecting Arduino: Attempt to invoke virtual method 'boolean android.hardware.usb.UsbDeviceConnection.claimInterface(android.hardware.usb.UsbInterface, boolean)' on a null object reference
I've read that the USB connector can be really unstable sometimes. But is it just that? Can I work around this so that the Arduino is connected and disconnected only once?
Related
I have a xamarin project (API 28, soon to be 29), and I need to catch the event of bluetooth a2dp device.
I have a broadcast receiver with the following intent filter:
IntentFilter bluetoothFilter = new IntentFilter();
bluetoothFilter.AddAction(BluetoothDevice.ActionAclConnected);
bluetoothFilter.AddAction(BluetoothDevice.ActionAclDisconnectRequested);
bluetoothFilter.AddAction(BluetoothDevice.ActionAclDisconnected);
var btReciever = new BluetoothReceiver();
this.RegisterReceiver(btReciever, bluetoothFilter);
In my manisfest, I got the following permission:
<uses-permission android:name="android.permission.BLUETOOTH" />
In the Receiver.OnReceive, I got this code:
public override void OnReceive(Context context, Intent intent) {
String action = intent.Action;
BluetoothDevice device = (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
There I have a switch:
switch (action)
{
case BluetoothDevice.ActionFound:
Android.Util.Log.Debug(TAG, "Device Found");
//Device found
break;
case BluetoothDevice.ActionAclConnected:
Android.Util.Log.Debug(TAG, "Device Connected");
BluetoothAdapter.DefaultAdapter.GetProfileProxy(context, btsListener, ProfileType.A2dp);
Thread.Sleep(1500);
var manager = context.GetSystemService(Context.AudioService) as AudioManager;
var devices = manager.GetDevices(GetDevicesTargets.Outputs);
Android.Util.Log.Debug(TAG, "devices=" + devices.Length);
foreach (var dev in devices)
{
Android.Util.Log.Debug(TAG, "dev: id={0} name={1} type={2}", dev.Id, dev.ProductName, dev.Type);
if (dev.ProductName == device.Name)
{
if (dev.Type.ToString().Contains("a2dp"))
{
BluetoothAdapter.DefaultAdapter.GetProfileProxy(context, btsListener, ProfileType.A2dp);
}
Android.Util.Log.Debug(TAG, "Found output device");
}
}
//Device is now connected
break;
...
}
And I got a listener that implements the IBluetoothProfileServiceListener interface, and looks like this:
var btsListener = new BTServiceListener();
class BTServiceListener : AppCompatActivity, IBluetoothProfileServiceListener
{
public void OnServiceConnected([GeneratedEnum] ProfileType profile, IBluetoothProfile proxy)
{
if (profile == ProfileType.A2dp)
{
Android.Util.Log.Debug(TAG, "A2dp");
}
}
...
}
I need to catch the event onConnect of the bluetooth a2dp (and later headset), but I have no idea how exactly I should do it.
This code in the receiver, shows the bluetooth onConnect event (BluetoothDevice.ActionAclConnected in the switch), then I check the device list, there is not yet the connected device, then I wait 1500ms (I need somehow to improve this method, this cannot stay like this), for the audioService to add the actual a2dp device to the list, and in the for loop, I find the additional device via its name, and I am certain it is the right one. BUT, I have no programmaticaly way to find out what type of device was connected (remote, headset, a2bp...) other than to check is the name contains a2dp (see for loop)
After my research, I found this line:
BluetoothAdapter.DefaultAdapter.GetProfileProxy(context, btsListener, ProfileType.A2dp);
This uses the context, the listener, and the desierd type of device (see Listener: BTServiceListener ), the problem is, I don't know if the proxy in the listener is the same device as the device in the broadcast receiver onConnect, and I have no idea how to use that function.
So my questions:
How and when should I use the BluetoothAdapter.DefaultAdapter.GetProfileProxy function and be certain that I have the same device in the listener and in the onConnect function?
How to get all the devices from the manager without putting the thread to sleep? Because, without the Thread.Sleep, the actual device is not in the list because the onConnect function is called earlyer then the addition of the device to the audioService.
Thread.Sleep(1500); // <-- this needs to go
var manager = context.GetSystemService(Context.AudioService) as AudioManager;
var devices = manager.GetDevices(GetDevicesTargets.Outputs);
How should I distinguish between the device types? Because, I have a feeling that my method of String.Contains(string) is not the way to go
Sorry for the long question, thank you for your help and time.
Let me know, if you need anything else.
I have Android application which exposes BLE Server. I connect with BluetoothGattServer#connect. It works - my app gets call to BluetoothGattServerCallback#onConnectionStateChange with STATE_CONNECTED. When I'm done with the client I try to disconnect from my app with BluetoothGattServer#cancelConnection.
But I do not get call to BluetoothGattServerCallback#onConnectionStateChange and it seems that the connection is still active as my BLE client does not start to advertise (which it does when nothing is connected to it).
In logcat I see only:
BluetoothGattServer: cancelConnection() - device: XX:XX:XX:XX:XX:XX
The funny part is, my app gets call to BluetoothGattServerCallback#onConnectionStateChange with STATE_DISCONNECTED as soon as I turn off BT completely.
Similar issues in Google's tracker: 63461 and 63464.
When newState==BluetoothProfile.STATE_CONNECTED, you have to call BluetoothGattServer.connect();.
#Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED){
mDevice = device;
mBluetoothGattServer.connect(device, false);
}else {
mDevice = null;
}
}
private void cancelConnection(){
if (mDevice != null) {
mBluetoothGattServer.cancelConnection(mDevice);
}
}
Encountering same issue when calling disconnect() method.. no disconnect is given in onConnectionStateChange in my BluetoothGattCallback.
Cycling Bluetooth seems the be the only thing that works.
edit:
also, after disconnect() and close() method are called, I am still connected according to this code:
public int getConnectedBLEDevices() {
int i = 0;
List<BluetoothDevice> devices = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
for(BluetoothDevice device : devices) {
if(device.getType() == BluetoothDevice.DEVICE_TYPE_LE) {
Logs.writeEvent(TAG+".getConnectedBLEDevices()", device.getAddress() + "\n"+ getStateAsString(mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT)));
i++;
}
}
return i;
}
pls see https://issuetracker.google.com/issues/37127644
Status: Won't Fix (Intended Behavior)
You must call BluetoothGattServer.connect() to mark connection as used, then BluetoothGattServer.disconnect() to mark it as no longer used. Then after a timeout stack can decide to disconnect from the remote if no one else is using the connection.
If BluetoothGattServer.connect() is not called after the connection is established, then the stack is keeping the connection until some gatt client/server app start using this connection.
I've seen many other posts regarding this specific issue, all with results that did not help me or were relevant to my case.
Here is my problem, I'm trying to setup a bluetooth piconet, with one node as a server and 7 as clients, each given a number as a location representative starting from 0 ( the server) and going to 7 (the clients). Currently I'm trying to get this to work for just two devices, the server and one client. And I assume that they're already paired. In the following code uuid is
private UUID uuid=UUID.fromString("0000111f-0000-1000-8000-00805f9b34fb");
Here is my thread which accepts incoming connections, ad is just the bluetooth adapter
private class BTServerThread implements Runnable{
#Override
public void run() {
try {
if (ad != null) {
if (ad.isEnabled()) {
BluetoothServerSocket btss=ad.listenUsingInsecureRfcommWithServiceRecord("MyApp",uuid);
Location=0;
Integer loc=1;
Log.wtf("Server","Searching");
while(loc<=7){
Thread t=new Thread(new BTServerHandler(btss.accept(),loc));
t.start();
Log.wtf("BTS","Found");
loc++;
}
} else {
Log.e("error", "Bluetooth is disabled.");
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
And here is my client thread which attempts to connect
private class BTClientThread implements Runnable{
#Override
public void run() {
try {
if (ad != null) {
if (ad.isEnabled()) {
Set<BluetoothDevice> bondedDevices = ad.getBondedDevices();
if (bondedDevices.size() > 0) {
Iterator<BluetoothDevice> iter = bondedDevices.iterator();
BluetoothDevice device = iter.next();
Log.wtf("dev", device.getName());
BluetoothSocket clientsocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
clientsocket.connect();
Log.wtf("Connected",device.getName());
}
Log.e("error", "No appropriate paired devices.");
} else {
Log.e("error", "Bluetooth is disabled.");
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
Hold your breath, here comes the weird part, the call btss.accept() hangs forever (Doesn't even return once), while at the same time, the client device connects somehow. When I call
BluetoothSocket clientsocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
clientsocket.connect()
This pops the toast on the phone which is hanging on accept saying "DeviceName connected" then after a while it pops another toast saying "DeviceName disconnected" on its own, without me doing ANYTHING, and at the same time the serverphone is still hanging on accept.
Here are my questions, why is it hanging on accept when the toast popped saying connected? And how could it possibly connect when the other phone is still listening for a connection?
Thanks for the help.
As it turns out, using that specific UUID caused a problem from some reason I still don't understand? After trying many random things, I finally decided to try another random UUID and that magically caused it to work.
Here is my new UUID
private UUID uuid = UUID.fromString("56e8a14a-80b3-11e5-8bcf-feff819cdc9f");
After steeping in the wrong path for almost two months i found out what my mistake was.
Now i am pacing a new problem which I cannot find the answer to:
Using this function while trying to connect to the headset:
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
final BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
}
}
};
I cannot initialize the mBluetoothHeadset object ,for some reason the debugger wont step into the onServiceConnected function..
Any help will be appreciated...realy needs one
shai
More Info:
Inded what haped was that after a android restart Bluetooth nneded to be enabled'solved in code:
This is the function code:
Log("PM.CheckForHeadSet","In");
if (mBluetoothAdapter == null) {
Log("PM.CheckForHeadSet","BlueTooth adapter not found");
return "Error Bluetooth adapter";
}
switch (mBluetoothAdapter.getState()){
case BluetoothAdapter.STATE_OFF:
Log("PM.CheckForHeadSet.getState"," STATE_OFF");
mBluetoothAdapter.enable();
break;
case BluetoothAdapter.STATE_TURNING_ON:
Log("PM.CheckForHeadSet.getState","STATE_TURNING_ON");
break;
case BluetoothAdapter.STATE_ON:
Log("PM.CheckForHeadSet.getState","STATE_ON");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Log("PM.CheckForHeadSet.getState","STATE_TURNING_OFF");
break;
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices, add each one to the ArrayAdapter
if (pairedDevices.size() == 1) {
for (BluetoothDevice device : pairedDevices)
if(device.getBondState() == BluetoothDevice.BOND_BONDED){
Log("PM.CheckForHeadSet Connected to:",device.getName());
}
}
Log("PM.CheckForHeadSet ServiceListener:","In");
final BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null; }
}};
if(mBluetoothHeadset == null)
Log("PM.CheckForHeadSet","mBluetoothHeadset = null");
else
Log("PM.CheckForHeadSet","mBluetoothHeadset = " + mBluetoothHeadset.toString());
if(context == null)
Log("PM.CheckForHeadSet","context = null");
else
Log("PM.CheckForHeadSet","context = " + context.toString());
if(mProfileListener == null)
Log("PM.CheckForHeadSet","mProfileListener = null");
else
Log("PM.CheckForHeadSet","mProfileListener = " + mProfileListener.toString());
if(mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET) == true)
Log("PM.CheckForHeadSet.getProfileProxy","true");
else
Log("PM.CheckForHeadSet.getProfileProxy","false");
Log("PM.CheckForHeadSet","Out");
return "Set Headset";
If i place the GetProfileProxy above the new ProfileListener (as in the docomantaion example|) the mProfileListener var is still null and getProfileProxy return false
And this is the logcat:
03-12 10:09:49.906: D/SpySitter(4205): PM.CheckForHeadSet-In
03-12 10:09:50.968: D/dalvikvm(4205): threadid=1: still suspended after undo (sc=1 dc=1)
03-12 10:09:59.453: D/SpySitter(4205): PM.CheckForHeadSet.getState-STATE_ON
03-12 10:10:02.640: D/SpySitter(4205): PM.CheckForHeadSet Connected to:-Motorola H790
03-12 10:10:04.226: D/SpySitter(4205): PM.CheckForHeadSet ServiceListener:-In
03-12 10:10:13.945: D/SpySitter(4205): PM.CheckForHeadSet-mBluetoothHeadset = null
03-12 10:10:17.984: D/SpySitter(4205): PM.CheckForHeadSet-context = android.app.Application#408472a0
03-12 10:10:21.820: D/SpySitter(4205): PM.CheckForHeadSet-mProfileListener = com.example.HelloForm.Tools$1#40894d00
03-12 10:10:28.796: D/SpySitter(4205): PM.CheckForHeadSet.getProfileProxy-true
03-12 10:10:31.226: D/SpySitter(4205): PM.CheckForHeadSet-Out
getProxyProfile returns false in three cases (this is according to the android-15 source, so it might be slightly different in android-11):
the Context passed in is null
the BluetoothProfile.ServiceListener passed in is null
the int passed in is not one of BluetoothProfile.HEADSET, BluetoothProfile.A2DP, BluetoothProfile.INPUT_DEVICE, BluetoothProfile.PAN, or BluetoothProfile.HEALTH
I'd suggest setting a breakpoint on your call to getProxyProfile to figure out which of these cases is causing the false return value.
edit: Further info
Bluetooth has to be supported and enabled for the interface methods to be called. If Bluetooth is not supported, getDefaultAdapter() will return null. If you have an adapter, you can check whether Bluetooth is enabled by calling isEnabled() on the adapter. That's pretty straightforward, so you may have already done that.
onServiceConnected is called by the android.content.ServiceConnection member (mServiceConnection) in the BluetoothHeadset class, which is in turn called by the Android OS by virtue of a bindService call when the BluetoothHeadset object is created. If the binding of this service fails, there should be an error in the logcat message log something like:
"Could not bind to Bluetooth Headset Service"
with a tag of "BluetoothHeadset". If you don't see this error, things are probably working as they should under the hood.
A final note is that Android only supports one connected headset at a time. Make sure that no headset is connected when you are running this code. On a similar note, many devices only support one bluetooth connection at a time. If that applies to your device, you'll want to make sure it is not already connected when you run this code.
That pretty much exhausts what I know and can easily determine about Bluetooth connections. Hope it helps you solve your problem.
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. When I press "Pair" the dialog is removed and nothing happens.
I only need to support devices with Android 2.0 and newer.
Currently I am using the following code to start the pairing progress:
public void pairDevice(BluetoothDevice device) {
String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
Intent intent = new Intent(ACTION_PAIRING_REQUEST);
String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
intent.putExtra(EXTRA_DEVICE, device);
String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT";
int PAIRING_VARIANT_PIN = 0;
intent.putExtra(EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
Before starting a pairing request I stop scanning for new devices.
My application has the following bluetooth permissions:
android.permission.BLUETOOTH_ADMIN
android.permission.BLUETOOTH
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.
It's my answer:
in onCreate() write this:
registerReceiver(incomingPairRequestReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST));
then create variable
private final BroadcastReceiver incomingPairRequestReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//pair from device: dev.getName()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
dev.setPairingConfirmation(true);
//successfull pairing
} else {
//impossible to automatically perform pairing,
//your Android version is below KITKAT
}
}
}
};
Unfortunately, I think the best that you are going to get is opening up Settings/Wireless & networks/Bluetooth Settings for the user like so:
Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivityForResult(intent, REQUEST_PAIR_DEVICE);
Using reflection you can call the method createBond from the BluetoothDevice class.
See this post: How to unpair or delete paired bluetooth device programmatically on android?
There is also a solution for unpair.
Reflection is DODGY, different manufacturers can change these underlying methods as they wish! I have tested many different apps on our 10 devices here and these reflection method only works fully on roughly 75% of devices. If you want an app that works for everyone be very careful when using reflection - try some cloud testing to test your app on 100+ devices and check the failure rate.
In this case reflection is not needed at all since API 19 (KitKat 4.4)
BluetoothDevice has new method CreateBond.
private void pairDevice(BluetoothDevice device) {
device.createBond();
}
developer.android.com/reference/android/bluetooth/BluetoothDevice.html
May be you need to startActivityForResult instead of only startActivity?
Other option is to look into the BluetoothChat application sample and start an RFComm connection socket, as soon as you start the socket a pairing request will automatically appear without needing to send a separate intent for pairing. This way you won't need to handle pairing.
http://developer.android.com/resources/samples/BluetoothChat/index.html
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.
This is how I get it:
Bluetooth device = mBtAdapter.getRemoteDevice(address);
//address:11:23:FF:cc:22
Method m = device.getClass()
.getMethod("createBond", (Class[]) null);
m.invoke(device, (Object[]) null); // send pairing dialog request
After pairing//
connectDevice(address);
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);