Background Work in Android Applications

Background work are tasks that Android applications perfrorm while neither of their user interface elements are visible on the screen. Examples of background work include: playing media while the screen is turned off, continuously receiving data from an external Bluetooth device, periodic syncs of the app’s state with the server and more.

In this article, I’ll review the evolution of background work in Android and explain how to choose the best approach for your app’s specific requirements.

History of Background Work in Android

Background work in Android is a very complex subject, 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 so-called Doze Mode. This is a special state enabled by the Android OS when the device is “inactive”. In this state, the system restricts applications’ background work and network access. 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 the 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 a very challenging and nuanced topic. This evolution benefited the users, but complicated the lives of Android developers.

Guidelines for Background Work in Android

Next sections provide guidelines for choosing the optimal mechanism for 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 stable].

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 timeframe. This is an ideal use case for WorkManager.

WorkManager is the most battery-friendly background work mechanism in Android. This framework allows you to schedule recurring tasks, define execution constraints, sequence multiple tasks into conditional chains and more. Furthermore, the work you schedule 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 the only option.

Working with exact alarms used to be as simple as with inexact alarms. However, due to changes in Android 12 (API 31), which introduced SCHEDULE_EXACT_ALARM runtime permission, it became more complicated. After this change, developers had to deal with potential rejection of this permission by either the user or the system. Then Android 13 (API 33) introduced USE_EXACT_ALARM permission that is subject to special GooglePlay policy checks. Applications that didn’t qualify for the new permission could still use SCHEDULE_EXACT_ALARM in Android 13, but, 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 take into consideration that users might not grant this permission to their apps to begin with.

All in all, going forward, I recommend trying to avoid background work that requires timing accuracy and, consequently, requires 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’ll need to apply for USE_EXACT_ALARM permission. This request will be approved only if your application requires the exact alarms for its core functionality, so I expect this to be a very high bar to pass.

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

This article summarizes the most important aspects of the background work in Android applications. If you spotted a mistake, or believe that I missed some important piece of info, please let me know in the comments section below.

Thanks for reading and, if you liked this post, don’t forget to subscribe to my email list to receive notifications about future articles.

Check out my premium

Android Development Courses

Leave a Comment