Search code examples
androidibeaconibeacon-androidaltbeacon

AltBeacon: ranging not working as expected


I am building an Android App, which should start actions in the background, when the user enters or leaves a "bluetooth zone", which the user can define. Like Geofencing from Google.

I have read a lot here and adapted the code, how I thought, it have to be.

The "bluetooth zones" are configured by the user, by scanning the bluetooth devices, choosing the device and adding a radius to it. This workes as expected. This "bluetooth zone" is then persisted and ranged by the BeaconManager as a region in an own activity:

    BeaconManager mBeaconManager = BeaconManager.getInstanceForApplication(this);
    Region singleBeaconRegion = new Region(mRegion.getText().toString(), listB);
    try {
        mBeaconManager.startRangingBeaconsInRegion(singleBeaconRegion);
    } catch (RemoteException e) {   } 

Also I have an Application, which looks like this:

    public class BtZoneApplication extends Application implements BootstrapNotifier, RangeNotifier{
private static final String TAG = "BeaconReferenceAppl";
private BeaconManager mBeaconManager;
private Region mAllBeaconsRegion;
private BackgroundPowerSaver mBackgroundPowerSaver;
private RegionBootstrap mRegionBootstrap;
private Worker worker;
private final static String ALLBEACONSREGION = "##AllBeaconsRegion##";
DbServerHelper datasourceServer;
DbZoneHelper datasource;

@Override
public void onCreate() {
    mAllBeaconsRegion = new Region(ALLBEACONSREGION, null, null, null);
    mBeaconManager = BeaconManager.getInstanceForApplication(this);
    mBackgroundPowerSaver = new BackgroundPowerSaver(this);
    mBeaconManager.setBackgroundBetweenScanPeriod(30000L);
    mBeaconManager.setBackgroundScanPeriod(2100L);
   // wake up the app when a beacon is seen
    mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
    mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
}

@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
    // Start actions
    if (region.getUniqueId().equals(ALLBEACONSREGION)){
        return;
    }
    if (beacons.size() > 0) {
        for (Beacon beacon: beacons) {
            Log.d(TAG, "Beacon "+beacon.toString() + " is about " + beacon.getDistance() + " meters away, with Rssi: " + beacon.getRssi());
            // 
            if (beacon.getDistance() < radius && !status) {
                // set status to true
                // start action at entering zone
            }
            // radius * 2 for testing
            if (beacon.getDistance() > radius * 2 && status) {
                // set status to false
                // start action at exiting zone
            }
        }
    }
}

@Override
public void didDetermineStateForRegion(int arg0, Region arg1) {
   // do nothing
}

@Override
public void didEnterRegion(Region region) {
    Log.d(TAG, "entered region.  starting ranging");
    setRegionsAtBoot();
    mBeaconManager.setRangeNotifier(this);
}

@Override
public void didExitRegion(Region region) {
   // do nothing. Ranging should work further
}

// Set regions to monitor at boot/startup
private void setRegionsAtBoot(){
    ...
    for (Iterator<SimpleBeacon> iterator = beacons.iterator(); iterator.hasNext();) {
        ...
        try {
            mBeaconManager.startRangingBeaconsInRegion(new Region(simpleBeacon.getId(), listB));
        } catch (RemoteException e) {
        }
    }
}

My problem is, that it does not start ranging at start of the app, allthough the BluetoothLeScanner sees the device. Then sometime it starts suddenly. It is a strange behavior.

When it runs then the entering/exiting is reported multiple times, even the device is not moving and often the entering/exiting is not reported (in time?) in the background. Do I miss something?


Solution

  • A couple of issues in the Application code:

    • There is no need to implement BeaconConsumer or call bind explicitly when using RegionBootstrap, as binding happens automatically inside RegionBootstrap.

    • I would move the call to setRegionsAtBoot to didEnterRegion.

    It is not totally clear why the symptoms you describe would happen, but the above may be contributors.

    You might also use an off the shelf scanner like Locate Beacon to make sure your beacons can be ranged reliably. This would help eliminate a hardware issue.

    Finally, get it working in the foreground first, then focus on background operations.