【问题标题】:Android Bluetooth LE - BluetoothGatt - onNotify stops receiving dataAndroid 蓝牙 LE - BluetoothGatt - onNotify 停止接收数据
【发布时间】:2014-08-13 08:49:48
【问题描述】:

我正在连接到作为中心的蓝牙 LE 外围设备。我正在向一个特征写入数据,我通过通知以 20 个字节的块接收数据。

通知订阅:

private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w("BluetoothAdapter not initialized");
        return;
    }

    Log.d("Enabling Notifications");

    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

    BluetoothGattDescriptor descriptor =
            characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));

    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

    mBluetoothGatt.writeDescriptor(descriptor);
}

如果在写入之间只需要接收少量的块,这可以正常工作。蓝牙堆栈为每个块发送通知:

D/BluetoothGatt﹕ onNotify() - Device=B0:EC:8F:00:07:AA UUID=06d1e5e7-79ad-4a71-8faa-373789f7d93c

但是如果写入之间的块数大于大约 10,堆栈将停止通知,其余数据将丢失!设备肯定会发送更多数据,因为我们可以在 iOS 设备上接收。

收到的通知数量因 Android 设备而异。 Galaxy S3 (4.3) 收到 5,nexus 5 (4.4.4) 和 htc one (4.4.2) 收到 12。

BT 堆栈在最后一次通知后 30 秒关闭连接。

D/BluetoothGatt﹕ onClientConnectionState() - status=0 clientIf=5 device=B0:EC:8F:00:00:88

谁能重现这个问题?

由于蓝牙 LE 堆栈是基于轮询的,我猜想堆栈出于某种原因停止从外围设备轮询数据。目标设备不支持指示。

更新:Android L 蓝牙堆栈提供的附加信息:

06-27 12:20:02.982 18909-18946/? D/BtGatt.GattService﹕ onNotify() - address=B0:EC:8F:00:01:09, charUuid=06d1e5e7-79ad-4a71-8faa-373789f7d93c, length=20

06-27 12:20:07.666 18909-18984/? E/BTLD:############################################# ######################## 06-27 12:20:07.666 18909-18984/? E/BTLD:# 06-27 12:20:07.666 18909-18984/? E/BTLD:# WARNING : BTU HCI(id=0) 命令超时。操作码=0xfd55 06-27 12:20:07.666 18909-18984/? E/BTLD:# 06-27 12:20:07.666 18909-18984/? E/BTLD:############################################# ######################## 06-27 12:20:07.670 18909-18984/? E/bt-btm﹕无法解释 IRK VSC cmpl 回调 06-27 12:20:07.670 18909-18984/? W/bt-hci﹕HCI Cmd 超时计数器 1 06-27 12:20:34.315 18909-18984/? E/bt-btm﹕btm_sec_disconnected - 清除挂起标志

【问题讨论】:

  • 这正是我们所看到的。尝试多次后通知失败,然后设备在 Nexus 5 上大约 15 秒后自动断开连接。我们的 BLE 设备在 iOS 上就像一个魅力。值得注意的是,使用特定代码,Galaxy S4 将在发生这种情况时自动重新连接,这使我们相信三星识别并开发了自定义处理的 BLE 堆栈中存在问题。另外值得注意的是,Android L Preview 没有解决这个问题。
  • 添加了来自 Android L 的附加日志。我们目前通过将外围设备端的通知延迟 60 毫秒来解决此问题。但这不是我所说的修复,因为它会大大减慢速度。
  • 你有没有尝试过做一个异步任务?
  • 我不确定你的意思,你能更具体一点吗?如果这就是您的意思,我会在单独的线程中进行每个 BT 调用。但问题出现在 Android BT 堆栈的某个地方。即使我从 onCharacteristicChanged() 中删除所有代码,行为也是一样的。
  • Philipp,另一个考虑是 BT 堆栈在异步 BtGattCallback 接口下是同步的。通过确保 BT 堆栈一次只处理一个操作 - 即任何会回调到 BtGattCallback 的操作 - 我提高了我们应用程序的整体稳定性。

标签: android bluetooth bluetooth-lowenergy android-bluetooth


【解决方案1】:

也许不是一个理想的解决方案,但我已经开始接受通知根本不起作用或停止工作,这是在 Android 上执行 BLE 的不幸现实。考虑到这一点,我相信最好在正常通知出现故障时通过读取轮询来设置自己的“伪通知”备份机制。例如,在 Handler#postDelayed() 循环中每秒一次。您甚至可以将其抽象到一个单独的类后面,该类存储上次读取的值,并且仅在上次读取的值不等于新值时通知您的 UI。

【讨论】:

    【解决方案2】:

    最终对我们有用的是外围设备上的两个更改:

    -为外设上的每个响应添加一个小延迟

    -将slave延迟降低到0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多