Header image by Virginia Poltrack

Use WorkManager for immediate background execution

Some tasks just shouldn’t be deferred

Ben Weiss
Android Developers
Published in
3 min readJul 23, 2020

--

When you have to execute long running tasks while your app is in the background, you will encounter restrictions to background execution that were introduced with Android 8.0. These restrictions incentivize developer behavior that improves the user’s experience of the entire platform.
To make it easier to accommodate different use cases, we also improved the developer experience when working with background restrictions by adding functionality to WorkManager.

We recommend you use WorkManager to execute long running immediate tasks.

Follow along and learn about the benefits of using WorkManager for immediate execution of long running tasks and how to set everything up.

Introduction to the API

Starting with WorkManager version 2.3.0, every Worker has access to methods to run tasks in a foreground service. The Worker base class, ListenableWorker, provides a new setForegroundAsync() function.

This post uses CoroutineWorker for demonstration purposes. In CoroutineWorker, setForegroundAsync() is wrapped in a suspending setForeground() function. The class also provides the suspending doWork function which allows running code off the main thread. But all of this post’s content is also applicable to the corresponding functions for other Worker classes.

When you use setForeground(Async), the scheduled task will be run in a foreground service, immediately, once the constraints are met. As a bonus, WorkManager takes care of handling the service’s lifecycle for you. And, the ten minute time limit for background work won’t apply to the work you’re doing in a worker running in a foreground service.

Get started with immediate execution

Let’s take a look at how to make an existing worker execute work in a foreground service.

Our starting point is a very simplified doWork() function. Code is executed asynchronously, and depending on whether it succeeds or not, the corresponding Result is returned.

In doWork() you will also tell WorkManager that the task should be run immediately and in a foreground service.

To do this, you have to create a ForegroundInfo object and provide it to setForeground(). ForegroundInfo takes a notification id as well as the Notification that will be displayed as parameters.
This information is used to set up and run the foreground service once constraints are met.

Set up ForegroundInfo

Correctly setting up ForegroundInfo is as easy as 1, 2, 3:

  1. Create a Notification
  2. Create a Notification Channel
  3. Provide the Notification to ForegroundInfo

In the code below, createForegroundInfo() calls createNotification(), which in turn populates the notification and creates the corresponding channel.

Run work in a foreground service

Now let’s bring things together. Since we already have an implemented doWork() function, we can call setForeground() and pass required information by calling createForegroundInfo().

⚠️⚠️⚠️
Call setForeground() before your long running task kicks off.
Otherwise your worker will be treated as non-foreground service until setForeground() has been called, which might result in unwanted results such as work being cancelled.
⚠️⚠️⚠️

🐾 Next steps

Now that you know when and how to use long running workers you can go ahead and get started implementing them in your app.

👩‍💻👨🏽‍💻 To see this running in an example, check out the WorkManager sample on GitHub. The code to run work in a foreground service can be found in the BaseFilterWorker class and this commit.

🔖 For a detailed guide on long running workers and foreground services, take a look at the advanced WorkManager guide for long running workers.

🦮 Make sure to check out the updated Guide to background processing and read through the Kotlin coroutines on Android to learn more about the topic.

📚 To learn more about WorkManager, Lyla and Pietro created a blog series to guide you from the basics to advanced features of WorkManager.

🐛 Report any issues you face on the Google IssueTracker. This will help us prioritize features and bug fixes as they come in.

📝 Let me know how running immediate tasks works for you in a comment below or on Twitter.

--

--