7
votes

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.

2
You need something like callback? Not sure what the problem is?Vasil Valchev
Sorry if it wasn't but I thought I was quite clear that I need some way of knowing how a device subscribed. If that's through a callback then great, but I just need to know how to get that information. It's a callback on iOS, so that's the only reference I have as an example.Kane Cheshire
@kanecheshire did you find something? need the samestefreak
What about BluetoothGattCallback.onCharacteristicChanged()? developer.android.com/reference/android/bluetooth/…, android.bluetooth.BluetoothGattCharacteristic)josemigallas
I think BluetoothGattCallback is for the Central and not the peripheral side... Or is it? @josemigallasstefreak

2 Answers

8
votes

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)

3
votes

Agree with @stefreak

and,

bluetoothGatt.setCharacteristicNotification(characteristicToSubscribeTo, true);

did nothing for remote device, this API only changed a notification bit at the local Bluetooth stack, i.e. if peripheral send notifications to local, local stack will judge whether apps already registered this notification and if yes, transfer it to app otherwise, ignore it.

so except setCharacteristicNotification you should also need writeDescriptor for your registered notification(this is the steps that tell remote need send notifications).