【问题标题】:Android 4.3 Bluetooth Low Energy unstableAndroid 4.3 低功耗蓝牙不稳定
【发布时间】:2013-07-26 01:32:52
【问题描述】:

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

按照指南here,我可以成功连接到设备,扫描服务和特征,以及读/写/接收通知,没有任何问题。但是,断开连接并重新连接后,我经常无法扫描服务/特征或无法完成读/写。我在日志中找不到任何内容来说明为什么会发生这种情况。

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

每当设备断开连接时,我都会确保在 BluetoothGatt 对象上调用 close() 并将其设置为 null。有什么见解吗?


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

Successful connection - 重启手机并安装应用程序后的第一次尝试。我能够连接、发现所有服务/特征以及读/写。

Failed Attempt 1 - 这是从上述成功连接断开后的下一次尝试。似乎我能够发现特征,但第一次尝试读取返回一个空值并在此后不久断开连接。

Failed Attempt 2 - 我什至无法发现服务/特征的示例。


编辑 2:
我尝试连接的设备基于 TI 的 CC2541 芯片。我获得了一个TI SensorTag(也是基于CC2541)来玩,发现TI 昨天为SensorTag 发布了an android app。但是,这个应用有同样的问题。我在另外两台 Nexus 4 上测试了这个,结果相同:第一次或第二次连接到 SensorTag 成功,但(根据日志)失败之后发现服务,导致各种崩溃。我开始怀疑这是不是这个特定芯片的问题?

【问题讨论】:

  • 请发布您手机从启动到遇到问题的完整日志。
  • 我正在使用三星 Galaxy S4 并安装了泄露的 Google 版本 Android 4.3;经过多次连接/断开连接,当我发现服务时,我会随机获得 129(GATT_INTERNAL_ERROR) 并获得状态为 133 (GATT_ERROR),state = BluetoothProfile.DEVICE_DISCONNECTED 的 onConnectionStateChange。
  • 有一次或两次,我在短时间内收到了多个状态 129 和 133 回调,在我重新启动设备之前,我永远无法在 BluetoothGattCallback 中收到任何回调(但扫描没问题)。
  • 忘了说我正在测试大约十台使用 TI 芯片的设备(抱歉我不知道他们的型号)和一台使用 Nordic 芯片的设备。带有北欧芯片的设备从不报告错误。(但不足以证明问题是 TI 特定的)
  • 我可以确认三星 Galaxy S5(G900VVRU2BOG5G900VVRU2BOA8 构建版本)上仍然存在此问题。如果我从 Settings>Application Manager>>All>>Bluetooth 清除数据,它会暂时起作用。

标签: android bluetooth bluetooth-lowenergy android-bluetooth android-4.3-jelly-bean


【解决方案1】:

重要的实现提示

(也许由于 Android 操作系统更新,其中一些提示不再需要。)

  1. 一些设备,如 Nexus 4 和 Android 4.3 take 45+ seconds to connect using an existing gatt instance。解决方法:始终在断开连接时关闭 gatt 实例,并在每次连接时创建一个新的 gatt 实例。
  2. 别忘了拨打android.bluetooth.BluetoothGatt#close()
  3. 在里面开始一个新线程 onLeScan(..) 然后连接。原因:BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) 总是失败,如果在带有 Android 4.3 的三星 Galaxy S3 上的同一线程中的 LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) 内部调用(至少对于构建 JSS15J.I9300XXUGMK6)
  4. Most devices filter advertising
  5. 最好不要使用 android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) 带有过滤某些服务 UUID 的参数,因为这在带有 Android 4.3 和 doesn't work for 128bit UUIDs 的三星 Galaxy S3 中完全被破坏了。李>
  6. Gatt 一次只能处理一个命令。如果几个命令一个接一个地被调用,第一个被取消due to the synchronous nature of the gatt implementation.
  7. 即使在装有 Android 5 的现代设备上,我也经常看到 Wifi 会干扰蓝牙,反之亦然。 万不得已,请关闭 wifi 以稳定蓝牙。

初学者教程

对于新手来说,一个相当不错的切入点可能是这个视频教程:为 Android 开发蓝牙智能应用程序http://youtu.be/x1y4tEHDwk0

下面描述的问题和解决方法现在可能已通过操作系统更新修复

解决方法:我可以“稳定”我的应用这样做...

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

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

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

【讨论】:

  • 谷歌,你现在必须解决这个问题。这种解决方法(我之所以加它是因为它确实有效)是荒谬的。
  • 有时,服务发现会以状态 0 成功(假设没有问题),但特征读取将产生 NULL 值,因为它实际上并未真正连接或未发现特征(我在日志中看到了这一点: 11-01 18:37:32.131: WARN/BluetoothGatt(20119): 未处理的异常: java.lang.NullPointerException)
  • @Lo-Tan 我总是在服务发现后检查是否包含我预期的服务。如果服务发现给出任何结果,您也永远无法确定。有时我没有收到回电。所以我为服务发现申请了超时。
  • 我的经验是:三星S3(4.3)在关闭Gatt客户端后成功重新连接,如上文第2段所述;使用 Nexus 4 & 7 (4.4.2) 连接断开后我无法重新连接,即使重新启动 BL 适配器,但它可以在 2 分钟后自动重新连接
  • 谁能确认 android.bluetooth.BluetoothGatt 是否只能处理一个待处理的 GATT 操作 PER DEVICEPER PROCESSPERIOD (即:跨所有进程)。我认为它是 PER DEVICE,但这个问题太复杂了,如果不是这样,我不会感到惊讶。如果限制只是每个设备,那么能够处理多个同时操作的操作系统/设备就是确凿证据证明这个问题纯粹是由于操作系统处理每个进程的 BluetoothAdapter 实例中的一些弱幼稚实现(我曾假设是跨所有进程的单例)。
【解决方案2】:

关闭 WIFI:

我也可以确认,关闭 WIFI 会使蓝牙 4.0 更加稳定,尤其是在 Google 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。

【讨论】:

  • 您说我在设备断开连接后重新启动 BLE。假设,如果用户通过蓝牙连接传输文件。然后,您将随时导致蓝牙传输失败。
  • “关闭然后打开适配器”是什么意思?
  • 我同意,Wifi 和蓝牙一起正在扼杀 Moto G 中的应用程序性能。
  • @MarianPaździoch ,通过“关闭然后打开适配器”@benka 表示蓝牙适配器
【解决方案3】:

确保您的 Nexus 已与设备配对。我无法验证通信是否正常,但您无需重新启动即可多次连接。似乎第一次连接不需要配对,但所有后续尝试都需要。

我会在几天后在不重启的情况下测试服务发现和 gatt 读写请求时更新这个答案。

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

编辑: 我确实注意到,在 Nexus 7 2013 上,关闭 WiFi 时连接更加稳定。我想知道这是否对其他人有帮助。

编辑: 我似乎已经把它与配对倒退了。未配对时一切正常。配对后,我遇到了与 OP 完全相同的症状。目前尚不清楚这是否与我们的固件或 Android BLE API 有关。测试时要小心,因为一旦配对,由于post 的 3b 中解释的错误,您可能无法取消配对。

【讨论】:

  • 我一直在连接和重新连接到 CC2541 设备,无需任何手动配对或重启。
  • 在我看来,没有必要配对。官方文档也没有评论配对。我也可以在没有任何配对的情况下执行写入、读取、特性更改通知。然而,只是很短的时间。现在又摇摇晃晃了...... SAMSUNG BLE SKD v2.0 也不需要配对并且工作得很好。
  • 我可以确认,关闭Wifi后更稳定。大家应该试试。
  • 是否需要配对取决于设备实现。 nrf8002 设备需要配对,三星 2.0 和 1.2 API 都支持这一点。好像官方的api支持在配对方面有问题,因为我配对了一个ble设备后,似乎无法取消配对!
  • 我可以解决无法取消配对的问题。 1)进入你的bt菜单,选择取消配对,从该区域移除BLE设备或将其断电,在bt菜单中选择BLE设备,它会尝试配对并失败,然后重置蓝牙。重置后,设备将取消配对。
【解决方案4】:

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

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

btGatt.disconnect();
btGatt.close();

【讨论】:

  • 为什么需要close
  • 当您想多次连接蓝牙时,正确的关闭程序是关键。根据我的经验,如果您在单独的 UNBOUND 服务中运行 Ble 连接,则效果最好,这样您就可以手动启动和停止它。你打电话给 mConnectedGatt.disconnect(); ble_device=null;在你的 inDestroy() 中。就我而言,这种模式可以稳定运行,没有问题。
【解决方案5】:

我遇到了类似的问题。我的解决方法是

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

& 断开连接后调用 close。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多