Estimote beacons region detection from a service in background
android, estimote, ibeacon, ibeacon-android
Solution
This code is working for me. Make sure you are placing the correct UUID, minor and major numbers.
//Using something like that as global variable
private static final Region[] BEACONS = new Region[] {
new Region("beacon1", "uuid1", 1, 19227), //uuid without "-"
new Region("beacon2", "uuid2", 1, 61690),
new Region("beacon3", "uuid3", null, null)
};
//Note: setting minor == null and major == null will detect every beacon with that uuid
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startMonitoring();
return START_STICKY;
}
private void startMonitoring() {
if (beaconManager == null) {
beaconManager = new BeaconManager(this);
// Configure verbose debug logging.
L.enableDebugLogging(true);
/**
* Scanning
*/
beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 1);
beaconManager.setRangingListener(new RangingListener() {
@Override
public void onBeaconsDiscovered(Region paramRegion, List<Beacon> paramList) {
if (paramList != null && !paramList.isEmpty()) {
Beacon beacon = paramList.get(0);
Proximity proximity = Utils.computeProximity(beacon);
if (proximity == Proximity.IMMEDIATE) {
Log.d(TAG, "entered in region " + paramRegion.getProximityUUID());
postNotification(paramRegion);
} else if (proximity == Proximity.FAR) {
Log.d(TAG, "exiting in region " + paramRegion.getProximityUUID());
removeNotification(paramRegion);
}
}
}
});
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
@Override
public void onServiceReady() {
try {
Log.d(TAG, "connected");
for (Region region : BEACONS) {
beaconManager.startRanging(region);
}
} catch (RemoteException e) {
Log.d("TAG", "Error while starting monitoring");
}
}
});
}
}
***Editing: code to compute accuracy
public static double computeAccuracy(Beacon beacon)
{
if (beacon.getRssi() == 0)
{
return -1.0D;
}
double ratio = beacon.getRssi() / beacon.getMeasuredPower();
double rssiCorrection = 0.96D + Math.pow(Math.abs(beacon.getRssi()), 3.0D) % 10.0D / 150.0D;
if (ratio <= 1.0D)
{
return Math.pow(ratio, 9.98D) * rssiCorrection;
}
return (0.103D + 0.89978D * Math.pow(ratio, 7.71D)) * rssiCorrection;
}
public static Proximity proximityFromAccuracy(double accuracy)
{
if (accuracy < 0.0D)
{
return Proximity.UNKNOWN;
}
if (accuracy < 0.5D)
{
return Proximity.IMMEDIATE;
}
if (accuracy <= 3.0D) {
return Proximity.NEAR;
}
return Proximity.FAR;
}
public static Proximity computeProximity(Beacon beacon) {
return proximityFromAccuracy(computeAccuracy(beacon));
}
Problem
i recently started testing Estimote Beacons, and I'm trying to launch a notification from a background service when entering a beacon region, but unfortunately my solution doesn't work. It doesn't give errors but the notification is not being launched when a beacon is discovered. I don't know if it is some code error or simply the way of doing it is wrong. I've read this other question but it seems a bit different since what i use is a service instead of an activity, but maybe the answer is similar (app context related)... here is my service code ``` public class BeaconsMonitoringService extends Service{ private BeaconManager beaconManager; private String user; @Override public void onCreate() { // Configure BeaconManager. beaconManager = new BeaconManager(this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "Beacons monitoring service starting", Toast.LENGTH_SHORT).show(); user = intent.getStringExtra("user"); // Check if device supports Bluetooth Low Energy. if (!beaconManager.hasBluetooth()||!beaconManager.isBluetoothEnabled()) { Toast.makeText(this, "Device does not have Bluetooth Low Energy or it is not enabled", Toast.LENGTH_LONG).show(); this.stopSelf(); } connectToService(); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "Beacons monitoring service done", Toast.LENGTH_SHORT).show(); } private void connectToService() { beaconManager.connect(new BeaconManager.ServiceReadyCallback() { @Override public void onServiceReady() { notifyEnterRegion(0); // try { beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0); Log.i("BEACOON ", "ANTES DE"); beaconManager.setMonitoringListener(new MonitoringListener() { @Override public void onEnteredRegion(Region region, List<Beacon> beacons) { Log.i("BEACOON ", String.valueOf(beacons.get(1).getMinor())); for (Beacon beacon: beacons){ Log.i("BEACOON ", String.valueOf(beacon.getMinor())); if (beacon.getMinor() == 64444) { notifyEnterRegion(6444); } else if (beacon.getMinor() == 36328) { notifyEnterRegion(36328); } else if (beacon.getMinor() == 31394) { notifyEnterRegion(31394); } } } @Override public void onExitedRegion(Region region) { notifyExitRegion(); } }); } }); } public void notifyEnterRegion(int code) { Toast.makeText(this, "Beacon "+code, Toast.LENGTH_SHORT).show(); Intent targetIntent = new Intent(this, MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, targetIntent, PendingIntent.FLAG_UPDATE_CURRENT); Notification noti = new Notification.Builder(this) .setContentTitle("Bienvenido "+user+"!") .setContentText("Sólo por estar aquí has ganado....") .setSmallIcon(com.smt.beaconssmt.R.drawable.beacon_gray) .setContentIntent(contentIntent) .getNotification(); NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); nManager.notify(1, noti); } public void notifyExitRegion(){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Hasta pronto!") .setTitle(user+", estás abandonando la zona de beacons"); builder.setPositiveButton("Ver web", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User clicked OK button Intent i = new Intent(BeaconsMonitoringService.this, WebViewActivity.class); i.putExtra("web", "http://www.google.com/"); startActivity(i); } }); builder.setNegativeButton("Adios!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User cancelled the dialog } }); AlertDialog dialog = builder.create(); dialog.show(); } } ``` i will appreciate very much any kind of help, thanks in advance!