33

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.

Vedprakash Wagh
  • 3,595
  • 3
  • 12
  • 33

3 Answers3

36

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.

Vedprakash Wagh
  • 3,595
  • 3
  • 12
  • 33
  • 1
    I have the same issue on a Pixel 6 - Android 12 device. Event if my app launches a foreground service thanks to the Activity Recognition API, Crashlytics recorded these exceptions – StevenTB Nov 04 '21 at 15:53
  • Yeah, it's really annoying. Just downgrade to API Level 30 and it should go away. – Vedprakash Wagh Nov 06 '21 at 13:56
  • 1
    @user924 No, they added this new restriction in Android 12. You cannot start a service from background without user doing something on your apps UI. – Vedprakash Wagh Nov 20 '21 at 12:32
  • @user924 No it is not. I've literally linked an article which states this is a behaviour change starting from API level 31. You can check the article by Google from the last 2 links in answer. If you have an official source stating that this behaviour is same for Android 11, feel free to link it. – Vedprakash Wagh Dec 04 '21 at 04:01
  • 1
    @StevenTB I have the same issue as yours. Have you got any solution for it? – user1443721 Mar 25 '22 at 05:35
  • 1
    @user1443721 I had to ask the user to disable the battery optimization in order to avoid background start restrictions : https://developer.android.com/guide/components/foreground-services#background-start-restriction-exemptions – StevenTB Mar 25 '22 at 11:41
  • 1
    Thanks! battery optimization is another Exemption. Wondering why the exemption of activity recognition transition does not work. – user1443721 Mar 25 '22 at 14:29
  • @user1443721 Activity Recognition Transition is an exemption special case, so you can start your job even if the app is not in foreground :) – StevenTB Mar 25 '22 at 19:41
  • @StevenTB Not always. Sometimes I got the exception :(. My phone is Pixel 3a with Android 12. check my post https://stackoverflow.com/questions/71583345/how-to-use-activity-recognition-exemptions-to-start-foregroundservice-from-backg – user1443721 Mar 26 '22 at 05:45
  • @user1443721 geofencing events also come under the exemption but getting ForegroundServiceStartNotAllowedException when I try to start my service from there. Did you find any solution? – Himanshi Thakur Mar 29 '22 at 10:35
  • I don't know why Google is confused to start background work. Before Android 8 there were no restrictions then they came to foreground services by separating background services then they came to start background service using only Worker and in Android 12 they are again saying to use Exact Alarm to start foreground service...what the hell they are trying to do, don't know. Just do whatever they want at the SDK level, just ask the developer to write only one line of code. Why Foreground, Background, Alarm, Worker, JobIntentService, Scheduler lablablab.... – Ready Android Mar 29 '23 at 11:07
  • Being a senior developer you can't find the solution for ForegroundServiceStartNotAllowedException then what about freshers and Juniors...Seriously there is no straightforward answer to this issue...Round, Round, Round and no solution... – Ready Android Mar 29 '23 at 11:10
  • @VedprakashWagh Can you post your solution here? The solution using WorkManager. My doubt is should I start the service from the doWork() method? – Aanal Shah Mar 31 '23 at 09:04
  • @AanalShah No you don't have to use Services if you're using WorkManager. What's your specific use case? – Vedprakash Wagh Apr 01 '23 at 10:50
  • @VedprakashWagh I want to display a Foreground Service. I am getting crashes for Android 12 and 13. – Aanal Shah Apr 03 '23 at 13:34
14

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

Also note, if you are using ExoPlayer then see the suggestions from the Android team here that may help with tracking down the cause of crashes due to ForegroundServiceStartNotAllowedException exceptions being thrown

https://github.com/androidx/media/issues/111#issuecomment-1406466363

Furthermore, there is some really useful and up to date (to API31) information on ForegroundServices here: https://www.hellsoft.se/your-guide-to-foreground-services-on-andorid/

Jadent
  • 974
  • 8
  • 14
  • 1
    Thanks for this. Gave it a try and unfortunately it did not work. I have a similar question over [here](https://stackoverflow.com/questions/70711950/android-12-foregroundservicestartnotallowedexception-while-in-foreground) Except it seems that i'm getting this error while in foreground – brettywhite Jan 14 '22 at 14:57
  • 3
    This does not help at all, at least not on Samsung devices. When the service get started by something like KEYCODE_MEDIA_PLAY, while the app is totally background it still crashes. – slezadav Jan 23 '22 at 16:06
  • adding the service type is not fixing the issue! – Ahmed Garhy Sep 12 '22 at 01:03
-2

use .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE) in creating the Notification and also NotificationManager.IMPORTANCE_MAX.

Dan
  • 3,647
  • 5
  • 20
  • 26