I upgraded my apps targetSdkVersion
and compileSdkVersion
to SDK 31, and started receiving the following crash in app in a service that updates widget in background.
java.lang.RuntimeException:
at android.app.ActivityThread.handleReceiver (ActivityThread.java:4321)
at android.app.ActivityThread.access$1600 (ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2068)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loopOnce (Looper.java:201)
at android.os.Looper.loop (Looper.java:288)
at android.app.ActivityThread.main (ActivityThread.java:7842)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1003)
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.readParcelable (Parcel.java:3333)
at android.os.Parcel.createExceptionOrNull (Parcel.java:2420)
at android.os.Parcel.createException (Parcel.java:2409)
at android.os.Parcel.readException (Parcel.java:2392)
at android.os.Parcel.readException (Parcel.java:2334)
at android.app.IActivityManager$Stub$Proxy.startService (IActivityManager.java:5971)
at android.app.ContextImpl.startServiceCommon (ContextImpl.java:1847)
at android.app.ContextImpl.startForegroundService (ContextImpl.java:1823)
at android.content.ContextWrapper.startForegroundService (ContextWrapper.java:779)
at android.content.ContextWrapper.startForegroundService (ContextWrapper.java:779)
at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onUpdate (WidgetClassName.java:48)
at android.appwidget.AppWidgetProvider.onReceive (AppWidgetProvider.java:66)
at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onReceive (WidgetClassName.java)
at android.app.ActivityThread.handleReceiver (ActivityThread.java:4312)
at android.app.ActivityThread.access$1600 (ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2068)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loopOnce (Looper.java:201)
at android.os.Looper.loop (Looper.java:288)
at android.app.ActivityThread.main (ActivityThread.java:7842)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1003)
Caused by: android.os.RemoteException:
at com.android.server.am.ActiveServices.startServiceLocked (ActiveServices.java:691)
at com.android.server.am.ActiveServices.startServiceLocked (ActiveServices.java:616)
at com.android.server.am.ActivityManagerService.startService (ActivityManagerService.java:11839)
at android.app.IActivityManager$Stub.onTransact (IActivityManager.java:2519)
at com.android.server.am.ActivityManagerService.onTransact (ActivityManagerService.java:2498)
Also, if you're using something like Firebase Crashlytics, your stacktrace must be something like this ->
Caused by android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service com.mypackage.appname/.ui.widget.widget_package.MyForegroundServiceName
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:3333)
at android.os.Parcel.createExceptionOrNull(Parcel.java:2420)
at android.os.Parcel.createException(Parcel.java:2409)
at android.os.Parcel.readException(Parcel.java:2392)
at android.os.Parcel.readException(Parcel.java:2334)
at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:5971)
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1847)
at android.app.ContextImpl.startForegroundService(ContextImpl.java:1823)
at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onUpdate(WidgetClassName.java:48)
at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:66)
at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onReceive(WidgetClassName.java)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4312)
at android.app.ActivityThread.access$1600(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2068)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
I'm adding the way to reproduce this issue, and fixes to this problem, because I did not find any documentation about this on StackOverflow when I searched for it.
Inside the onReceive() method I call stopforeground(true) and it hides the notification. And then stopself() to stop the service.
Foreground refers to the active apps which consume data and are currently running on the mobile. Background refers to the data used when the app is doing some activity in the background, which is not active right now. This is due to the fact that whether they are active or not, apps consume data.
If an app tries to start a foreground service while the app is running in the background, and the foreground service doesn't satisfy one of the exceptional cases, the system throws a ForegroundServiceStartNotAllowedException. Your app transitions from a user-visible state, such as an activity.
This is caused by a security change to Android 12. For apps targeting SDK 31, Android 12 now blocks starting a foreground service except in very specific circumstances. Typically, your app must visible on the screen to start a foreground service. Since this is an Android 12 security restriction, there is no way for the library to "fix" this.
Devices that run Android 12 (API level 31) or higher provide a streamlined experience for short-running foreground services. On these devices, the system waits 10 seconds before showing the notification associated with a foreground service. There are a few exceptions; several types of services always display a notification immediately.
The notification cannot be dismissed unless the service is either stopped or removed from the foreground. Devices that run Android 12 (API level 31) or higher provide a streamlined experience for short-running foreground services. On these devices, the system waits 10 seconds before showing the notification associated with a foreground service.
Step 1. Update your targetSdkVersion
and compileSdkVersion
to SDK 31.
Step 2. Try to run any Foreground service when your app is in background. In my case, it was the widget's onUpdate
method being called after updatePeriodMillis
time, which will start a Foreground service, which updates the data by fetching appropriate information from internet.
Remember: The background execution limits added in Android 8.0 have nothing to do with this problem. This limitation/exception was added in Android 12/SDK 31 - Source.
Apps that target Android 12 (API level 31) or higher can't start foreground services while running in the background, except for a few special cases. If an app tries to start a foreground service while the app is running in the background, and the foreground service doesn't satisfy one of the exceptional cases, the system throws a ForegroundServiceStartNotAllowedException
.
These special cases are:
Your app transitions from a user-visible state, such as an activity.
Your app can start an activity from the background, except for the case where the app has an activity in the back stack of an existing task.
Your app receives a high-priority message using Firebase Cloud Messaging.
The user performs an action on a UI element related to your app. For example, they might interact with a bubble, notification, widget, or activity.
Your app invokes an exact alarm to complete an action that the user requests.
Your app is the device's current input method.
Your app receives an event that's related to geofencing or activity recognition transition.
After the device reboots and receives the ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED, or ACTION_MY_PACKAGE_REPLACED intent action in a broadcast receiver.
Your app receives the ACTION_TIMEZONE_CHANGED, ACTION_TIME_CHANGED, or ACTION_LOCALE_CHANGED intent action in a broadcast receiver.
Your app receives a Bluetooth broadcast that requires the BLUETOOTH_CONNECT or BLUETOOTH_SCAN permissions.
Apps with certain system roles or permission, such as device owners and profile owners.
Your app uses the Companion Device Manager and declares the REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND permission or the REQUEST_COMPANION_RUN_IN_BACKGROUND permission. Whenever possible, use REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND.
The user turns off battery optimizations for your app. You can help users find this option by sending them to your app's App info page in system settings. To do so, invoke an intent that contains the ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent action.
This will work for a while in Play Store until Google makes it mandatory to upgrade to API level 31.
Currently, starting November 2021 all apps must target API Level 30 and above. So if you're using API Level 31 for your app, downgrading your compileSdkVersion
& targetSdkVersion
to API Level 30 should fix the issue (atleast for a while).
If you were using Foreground service to do work that is time sensitive, start Foreground services within an exact alarm. Check out more about this from documentation here -> Set an exact alarm.
This is the solution that I ended up using for my app. Use WorkManager
to schedule and start the background work. Check out more about this from documentation here -> Schedule expedited work.
You can know more about WorkManager here -> WorkManager
Github Repo for WorkManager samples -> WorkManager Samples
I added this answer specifically because searching for this exception does not bring up any resources to know why the service behaves differently on Android 12. All this is present in Google's documentation, and always remember to check the behaviour changes from the doc.
Everything related to this change can be found here -> Android 12 Behavior Changes, specifically within the Foreground Service launch restrictions.
If your App is a MediaPlayer (i.e. uses a MediaBrowseService
) and you are experiencing the ForegroundServiceStartNotAllowedException
crash then you may need to:
Update your Manifest to specify that your service is for media playback using android:foregroundServiceType="mediaPlayback"
in the Service
declaration
Include the ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
parameter in your call to the Serivce.startForeground
method
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With