安卓BLE BluetoothGatt.writeDescriptor()有时会返回false。

12
我正在尝试编写BLE Android应用程序。我发现有时候当我调用BluetoothGatt.writeDescriptor()时,它会返回false。
我没有在文档中找到关于此函数的任何限制说明。但是堆栈溢出上的人说,我需要等待BluetoothGattCallback.onDescriptorWrite(),然后再尝试写另一个描述符。
有人回复说BLE正忙,无法进行其他写入操作。
还有另一个线程说,您不能调用两次writeCharacteristic()。
我的问题是:
  • 这是真的吗?
  • 是否确实缺少内部android API缓冲区来序列化BLE请求,每个开发人员都必须自己完成它?
  • 不同的函数是否也有此限制?例如,当我调用writeDescriptor()时,我了解到在收到onDescriptorWrite()之前,我不能再次调用writeDescriptor()。但是当我想要调用writeCharacteristic()时,我是否需要等待onDescriptorWrite()
  • 此外,如果存在互函数依赖性,则还有哪些函数具有此限制(即:readCharacteristic()readDescriptor()requestMtu()...)?
  • 最后,BluetoothGattServer和BluetoothGatt之间是否存在相互依赖性?因此,例如,当我调用BluetoothGattServer.notifyCharacteristicChanged()时,我是否应该等待BluetoothGattServerCallback.onNotificationSent,然后才能调用BluetoothGatt.writeDescriptor()BluetoothGatt.writeCharacteristic()?(顺便称赞谷歌文档onNotificationSent()——它已被恰当地记录。文档说:

当要发送多个通知时,应用程序必须等待接收此回调才能发送其他通知。

  • 最后,有了所有这些问题,我感到Android BLE API的文档不足。或者我错了,有文档说明允许的方法调用顺序吗?如果是,请指向这样的文档。否则,我们是否可以与谷歌开放问题的渠道并要求将某些内容添加到文档中?我的意思是它可能不需要太多文本——像onNotificationSent()这样的函数已经得到了适当的记录。他们只需要将此句子复制到其他功能中。
1个回答

30

这份文档缺乏信息。但是你可以阅读源代码以了解目前的规则,它们如下:

对于每个BluetoothGatt对象,您一次只能有一个未完成的请求,包括requestMtureadCharacteristicwriteCharacteristicreadDescriptorwriteDescriptorexecuteReliableWrite。因此,如果您发出读取请求,则需要在发出写入请求之前等待读取响应。虽然他们实现了在BluetoothGatt.java中返回false的代码,如果有正在进行的操作,但他们忘记为requestMtu执行此操作,因此,在一些最新版本中,如果您同时有多个请求,其中一个是requestMtu,那么您迟早会遇到随机错误。

所以,是的,每位开发者都必须手动序列化请求。请注意,蓝牙堆栈实际上具有请求队列,但仅限于每个客户端(即BluetoothGatt对象)的一个请求。因此,如果同一手机上的两个应用程序同时连接到同一设备,则永远不会收到“忙”错误。唯一的例外是,如果您使用了无响应写入,则当前数据流实现相当有缺陷(请参见https://issuetracker.google.com/issues/37121017,谷歌似乎已忽略此问题)。

您可以在写入特征值的同时发送通知,因为服务器和客户端的角色是分开的。

关于文档的更新,您可以尝试在https://issuetracker.google.com提交问题(但我感觉没人会看),或者由于Android是开源的,向https://android-review.googlesource.com/ 提交拉取请求,从而更新生成文档的Javadoc。


很棒的解释!很难找到这个答案。 - smörkex
你如何等待响应? - Displee
只需等待相应的回调被调用即可。例如,如果您调用了 writeCharacteristic,则需要在您的 BluetoothGattCallback 中实现 onCharacteristicWrite - Emil
我曾经遇到过同样的问题,后来找到了这个维护队列的代码 https://gist.github.com/SoulAuctioneer/ee4cb9bc0b3785bbdd51 - Sumit
1
那段代码似乎不是线程安全的,因此可能会遭受竞态条件的影响。请注意,onCharacteristicWrite 是从 Binder 线程调用的,这通常不是您发起操作的线程。因此,txQueue 可能会被两个线程同时使用。该代码还存在一个问题,如果您连接到不同的蓝牙地址,则会泄漏先前的 BluetoothGatt 对象(作者忘记了它必须关闭)。 - Emil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接