Zygote
Background workintermediate

Foreground services

A foreground service is a contract with the user: you may keep running, and in exchange you must say what you are doing. Since Android 14 the contract has a type, a permission and, for some types, a deadline.

12 minAPI 21–37 · 17interactivequizverified 2026-10-27

The foreground service is Android's most honest background API. It does not pretend the work is free: it makes the app show a notification for as long as it runs, and it makes the user able to see and stop it.

TL;DR#

  • A foreground service is a service with an ongoing notification. The notification is the point, not an inconvenience.
  • Since API 28 it needs the FOREGROUND_SERVICE permission. Since API 34 it must declare a type, and each type has its own permission.1
  • Since API 31 an app in the background cannot start a foreground service without an exemption.2
  • Some types have additional restrictions: camera and microphone cannot run from the background, and dataSync has a time limit from API 35.
  • The notification still appears even if POST_NOTIFICATIONS is denied, but the app's other notifications do not.3

Mental model#

Think of a construction permit.

A normal service is a worker who shows up and starts building. Nobody necessarily knows they are there; the city finds out when something goes wrong.

A foreground service is a permitted construction site. The permit is displayed at the entrance — the notification — and it says what kind of work is happening. Since the last round of rules, the permit has a category (demolition, excavation, electrical), and each category has its own insurance requirement. Some categories are not allowed to start at night.

The notification is not paperwork you do to satisfy the city. It is the sign that lets a passer-by know what is happening and complain.

Where the analogy breaks#

A construction permit is granted before work starts and is valid for a duration. An Android foreground service can be started by the app itself, and the "permit" is checked at start time — which is why the start-from-background rule matters so much. The app is both applicant and builder, and the platform is the inspector who may simply refuse.

The big picture#

Loading diagram…
Text description of this diagram

Four gates a foreground service passes before it may keep running, each added by a different release. Gate one, since API 34, requires a declared foregroundServiceType in the manifest plus the matching FOREGROUND_SERVICE permission; without it the service cannot start at all. Gate two, since API 28, requires the FOREGROUND_SERVICE normal permission, and the type-specific permission from API 34; failing it throws a SecurityException. Gate three, since API 31, requires that the start is allowed — a visible activity or one of a short list of exemptions — or foregroundServiceStartNotAllowedException is thrown; this is the gate that stopped the foreground service from being a universal workaround. Gate four, since API 35, requires the service to stay within its type's time budget, chiefly dataSync and mediaProcessing, and the system stops it and calls onTimeout when the budget expires. A list of start-from-background exemptions follows: a visible activity or existing foreground service, a high-priority FCM message for user-visible work, a user action on a notification or tile, and a privileged role or device owner.

The arc is consistent: each release moved the foreground service from "a service that happens to show a notification" toward "a declared, typed, time-bounded activity".

Deep dive#

The mechanics#

Three things must be true for a foreground service to start:

  1. The service is declared in the manifest with android:foregroundServiceType.
  2. The app holds FOREGROUND_SERVICE and the type-specific permission.
  3. The start is permitted — either the app is visible, or an exemption applies.
<service
    android:name=".sync.SyncService"
    android:exported="false"
    android:foregroundServiceType="dataSync" />
 
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
class SyncService : Service() {
 
    override fun onBind(intent: Intent?): IBinder? = null
 
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val notification = buildNotification()
 
        // The type argument was added in API 29 and is required from API 34.
        startForeground(
            NOTIFICATION_ID,
            notification,
            ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC,
        )
 
        scope.launch {
            try {
                repository.sync()
            } finally {
                stopForeground(STOP_FOREGROUND_REMOVE)
                stopSelf()
            }
        }
 
        return START_NOT_STICKY
    }
}

The types#

The type is not decoration. Each one maps to a permission and to a set of start rules:4

TypePermissionNotes
dataSyncFOREGROUND_SERVICE_DATA_SYNCTime-limited from API 35
mediaPlaybackFOREGROUND_SERVICE_MEDIA_PLAYBACKThe canonical "user is listening" case
locationFOREGROUND_SERVICE_LOCATIONAlso needs a location permission
cameraFOREGROUND_SERVICE_CAMERACannot start from the background
microphoneFOREGROUND_SERVICE_MICROPHONECannot start from the background
mediaProjectionFOREGROUND_SERVICE_MEDIA_PROJECTIONScreen capture; needs the projection consent
phoneCallFOREGROUND_SERVICE_PHONE_CALLCalling apps
connectedDeviceFOREGROUND_SERVICE_CONNECTED_DEVICEBluetooth, USB, companion devices
specialUseFOREGROUND_SERVICE_SPECIAL_USEFor cases the others do not cover; needs justification

The specialUse type exists because the list cannot be complete. It is deliberately awkward: Play review asks what the use case is, and using it to avoid picking a real type is a policy violation.

Starting from the background#

Since API 31, startForegroundService() from the background throws ForegroundServiceStartNotAllowedException unless an exemption applies.2 The exemptions are narrow and specific:

  • The app has a visible activity or a foreground service already.
  • The app received a high-priority FCM message intended for user-visible work.
  • The user performed an action on a notification, widget or tile.
  • The app holds a role such as SYSTEM_ALARM_CALL or is a device owner.
  • The app is in the middle of a BOOT_COMPLETED broadcast for certain types.

The practical implication: start the service while the app is visible. A button press is a permission. A timer firing an hour later is not.

Time limits#

Some types are bounded:5

  • dataSync has a time budget from API 35. When it expires, the system stops the service and calls Service.onTimeout() on API 35+; the app is expected to stop cleanly.
  • mediaProcessing (API 35) has a similar budget.
  • Short service was introduced as a general mechanism for "run for a couple of minutes and finish", without a type.
// The service is told it is about to be stopped.
override fun onTimeout(startId: Int) {
    // Persist progress, then stop.
    stopSelf()
}

Short service and the dataSync timeout behaviour were refined across API 34 and 35.

unverified(the exact timeout durations and the onTimeout signature vary by API level; confirm against the current reference for the levels you support)

The notification#

The notification is required, and it must be a real one:

  • A small icon is mandatory.
  • The channel's importance determines whether it makes a sound. A low-importance channel is the right choice for an ongoing sync.
  • The notification should say what is happening. "Syncing 3 of 12 photos" is a contract; "App is running" is noise.

If POST_NOTIFICATIONS is denied on API 33+, the foreground service notification is still shown — the system makes an exception — but the app's other notifications are silently dropped. That asymmetry is worth knowing: you cannot rely on notification permission for anything except the foreground service's own notification.

What Play policy requires#

Google Play restricts the USE_EXACT_ALARM permission to alarm-clock and calendar apps, and reviews foreground service usage for the declared type. The policy language is about user-visible work: if the user cannot tell the service is running and would not want it to be, the type is wrong.

The decision that precedes the code#

Before writing a foreground service, answer three questions in writing. They are the same three the platform will ask, and the same three a Play reviewer may ask.

What is the user watching? If the answer is "nothing", the service should be WorkManager. A foreground service exists to make work visible; if visibility adds nothing, the notification is pure cost.

Which type describes the work? Not the one that is easiest to start. The type determines the permission, the start rules and the time budget, and picking the wrong one means fighting restrictions designed for a different activity.

When does it stop? Every foreground service should have a termination condition that is not "the user force-stops the app". A sync ends when the sync finishes. A call ends when the call ends. A service with no natural end is a design problem, and on API 35 the platform will eventually end it for you.

The migration away from a foreground service#

The most common refactor in modern Android is replacing a long-running foreground service with a WorkManager job that shows progress through a notification it updates itself. The user-visible result is similar; the system-visible result is very different.

The exception is media playback, and it is a genuine one. The user must be able to pause, and the service must survive the app being backgrounded indefinitely. That is what mediaPlayback is for, and why it has no time limit.

Reading the exception#

ForegroundServiceStartNotAllowedException is not a generic "denied". It carries a message naming the reason, and the reason maps directly to a gate.

The three messages you will actually see are: the app is in the background, the app is in a restricted bucket, or the type is not permitted from the background. Each has a different fix — the first means "start it while visible", the second means "the user has not opened this app in weeks", and the third means "this type cannot start from here at all, use WorkManager".

Logging the exception message rather than a generic failure is the difference between a one-minute diagnosis and an afternoon of guessing.

How it evolved#

2008–2013Optional notificationa service could be foreground, or not
2018–2020The permissionFOREGROUND_SERVICE required from API 28
2021–2022The launch ruleno starting from the background without an exemption
2023–nowTypes and deadlinestypes, per-type permissions, timeouts
Background and power changes12 releases
APIVersionWhat changed
11.0
  • The original android.* SDK: Activity, Service, BroadcastReceiver, ContentProvider
174.2 Jelly Bean
  • Daydream service
194.4 KitKat
  • AlarmManager becomes inexact by default for targeting apps
215.0 Lollipop
  • JobScheduler
  • Implicit service intents restricted for targeting apps
268.0 Oreo
  • Background service limits
289 Pie
  • Foreground service permission
2910
  • Background activity starts restricted
3011
  • Background location requires a second request
3112
  • Exact alarms need SCHEDULE_EXACT_ALARM
  • Foreground service launch restrictions from the background
3414 Upside Down Cake
  • Foreground service types required when targeting 34
  • User-initiated data transfer jobs
3515 Vanilla Ice Cream
  • Deprecated APIs: WindowInsetsController hiding, elevate the importance of foreground services
3616 Baklava
  • JobScheduler quota changes

Under the hood#

ActiveServices is where the exception is thrown. Reading setFgsRestrictionLocked in that file is the fastest way to see the actual list of exemptions the platform enforces.

Curiosity corner#

  • A foreground service is not a thread. It runs on the main thread unless you move work off it, and startForeground returning does not mean the work has started.
  • stopForeground(STOP_FOREGROUND_REMOVE) removes the notification; STOP_FOREGROUND_DETACH leaves it behind. Removing is almost always what you want.
  • The media playback type has no time limit, because stopping a user's music is worse than the battery it costs. That is a policy decision, not a technical one.

Try it#

See the foreground service state

adb shell dumpsys activity services com.example.app

Example output
isForeground=true foregroundId=1001 types=0x00000001
Check the FGS permission

adb shell dumpsys package com.example.app | grep FOREGROUND_SERVICE

Example output
android.permission.FOREGROUND_SERVICE_DATA_SYNC: granted=true
Force a background start to fail

adb shell am start-foreground-service com.example.app/.sync.SyncService

Example output
java.lang.ForegroundServiceStartNotAllowedException

Build it#

Write a service that declares dataSync, start it from a button, and watch the notification. Then try to start it from a BroadcastReceiver while the app is in the background, and read the exception. The two observations together are the whole rule.

Check yourself#

Check yourself

1 / 12

Put these background restrictions in the order they were introduced.

Drag, or use the arrows to reorder.

  1. 1Background services are stopped after the app leaves the foreground (API 26)
  2. 2Alarms become inexact by default (API 19)
  3. 3Doze defers network, jobs and alarms (API 23)
  4. 4Foreground service types become mandatory (API 34)
  5. 5Background activity starts are blocked (API 29)
0 answered · 0 correct

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsBehavior changes: Apps targeting Android 14developer.android.comaccessed 2026-10-27↩
  2. docsBehavior changes: Apps targeting Android 12developer.android.comaccessed 2026-10-27↩
  3. docsBehavior changes: Apps targeting Android 13 or higherdeveloper.android.comaccessed 2026-10-27↩
  4. docsForeground services overview | Background workdeveloper.android.comaccessed 2026-10-27↩
  5. docsBehavior changes: Apps targeting Android 15 or higherdeveloper.android.comaccessed 2026-10-27↩
  6. docsBehavior changes: Apps targeting Android 11developer.android.comaccessed 2026-10-27↩
  7. docsNotifications overviewdeveloper.android.comaccessed 2026-10-27↩
  8. docsPermissions best practicesdeveloper.android.comaccessed 2026-10-27↩