简体   繁体   中英

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.

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 )

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, ie 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).

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