我写了一个连接到BLE设备的应用程序。该应用程序在大多数设备上运行正常但有些设备(最明显的是华为P8 Lite和Nexus 6P)在蓝牙适配器被禁用后拒绝连接。
这是测试序列:
这是我用来连接的代码:
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);
}
}
}
};
所有调用都通过Handler发布到主线程。我可以看到它等待连接,在30秒后放弃我在对象上调用BluetoothGatt.close()并使其为空。这就像什么都没有。
过了一段时间,在当天晚些时候,它再次起作用。
非常感谢帮助:-)
更新2018年9月14日:经过Emil的精彩解释后,我更新了我们的应用程序,因此在Nexus上没有这个问题。我注意到华为P8 Lite继续在后台扫描,似乎没有什么办法可以阻止它。
为了演示这些问题,我制作了一个非常简单和干净的应用程序,它在手机上运用蓝牙LE功能并用它来演示这个问题,并且P8也被打破了。该应用程序可在此处获取:https://play.google.com/store/apps/details?id=eu.millibit.bluetootherror来源可在此处获取:https://bitbucket.org/millibit/eu.millibit.bluetootherror/src/master/
我希望我随着时间的推移可以扩展这个应用程序,使其成为Android的一个测试工具,记录Android的所有stange行为并将其收集在数据库中。如果您有兴趣贡献,请不要犹豫,给我发邮件[email protected]
Android蓝牙堆栈的API存在设计缺陷。当您通过蓝牙设备地址连接到特定设备时,无法判断您是指公共地址还是随机地址。
如果您开始连接到autoConnect = false且未绑定且最近未在扫描中看到的设备,则会假定您的意思是公共地址。因此,如果您尝试连接到具有静态随机地址的设备,它将失败。
如果设备未绑定,请确保使用正确的地址类型连接,必须首先执行扫描,找到设备,然后开始连接尝试。