AltBeacon / android-beacon-library

Allows Android apps to interact with BLE beacons
Apache License 2.0
2.84k stars 836 forks source link

Handle Foreground Service Start Failures in Android 12 #1088

Closed davidgyoung closed 2 years ago

davidgyoung commented 2 years ago

Apps using this library on Android 12 can crash if they configure the library's foreground service for scanning as reported in #1082. This happens because Android 12 restricts when foreground services can be started to when:

While it is possible to code around the above, the restrictions make it difficult to use the library. These following changes are designed to make using the library with a foreground service on Android 12 easier.

  1. The library will detect if starting its foreground service fails, catching the exception and preventing a crash.
  2. If the foreground service can't be started, the library will fall back to using the default ScanJob scanning strategy. This will keep beacon detections working, albeit in a degraded fashion.
  3. If the library detects the app has come to the foreground after the above failure has happened, it will start the foreground service at that time.
  4. A new public API method on BeaconManager indicates if a failure to start the foreground service has happened: foregroundServiceStartFailed()
  5. A new public API method on BeaconManager allows the app to retry starting the foreground service (useful for the case that a qualifying event other than the automatically handled foreground change is known to have happened): retryForegroundServiceScanning()

For this change I performed the following tests with the Kotlin reference app:

  1. Modifying app to use a forreground service but long background between scan periods
  2. Launching app with no beacons around
  3. Killing foreground service from adb while app is in a between scan cycle.
  4. Turning on a beacon to re-launch the app in the background. I see this:
2022-06-03 11:47:45.897 5802-5802/org.altbeacon.beaconreference I/BeaconManager: Attempting to starting foreground beacon scanning service.
2022-06-03 11:47:45.905 5802-5802/org.altbeacon.beaconreference W/BeaconManager: Foreground service blocked by ServiceStartNotAllowedException.  Falling back to job scheduler

The above confirms fallback to ScanJobs works.

Now test failover when the app. comes to the foreground:

  1. Tapp app launcher to bring to foreground
06-03 11:52:38.440  5802  5802 I BeaconManager: unbinding all consumers for strategy failover
06-03 11:52:38.440  5802  5802 D BeaconManager: Unbinding
06-03 11:52:38.440  5802  5802 D BeaconManager: Not unbinding from scanning service as we are using scan jobs.
06-03 11:52:38.440  5802  5802 D BeaconManager: Before unbind, consumer count is 1
06-03 11:52:38.440  5802  5802 D BeaconManager: After unbind, consumer count is 0
06-03 11:52:38.440  5802  5802 I BeaconManager: Cancelling scheduled jobs after unbind of last consumer.
06-03 11:52:38.440  5802  5802 I ScanJob : Using immediateScanJobId from manifest: 208352939
06-03 11:52:38.442  5802  5802 I ScanJob : Using periodicScanJobId from manifest: 208352940
06-03 11:52:38.442  5802  5802 I BeaconManager: binding all consumers for strategy failover
06-03 11:52:38.443  5802  5802 D BeaconManager: Need to rebind for switch to foreground service
06-03 11:52:38.443  5802  5802 D BeaconManager: Binding to service
06-03 11:52:38.443  5802  5802 I BeaconManager: Attempting to starting foreground beacon scanning service.
06-03 11:52:38.444  5802  5802 I BeaconManager: successfully started foreground beacon scanning service.
06-03 11:52:38.446  5802  5802 D BeaconManager: consumer count is now: 1
06-03 11:52:38.446  5802  5802 I BeaconManager: Done with failover

Verify foreground service is started and beacons are being scanned.

davidgyoung commented 2 years ago

This has been moved to #1090 with a cleaner set of changes.