Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Guide to Foreground Services on Android

Guide to Foreground Services on Android

Foreground services are an essential component for executing long-running tasks on Android. However, as each new Android version introduces changes and limitations, implementing them correctly has become increasingly challenging.

In this session, we will cover what a foreground service is, the changes introduced in recent Android versions, and how to update your apps to target the latest SDK versions. You will learn about different types of foreground services and common errors to avoid. We will also explore alternative approaches for handling background work.

Additionally, we will take a practical look at how to correctly implement foreground services through a sample project.

Walk away feeling confident you can leverage foreground services for long-running work in your apps.

Domen Lanišnik

March 21, 2025
Tweet

More Decks by Domen Lanišnik

Other Decks in Programming

Transcript

  1. What is a Service? Overview • An application component that

    can perform long-running operations in the background • Network requests, playing audio, ML models, data syncing, … • Does not provide a user interface • Components can bind to it and interact with it • Runs on the main thread
  2. What is a Foreground Service? • Perform long-running operations •

    Continue user actions in the background • Noticeable to the user (status bar noti fi cation) • Examples: • Music player app (like Spotify) • Navigation app (like Google Maps) • Fitness app (like Samsung Health) Overview
  3. Foreground vs Background Service? Overview • Foreground: • performs work

    that is noticeable to the user • stays alive even if app is terminated • must display a noti fi cation • Background: • Performs work that is not noticeable to the user • only runs while the app is running • many restrictions on API 26 onwards
  4. When to choose a foreground service? Coroutines RxJava WorkManager <

    3 minutes CompanionDevice Manager Geofence API https://developer.android.com/develop/background-work/background-tasks#categories_of_background_tasks Continue task while app in background? Asynchronous work Okay if task deferred or interrupted? Task scheduling APIs Short, critical task? shortService foreground service Alternative API available? Alternative API Foreground service No Yes No No No Yes Yes Yes
  5. Android 9
 API 28 Introduces FOREGROUND_SERVICE permission Android 10 API

    29 Introduces foregroundServiceType property that is mandatory for location type Android 11 API 30 New camera and microphone foreground service types Restrictions to access camera and microphone when FGS started from background Android 12 API 31 Restrictions on starting a FGS while in the background Android 13 API 33 Introduces noti fi cation permissions and FGS noti fi cations can be dismissed Android 14 API 34 Declaring foregroundServiceType property becomes mandatory Introduces health, remoteMessaging and special types Android 15 API 35 New mediaProcessing foreground service type BOOT_COMPLETED receivers are not allowed to launch some types of foreground services
 Introduces service timeouts Android 16 API 36 New granular health permissions that a ff ect the health foreground service type https://developer.android.com/develop/background-work/services/fgs/changes
  6. Foreground Service Types • Describes what kind of work the

    service does • Needs to be declared in the manifest and in the service • Mandatory with Android 14 for correct usage of FGS and consistency across device manufacturers • Each type has runtime prerequisites that need to be ful fi lled • A service can de fi ne multiple types
  7. Foreground Service Types camera connectedDevice dataSync health location mediaPlayback mediaProjection

    microphone phoneCall remoteMessaging shortService* specialUse* systemExempted* mediaProcessing https://developer.android.com/develop/background-work/services/fg-service-types
  8. Foreground Service Types <!-- Request the speci fi c foreground

    service permission for each declared type --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <uses-permission android:name=“android.permission.FOREGROUND_SERVICE_CAMERA" /> <!-- Request the general foreground service permission --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  9. location Foreground Service Types • For long-running use cases that

    require location like navigation apps • Required from Android 10 and newer • Runtime prerequisites: • Enabled location services • ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION runtime permissions • Alternative APIs: • Speci fi c locations -> GeofenceAPI
  10. connectedDevice Foreground Service Types • When interacting with an external

    device through Bluetooth, NFC, USB or network connection • Runtime prerequisites (at least one of the following): • Declare one of the permissions in manifest: • CHANGE_NETWORK_STATE, CHANGE_WIFI_STATE, CHANGE_WIFI_MULTICAST_STATE, NFC, TRANSMIT_IR • One of the runtime permissions: • BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE, BLUETOOTH_SCAN, UWB_RANGING • Call UsbManager.requestPermission()
  11. connectedDevice Foreground Service Types • Alternative APIs: • Continuous data

    transfer to external device -> CompanionDeviceManager • Scan for BT devices -> Bluetooth scan API
  12. dataSync Foreground Service Types • Data transfer operations like upload

    or download, backup, … • Will be deprecated in future Android versions, recommended to migrate • Alternative APIs: • User Initiated Data Transfer • WorkManager (expedited work) • shortService type • Runtime prerequisites: None https://developer.android.com/about/versions/15/changes/datasync-migration
  13. mediaProcessing Foreground Service Types • New in Android 15 •

    For performing time-consuming operations on media assets, like converting media to di ff erent formats • Time limit of 6 hours per 24h • Runtime prerequisites: None
  14. Service Timeouts Foreground Service Types • System places time restrictions

    starting with Android 15 to dataSync and mediaProcessing types • Time limit of 6 hours per 24h per type • Timer starts from when startForeground() is called • Service.onTimeout(int, int)-> Service.stopSelf() • ANR: ”A foreground service of <fgs_type> did not stop within its timeout: <component_name>” https://developer.android.com/develop/background-work/services/fgs/timeout
  15. Service Timeouts Cont. Foreground Service Types • Service.onTimeout is ignored

    on Android 13 and lower • ForegroundServiceStartNotAllowedException: “Time limit already exhausted for foreground service type dataSync" https://developer.android.com/develop/background-work/services/fgs/timeout
  16. shortService* Foreground Service Types • Quickly (3 min) fi nish

    critical work that cannot be interrupted or postponed • Cannot start other foreground services • A FGS can change its type to shortService at any time, starting the timeout • Runtime prerequisites: None • Doesn’t require Play Console justi fi cation
  17. specialUseCase* Foreground Service Types • For valid use cases that

    are not covered by other FGS types • Requires providing explanation for the Play Console review • Runtime prerequisites: None
  18. Play Console Declaration • For each FGS type you declare:

    • Describe app functionality • Describe user impact if task 
 deferred or interrupted • Include a link to a demo video • Select from a pre-de fi ned list of
 use cases https://developer.android.com/develop/background-work/services/fg-service-types#google-play-enforcement • Required when targeting Android 14 and above
  19. FGS Notification • Displaying a noti fi cation is required

    when starting a FGS • Visible for the duration of the service • Requires channels, runtime permissions, … • Android 12+, system waits 10 seconds before 
 showing noti fi cation • Android 13+, dismissible -> app shown in task manager
  20. Background restrictions • Apps targeting Android 12 or newer can’t

    start FGS from background* • App has a visible window or activity in back stack or started recently • User performs an action on a UI element (noti fi cation, widget, bubble) • App receives a high-priority message using FCM* • Exact alarms • App receives BOOT_COMPLETED action*, … • ForegroundServiceStartNotAllowedException https://developer.android.com/develop/background-work/services/foreground-services#background-start-restriction-exemptions
  21. While-in-use permission restrictions Camera, location, microphone • Permissions only apply

    while app is in the foreground • Can’t start a FGS from background that requires 
 permissions for which the app only has a 
 while-in-use permissions • pre-A14 -> FGS will launch, but result in an exception • after-A14 -> exception when creating FGS • Recommended to only launch this 
 FGS type while app has visible activity https://developer.android.com/develop/background-work/services/foreground-services#wiu-restrictions
  22. Responding to an event Coroutines RxJava Finishes in a few

    seconds? Asynchronous work User-initiated & needs to run immediately? App is in foreground, or can start from background? Foreground service Task scheduling APIs Yes No Yes No WorkManager JobScheduler Yes No https://developer.android.com/develop/background-work/background-tasks#categories_of_background_tasks
  23. How to create a Foreground Service? 1. Create a Service

    and call startForeground() OR 2. Use WorkManager to de fi ne a long-running Worker by calling startForeground()
  24. class ExampleForegroundService : Service() { override fun onStartCommand(intent: Intent?, fl

    ags: Int, startId: Int): Int { // TODO Start as foreground service return super.onStartCommand(intent, fl ags, startId) } } 1. Create a service
  25. <service android:name=".service.ExampleForegroundService" android:exported="false" android:foregroundServiceType="location" /> 2. Declare service in Manifest

    <!-- Request location permission to be able to use the location foreground service type --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  26. 3. Declare FGS permissions <!-- Request the general foreground service

    permission --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Request the speci fi c foreground service permission for each declared type --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
  27. 3. Declare FGS permissions Common errors java.lang.SecurityException: Permission Denial: startForeground

    from pid=8589, uid=10623 requires android.permission.FOREGROUND_SERVICE java.lang.SecurityException: Starting FGS with type location targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_LOCATION]
  28. 4. Call startForeground() // promote service to foreground service ServiceCompat.startForeground(

    this, // service 1, // noti fi cation ID noti fi cation, // actual noti fi cation to display if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // mandatory FGS type ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION } else { 0 } )
  29. 4. Call startForeground() • Can pass multiple types by using

    the or operator • Can declare a subset of types and call startForeground() multiple times ServiceCompat.startForeground( this, 1, noti fi cation, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION or ServiceInfo.FOREGROUND_SERVICE_MEDIA_PLAYBACK } else { 0 } )
  30. 4. Call startForeground() • Passing 0 for foregroundServiceType android.app.InvalidForegroundServiceTypeException: Starting

    FGS with type none targetSDK=34 has been prohibited Common errors java.lang.IllegalArgumentException: foregroundServiceType 0x00000002 is not a subset of foregroundServiceType attribute 0x00000000 in service element of manifest fi le • Passing a type that is not declared in manifest
  31. 4. Call startForeground() • startForeground() has to be called within

    10 seconds of receiving onStartCommand() Common errors cont. android.app.ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground()
  32. 4. Call startForeground() Noti fi cations fun buildNoti fi cation(context:

    Context): Noti fi cation { createNoti fi cationChannel(context)
 return Noti fi cationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle("Title") .setContentText("Description") .setSmallIcon(R.drawable.ic_launcher_foreground) .setForegroundServiceBehavior(Noti fi cationCompat.FOREGROUND_SERVICE_DEFAULT) .setContentIntent(Intent(context, MainActivity::class.java).let { noti fi cationIntent -> PendingIntent.getActivity(context, 0, noti fi cationIntent, PendingIntent.FLAG_IMMUTABLE) }) .build() } FOREGROUND_SERVICE_IMMEDIATE FOREGROUND_SERVICE_DEFERRED
  33. 5. Start the service Crash java.lang.SecurityException: Starting FGS with type

    location targetSDK=34 requires permissions: - all of the permissions allOf=true - [android.permission.FOREGROUND_SERVICE_LOCATION] - any of the permissions allOf=false - [android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_FINE_LOCATION]
  34. 6. Request runtime permissions private val locationPermissionRequest = registerForActivityResult( ActivityResultContracts.RequestPermission()

    ) { granted -> if (granted) { // Precise location access granted, service can run startForegroundService() } else { } } locationPermissionRequest.launch(ACCESS_FINE_LOCATION)
  35. override fun onStartCommand(intent: Intent?, fl ags: Int, startId: Int): Int

    { val fi neLocationPermission = PermissionChecker.checkSelfPermission(this, ACCESS_FINE_LOCATION) if ( fi neLocationPermission != PermissionChecker.PERMISSION_GRANTED) { // stop the service if we don't have the necessary permissions stopSelf() } else { startAsForegroundService() startLocationUpdates() } return super.onStartCommand(intent, fl ags, startId) }
  36. • stopForeground(notificationBehavior: Int) for removing the service from foreground (does

    NOT stop the entire service) • STOP_FOREGROUND_REMOVE • STOP_FOREGROUND_DETACH • STOP_FOREGROUND_LEGACY • stopSelf() for stopping the entire service 8. How to stop the service?
  37. Create FGS using WorkManager • WorkManager has built-in support for

    long running workers • Manages and runs a foreground service on your behalf • These Workers can run longer than 10 minutes • Examples: tasks important to user, uploads/downloads, local ML models, … • Same rules around FGS types and pre-requisites apply • Use setForeground() in your Worker https://developer.android.com/develop/background-work/background-tasks/persistent/how-to/long-running
  38. 1. Declare FGS service and permissions <!-- Request location permission

    to be able to use the location foreground service type --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  39. class ForegroundWorker( private val appContext: Context, params: WorkerParameters ) :

    CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { setForeground(createForegroundInfo()) processLocationUpdates() return Result.success() } private fun createForegroundInfo(): ForegroundInfo { ... } } 2. Create Worker
  40. private fun createForegroundInfo(): ForegroundInfo { Noti fi cationsHelper.createNoti fi cationChannel(appContext)

    val noti fi cation = Noti fi cationsHelper.buildNoti fi cation(appContext) return ForegroundInfo( 1, // noti fi cation ID noti fi cation, // Noti fi cation object if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION } else { 0 } ) } 3. Create ForegroundInfo
  41. 5. What to watch out for? • Declare FGS types

    like with Service • Check for required runtime permissions before starting the work • Only use when the work is important to the user • Also requires Play Store declaration
  42. Summary • Android 14 brought a lot of changes related

    to FGS • Can start FGS using Service or WorkManager • Need to declare FGS types and ful fi ll runtime pre-requisites • Fill-out Play Store Declaration • Consider using alternative APIs
  43. Sample app • Starting a FGS of type location from

    UI • Requesting runtime permissions before starting FGS • Binding to the FGS from Activity to display 
 the service status and location updates • Stopping the service from the UI • Using WorkManager to launch a FGS* https://github.com/landomen/ForegroundService14Sample