Foreground service launch restrictions

Apps that target Android 12 (API level 31) can no longer 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.

If your app is affected by this change, migrate to using WorkManager. WorkManager is the recommended solution for starting higher-priority background tasks.

Starting in WorkManager 2.7.0, your app can call setExpedited() to declare that a Worker should use an expedited job. This new API uses expedited jobs when running on Android 12, and the API uses foreground services on prior versions of Android to provide backward compatibility.

The following code snippet shows an example of how to use the setExpedited() method:

Kotlin

OneTimeWorkRequestBuilder<T>().apply {
    setInputData(inputData)
    setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
}.build()

Java

OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
    .setInputData(inputData)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build();

Because the CoroutineWorker.setForeground() and ListenableWorker.setForegroundAsync() methods are backed by foreground services, they're subject to the same foreground service launch restrictions and exemptions. You can use the API opportunistically, but be prepared to handle an exception if the system disallows your app from starting a foreground service. For a more consistent experience, use setExpedited().

To see a complete example of how WorkManager 2.7.0 uses expedited jobs, look through the WorkManagerSample on GitHub.

Expedited jobs

Expedited jobs, new in Android 12, allow apps to execute short, important tasks while giving the system better control over access to resources. These jobs have a set of characteristics somewhere in between a foreground service and a regular JobScheduler job:

  • They're meant for short tasks that complete within a few minutes. Unless your app has enough quota, the system might stop an expedited job if the job has already been running for at least 3 minutes.
  • They're less affected by some of the system's power management restrictions, including Battery Saver and Doze.
  • The system runs them immediately, provided that the system's current workload makes it possible to do so.

Expedited jobs might be deferred

The system tries to execute a given expedited job as soon as possible after the job is invoked. However, as is the case with other types of jobs, the system might defer the start of new expedited jobs, such as in the following cases:

  • The system load is too high, which can occur when too many jobs are already running, or when the system doesn't have enough memory.
  • The expedited job quota limit has been exceeded. Expedited jobs use a quota system that's based on the App Standby Buckets and limits the maximum execution time within a rolling time window. The quotas used for expedited jobs are more restrictive than the ones used for other types of background jobs.

Effects on Alarm Manager APIs

In general, apps that target Android 12 can't start foreground services using an alarm.

To support use cases in which apps need to send time-sensitive alarms or reminders to users, you can still start foreground services when your exact alarms go off. In order to set exact alarms, your app must declare the SCHEDULE_EXACT_ALARM permission.

Learn more about the exact alarm permission.

Enable foreground service launch notifications for testing

To better understand when your app attempts to launch a foreground service while running in the background, enable notifications that appear each time this behavior occurs.

To enable notifications for testing purposes, execute the following ADB command on the development machine connected to your test device or emulator:

adb shell device_config put activity_manager \
  default_fgs_starts_restriction_notification_enabled true

Cases where foreground service launches from the background are allowed

In the following situations, your app can start foreground services even while your app is running in the background: