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:
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 [email protected]
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.