AltBeacon / android-beacon-library

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

Monitoring not working after app is killed #1110

Open NickLou26 opened 1 year ago

NickLou26 commented 1 year ago

Expected behavior

I should receive a post request to my api when the device detects ble beacons. I receive the request correctly when the app is opened, but when it is killed, I don't receive the call.

Actual behavior

I don't receive any request.

Steps to reproduce this behavior

class CustomApplication : FlutterApplication() { companion object { private const val TAG = "CustomApplication" }

override fun onCreate() {
    super.onCreate()
    //Works here, i receive the call on my api properly
    //sendRequest() 
    Log.d(TAG, "App started up")
     val beaconManager: BeaconManager = BeaconManager.getInstanceForApplication(this)
     val region = Region("FetchVision", null, null, null)
     beaconManager.getRegionViewModel(region).regionState.observeForever(monitoringObserver)
     beaconManager.startMonitoring(region)
}

private val monitoringObserver = Observer<Int> { state ->
    if (state == MonitorNotifier.INSIDE) {
        Log.d(TAG, "Got a didEnterRegion call")
        //Doesn't work when app is killed, but works when is open
        sendRequest()
    }
    else {
        Log.d(TAG, "No beacons detected")
    }
}

}

Mobile device model and OS version

Google pixel 5, Android 13

davidgyoung commented 1 year ago

Please see this page from the library documentation: https://altbeacon.github.io/android-beacon-library/resume-after-terminate.html

Is what you are witnessing different from what is described there? Please note the specific ways apps can be stopped and later restarted by the library as described on that page, then update this issue with details.

NickLou26 commented 1 year ago

After consulting the page, I tested it again and it seems to be launching the app correctly after termination. However, if we look at my code :

override fun onCreate() {
    super.onCreate()
    //Works here, i receive the call on my api properly
    //sendRequest() 
    Log.d(TAG, "App started up")
     val beaconManager: BeaconManager = BeaconManager.getInstanceForApplication(this)
     val region = Region("FetchVision", null, null, null)
     beaconManager.getRegionViewModel(region).regionState.observeForever(monitoringObserver)
     beaconManager.startMonitoring(region)
}

private val monitoringObserver = Observer<Int> { state ->
    if (state == MonitorNotifier.INSIDE) {
        Log.d(TAG, "Got a didEnterRegion call")
        //Doesn't work when app is killed, but works when is open
        sendRequest()
    }
    else {
        Log.d(TAG, "No beacons detected")
    }
}

When the app is launched automatically in background, the sendRequest() in onCreate() is called correctly but the sendRequest() in monitoringObserver is never called. Is this normal? I'm trying to make an app where I will be running ble scans in the background.

davidgyoung commented 1 year ago

Let's clarify this: sendRequest in monitoring observer is never called. Two questions:

  1. Do you see the monitoringObserver get called shortly after app re-launch (regardless of the value of state)?
  2. If after app re-launch if you turn off your beacon, wait at least 25 minutes, then turn on your beacon and wait another 25 minutes, do you get any calls to monitoringObserver? (Waiting > 25 minutes is necessary to trigger background/foregrond transitions is necessary on Android 8+ using default settings because this is how often the job scheduler -- the default scan strategy with the library -- allows scheduling scans.)

Understand that the monitoring observer won't be called again (even if the app is killed and restarted) until the state changes from INSIDE to OUTSIDE or back, and this can take up to 25 minutes for the reasons described above.

It is possible to disable state preservation with the app so you do get a new call to monitoringObserver if the app is killed and restarted. But by default you do not get a call if the state does not change even after app restart.

NickLou26 commented 1 year ago

sendRequest in monitoring observer is called when the app is opened, but not when killed (after re-launch).

  1. I tried calling sendRequest like this but it is still not called :

    private val monitoringObserver = Observer<Int> { state ->
        sendRequest()
        if (state == MonitorNotifier.INSIDE) {
            Log.d(TAG, "Got a didEnterRegion call")
        }
        else {
            Log.d(TAG, "No beacons detected")
        }
    }
  2. I tried to do as you said and i still didn't get any calls from sendRequest in monitoringObserver. I do get the call from sendRequest in onCreated though.

davidgyoung commented 1 year ago

I think the easiest way to address this problem is for you to call:

beaconManager.setRegionStatePeristenceEnabled(false)

You can see details here: https://altbeacon.github.io/android-beacon-library/state-persistence.html