Best practice for handling Always-On Proximity Beacon Observation | Android

I am intending to use Proximity Beacons to detect when a customer who has my Android app enters a location that contains a beacon. The app will push a notification to their device once a beacon is detected.

As far as I can tell on Android 8.0+, the only way to do this is to use the .withScannerInForegroundService, which runs the scan in the foreground and forces an ongoing notification to the user. Since I want to always be scanning for beacons, this isn’t ideal as it drains battery power and annoys the user.

The solution I’ve come up with is to schedule a job that does a 5 second scan every 15 minutes, and if it detects a beacon in that time it pushes the notification. This would be a lot less annoying to the user, however it relies on the user being within the beacon’s range for a maximum 15 minutes to guarantee they’ll get the notification, so it isn’t ideal. A lot of customers will simply pass by a beacon at the entrance to a facility and won’t linger for nearly 15 minutes.

Is this the best solution to solve my problem? Has anyone figure out a different approach?

It seems like the Proximity Trigger feature could be the solution but it is apparently still experimental and in development, and is evidently unsupported on Android 8.1.0

Another solution I’ve thought of is using GeoFencing to determine if the user is near a location with a beacon, and if so just turn on beacon scanning when they enter and run continuously until they exit.

It’s a complex topic (:

On Androids < 8, running the scanner in a background service was the most common option. However, even though the “stock” Android had no restrictions on background services until 8.0, many Android manufacturers were implementing their own restrictions. So a foreground service is a more reliable option in our opinion.

On Android >= 8, background service is no longer an option. Foreground service remains a valid solution. Alternatively, there’s a new “PendingIntent” API for BLE scanning, which doesn’t need any service. This API is what the ProximityTrigger is built upon—we started experimenting with it, but haven’t finished yet.

With the just-revealed Android 10, there’s also a new option: the new “allow this app to access user’s location even when not in use” prompt. As far as we understand it, this will allow apps to run a background service, specifically for things like geo-fencing.

The important thing to note is, all these options are pretty much equal in terms of energy use. Whether you have your scanner inside a background service, foreground service, or receiving scan results via PendingIntents, doesn’t really matter, the amount of work done (= energy used) is more or less the same.

Note that modern smartphones often delegate a lot of the Bluetooth work to the Bluetooth chip (controller) itself. This way, the CPU can go to sleep, and be woken up only when a matching Bluetooth packet is found. (So for example, if you’re only in range of Estimote Beacons once a week, the energy used by the Proximity SDK will be minimal. If you’re constantly in range of Estimote Beacons, the energy usage will be much higher, since we’re constantly processing Bluetooth data.)