Search code examples
androidbluetooth-lowenergyuuid

Android BLE Advertising UUID Length differs on different SDK level?


I want to broadcast some data via BLE.

The addServiceData function takes a ParcelUuid and the data.

https://developer.android.com/reference/android/bluetooth/le/AdvertiseData.Builder.html

I tested it on my Android 7.0 Smartphone and the Uuid got shrinked down to 16 bits.

https://code.tutsplus.com/tutorials/how-to-advertise-android-as-a-bluetooth-le-peripheral--cms-25426

While this utility creates a 128-bit UUID, the Android system only uses 16-bit UUIDs for advertisement and will automatically adjust a 128-bit UUID to conform.

This is fine, cause I need the bandwidth for the data I send. But the same App sends the full 128 bit Uuid on an Android 8.1 device.

I dont understand this and I want my app to send always the 16 bit Uuid. I found no option to choose the length of the Uuid.


Solution

  • The 16-bit Bluetooth UUID is a shortcut for:

    0000xxxx-0000-1000-8000-00805F9B34FB
    

    … where xxxx is the 16 bits. For example, if you want to advertise a BEEF UUID, I believe you need to pass 0000BEEF-0000-1000-8000-00805F9B34FB to AdvertiseData.Builder.

    Further down the stack, Android should recognize this as a 16-bit Bluetooth UUID, and broadcast only the two bytes. The relevant code is in the AdvertiseHelper and BluetoothUuid classes in the AOSP:

    public static byte[] uuidToBytes(ParcelUuid uuid) {
        if (uuid == null) {
            throw new IllegalArgumentException("uuid cannot be null");
        }
    
        if (is16BitUuid(uuid)) {
            byte[] uuidBytes = new byte[UUID_BYTES_16_BIT];
            int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
            uuidBytes[0] = (byte) (uuidVal & 0xFF);
            uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8);
            return uuidBytes;
        }
    
        ...
    

    I guess this behavior may have changed between 7.0 and 8.1. Looks like previously, they may have been converting the 128-bit UUID to a 16-bit UUID no matter what. Now, looks like it'll correctly only do so if the 128-bit UUID follows the Bluetooth standard/notation.