I'm writing an Android App custom Class that utilises AltBeacon's Android-Beacon-Library.
Instead of posting the class, I am reproducing the problem using the reference implementation samples provided with the library.
If I activate both monitoring (by implementing a RegionBootstrap) and ranging beaconManager.bind(new BeaconConsumer()...) directly in onCreate(), everything works perfectly.
I would like however to start ranging only when a Beacon enters region, so in didEnterRegion(Region arg0) callback of the RegionBootstrap, but when I do so, onBeaconServiceConnect() is never called. I believe doing it this way would be more efficient in terms of battery consumption.
I have tried force executing on the main thread as well as using delayed timers but it didn't work.
Anyone could get this to work ? Any help appreciated!
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "AndroidProximityReferenceApplication";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
BeaconManager beaconManager;
Context context = this;
public void onCreate() {
super.onCreate();
beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// Setup beacon layout - should be done once only
List<BeaconParser> bp = beaconManager.getBeaconParsers();
bp.add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
Region region = new Region("backgroundRegion", null, null, null);
regionBootstrap = new RegionBootstrap(this, region);
backgroundPowerSaver = new BackgroundPowerSaver(this);
// THIS WORKS
bindBeaconConsumer();
}
public void bindBeaconConsumer() {
beaconManager.bind(new BeaconConsumer() {
@Override
public void onBeaconServiceConnect() {
// ISSUE : Does not pass here when bindBeaconConsumer() is called from didEnterRegion
// Set Range Notifier and start ranging
}
@Override
public Context getApplicationContext() {
return context;
}
@Override
public void unbindService(ServiceConnection serviceConnection) {
context.unbindService(serviceConnection);
}
@Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
return context.bindService(intent, serviceConnection, i);
}
});
}
@Override
public void didEnterRegion(Region arg0) {
Log.d(TAG, "did enter region.");
// THIS DOESN'T WORK : onBeaconServiceConnect() never called
// bindBeaconConsumer();
}
@Override
public void didExitRegion(Region region) {
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
}
}
The reason calling bindBeaconConsumer()
doesn't work in the monitoring callback is because by the time it executes, the class is already bound to the service. If you look at LogCat, you will see a warning message about this. Since it is already bound, the code does not get a callback to onBeaconServiceConnect()
.
Why is it already bound? Because of the line below:
regionBootstrap = new RegionBootstrap(this, region);
The RegionBootsrap
class does a bind operation behind the scenes, which executes in a second or so.
The easiest way to fix this is to remove the call to bindBeaconConsumer()
in the didEnterRegion
method and instead just call beaconManager.startRangingBeaconsInRegion(...)
. You don't need to bind again because by that point, the service is already bound.