Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting android.app.ForegroundServiceStartNotAllowedException in Android 12 (SDK 31)

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.

like image 900
Vedprakash Wagh Avatar asked Oct 17 '21 13:10

Vedprakash Wagh


People also ask

How do you stop foreground service?

Inside the onReceive() method I call stopforeground(true) and it hides the notification. And then stopself() to stop the service.

What is allow foreground activity?

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.

What is foregroundservicestartnotallowedexception in Android?

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.

Why can't I start a foreground service on Android 12?

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.

What is a short-running foreground service on Android?

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.

How do I dismiss notifications from foreground services on Android?

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.


Video Answer


2 Answers

How to reproduce the crash

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.


What is this exception, and why was it added?

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.


Possible solutions

Solution 1

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).

Solution 2

For time-sensitive work

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.

For time-insensitive/expedited work

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.

like image 147
Vedprakash Wagh Avatar answered Oct 23 '22 20:10

Vedprakash Wagh


If your App is a MediaPlayer (i.e. uses a MediaBrowseService) and you are experiencing the ForegroundServiceStartNotAllowedException crash then you may need to:

  1. Update your Manifest to specify that your service is for media playback using android:foregroundServiceType="mediaPlayback" in the Service declaration

  2. Include the ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK parameter in your call to the Serivce.startForeground method

like image 10
Jadent Avatar answered Oct 23 '22 21:10

Jadent