如何知道 BLE 指示是否在 Android 中得到确认
How to know if BLE indicate was acknowledged in Android
我们正在研究两个 Android 应用程序之间的低功耗蓝牙通信。一个是 peripheral/server,一个是 central/client。
如果数据已更改,服务器将向客户端发送指示。但是,我们没有找到一种方法来确保数据确实在客户端得到确认。
我们如何确定客户端是否收到并确认了数据以便在服务器端对其做出相应的反应?
根据 Android 文档,BleutoothGattServer 有回调 onNotificationSent。
https://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback#onNotificationSent(android.bluetooth.BluetoothDevice,%20int)
然而,通过调试和做一些测试,似乎这个方法真的只是在发送通知时才被调用。不保证消息确实被接收或确认。
下面是我们如何设置 GattServer 的特性
BluetoothGattService service = new BluetoothGattService(SERVICE_LOGIN_UUID,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
// Write characteristic
BluetoothGattCharacteristic writeCharacteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_LOGIN_UUID,
BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ| BluetoothGattCharacteristic.PROPERTY_INDICATE,
// Somehow this is not necessary, the client can still enable notifications
// | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ);
service.addCharacteristic(writeCharacteristic);
mGattServer.addService(service);
然后我们通过调用这个
通知客户
mHandler.post(() -> {
BluetoothGattService service = mGattServer.getService(SERVICE_LOGIN_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(uuid);
log("Notifying characteristic " + characteristic.getUuid().toString()
+ ", new value: " + StringUtils.byteArrayInHexFormat(value));
characteristic.setValue(value);
boolean confirm = BluetoothUtils.requiresConfirmation(characteristic);
for(BluetoothDevice device : mDevices) {
mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
}
});
*请暂时忽略此处的 FOR 循环
这将导致调用 onNotificationSent,但无助于了解它是否已被确认。
如果您需要其他代码部分,请告诉我。
谢谢大家,再见
不幸的是 Android,确认是 sent/received 在幕后进行的,也就是说,您没有可以在您的应用程序中使用它的机制。请看下面的link:-
如果你真的想要一些应用层机制来证明数据已经收到,你可以在你的服务器端实现另一个(额外的)特性。当中央端接收到数据时,它可以简单地写入该特征以证明它具有。这样做的缺点是会使您的应用程序更复杂,但可以说更可靠。这样做的原因是您从应用层手动发送确认,确保一切都按预期工作,而从基带层自动发送 ACK 并不能证明一切都 100% 成功(例如,数据没有'无法从基带连接到应用程序,或者您的应用程序已崩溃等)。
希望对您有所帮助。
我们正在研究两个 Android 应用程序之间的低功耗蓝牙通信。一个是 peripheral/server,一个是 central/client。 如果数据已更改,服务器将向客户端发送指示。但是,我们没有找到一种方法来确保数据确实在客户端得到确认。 我们如何确定客户端是否收到并确认了数据以便在服务器端对其做出相应的反应?
根据 Android 文档,BleutoothGattServer 有回调 onNotificationSent。 https://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback#onNotificationSent(android.bluetooth.BluetoothDevice,%20int)
然而,通过调试和做一些测试,似乎这个方法真的只是在发送通知时才被调用。不保证消息确实被接收或确认。
下面是我们如何设置 GattServer 的特性
BluetoothGattService service = new BluetoothGattService(SERVICE_LOGIN_UUID,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
// Write characteristic
BluetoothGattCharacteristic writeCharacteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_LOGIN_UUID,
BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ| BluetoothGattCharacteristic.PROPERTY_INDICATE,
// Somehow this is not necessary, the client can still enable notifications
// | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ);
service.addCharacteristic(writeCharacteristic);
mGattServer.addService(service);
然后我们通过调用这个
通知客户mHandler.post(() -> {
BluetoothGattService service = mGattServer.getService(SERVICE_LOGIN_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(uuid);
log("Notifying characteristic " + characteristic.getUuid().toString()
+ ", new value: " + StringUtils.byteArrayInHexFormat(value));
characteristic.setValue(value);
boolean confirm = BluetoothUtils.requiresConfirmation(characteristic);
for(BluetoothDevice device : mDevices) {
mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
}
});
*请暂时忽略此处的 FOR 循环
这将导致调用 onNotificationSent,但无助于了解它是否已被确认。
如果您需要其他代码部分,请告诉我。
谢谢大家,再见
不幸的是 Android,确认是 sent/received 在幕后进行的,也就是说,您没有可以在您的应用程序中使用它的机制。请看下面的link:-
如果你真的想要一些应用层机制来证明数据已经收到,你可以在你的服务器端实现另一个(额外的)特性。当中央端接收到数据时,它可以简单地写入该特征以证明它具有。这样做的缺点是会使您的应用程序更复杂,但可以说更可靠。这样做的原因是您从应用层手动发送确认,确保一切都按预期工作,而从基带层自动发送 ACK 并不能证明一切都 100% 成功(例如,数据没有'无法从基带连接到应用程序,或者您的应用程序已崩溃等)。
希望对您有所帮助。