2

I have written an app that connects to a BLE device. The app works OK on most devices; but some devices (most noticeably Huawei P8 Lite and Nexus 6P) refuse to connect after the Bluetooth adapter has been disabled.

This is the test sequence:

  1. Make sure the app is NOT running.
  2. Slide down from the top, disable BT for a couple of seconds, then re-enable bluetooth.
  3. Start the app. The app automatically connects to a bluetooth address stored in the preferences.
  4. Wait for connect. This is where nothing happens on Huawei phones, but other phones, such as Samsung, works like a charm.
  5. Verify from another phone the device is advertising and you can connect to it.

This is the code I use to connect:

private final Runnable mBeginConnectRunnable = new Runnable() {
    @Override
    public void run() {
        synchronized (GattConnection.this) {
            if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
                try {
                    mBluetoothAdapter.cancelDiscovery();
                    mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(mAddress);
                    mGatt = mBluetoothDevice.connectGatt(mContext, mBackgroundConnect, mGattCallback);
                    final boolean connectSuccess = mGatt.connect();
                    Log.d(TAG, String.format(Locale.ENGLISH, "mGatt.connect(%s, %s) %s",
                            mAddress,
                            mBackgroundConnect ? "background[slow]" : "foreground[fast]",
                            connectSuccess ? "success" : "failed"));
                    refreshDeviceCache(mGatt);

                } catch (Exception ex) {
                    Log.e(TAG, "Create connection failed: " + ex.getMessage());
                    setState(State.Closed);
                }
            } else {
                Log.d(TAG, "Can't create connection. Adapter is disabled");
                setState(State.Closed);
            }
        }
    }
};

All calls are posted via a Handler to the main thread. I can see it waits for a connect, gives up after 30 seconds at which I call BluetoothGatt.close() on the object and nulls it. It's like nothing is out there.

After some time, later in the day, it works again.

Help is highly appreciated :-)

Update September 14, 2018: After great explanation from Emil I've updated our app and as such don't have this problem on the Nexus. I've noticed the Huawei P8 Lite continues to scan in the background and it seems there is nothing you can do to stop it.

To demonstrate the problems I've made a very simple and clean app that exercise the Bluetooth LE functionality on a phone and used it to demonstrate this problem and also the P8 is broken. The app is available here: https://play.google.com/store/apps/details?id=eu.millibit.bluetootherror Source is available here: https://bitbucket.org/millibit/eu.millibit.bluetootherror/src/master/

I hope I over time can extend this app to make it a test vehicle for Android documenting all the stange behavior from Android and collect it in a database. In case you are interested in contributing, don't hesitate to drop me a mail on bt.error@millibit.dk

millibit
  • 175
  • 1
  • 7
  • I disable BT for a few seconds, then enable it again. Then I start the app which will automatically connect to the same address to which it was last connected. I'v confirmed this from the log: 11:23:19.191 D/GattConnection: mGatt.connect(DE:97:0D:7F:2E:32, foreground[fast]) success 11:23:49.193 D/GattConnection: onBluetoothDisconnect – millibit Aug 30 '18 at 09:44
  • Does your peripheral have a Public Bluetooth device address or a Random address? Also, are your devices bonded? But I don't really understand your problem; of course you can't connect if Bluetooth is turned off? – Emil Aug 30 '18 at 17:53
  • Bluetooth is not turned off. I've updated the description to better explain. The address is random doesn't change. The "random" address is stored in factory settings in the device. Also, the device is not bonded. I have full control over the device and have confirmed no connection attempt is made. I've also checked this with an IToken. The problem is the same. After Bluetooth has been disabled, you can't make a connection. – millibit Aug 30 '18 at 19:30
  • Yeah, the Huawei P8 Lite's BLE is broken in many ways. It often just fails randomly. – Emil Sep 14 '18 at 12:12

1 Answers1

3

The Android Bluetooth stack has a design flaw in its API. When you connect to a specific device by Bluetooth Device Address, there is no way to tell if you mean a Public address or Random address.

If you start to connect to a device with autoConnect=false which is not bonded and has not recently been seen in a Scan, it will assume you mean a Public address. So if you try to connect to a device having a static random address, it will fail.

To be sure you connect with the correct address type if the device is not bonded, you MUST perform a scan first, find the device and THEN start the connection attempt.

Emil
  • 16,784
  • 2
  • 41
  • 52