Reputation: 850
I’m using Android Beacon Library(AltBeacon SDK) in one of my project. My requirement is to show some checkin notification If user enter into the beacon range and checkout notification If exit the beacon range but the issue I’m facing is I’m keep getting the notifications i.e. didRangeBeaconsInRegion(Collection beacons, Region region) called multiple times. Is there any way that this function should call only once when the app come in range of beacon?
public class BeaconMonitoringService extends Service implements BootstrapNotifier, BeaconConsumer, RangeNotifier {
private static final String TAG = "BeaconMonitoringService";
private BeaconManager beaconManager;
@SuppressWarnings("unused")
private RegionBootstrap regionBootstrap;
@SuppressWarnings("unused")
private BackgroundPowerSaver backgroundPowerSaver;
private Region region;
@Override
public void onCreate() {
super.onCreate();
beaconSession = new BeaconSession(this);
beaconManager = 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"));
region = new Region("MyBeacon", Identifier.parse("0800200C9A66"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
beaconManager.setBackgroundMode(true);
backgroundPowerSaver = new BackgroundPowerSaver(this);
beaconManager.bind(this);
}
@Override
public void didEnterRegion(Region region) {
try {
Log.d(TAG, "Did Enter Region.");
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
if (BuildConfig.DEBUG) Log.d(TAG, "Can't start ranging");
}
}
@Override
public void didExitRegion(Region region) {
try {
Log.d(TAG, "Did Exit Region");
} catch (RemoteException e) {
if (BuildConfig.DEBUG) Log.d(TAG, "Can't start ranging");
}
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
switch (state) {
case MonitorNotifier.INSIDE:
Log.d(TAG, "INSIDE");
didEnterInRegion = true;
break;
case MonitorNotifier.OUTSIDE:
Log.d(TAG, "OUTSIDE");
didEnterInRegion = false;
break;
default:
didEnterInRegion = false;
Log.d(TAG, "state" + state);
break;
}
}
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
for (Beacon beacon : beacons) {
if (beacon.getId1().equals(Identifier.parse("0800200C9A66")) && beacon.getDistance() < 1.0) {
sendNotification(beacon);
}
}
}
}
@Override
public void onBeaconServiceConnect() {
beaconManager.addRangeNotifier(this);
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
beaconManager.unbind(this);
super.onDestroy();
}
}
Upvotes: 0
Views: 631
Reputation: 64941
The didRangeBeaconsInRegion
is designed to fire regularly at the end of each scan cycle (by default every ~ 1 second) to tell you which beacons were seen over that period.
If you only want an event to fire once fore each beacon detected you can create a class variable to hold a flag indicating whether or not you have processed each beacon already.
Like this:
// Put this at your class level
Set<String> mBeaconsProcessed = new HashSet<>();
...
// Put this code inside your didRangeBeaconsInRegion method
// Only process this beacon if we have not done so before
if (!mBeaconsProcessed.contains(beacon.toString)) {
if (beacon.getId1().equals(Identifier.parse("0800200C9A66")) && beacon.getDistance() < 1.0) {
sendNotification(beacon);
// Mark this beacon as having already been processed.
mBeaconsProcessed.put(beacon.toString));
}
}
}
Upvotes: 0