According to Google Play Console Crashes and ANRs, my app is experiencing a lot of ForegroundServiceStartNotAllowedException
crashes on Android 12+ devices. This is since Google introduced the restriction that apps in the background cannot start foreground services.
The app is a music player.
I don't have an Android 12+ device, so I set up the emulator, running Android 13, to replicate. However, I cannot replicate this crash and I wondered if this is because I'm using the emulator. Is there a way of setting up the emulator to make sure it occurs?
Here's an example stack trace reported by Google Play Console:
Exception java.lang.RuntimeException:
at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:5261)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2447)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loopOnce (Looper.java:226)
at android.os.Looper.loop (Looper.java:313)
at android.app.ActivityThread.main (ActivityThread.java:8757)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
Caused by android.app.ForegroundServiceStartNotAllowedException:
at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel (ForegroundServiceStartNotAllowedException.java:54)
at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel (ForegroundServiceStartNotAllowedException.java:50)
at android.os.Parcel.readParcelableInternal (Parcel.java:4787)
at android.os.Parcel.readParcelable (Parcel.java:4755)
at android.os.Parcel.createExceptionOrNull (Parcel.java:3018)
at android.os.Parcel.createException (Parcel.java:3007)
at android.os.Parcel.readException (Parcel.java:2990)
at android.os.Parcel.readException (Parcel.java:2932)
at android.app.IActivityManager$Stub$Proxy.setServiceForeground (IActivityManager.java:6978)
at android.app.Service.startForeground (Service.java:743)
at github.daneren2005.dsub.util.Notifications.startForeground (Notifications.java:462)
at github.daneren2005.dsub.util.Notifications.shutGoogleUpNotification (Notifications.java:384)
at github.daneren2005.dsub.service.DownloadService.onStartCommand (DownloadService.java:317)
at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:5243)
I know the crash should happen, because I have added logging to my code that starts the foreground service:
...
Log.d(TAG, "Notifications, current state: " + ProcessLifecycleOwner.get().getLifecycle().getCurrentState());
downloadService.startForeground(notificationId, notification);
...
At this point, the lifecycle state is CREATED which I believe means it's in the background. However, the crash doesn't appear to occur and the app keeps running.
ActivityManager: Service.startForeground() not allowed due to bg restriction: service ga.asti.android/github.daneren2005.dsub.service.DownloadService
in logcat. Is this the same issue occurring? Why does it not cause a crash?There are a number of guides about around fixing this, but I want to know how to replicate it first so I know my fixes are working.
I'm going to leave this as an answer for now, unless someone can provide a way to produce a more visual crash in the emulator.
The only indication I've found that my app requests foreground services when running in the background is to configure ActivityManager to alert such cases and then follow and grep logcat to report them.
Enable ActivityManager logging restricted foreground starts.
adb shell device_config put activity_manager \
default_fgs_starts_restriction_notification_enabled true
Put app into background by clicking the Home key
Start watching logcat:
adb logcat -T 1 | grep ActivityManager
Cause the behaviour which might run startForeground (in my app, a music player: while music is playing, make a call to the phone in the emulator, receive the call, then hang up).
Observe logcat output for something like:
Service.startForeground() not allowed due to bg restriction: service my.app.packagename/my.app.XyzService