Android 4.3蓝牙低功耗不稳定

sa.*_*dow 186 android bluetooth bluetooth-lowenergy android-bluetooth android-4.3-jelly-bean

我目前正在开发一种将使用蓝牙低功耗的应用程序(在Nexus 4上进行测试).在开始使用Android 4.3中的官方BLE API之后,我注意到在我第一次连接设备后,我很少能够成功连接到该设备或与该设备或任何其他设备进行通信.

按照此处的指南,我可以成功连接到设备,扫描服务和特性,以及读取/写入/接收通知而不会出现任何问题.但是,在断开连接并重新连接后,我经常无法扫描服务/特性或无法完成读/写操作.我在日志中找不到任何内容来说明为什么会发生这种情况.

一旦发生这种情况,我必须卸载应用程序,禁用蓝牙,然后重新启动手机才能再次开始工作.

每当设备断开连接时,我都要确保在BluetoothGatt对象上调用close()并将其设置为null.任何见解?


编辑:
日志转储:对于这些日志,我根据我的手机并在/etc/bluetooth/bt_stack.conf中提升了相关项目的跟踪级别

连接成功 - 重新启动手机并安装应用后首次尝试.我能够连接,发现所有服务/特性,以及读/写.

失败尝试1 - 这是断开上述成功连接后的下一次尝试.似乎我能够发现特征,但是第一次尝试读取时返回了一个空值并且很快就断开了.

失败的尝试2 - 我甚至无法发现服务/特征的示例.


编辑2:
我尝试连接的设备基于TI的CC2541芯片.我获得了TI SensorTag(也基于CC2541),并发现TI 昨天为SensorTag 发布了一个Android应用程序.但是,这个应用程序有同样的问题.我在另外两个Nexus 4上进行了测试,结果相同:第一次或第二次连接SensorTag成功,但是(根据日志)之后无法发现服务,导致各种崩溃.我开始怀疑这个特定芯片是否存在问题?

One*_*rld 179

重要的实施提示

(由于Android操作系统更新,可能不再需要其中一些提示.)

  1. 使用Android 4.3的Nexus 4等设备需要45秒以上才能使用现有的gatt实例进行连接.解决方法:始终在断开连接时关闭gatt实例,并在每个连接上创建一个新的gatt实例.
  2. 别忘了打电话 android.bluetooth.BluetoothGatt#close()
  3. 在里面开始一个新线程 onLeScan(..),然后连接.原因:BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)总是失败,如果LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)在Android 4.3的三星Galaxy S3上的同一个线程中调用(至少对于构建JSS15J.I9300XXUGMK6)
  4. 大多数设备过滤广告
  5. 最好不要使用 android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) 参数来过滤某些服务UUID,因为这在使用Android 4.3的Samsung Galaxy S3中完全被破坏,并且通常不适用于128位UUID.
  6. Gatt总是可以一次处理一个命令.如果多个命令被一个接一个地调用,则第一个命令由于gatt实现的同步特性而被取消.
  7. 我经常在使用Android 5的现代设备上看到,Wifi会干扰蓝牙,反之亦然.作为最后的手段,关闭wifi以稳定蓝牙.

初学者教程

这个视频教程可以为新手提供一个非常好的切入点:为Android开发蓝牙智能应用程序http://youtu.be/x1y4tEHDwk0

下面描述的问题和解决方法现在可能已由OS更新修复

解决方法:我可以"稳定"我的应用程序......

  1. 我为用户提供了"重启蓝牙"设置.如果启用该设置,我会在某些指示BLE堆栈开始变得不稳定的点重新启动蓝牙.例如,如果startScan返回false.如果serviceDiscovery失败,也可能是一个好点.我只是打开蓝牙.
  2. 我提供另一个设置"关闭WiFi".如果启用了该设置,我的应用程序会在应用程序运行时关闭Wifi(之后将其重新打开)

这项工作基于以下经验......

  • 在大多数情况下,重新启动蓝牙有助于解决BLE问题
  • 如果关闭Wifi,BLE堆栈会变得更加稳定.但是,它也适用于大多数打开wifi的设备.
  • 如果您关闭Wifi,重新启动蓝牙将完全恢复BLE堆栈,而无需在大多数情况下重启设备.

  • 谷歌,你现在必须解决这个问题.这项工作(我做了加上因为它确实有效)是荒谬的. (32认同)
  • 有时,服务发现将成功,状态为0(假设没有问题),但特征性读取将产生NULL值,因为它基本上没有真正连接或未发现特征(我在日志中看到:11-01 18:37: 32.131:WARN/BluetoothGatt(20119):未处理的异常:java.lang.NullPointerException) (4认同)
  • 伟大的更新@OneWorld!如果我能:)我会再次投票 (4认同)
  • @ Lo-Tan如果包含我的预期服务,我总是在服务发现后检查.如果服务发现给出任何结果,您也永远无法确定.有时候我没有收到任何回调.所以我为服务发现应用了超时. (2认同)
  • 我的经验是:三星S3(4.3)在关闭Gatt客户后成功重新连接,如上文第2段所述; 使用Nexus 4和7(4.4.2)我连接掉线后无法重新连接,即使重启BL适配器,但2分钟后它可以自动重新连接 (2认同)
  • 任何人都可以确认 android.bluetooth.BluetoothGatt 是否只能处理一个挂起的 GATT 操作 **PER DEVICE**、**PER PROCESS** 或 **PERIOD**(即:跨所有进程)。我认为它是 PER DEVICE,但是这个问题太复杂了,如果不是这样,我也不会感到惊讶。如果限制仅限于每个设备,那么能够处理多个同时操作的操作系统/设备是确凿的证据,证明这个问题纯粹是由于操作系统处理每个进程的 BluetoothAdapter 实例中的一些弱幼稚的实现(我假设是跨所有进程的单例)。 (2认同)

ben*_*nka 16

关闭WIFI:

我也可以确认,关闭WIFI会使蓝牙4.0更稳定,特别是在谷歌Nexus上(我有一台Nexus 7).

问题

是应用程序,我发展的需求WIFI和连续蓝牙LE扫描.所以关闭WIFI对我来说是没有选择的.

此外我已经意识到,连续蓝牙LE扫描实际上可以杀死WIFI连接并使WIFI适配器无法重新连接到任何WIFI网络,直到BLE扫描开启.(我不确定移动网络和移动互联网).
这肯定发生在以下设备上:

  • Nexus 7
  • 摩托罗拉Moto G.

然而,使用WIFI进行BLE扫描似乎非常稳定:

  • 三星S4
  • HTC One

我的解决方法

扫描BLE一小段时间3-4秒然后我关闭扫描3-4秒.然后再次开启.

  • 显然,当我连接到BLE设备时,我总是关闭BLE扫描.
  • 当我从设备断开连接时,我重新启动BLE(关闭适配器然后再打开)以重置堆栈,然后再次开始扫描.
  • 我发现servicescharacteristics失败时也会重置BLE .
  • 当我从应用程序应该连接的设备获取广告数据时(假设500次无法连接 - 这大约是5-10秒的广告)我再次重置BLE.


Mik*_*t25 7

确保您的Nexus与设备配对.我无法验证通信是否正常工作,但您可以在不重启的情况下连接多次.似乎第一次连接不需要配对,但所有后续尝试都需要配对.

我将在几天内更新此答案,当我测试服务发现和gatt读取和写入请求而不重新启动时.

编辑:事实证明我正在测试开发固件版本(我们的传感器),如果没有配对就会导致问题.我们最新的生产固件版本在2540s和2541s上运行良好.

编辑:我注意到在Nexus 7 2013上,当WiFi关闭时,连接更加稳定.我想知道这是否有助于其他任何人.

编辑:我似乎已经配对了倒退.没有配对时一切正常.配对后,我遇到与OP完全相同的症状.目前还不知道这是否与我们的固件或Android BLE API有关.要小心,如果在这个3b的测试,是因为一旦配对,您可能无法取消配对由于错误解释.

  • 我可以确认,**关闭Wifi后它会更稳定.**每个人都应该尝试一下. (3认同)
  • 我有一个无法取消配对的工作.1)转到你的bt菜单,选择unpair,从该区域删除ble设备或降低它,在bt菜单中选择ble设备,它将尝试配对和失败,然后重置蓝牙.重置后,设备将取消配对. (2认同)

Kry*_*ian 5

在某些模型中存在缺陷:https : //code.google.com/p/android/issues/detail?id=180440

另一方面,在我的情况下,问题是在onDestroy方法中未正确关闭我的连接。正确关闭后,对我来说不存在问题,无论是否打开或关闭wifi。

btGatt.disconnect();
btGatt.close();
Run Code Online (Sandbox Code Playgroud)

  • 当您想多次连接蓝牙时,正确的关闭步骤是“关键”。以我的经验,最好在单独的UNBOUND服务中运行Ble连接,以便手动启动和停止它。然后调用mConnectedGatt.disconnect(); ble_device = null; 在您的inDestroy()中。就我而言,此模式可以稳定运行而不会出现问题。 (2认同)

小智 5

我面临着类似的问题。我的解决方法是

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}
Run Code Online (Sandbox Code Playgroud)

& 断开连接后调用关闭。