xamarin.formsxamarin.androidaltbeacon

i-beacons on Xamarin Android getting filtered when using the Alt-beacon library


I think I have tried all that I could. May be missing something simple here. So here is the setup. I have a Xamarin forms application with a dependency service which runs beacon monitoring. It has a MonitorNotifier and a RangeNotifier. I'm searching for iBeacon using the alt-beacon library. I'm on 2.19.4.I created a Xamarin bindings with some additional partial classes so that the binding library would compile. The application asks user for Access_Fine_Location and Access_background_location etc. Bluetooth permissions are also asked at runtime.

(Android.Manifest.Permission.BluetoothScan, true),
(Android.Manifest.Permission.BluetoothConnect, true),           
(Android.Manifest.Permission.BluetoothAdmin, true)

then it also asks for runtime location permissions:

            var array = new List<(string androidPermission, bool isRuntime)>();
            if (Build.VERSION.SdkInt >= BuildVersionCodes.M && _isAskingFineLocation)
            {
                array.Add((Android.Manifest.Permission.AccessFineLocation, true));
            }

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Q && _isAskingBackgroundLocation)
            {
                array.Add((Android.Manifest.Permission.AccessBackgroundLocation,true));
            }
            return array.ToArray();

Android Manifest does not have "neverforlocation" set in bluetooth permissions. And yet, I get the following:

07-13 18:27:50.990 V/BtGatt.GattService( 4285): Skipping data matching denylist: ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0a834234-e4a6-4fbd-a596-383e852d706f], mServiceSolicitationUuids=[], mManufacturerSpecificData={76=[2, 21, 111, 112, 45, -123, 62, 56, -106, -91, -67, 79, -90, -28, 52, 66, -125, 10, 0, 0, -33, 126, -59]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=ACS Beacon, mTransportBlocks=[]]
07-13 18:27:50.990 I/BtGatt.GattService( 4285): Skipping client for location deny list
07-13 18:27:50.990 V/BtGatt.GattService( 4285): Skipping data matching denylist: ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0a834234-e4a6-4fbd-a596-383e852d706f], mServiceSolicitationUuids=[], mManufacturerSpecificData={76=[2, 21, 111, 112, 45, -123, 62, 56, -106, -91, -67, 79, -90, -28, 52, 66, -125, 10, 0, 0, -33, 126, -59]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=ACS Beacon, mTransportBlocks=[]]
07-13 18:27:50.990 I/BtGatt.GattService( 4285): Skipping client for location deny list
07-13 18:27:50.991 V/BtGatt.GattService( 4285): Skipping data matching denylist: ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0a834234-e4a6-4fbd-a596-383e852d706f], mServiceSolicitationUuids=[], mManufacturerSpecificData={76=[2, 21, 111, 112, 45, -123, 62, 56, -106, -91, -67, 79, -90, -28, 52, 66, -125, 10, 0, 0, -33, 126, -59]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=ACS Beacon, mTransportBlocks=[]]
07-13 18:27:50.991 I/BtGatt.GattService( 4285): Skipping client for location deny list
07-13 18:27:50.991 V/BtGatt.GattService( 4285): Skipping data matching denylist: ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0a834234-e4a6-4fbd-a596-383e852d706f], mServiceSolicitationUuids=[], mManufacturerSpecificData={76=[2, 21, 111, 112, 45, -123, 62, 56, -106, -91, -67, 79, -90, -28, 52, 66, -125, 10, 0, 0, -33, 126, -59]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=ACS Beacon, mTransportBlocks=[]]
07-13 18:27:50.991 I/BtGatt.GattService( 4285): Skipping client for location deny list

I found on

https://android.googlesource.com/platform/packages/apps/Bluetooth/+/master/src/com/android/bluetooth/gatt/GattService.java

about filtering based on location deny list, but I don't have any location permission denied. My Android is targeting 13. So is the alt-beacon-binding.

Edit: Regarding the beacon parser layout:

var parser = new BeaconParser();
parser.SetBeaconLayout(Constants.BeaconLayout);
parser.SetHardwareAssistManufacturerCodes(new int[]{0x004c});

_beaconManager = BeaconManager.GetInstanceForApplication(Application.Context);
            _beaconManager.BeaconParsers.Clear();
            _beaconManager.BeaconParsers.Add(parser);

where BeaconLayout is this: enter image description here


Solution

  • It is always extra tricky to get beacon detection working on Xamarin or other abstraction frameworks, because there is yet another layer that can cause problems. Assuming the problem is not introduced by the Xamarin layer (I am no expert there, so I cannot offer much help), the first things I would look at are:

    1. Make sure you have a BeaconParser set up for iBeacon. By default, the AndroidBeaconLibrary only detects AltBeacon. You have to configure a parser for iBeacon. With native Android Kotlin code, you do that like this:
    val parser = BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")      
    beaconManager.getBeaconParsers().add(parser)
    
    1. Go to Settings -> Apps -> Your App -> Permissions and look very closely at the Bluetooth and Location permissions to make sure they are granted. In particular make sure the Location permission as the "Use Precise Location" switch turned on.

    2. Check your merged AndroidManifest.xml file see here to see if your BLUETOOTH_SCAN permission has the attribute “neverForLocation”. If it is, you must remove that marking in the declaration. (It may get added by a different included library.) Doing this requires a tools:replace entry in your manifest. See here.

    3. If the above doesn't help, go thorough this detection troubleshooting checklist on the Android Beacon Library support site.