Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluetooth RFCOMM connection couldn't be established consecutively on Android 4.2

I have an application which talks to a custom device through RFCOMM via Bluetooth. The communication code is based on BluetoothTalk sample project. It was running without any problem before on either Galaxy S3, Galaxy S2, Galaxy Note and Nexus 7.

Recently, Nexus 7 were upgraded to Android 4.2 and since then, the problem happens as follows:

  1. When you use the app to set up a connection for the first time, meaning that the device is just turned on and app is just launched, no problem, you can get data normally.

  2. Then if you stop the communication, and try to restart, the communication fails with error "java.io.IOException: bt socket closed, read return: -1". From then on, no matter how many times you try to reconnect, it simply always fails.

  3. The only way to make it work again is, if you reboot the custom device AND the app, then try to connect, the communication becomes normal. But then, once you stop and restart the communication, it keeps on failing.

I borrowed a Nexus 4 with Android 4.2 and the issue remains.

It's really annoying because the main value of our device is relying upon the Bluetooth RFCOMM application. I double checked about the documentation on BT in Android 4.2 and didn't see any significant change. I'm fairly confident about the code on my side because it works for any Android device not running 4.2

Any hint or suggestion would be greatly appreciated. The device need to be demoed in the very beginning of December and we really want to address this issue ASAP.

EDIT: Now that 4.2.1 has been released and the problem is still not solved. Can we at least get some confirmation regarding if it's under working and will be fixed soon?

like image 866
cnbuff410 Avatar asked Nov 19 '12 19:11

cnbuff410


3 Answers

This doesn't help you much, but note that Google introduced a completely new Bluetooth stack with 4.2.

This should be a good thing - in my experience as a user and developer, Android with Bluez (the old combo) never functioned reliably, so I was quite pleased to hear that they undertook a total rewrite.

I guess all I can say is that it sounds like you have encountered a bug or quirk in the new stack. It is unfortunate to hear that there are problems with the new stack too.

Regarding your demo, note that Google publishes the firmware images for all of their Nexus devices (https://developers.google.com/android/nexus/images), and flashing them to your devices is fairly easy.

So I suggest you file a bug report and then flash your devices to 4.1.2.

like image 105
Tom Avatar answered Nov 04 '22 07:11

Tom


It happened to me in my tests too. I the BluetoothChat sample code you should look at connectionLost method. I don't remember if there is any variable that keeps the number of lost connections, but you could add that yourself. in the connectionLost method, test if the number of lost connections is less than a predefined number (in my case 3). If that's true, send a message to the UI with mHandler ( a toast) and call connect(device) again. If that's not true (you lost connection more than 3 times), call stop() method.

Also be sure to open the socket in ConnectThread like this:

    public ConnectThread(BluetoothDevice device, boolean isSecure) {
        mmDevice = device;
        BluetoothSocket tmp = null;
        mSocketType = isSecure ? "Secure" : "Insecure";
        // Get a BluetoothSocket for a connection with the given BluetoothDevice
        if (isSecure) {
            // reflection is better to use
            Method m = null;
            try {
                Log.d(TAG, "create reflection");
                m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class });
                } catch (NoSuchMethodException e1) {
                e1.printStackTrace();
            }
            try {
                tmp = (BluetoothSocket) m.invoke(device, 1);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            mmSocketFallBack = tmp;
        } else {
            Log.d(TAG, "create insecure");
            try {
                tmp = device
                        .createInsecureRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mmSocket = mmSocketFallBack;
    }

Your connectionLost should look something like:

public void connectionLost() {
    init = false;
    Log.d(TAG, "connectionLost -> " + mConnectionLostCount);
    mConnectionLostCount++;
  if (mConnectionLostCount < 3) {
    // Send a reconnect message back to the Activity
        Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(WebAppInterface.TOAST, "Connection lost. Reconnecting...");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        connect(mSavedDevice,true);     
    } else {
    mConnectionLostCount = 0;
    Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(WebAppInterface.TOAST,"Device connection was lost!");
    msg.setData(bundle);
    mHandler.sendMessage(msg);
    cBluetooth.this.stop();
    }
}

I hope you can adapt it for your case. You could check this links too, they helped me a lot:

  1. remote control example
  2. connection dying solution
  3. Bluetooth Service example to get inspired from
like image 39
bboydflo Avatar answered Nov 04 '22 09:11

bboydflo


I had a similar problem and spent some time debugging this issue. I am running Android 4.3 and found the only basic modification that was required to BluetoothChat sample code was setting:

MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

I am trying to connect to a HC-05 bluetooth module and I believe it uses the SPP profile as indicated by this UUID. You can query a device's UUID with this line of code:

UUID uuid = device.getUuids()[0].getUuid();

Verify the UUID and see if it matches up with a profile that makes sense, based on the type of device you are connecting to.

MY_UUID_SECURE = uuid;

The UUID may indicate a different type of device profile, depending on what you are connecting to. With the proper UUID, I was still able to run the AcceptThread code and listen as a BluetoothServerSocket without any issues. I hope this helps, however, I am relatively new to Android and Bluetooth development, so if my assumptions are wrong, please correct me.

like image 1
grum Avatar answered Nov 04 '22 09:11

grum