Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know when a BLE device subscribes to a characteristic on Android?

Coming from an iOS dev background, when working with Bluetooth LE acting as a peripheral you can register for a callback when a "central" BLE device subscribes (enables notifications) for a characteristic.

I'm struggling to see how this is achieved on Android. If you're working with Bluetooth LE acting as the central, I can see how you'd subscribe: bluetoothGatt.setCharacteristicNotification(characteristicToSubscribeTo, true);

Which is the same as this on iOS: peripheralDevice.setNotifyValue(true, forCharacteristic characteristicToSubscribeTo)

Now, after calling the above on iOS, on the peripheral side you then get a callback to say the central has subscribed with a method similar to: peripheralManager(manager, central subscribedCentral didSubscribeToCharacteristic characteristic) which then gives you a reference to the device that subscribed/enabled notifications and to what characteristic.

What's the equivalent on Android?

For clarity I'll point out that I don't need to subscribe to a characteristic on Android, the device is acting as the peripheral and needs to be notified when other devices subscribe to characteristics.

Sorry if this is obvious but I can't find it in the docs or elsewhere.

like image 361
Kane Cheshire Avatar asked Mar 24 '16 12:03

Kane Cheshire


1 Answers

Just after setting the bounty I had an idea, haha should've waited a little more give my brain more time to think ;)

It seems that iOS has abstracted away a little bit how subscriptions work internally. Under the ios CoreBluetooth hood a certain "Descriptor" of the characteristic is written by the Center, which indicates the center wants to subscribe the characteristic's value.

Here is the code that you need to add to your BluetoothGattServerCallback subclass:

    @Override
    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);

        Log.i(TAG, "onDescriptorWriteRequest, uuid: " + descriptor.getUuid());

        if (descriptor.getUuid().equals(Descriptor.CLIENT_CHARACTERISTIC_CONFIGURATION) && descriptor.getValue().equals(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) {
            Log.i(TAG, "its a subscription!!!!");

            for (int i = 0; i < 30; i++) {
                descriptor.getCharacteristic().setValue(String.format("new value: %d", i));
                mGattServer.notifyCharacteristicChanged(device, descriptor.getCharacteristic(), false);
            }
        }
    }

would be best to use https://github.com/movisens/SmartGattLib for the uuid (Descriptor.CLIENT_CHARACTERISTIC_CONFIGURATION but the raw value is 00002902-0000-1000-8000-00805f9b34fb)

like image 83
stefreak Avatar answered Oct 07 '22 01:10

stefreak