Search code examples
androidservicebeaconaltbeaconandroid-ibeacon

Android Beacon Library: Do I need the BootstrapNotifer when I want frequent ranging in background, after the application was launched?


I am working on an Application with the Android Beacon Library with Android 8+ and I need to do ranging in the background. For this purpose I use the nativly supported possibility to start the service as a foreground service. The Application should keep ranging, even when the application is closed! So implementing the BeaconConsumer Interface in an activity is not a good idea, beacuse if the Acitivity gets removed from the memory ranging will obviously stop. To work around this I created a custom application class and implemented a BeaconConsumer and started ranging in this component. So the custom application is the Consumer and handles the results in the onServiceConnect(...) Method. Do I need the BootstrapNotifier for my goal, or will it work like this? Will the Application keep ranging if the application is closed?

public class App extends Application implements BeaconConsumer {
   onCreate(){
     mbeaconManager = 
     org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
     mbeaconManager.setDebug(true);

    // Create Notification for the Foreground Service
    Intent intent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(
            this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
    );

    Notification notification = new 
    NotificationCompat.Builder(getApplicationContext(),CHANNEL_1_ID)
            .setSmallIcon(R.drawable.icon)
            .setContentTitle("\"Ranging runs in background!")
            .setContentIntent(pendingIntent)
            .build();

    // Set Scanning Settings
    mbeaconManager.enableForegroundServiceScanning(notification, 
    notificationID);
    mbeaconManager.setEnableScheduledScanJobs(false);
    mbeaconManager.setBackgroundBetweenScanPeriod(100);
    mbeaconManager.setBackgroundScanPeriod(100);
  }

    public void onBeaconServiceConnect() {
        mbeaconManager.removeAllRangeNotifiers();
        mbeaconManager.addRangeNotifier(new RangeNotifier() {

         public void didRangeBeaconsInRegion(...) { 
         // handle found beacons
      }

       mbeaconManager.startRangingBeaconsInRegion(...);
   }
 }
}

Solution

  • What you have looks fine. A few points for you to fully understand:

    1. RegionBoostrap is just a helper class designed to make it easier to set up automatic beacon detection on app startup using monitoring in an Application class. You can do the same thing with beaconManager.bind(...) then start monitoring in the onBeaconServiceConnected callback.

    2. Since you only care about ranging not monitoring (perfectly legitimate for your use case) then setting up manually like you did is a simpler way to go, as it avoids the unnecessary monitoring created by RegionBootstrap.

    3. If you want your app to automatically resume to respond to beacon events, the key thing to do is put the code that sets this up in the onCreate method of a custom Application class. If you do that, it doesn't matter whether you use BootstrapNotifier or BeaconConsumer.

    Why is Application.onCreate so important?

    The library sets up a number of hooks that will request an app restart for beacon scanning in a number of cases:

    1. Every ~15 minutes on Android 8+ if you are using the default JobScheduler instead of a Foreground Service
    2. On Boot
    3. After a beacon matching a ranged or monitored beacon is detected using a hardware filter on Android 8+.
    4. After the internal BeaconService (used when a foreground service is active on Android 8+ or always on Android 7 and earlier) is killed (due to memory pressure)
    5. Within 5 minutes of the app being stopped otherwise (on Android 7 and earlier)

    In all of the above cases, what makes restarting beacon scanning possible is having code in Application.onCreate. That method is the very first app level code that gets executed when an Android app starts up. So if you set up your library initialization here, then the initialization will be done on any of the above events and you will resume beacon scanning as if you app never stopped running at all.