Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 5.0 and BLE advertising of custom Service UUID

Problem

I currently have only one 5.0 phone to test this on (Moto E2 3G on 5.0 Lollipop), but I am not able to advertise Custom UUID's on Android 5.0. When I say a custom UUID I mean one that isn't predefined by the Bluetooth LE spec.

On my Nexus 6 Android 5.1, everything works fine.

Code

    AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
    AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();

    // Advertising this spec assigned UUID works
    //ParcelUuid temp = new ParcelUuid(UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb"));

    // Advertising this custom UUID doesn't work!!
    ParcelUuid temp = new ParcelUuid(UUID.fromString("02FD04F4-CFFF-4573-B478-F7470A7CF2F2"));

    dataBuilder.addServiceUuid(temp);

    settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);               settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
    settingsBuilder.setConnectable(true);

    AdvertiseData ad = dataBuilder.build();

    bluetoothLeAdvertiser.startAdvertising(settingsBuilder.build(), ad, null, advertiseCallback);

Observed Behaviour

When viewing the Advertising packet of the Moto E2 with a custom UUID, here's what I can see - notice there is no information about the Service UUID:

IMAGE

If I advertise an assigned service UUID on the Moto E2 (0000180D-0000-1000-8000-00805f9b34fb), I can see the 16-bit representation of the UUID is available:

IMAGE

If I advertise a custom UUID on the Nexus 6, I see the UUID data as expected:

IMAGE

Is anyone able to confirm this behaviour on another 5.0 device? Do I need to make the minimum supported version 5.1? The only other related reference I've been able to find on the internet about this, is this empty ticket on the Android bug tracker.

like image 429
14 revs, 12 users 16% Avatar asked Jul 16 '15 16:07

14 revs, 12 users 16%


1 Answers

I can confirm that this is a bug on the Moto G 2014 running 5.0.2 (and possibly other devices and/or versions).

My workaround is to just insert your custom UUID into the manufacturer data instead of the service UUID field. This will only work if you have access to the central that is scanning for it and can explicitly check the manufacturer data to see if the UUID is present in making your decision to connect.

With my implementation I had control over what the central checks to decide whether to connect, so I just adopted this scheme for all Android devices that operate in the peripheral mode, instead of using the normal 'addServiceUuid" method. Tested on Galaxy S6 (5.0.2) and Nexus 5X (6.0) and it's working.

private AdvertiseData buildAdvertiseData()
{
    int manufacturerID = 0x0001;
    byte[] uuidBytes = new byte[]{ (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F };
    return new AdvertiseData.Builder()
            .addManufacturerData(manufacturerID, uuidBytes)
            .setIncludeDeviceName(false)
            .build();
}

Make sure you exclude the device name, some devices will put the advertising packet over the 31 bytes otherwise and it will fail to start advertising.

like image 140
jcady Avatar answered Sep 30 '22 17:09

jcady