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?
Example stack trace
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)
Current replication process
- Start music playing in my app.
- Click the Home button.
- Click CALL DEVICE on the emulator. (At this point the music is paused).
- Hang up on the call. (After a short pause, the music starts playing again - this is where I expect the crash).
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.
Things I've tried
- Make sure battery optimisation is enabled for the app - tried "Optimized" and "Restricted".
- Changed the battery settings in the emulator.
- Enabled ActivityManager logging restricted foreground starts. With this I have seen
ActivityManager: Service.startForeground() not allowed due to bg restriction: service ga.asti.android/github.daneren2005.dsub.service.DownloadServicein 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.
Put app into background by clicking the Home key
Start watching logcat:
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: