Background work are operations that Android apps perfrorm while neither of their Activities are visible on the screen. In other words, background work are tasks that Android applications execute out of user’s sight. Examples of background work include: playing media after the user switches to another application, maintaining live connection to an external Bluetooth device, syncing cached data with the server and more.
In this article, I’ll review the evolution of background work in Android and explain how to choose the approach that best suits your specific app’s requirements.
History of Background Work in Android
Background work in Android is a complex subject today, but it hasn’t always presented such challenges. For example, the first versions of Android OS allowed applications to start a Service when device boots, and then this Service could run pretty much uninterrupted until stopped. This made if very simple for developers to handle background work, but, unfortunately, this freedom also allowed lower-quality apps to claim excessive system resources and shorten battery life.
To address background work inefficiencies and plain abuse, in Android 6.0 Marshmallow (API 23), Google introduced Doze Mode, which is a special state that Android OS enables when the device is “inactive”. In this state the system defers applications’ background work and network access until device becomes “active” again and Doze Mode is disabled. This basically meant that developers couldn’t count on their background operations to execute continuously anymore.
Furthermore, alongside Doze Mode, Android 6.0 Marshmallow also introduced so called App Standby feature. Whereas Doze Mode is a system-wide state that affects all applications, App Standby monitors user’s engagement with individual apps and throttles the background work of “inactive” applications to conserve system resources and prolong battery life.
As a result of the aforementioned changes, starting with Android 6.0 Marshmallow, developers had to take into account that regular background tasks would not execute when user’s device enters Doze Mode, and that even when the device is active, background work could be delayed if the user hasn’t interacted with a specific application in a while. This was a groundbreaking shift in the background work paradigm in Android.
After Android 6.0 Marshmallow, Google kept adding more restrictions around background work. Most notably:
- Android 8.0 Oreo (API 26): Background Execution Limits for Services and Broadcasts.
- Android 8.0 Oreo (API 26): Background Location Limits.
- Android 9.0 Pie (API 28): App Standby Buckets. This is an enhancement of App Standby mechanism introduced in Android 6.0 Marshmallow.
- Android 12 (API 31): Addition of Restricted App Standby Bucket. This bucket contains apps that the user hasn’t interacted with for the last 45 days and apps that use system resources irresponsibly (so they’re added to the Restricted bucket as a punishment).
- Android 12 (API 31): Restriction on starting Foreground Services from the background.
- Android 12 (API 31): Introduction of SCHEDULE_EXACT_ALARM runtime permission.
- Android 13 (API 33): Restricted App Standby Bucket threshold is reduced from 45 days to 8 days.
- Android 13 (API 33): Introduction of USE_EXACT_ALARM permission, subject to Google Play policy checks.
- Android 14 (API 34): Foreground Service type information becomes mandatory and the system performs runtime checks to ensure that Foreground Services satisfy their type requirements.
- Android 14 (API 34): SCHEDULE_EXACT_ALARM runtime permission isn’t granted upon installation.
Due to all these changes, background work in Android became very challenging and nuanced topic. This evolution benefited the users, but made Android developers’ lives more complicated.
Guidelines for Background Work in Android
Now I’ll summarize the guidelines for choosing the optimal approach for a background work in your Android app. These guidelines are written with the assumption that your app targets Android 14 (API 34) and executes on a device powered by Android 14 as well. [As of the time of this writing, Android 14 was in late Beta, so I expect its performance and power related features to be in freeze].
Real-Time Background Work
If your application performs critical real-time work that must execute uninterrupted even in the background, then you need a Foreground Service. Examples of this type of work include media playback, video calls, GPS navigation, etc.
Please refer to my Foreground Service tutorial to learn more about this component (including why it’s called “foreground”, despite being a background execution mechanism).
Future Background Work that Doesn’t Require Timing Accuracy
When you need to schedule a background task to be executed in the future, and the accuracy of the time of the execution isn’t critical, use WorkManager. For example, if your app supports full offline work by caching data locally and then syncs with the server at a later time, you don’t usually care about the exact timing of the syncs, but just want to ensure that a sync will be performed in a reasonable time frame. This is an ideal use case for WorkManager.
WorkManager is the most battery-friendly approach for background work in Android. This framework allows you to schedule recurring tasks, define execution constraints, sequence multiple tasks into conditional chains and more. Furthermore, work scheduled using WorkManager persists across device reboots.
Please refer to my WorkManager tutorial to learn more about this component.
Future Background Work that Requires Timing Accuracy
In some rare scenarios, you might need to execute a background task at a very specific future time. In these cases, WorkManager’s timing guarantees, which are very loose, won’t suffice. Instead, you’ll need to set an alarm using AlarmManager and then, once the alarm goes off, start a Foreground Service to handle the task. However, due to evolving background work restrictions, using AlarmManager is not as straightforward as it used to be.
There are two types of alarms that AlarmManager supports: exact and inexact. Inexact alarms are simple to use, but they only guarantee timing accuracy of 10 minutes or more (in some cases, much more). Therefore, if you need more accurate timing, inexact alarms aren’t the right tool for the job. This leaves you with just the exact alarms as an option.
Working with exact alarms used to be as simple as with the inexact alarms, but, due to changes in Android 12 (API 31), which introduced SCHEDULE_EXACT_ALARM runtime permission, it got more involved. After this change, developers had to deal with potential rejection of this permission by either the user or the system. Android 13 (API 33) took a step further and introduced USE_EXACT_ALARM permission that is subject to special policy checks. Applications that didn’t qualify for the new permission could still use SCHEDULE_EXACT_ALARM. However, starting with Android 14 (API 34), SCHEDULE_EXACT_ALARM permission isn’t granted at installation time anymore. This means that, in addition to handling a potential rejection of SCHEDULE_EXACT_ALARM after the installation, developers should also assume that many users won’t grant this permission to begin with.
All in all, going forward, I recommend trying to avoid background work that requires timing accuracy and, consequently, mandates usage of the exact alarms. In some cases, this might require redesign of the existing features, but this seems to be the best (and, potentially, the only) long-term strategy. For cases that don’t have a viable workaround, you can try applying for USE_EXACT_ALARM permission, but, frankly, I expect this to be a very high bar to pass, unless your app needs this permission for its core functionality anyway.
Background Work Fragmentation
Unfortunately, the challenges of background work in Android aren’t limited to the ever-growing list of restrictions in newer Android versions. Background work is also subject to a major fragmentation problem.
See, Android device manufacturers (OEMs) can modify the Android OS to some degree before they install it on their devices. Many of them use this opportunity to introduce additional restrictions on the background work or implement more aggressive power-saving modes for the entire system. As a result, even if your app satisfies all the official requirements and adheres to all the best practices, your background tasks are still not guaranteed to be executed. For example, some OEMs go as far as shutting down active Foreground Services.
This website attempts to summarize all the non-standard, undocumented power saving features in Android devices implemented by different OEMs. I recommend reading it thoroughly if your app’s functionality depends on the ability to execute background work.
Recently, Google announced that they’ll work with OEMs to address this issue. Unfortunately, even if this collaboration will be successful, it’ll take years for its effects will propagate across Android ecosystem. That said, the first fruits are already here because Samsung pledged to stop killing Foreground Services in Android 14:
Changes in One UI 6 (with Android 14): To strengthen the Android platform, our collaboration with Google has resulted in a unified policy that we expect will create a more consistent and reliable user experience for Galaxy users. Since One UI 6.0, foreground services of apps targeting Android 14 will be guaranteed to work as intended so long as they are developed according to Android’s new foreground service API policy.
Application Management, Samsung Developers Website
Summary
In this article I summarized the most important and actionable information about the background work in Android applications. If you spotted a mistake, or believe that I missed some important aspect, please let me know in a comments section below.
Thanks for reading. If you found this post interesting or useful, subscribe to my mailing list below to get the highest-quality Android content right into your inbox.