我目前正在开发一个使用低功耗蓝牙的应用程序(在Nexus 4上测试(。在开始使用Android 4.3中的官方BLEAPI后,我注意到在第一次连接设备后,我很少能够再次成功连接到该设备或任何其他设备/与之通信。
按照此处的指南,我可以成功连接到设备,扫描服务和特征,并读取/写入/接收通知,而不会出现任何问题。但是,断开连接并重新连接后,我经常无法扫描服务/特征或无法完成读/写。我在日志中找不到任何内容来指示为什么会发生这种情况。
一旦发生这种情况,我必须卸载应用程序,禁用蓝牙,然后重新启动手机,然后才能再次开始工作。
每当设备断开连接时,我都会确保在蓝牙Gatt对象上调用close((并将其设置为null。有什么见解吗?
编辑:
日志转储:对于这些日志,我扎根了手机并提高了/etc/bluetooth/bt_stack.conf 中相关项目的跟踪级别
连接成功 - 重新启动手机并安装应用程序后首次尝试。我能够连接,发现所有服务/特征,并读/写。
失败的尝试 1 - 这是从上述成功连接断开连接后的下一次尝试。似乎我能够发现特征,但是第一次尝试读取返回了一个空值,并在此后不久断开连接。
失败的尝试 2 - 我什至无法发现服务/特征的示例。
编辑2:
我尝试连接的设备基于 TI 的 CC2541 芯片。我获得了一个TI SensorTag(也基于CC2541(来玩,并发现TI昨天发布了一个用于SensorTag的Android应用程序。但是,此应用程序具有相同的问题。我在另外两个 Nexus 4 上对此进行了测试,结果相同:第一次或第二次连接到 SensorTag 成功,但(根据日志(此后无法发现服务,导致各种崩溃。我开始怀疑这是否是这个特定芯片的问题?
重要的实现提示
(由于Android操作系统的更新,也许其中一些提示不再是必需的。
- 某些设备(如 Nexus 4 和 Android 4.3(需要 45+ 秒才能使用现有的 gatt 实例进行连接。解决方法:始终在断开连接时关闭 gatt 实例,并在每次连接时创建一个新的 gatt 实例。
- 别忘了打电话给
android.bluetooth.BluetoothGatt#close()
-
在
onLeScan(..)
内启动一个新线程,然后连接。原因:如果在三星Galaxy S3和Android 4.3上的同一线程中LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
内部调用,BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)
总是失败(至少对于构建JSS15J。I9300XXUGMK6( - 大多数设备过滤广告
-
最好不要将
android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback)
与参数一起使用来过滤某些服务 UUID,因为这在带有 Android 3 的三星 Galaxy S4.3 中完全被破坏,并且通常不适用于 128 位 UUID。 - Gatt 始终可以一次处理一个命令。如果几个命令接一个地被短调用,则由于 gatt 实现的同步性质,第一个命令将被取消。
- 即使在装有Android 5的现代设备上,我也经常看到Wifi会干扰蓝牙,反之亦然。作为最后的手段,关闭wifi以稳定蓝牙。
初学者教程
对于新手来说,一个相当不错的切入点可能是这个视频教程:为Android开发蓝牙智能应用程序 http://youtu.be/x1y4tEHDwk0
下面描述的问题和解决方法现在可能已通过操作系统更新修复
解决方法:我可以"稳定"我的应用程序这样做......
- 我为用户提供了"重新启动蓝牙"设置。如果启用了该设置,我会在某些指示BLE堆栈开始变得不稳定的点重新启动蓝牙。例如,如果 startScan 返回 false。一个好的点可能是如果服务发现失败。我只是关闭和打开蓝牙。
- 我提供了另一个设置"关闭WiFi"。如果启用了该设置,我的应用将在应用运行时关闭 Wifi(之后重新打开(
此解决方法基于以下经验...
- 在大多数情况下,重新启动蓝牙有助于解决BLE问题
- 如果您关闭 Wifi,BLE 堆栈会变得更加稳定。但是,它在大多数打开 wifi 的设备上也能正常工作。
- 如果您关闭 Wifi,重新启动蓝牙将完全恢复 BLE 堆栈,在大多数情况下无需重新启动设备.
关闭无线网络:
我也可以确认,关闭WIFI会使蓝牙4.0更加稳定,尤其是在Google Nexus上(我有一个Nexus 7(。
问题所在
是我正在开发的应用程序需要WIFI 和连续的蓝牙 LE 扫描。所以关闭无线网络对我来说是没有选择的。
此外,我意识到连续蓝牙LE扫描实际上可以杀死WIFI连接,并使WIFI适配器无法重新连接到任何WIFI网络,直到BLE扫描打开。 (我不确定移动网络和移动互联网(.
这肯定发生在以下设备上:
- 连结 7
- 摩托罗拉摩托G
然而,在WIFI开启的情况下进行BLE扫描似乎非常稳定:
- 三星 S4
- 宏达一号
我的解决方法
我扫描BLE一小段时间3-4秒,然后关闭扫描3-4秒。然后再次打开。
- 显然,当我连接到BLE设备时,我总是关闭BLE扫描。
- 当我断开与设备的连接时,我重新启动BLE(关闭适配器,然后打开(以重置堆栈,然后再开始扫描。
- 我也会在发现
services
或characteristics
失败时重置 BLE。 - 当我从应用程序应该连接到的设备获取广告数据时(假设 500 次无法连接 - 大约是 5-10 秒的广告(,我再次重置 BLE。
确保您的 Nexus 已与设备配对。 我无法验证通信是否正常工作,但您将能够多次连接而无需重新启动。 似乎第一次连接不需要配对,但所有后续尝试都需要配对。
我将在几天内更新此答案,当我在不重新启动的情况下测试服务发现和 gatt 读写请求时。
编辑:事实证明,我正在开发固件版本(我们的传感器(上进行测试,如果未配对,则会导致问题。 我们最新的生产固件版本在 2540 和 2541 上运行良好。
编辑:我确实注意到在Nexus 7 2013上,当WiFi关闭时,连接会更稳定。 我想知道这是否对其他人有帮助。
编辑:我似乎已经倒退了配对。 未配对时一切正常。 配对后,我遇到了与OP完全相同的症状。 只是还不知道这是否与我们的固件或Android BLE API有关。 如果对此进行测试,请小心,因为一旦配对,由于本文 3b 中解释的错误,您可能无法取消配对。
在某些模型中存在缺陷:https://code.google.com/p/android/issues/detail?id=180440
另一方面,就我而言,问题是我的连接在onDestroy方法中未正确关闭。正确关闭后,对我来说不存在问题,无论打开或关闭wifi。
btGatt.disconnect();
btGatt.close();
我遇到了类似的问题。我的修复是
if (Build.VERSION.SDK_INT >= 23) {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}
并在断开连接后呼叫关闭。