Search code examples
androidserviceibeaconbeaconandroid-ibeacon

Can I use Android Beacon Library in foreground service, even on Android 8 (Oreo)?


What I want to achieve

I am building an app for a shopping mall, with large amount of beacons installed not quite far away from each other (assume ~20m distance).
When a user walks in this mall, even without opening the app, the app needs to keep scan for beacons. When a beacon is detected, I will then query the server to ask if I need to and what local notification to push to user.

What I planned to do

My original plan was to create a Service, returns START_STICKY in onStartCommand() in order to make sure that the service will restart itself even the app is killed by a task manager.

This Service will keep scanning for beacons.

In fact, this is the existing approach of my colleague. According to this colleague, the service starts almost immediately after the app was killed by a task manager.

The problem

But soon I found that this approach is problematic.
The above approach has now 2 major problems:

My next plan

Although I know that JobScheduler can be used to replace Service, which is also the existing approach of Android Beacon Library, perform a scan every 15-25 minutes absolutely cannot fulfill my requirements, where beacons are very close to each other and therefore beacons need to be scanned frequently.

Therefore I come up with another plan:

  1. Use Android Beacon Library to run background detection
  2. Once the first beacon in filter list has been detected, start a foreground service (which will not be killed even in Android 8) that continuously scan for beacons
  3. When all beacons in the filter has been exited, stop the above foreground service. Android Beacon Library shall resume to its background detection state.

The intentions of this approach are:

  1. Make advantage of Android Beacon Library's background detection which saves battery, according to their documentation
  2. Step away of Android Beacon Library's handling of Android 8 due to its built-in limitation of long scanning interval
  3. Scanning goes on even on Android 8 since I am going to use a foreground service

My major question

By reading documentations, I already know how to scan for beacons in the background.
But how do I make use of Android Beacon Library to scan in a foreground service?
Plus, is there any problem that you can discover in the above approach / Do you have any better suggestions to achieve such requirements?

My other question

In fact according to this post, the background service starts 5 minutes after an app is killed.
But by returning START_STICKY in onStartCommand() of a Service, it is restarted almost immediately.
Then, why will there be a 5 minutes delay, even in pre-Oreo?


Solution

  • This approach is sound. The Android Beacon Library 2.15+ natively supports foreground services as a scan mechanism for supporting cases like this on Android 8. See here for more info.

    The tricky part is to switch back and forth between using Job Scheduler and a Service to do scanning. I have not tested this, but my suggestion would be to bind manually to the BeaconManager in a custom Application class. Then :

    1. On entering a region, stop monitoring and then unbind the BeaconManager.

    2. Start a custom foreground service

    3. In the foreground service, disable Scan Jobs, then bind to the BeaconManager and start ranging

    4. Once no beacons have been ranged for a time, stop ranging, unbind from the BeaconManager, enable Scan Jobs, bind again and then start monitoring.

    5. Finally, exit the foreground service

    On the second question, yes, START_STICKY will very quickly restart a service on most platforms. The library uses a 5 minute timer with the AlarmManager as a backup, which will relaunch the service if a START_STICKY restart fails. Indeed, in typical use, the scanning service restarts much more quickly than five minutes.