android - 被 BluetoothGattServerCallback#onCharacteristicWriteRequest 弄糊涂了
问题描述
对 Android BluetoothGattServerCallback#onCharacteristicWriteRequest方法感到困惑。
对于参数
preparedWrite
,我认为实现写操作是我的责任,回调如何知道我应该何时将消息排队?文档说
An application must call BluetoothGattServer.sendResponse(BluetoothDevice, int, int, int, byte[]) to complete the request.
,如果responseNeeded
是假的怎么办?BluetoothGattServer#sendResponse(BluetoothDevice, int, int, int, byte[])
无论我设置什么,调用似乎总是返回请求中的值value
。是预期的吗?
解决方案
用于支持长preparedWrite
写入(大于 MTU)。
BluetoothGattServerCallback#onCharacteristicWriteRequest
与 一起工作BluetoothGattServerCallback#onExecuteWrite
以重组对等设备发送的碎片数据。要回答您的问题:
当接收到传入数据的片段时,该参数
preparedWrite
为真,即数据需要排队等待更多数据到达。BluetoothGattServerCallback#onExecuteWrite
将在收到最终片段并且可以完全组装发送的特征值后调用。如果
responseNeeded
为假,请不要调用BluetoothGattServer.sendResponse(BluetoothDevice, int, int, int, byte[])
.只发一个空的
value
。这是一个例子
onCharacteristicWriteRequest
:
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log.d("SVC", "BluetoothGattServerCallback.onCharacteristicWriteRequest with " + value.length + " bytes");
if(preparedWrite) {
handleInputFragment(device, characteristic.getUuid(), value);
} else {
handleInputMessage(device, characteristic.getUuid(), value);
}
if(responseNeeded) {
Log.d("SVC", "sending response to write request for characteristic: " + characteristic.getUuid());
if(!gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, new byte[0])) {
Log.e("SVC", "response to characteristic write request failed");
}
}
}
和onExecuteWrite
@Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
Log.d("SVC", "BluetoothGattServerCallback.onExecuteWrite " + (execute ? "execute" : "cancelled"));
super.onExecuteWrite(device, requestId, execute);
Iterator<InputBuffer> itr = inputBuffers.iterator();
while(itr.hasNext()) {
InputBuffer buf = itr.next();
if(buf.device.equals(device)) {
itr.remove();
if(execute) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (byte[] b : buf.bytes) {
os.write(b, 0, b.length);
}
handleInputMessage(device, buf.characteristicUuid, os.toByteArray());
}
}
}
}
InputBuffer 机制的实现类似于
private class InputBuffer {
final BluetoothDevice device;
final UUID characteristicUuid;
final List<byte[]> bytes;
InputBuffer(BluetoothDevice device, UUID characteristicUuid, byte[] value) {
this.device = device;
this.characteristicUuid = characteristicUuid;
this.bytes = new ArrayList<>();
this.bytes.add(value);
}
}
private List<InputBuffer> inputBuffers = new LinkedList<>();
private void handleInputFragment(BluetoothDevice device, UUID characteristicUuid, byte[] value) {
Log.d("SVC", "handling input Fragment");
for(InputBuffer buf : inputBuffers) {
if(buf.device.equals(device)) {
buf.bytes.add(value);
return;
}
}
inputBuffers.add(new InputBuffer(device, characteristicUuid, value));
}
的实现handleInputMessage
是特定于应用程序的。
推荐阅读
- r - 在 R 中随机采样不规则的栅格范围
- regex - 我需要一个正则表达式来提取分隔符之间的特定字符
- jenkins-pipeline - 如何在 Jenkins 管道中的 zip 文件管道实用程序插件中排除 Jenkinsfile 和自动化脚本
- uvm - 在模拟运行时更改 uvm 详细程度
- python - Pandas Dataframe 时移列
- leaflet - 传单层在缩小时格式不正确
- python - python的舍入问题(实现Karatsuba的算法)
- c - 原始以太网 MAC 目标地址
- jquery - Jquery Chosen - 销毁方法不起作用
- cordova - cordova-hot-code-push-plugin 删除其他已安装的 ionic cordova 本机插件