I'm writing a simple beacon application in Android
If started outside a region it works (here's my custom log):
onCreate - In
onCreate - Out
onBeaconServiceConnect - In
onBeaconServiceConnect - Out
didDetermineStateForRegion (INSIDE)
didEnterRegion - In
dER - startRangingBeaconsInRegion OK
didEnterRegion - Out
didRangeBeaconsInRegion - 1 beacons
...... omitted .....
didRangeBeaconsInRegion - 0 beacons
didDetermineStateForRegion (OUTSIDE)
didExitRegion - In
dXR - stopRangingBeaconsInRegion OK
didExitRegion - Out
didRangeBeaconsInRegion - 0 beacons
If started inside a region, the bootstrapNotifier
(i.e. monitorNotifier
) methods are not called
Can anyone see where I'm going wrong here?
package it.test.test01;
import android.app.Application;
import android.os.RemoteException;
import android.util.Log;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import java.util.Collection;
public class testApplication extends Application
implements BootstrapNotifier, BeaconConsumer, RangeNotifier {
private final String TAG = "Application ";
protected static final Region beaconRegion = new Region("test01", null, null, null);
protected BeaconManager beaconManager = null;
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
protected static String sLog = "";
@Override
public void onCreate() {
super.onCreate();
logIt(TAG, "onCreate - In");
beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));//iBeacon (tutti)
//--- wake up the app when a beacon is seen
regionBootstrap = new RegionBootstrap(this, beaconRegion);
//--- activate power saver
backgroundPowerSaver = new BackgroundPowerSaver(this);
beaconManager.bind(this);
logIt(TAG, "onCreate - Out");
}
private void logIt (String TAG, String msg) {
sLog += TAG + msg + "\n";
Log.w(TAG, msg);
}
//-------------------------//
//--- BootstrapNotifier ---//
//-------------------------//
@Override
public void didDetermineStateForRegion(int state, Region region) {
String msg = "didDetermineStateForRegion ";
switch(state) {
case MonitorNotifier.INSIDE:
msg +="(INSIDE)";
break;
case MonitorNotifier.OUTSIDE:
msg +="(OUTSIDE)";
break;
default:
msg +="(state=" +state +")";
break;
}
logIt(TAG, msg);
}
@Override
public void didEnterRegion(Region arg0) {
logIt(TAG, "didEnterRegion - In");
try {
beaconManager.startRangingBeaconsInRegion(beaconRegion);
logIt(TAG,"dER - startRangingBeaconsInRegion OK");
} catch (RemoteException e) {
logIt(TAG, "dER - startRangingBeaconsInRegion Err " +e);
}
logIt(TAG, "didEnterRegion - Out");
}
@Override
public void didExitRegion(Region region) {
logIt(TAG, "didExitRegion - In");
try {
beaconManager.stopRangingBeaconsInRegion(beaconRegion);
logIt(TAG,"dXR - stopRangingBeaconsInRegion OK");
} catch (RemoteException e) {
logIt(TAG, "dXR - stopRangingBeaconsInRegion Err " +e);
}
logIt(TAG, "didExitRegion - Out");
}
//----------------------//
//--- BeaconConsumer ---//
//----------------------//
@Override
public void onBeaconServiceConnect() {
logIt(TAG, "onBeaconServiceConnect - In");
beaconManager.setRangeNotifier(this);
logIt(TAG, "onBeaconServiceConnect - Out");
}
//---------------------//
//--- RangeNotifier ---//
//---------------------//
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
logIt(TAG, "didRangeBeaconsInRegion - " +beacons.size() +" beacons");
}
}
If you are already inside the region when the app starts up, you will not get an entry event. This is by design.
EDIT: Library 2.9 has two modifications to make determining the region state at startup easier:
One the app starts monitoring, the didDetermineStateForRegion
callback is guaranteed to be called, telling you the state of the region. (The didEnterRegion
and didExitRegion
callbacks may not fire unless there is actually a change.)
If you want to disable region state persistence, you may do so with beaconManager.setRegionStatePeristenceEnabled(false);
This will guarantee a callback to didEnterRegion
the first time a beacon is seen after app startup, even if the beacon was visible a couple of seconds prior before app restart.
Please do not follow the instructions below if you are on 2.9+, because the solution is deprecated, and may not work in the future.
If you do want an extra entry event on first detection for each app startup, you can add this line of code: MonitoringStatus.getInstanceForApplication(this).stopStatusPreservationOnProcessDestruction();
We are working on making this behavior easier to configure in the next release.