Until now, in order to perform background work in Android, developers had to choose between multiple execution options. At Google I/O 2018, the Android team launched WorkManager as part of the Android Jetpack.
This library provides a simple and clean interface to specify deferrable, asynchronous tasks and when they should run. This blog post is the first in a new series on WorkManager. The series will include an overview about the Android memory model, existing background solutions, what’s happening behind the scenes and why and when we should use WorkManager.
Also, we will discover details about the architecture of the WorkManager library and about the main components(Worker, WorkRequest, WorkManager, WorkInfo) of it. Finally, we will highlight how to use WorkManager for scenarios like chained sequences of tasks that run in a specified order, unique named sequences, tasks that pass and return values and how to apply constraints in order to decide when to run the task.
In this blog post I’ll cover:
- Android memory model
- Android battery optimizations
- Current background processing solutions
- Where is WorkManager placed in the background work schema
In the mobile world, the app performance has an important impact on user retention. But what are the issues that could make a user unhappy? Personally, I have identified two main issues that could make a user unhappy:
- a fast draining battery
- a phone running out of memory
Research shows that about:
- 53% of all users uninstalled or removed a mobile app with severe issues like crashes, freezes or errors, and
- 36% will stop using a mobile app due to heavy battery usage.
That’s why mobile app performance should be taken seriously. ❗️❗️❗️
📑 Android Memory Model
As an android developer, I learned that when I develop an app it is not about me, it is about the users who will interact with the app I build. So it is all about the android ecosystem, because android is for everyone. What do I mean by Android ecosystem?
In terms of devices they could be split into 3 main categories based on their configuration. So we have entry level devices, mid-range devices and premium devices.
When we talk about memory availability and usage we should focus more on the entry level devices because the premium and mid-range ones have a good memory configuration. If we don’t build apps that are able to work properly on the entry level devices then these devices will stop being produced and based on that a big part of our users will also disappear. This is not a good thing. Those users will be disappointed.
On a device the physical memory is organised in pages and each page has about 4 kilobytes. And these pages could have 3 main statuses: used, cached and free pages.
If we put a device under memory pressure at the beginning we will have some free memory available, so we have a happy device because if an app needs memory we have enough for it. Over time because we use more memory the free memory goes down and in this case the linux kernel has a mechanism called kswapd and its job is to find more free memory. The main action done by this process is to reclaim cached pages. This action takes some time in order to reload the cached pages but it is not visible for users.
We continue to use the device memory and also the number of cached pages started to go down and the system starts to crash, which is a bad thing. At this moment low memory killer appears and starts to kill the running processes. It is a good thing for the memory, but it could impact the app currently used by the user.
📑 Android battery optimization
Regarding the battery optimization Android have provided battery saving features in the latest releases like:
- In Marshmallow it was introduced the deep doze mode — the device is put on a deep sleep under the condition that the device does not move — shuts down the background activity
- In Nougat — doze on the go — put the device on a slighter lighter sleep and wakes up more frequently to check if there are pending jobs to do (shuts down a part of the background work)
- In Oreo they were introduced the background service limitations
- And in Android Pie — adaptive battery based on app standby — the apps are moved in 4 buckets (active, working set, frequent and rare)
📑Background processing solutions
Over the years, Google have provided various methods for developers to assist in doing or scheduling work in the background.
- JobScheduler is a great new API, but is only supported for Android Lollipop (API 21) and above
- Firebase JobDispatcher is backward compatible as far as Ice Cream Sandwich (API 15) — but it requires Google Play services, which is big and heavy and not available in China. Also from next year, april 2020 it will be archived. Currently it is deprecated.
- AlarmManager works on all API levels, but requires BroadcastReceiver to survive device reboots and also is subject to some power manager restrictions, which got introduced in Android Pie.
So it looks like we have a choice between excluding older devices, or doing hours of work building it all from scratch.
A good way to organize the background solutions is to split them based on the time and importance:
- the vertical axis is the timing of the work: work should be done when it is specified or it could wait for a bit.
- the horizontal axis represents how important is the work. It should be done when the app is in foreground or it needs to be done at a certain point.
WorkManager is part of the 4th category of tasks that are deferrable but needs to be executed.
“WorkManager is a library for managing deferrable and guaranteed background work.”
Deferrable work : the task can run later and it is still useful (uploading logs vs send a message)
Guaranteed: the task will run even the app will be closed or the device restarts (backup images to a server)
❓Why to use WorkManager?
- Backward compatibility with different OS versions (API level 14+)
- Follows system health best practices
- Supports one-off and periodic tasks
- Supports chained tasks with input/output
- Defines constraints on when the task runs
- Guarantees task execution, even if the app or device restarts
❓When to use WorkManager?
- Fetching data periodically
- Uploading images/files to a server
- Syncing data between app and server
- Sending logs to a server
- Executing expensive operations on data
In the next article, we’ll take a look in depth at each WorkManager entity and examine how they might be applied in our code. Stay tuned!
That’s it for now, hope it helps! Enjoy and feel free to leave a comment if something is not clear or if you have questions. Thank you for reading! 🙌🙏😍✌