Search code examples
androidbluetooth-lowenergybeaconaltbeacon

Altbeacon 2.16.1 can't scan beacons with specific beacon type code


I am building an Android app that scans two types of beacon using the android-beacon-library:

  • iBeacon type (0x4c000215)
  • custom beacon which beacon type code is 0x4106

I know there was an issue that fixed broken Samsung screen off scans https://github.com/AltBeacon/android-beacon-library/pull/798.
That fix was implemented into the 2.15.3 release.
Since then, during every scan with a samsung device >= Android 8.0, I don't see any of my custom beacon but I do receive other beacon types like iBeacon. So I am still using the 2.15.2 release.

Here is my custom beacon layout:

"m:0-1=4106,i:2-3,i:4-4,i:5-6,i:7-8,i:9-10,i:11-11,i:12-12,i:13-13,i:14-14,i:15-15,i:16-16,i:17-17,i:18-23,p:24-24"  

I checked the code from the lib and I can see a filter that applies for samsung devices only:

if (Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
  // On the Samsung Galaxy Note 8.1, scans are blocked with screen off when the
  // scan filter is empty (wildcard).  We do a more detailed filter on Samsung only
  // because it might block detections of AltBeacon packets with non-standard
  // manufacturer codes.  See #769 for details.
  filters = new ScanFilterUtils().createScanFiltersForBeaconParsers( 
  mBeaconManager.getBeaconParsers());
}

If I remove this code, everything works as I expect.

Is there something I have to do so I don't need to edit the library?

Thanks.


Solution

  • The library uses both the BLE manufacturer ID and the beacon type code to match BLE filters when the app is in the background. For this to work, you must set these up exactly right, or the filters will not match.

    Two issues here:

    1. Your beacon type code should not include the BLE manufacturer ID. Instead of 0x4c000215 use 0x0215 (Note: 0x4c00 is the Apple BLE manufacturer ID, and will be applied separately.) If using a beacon layout string with this, you must adjust the byte offsets to account for this, so your layout starts with m:2-3=0215

    2. For any beacon layout that will be matched with these filters, you must set the hardware assist manufacturer identifiers. By default, the library includes 0x0118 (Radius Networks for AltBeacon) and 0x0215 (Apple for iBeacon) for all other manufacturer beacon types. For any custom beacon that uses yet another manufacturer code (see list here: https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers) you must add it like this (example shown for hardware manufacturer id 0x1234):

      beaconParser.setHardwareAssistManufacturerCodes(new int[]{0x1234});

    Important tip: Mobile devices have a limited number of bluetooth hardware filter slots. You can help ensure you do not run out of them by:

    1. Only register as many beacon layouts as you need. If not using the default AltBeacon layout, call beaconManager.getBeaconParsers().clear(); to remove it.

    2. Only register the exact hardware manufacturer codes you need with each BeaconParser. If you register more than one you will use more than one filter slot.

    The above APIs were designed before this Samsung restriction came into place making this a more serious issue. I am open to other ideas on how to make this API more intuitive so other folks don't run into the same problem as you did.