react-native-background-geolocation: [Android 12] Fatal Exception: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false
Hello, we are getting a lot of Crashlytics issues reported for our app on the android 12 devices. we do use background geolocation to monitor geofences only.
Your Environment
- Platform: Android
- OS version: 12
- Device manufacturer / model: Galaxy Note10+, Galaxy S21 Ultra 5G, Pixel 6 Pro, Pixel 4, Pixel 4a
- React Native version (
react-native -v
): 0.64.2 - Plugin config
const config = {
enableHeadless: true,
geofenceModeHighAccuracy: true,
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 10,
geofenceInitialTriggerEntry: false,
disableMotionActivityUpdates: true,
stopOnTerminate: false,
url,
};
await BackgroundGeolocation.ready(config);
BackgroundGeolocation.startGeofences();
Expected Behavior
App should never crash while attempting to start foreground service on android and geofences should work fine for all OS versions and devices.
Actual Behavior
App is crashing when plugin tries to start foreground service on android 12 devices.
Context
Crash Report: Fatal Exception: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service com.transistorsoft.locationmanager.service.TrackingService at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54) at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50) at android.os.Parcel.readParcelable(Parcel.java:3345) at android.os.Parcel.createExceptionOrNull(Parcel.java:2432) at android.os.Parcel.createException(Parcel.java:2421) at android.os.Parcel.readException(Parcel.java:2404) at android.os.Parcel.readException(Parcel.java:2346) at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:6914) at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1926) at android.app.ContextImpl.startForegroundService(ContextImpl.java:1892) at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:796) at com.transistorsoft.locationmanager.service.AbstractService$a.run(:10) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8641) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)
Caused by android.os.RemoteException: Remote stack trace: at com.android.server.am.ActiveServices.startServiceLocked(ActiveServices.java:771) at com.android.server.am.ActiveServices.startServiceLocked(ActiveServices.java:679) at com.android.server.am.ActivityManagerService.startService(ActivityManagerService.java:13987) at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2943) at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3030)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 36 (22 by maintainers)
@ZerozAndOnes
release-4.8.0
branch in the private repo implements a much more generalized solution for the.getCurrentPosition()
and.start()
problem in the background on Android 12.The SDK no longer needs to be concerned specifically with any particular method — it now simply does a
catch (ForegroundServiceStartNotAllowedException e) { ... }
and does theAlarmManager
oneShot event in the exception-handler, for every potential use-case.4.8.0 — Unreleased
Context.startForegroundService
withtry / catch
: the plugin will now catch exceptionForegroundServiceStartNotAllowedException
and automatically retry with anAlarmManager
oneShot event.android.permission.GET_TASKS
traditionally used for detecting when the app has been terminated. The new life-cycle mgmt system can detect Android headless-mode in a much more elegant manner.WhenInUse
behaviour: The plugin will not allow.changePace(true)
to be executed when the app is in the background (since Android forbids location-services to initiated in the background withWhenInUse
).useSignificantChangesOnly
behaviour. Will use a defaultmotionTriggerDelay
with minimum 60000ms, minimumdistanceFilter: 250
and enforcedstopTimeout: 20
.location.mock
will now be present for iOS when the location is mocked, just like Android.This issue hasn’t come up in our latest release, we can close this issue and the following ones in the private repo:
@ZerozAndOnes I’ve made another push to branch
release-4.7.2
@ZerozAndOnes I’ve reproduced this. I added a little bit of code to immediately launch a foreground-service when
.start()
is called but it seems under these conditions that OS will only allow the foreground-service to be launched specifically due to alocation
API request.I can work around this.
4.7.2 branch is not yet released. It’s not tagged yet.
I believe that somehow your code is going this while plugin is in background and disabled:
I will guard against this.
I can see it in your logs:
The
getCurrentPosition
method was correctly usingforceAlarmManager: true
. When initially developing this with my test case, I initially implemented withstart
method. It was only after moving on togetCurrentPosition
that I discovered that the OS provides a little leeway on background time (about 10s) to launch FG services. After I increasing theTimer
to15 seconds
, the exception was raised again and I remembered to useforceAlarmManager: true
on the ONESHOT.I just didn’t circle back to
.start()
.You will know you have
4.7.2
installed when you see this build number in the logs:Ok, turns out it was just a blunder on my part. The SDK has a general purpose “one-shot” timer mechanism built into it which uses
JobScheduler
by default. I neglected to pass the 3rd optional paramforceAlarmManager: true
.Only
AlarmManager
-based events are granted carte blanche by the OS to launch foreground-services.@ZerozAndOnes, @ozberkctn Please test branch
#release-4.7.2
just pushed.