Search code examples
androidbeaconaltbeaconibeacon-android

Android beacon library how to turn foreground service to background mode?


What I want to achieve is, when user enter geofencing, the beacons foreground service will start to run and after one beacon detected, I will kill this foreground service and start to run it on the background just like the sample code on android-beacon-library-reference library.

private fun monitorBeacons(startForegroundService: Boolean) {
    var beaconManager = WolApp.appContext?.beaconManager
    if (beaconManager == null) {
        WolApp.appContext?.beaconManager = BeaconManager.getInstanceForApplication(WolApp.appContext!!)
        beaconManager = WolApp.appContext?.beaconManager
        beaconManager?.backgroundMode = true
        beaconManager?.beaconParsers?.clear()
        beaconManager?.beaconParsers?.add(BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"))
        beaconManager?.removeAllMonitorNotifiers()
    }
    if (startForegroundService) {
        setupForegroundNotificationService(WolApp.appContext!!)
    } else {
        WolApp.appContext?.regionBootstrap?.disable()
        WolApp.appContext?.regionBootstrap = null
        try {
            WolApp.appContext?.beaconManager?.disableForegroundServiceScanning()
        } catch (e: IllegalStateException) {}

        if (beaconManager?.scheduledScanJobsEnabled == false) {
            beaconManager.setEnableScheduledScanJobs(true)
            beaconManager.backgroundBetweenScanPeriod = BeaconManager.DEFAULT_BACKGROUND_BETWEEN_SCAN_PERIOD
            beaconManager.backgroundScanPeriod = BeaconManager.DEFAULT_BACKGROUND_SCAN_PERIOD
        }
    }

    if (WolApp.appContext?.regionBootstrap == null) {
        WolApp.appContext?.regionBootstrap = RegionBootstrap(WolApp.appContext!!, regions)//regions are some iBeacon regions
    }
    if (!startForegroundService) {
        WolApp.appContext?.backgroundPowerSaver = BackgroundPowerSaver(WolApp.appContext!!)
    }
}

For setupForegroundNotificationService method is same with android-beacon-library-reference library.

I'm not quite sure if I'm doing this right or wrong, can anyone help, please?


Solution

  • It is a little bit tricky to switch a foreground service on or off because you are trying to change the behavior of multiple threads of execution that are already running behind the scenes in existing services.

    The key thing missing from the code shown is that you must also make sure you have stopped the library from scanning before you can switch. This is complex because it is asynchronous -- it takes time for the scanner to shut down its threads.

    If using regionBootstrap, the call to regionBootstrap.disable() does this. (You can also use beaconManager.unbind(...) if not using regionBootstrap). But the problem is those APIs do not give you a callback when the scaning service is fully shut down. And restarting it again before it is shut down can cause problems. I do not have a great suggestion here , other than perhaps using a timer -- say one second between stop and start?

    You might also want to look at this discussion of a similar setup: https://github.com/AltBeacon/android-beacon-library/issues/845