Home » Android » android – Bluetooth LE Scan filter not working

android – Bluetooth LE Scan filter not working

Posted by: admin June 15, 2020 Leave a comment

Questions:

I want to only scan BLE beacons with a specific UUID in my Android code. Even though I can add filter for specific MAC addresses, I cannot make it work with UUIDs. onScanResult function is never called. Why could that be? I’m using API 21 and I’m not getting any errors for the project.

final String tagUUID = "01122334-4556-6778-899a-abbccddeeff0";

//does not work
ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUID.fromString(tagUUID))).build();

//works
ScanFilter filter = new ScanFilter.Builder().setDeviceAddress(tagMAC).build();
How to&Answers:

I’m the author of the blog post mentioned above. Here’s how to fix your issue for Android 21+.

// Empty data
byte[] manData = new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

// Data Mask
byte[] mask = new byte[]{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0};

// Copy UUID into data array and remove all "-"
System.arraycopy(hexStringToByteArray("YOUR_UUID_TO_FILTER".replace("-","")), 0, manData, 2, 16);

// Add data array to filters
ScanFilter filter = new ScanFilter.Builder().setManufacturerData(76, manData, mask).build());

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

The issue here is that you can add UUID filtering but its not exactly straight forward

Answer:

It is possible that the filtering looks for the service UUID in the “Service UUID” AD Type Advertising Structure. Which actually makes sense and that’s how it should work.

For beacons, the UUID you are trying to find is actually located in the “Manufacturer Specific Data” AD Type structure. And nobody cares about looking for Service UUIDs there.

I believe that the service UUID filtering is only meant to filter for UUIDs of services in the GATT Database; those UUIDs would be located as I explained in the first paragraph.

That UUID in beacons is not a service UUID per se. It is rather a beacon identifier with an UUID format.