简体   繁体   中英

How to know if BLE indicate was acknowledged in Android

We are working on a Bluetooth Low Energy communication between two Android apps. One is the peripheral/server one the central/client. The server will send an indicate to the clients if the data has changed. However, we didn't find a way to make sure that the data was actually acknowledged on the client side. How can we figure out, if the client received and acknowledged the data in order to react accordingly on the server side to it?

According to Android documentation there is the callback onNotificationSent for the BleutoothGattServer. https://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback#onNotificationSent(android.bluetooth.BluetoothDevice,%20int)

However by debugging and doing some tests it seems this method really is just called if the notification is sent. There is no guarantee the message was actually received nor acknowledged.

So here is how we setup the characteristics for the 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);

and then we notify the clients by calling this

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);
            }
        });

*PLEASE IGNORE THE FOR LOOP HERE FOR THE MOMENT

This will cause onNotificationSent to be called but doesn't help to know if it was acknowledged or not.

Let me know if you need other code parts.

Thank you all already, many greetings

Unfortunately on Android, the acknowledgement is sent/received behind the scenes, ie there is no mechanism where you can use this in your app. Please have a look at the following link:-

Handling indications instead of notifications in Android BLE

If you really want some app-layer mechanism to prove that the data was received, you can implement another (additional) characteristic on your server side. When the data is received on the central side, it can simply write to that characteristic to prove that it has. This has the disadvantage of making your app more complex but is arguably more reliable. The reason for this is that you are manually sending the acknowledgements from the app-layer, ensuring that everything has worked as expected, whereas automatically sending ACKs from the baseband layer is not proof that everything is 100% working successfully (eg the data didn't make it from the baseband to the app, or your app has crashed, etc).

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM