Consider some use cases which we encounter in our daily android development tasks:
- Downloading data files from a remote server for a mobile game.
- Downloading files from a server.
- Synchronizing data collected on mobile with a back-end service, for example: uploading crash analytics, log files etc…
- Backing up device files to online storage.
What’s common between these use cases?
- They all are long running tasks.
- They can be deferred to run on a background thread, while the user interacts with the app. These tasks should not affect the app’s performance.
- They can also be run even when the user is not interacting with the app.
Performing such asynchronous tasks is very common in modern android applications. Rarely we come across apps that do not interact with any backend service and run completely offline. Hence, keeping this in mind the engineers at Google had developed many Job Scheduling APIs to schedule such tasks on Android such as Services, Alarm Manager, Job Scheduler, GCM Network Manager, Firebase Job Dispatcher, before coming up with their latest (and in my opinion the best) solution: Work Manager.
Work Manager, in my opinion, is by far the best API that Google has come up with, for android in recent years. But first, let’s discuss all the scheduling mechanisms other than the work manager and have a look at their pros and cons. In the end, I’ll explain why Work Manager can trump most of the existing solutions. Also, I’ll tell you when not to use the Work Manager.
In this article, we’ll be discussing these 4 scheduling mechanisms in order:
- Job Scheduler
- GCM Network Manager
- Firebase Job Dispatcher
So, let’s start!!
First up are services. Services have been around since as long as I can remember. They have been the go-to solution for developers for performing long running tasks such as playing music, downloading files, syncing the data, crunching your android app’s assets and many more. And although we now know that there are much better, power efficient ways of doing these tasks, services still very relevant for some use cases such as playing music in the background with a notification in the notification tray.
But for the rest of the use cases, we’ve come a long way and android has provided much better APIs than services, for such tasks. So, let’s see some of the problems with services:
- By default, services run on the Main Thread of the application in which is declared. So, any long running tasks such as image processing, networking, MP-3 playback slow down the performance of the apps and we start noticing jitters on the UI.
- You have to use inter-process communication to talk to it, which is slower than if it were in the same process as the client.
- Debugging is difficult as you have to attach to a different process.
- If your service crashes, it crashes independent of the main process. This can also be an advantage at times.
- For long running tasks, you’ll need to use threads inside services making the implementation more and more complex.
- If you forget to stop the service if a task is complete, it can keep running in the background and will drain the battery.
So, while services may be good for tasks such as playing music with notification, it is not the most suitable solution for long running tasks which can block the main thread such as networking, heavy computation, MP3 playback etc.
Job scheduler API was introduced in API level 21. It is efficient for networking tasks and will run in the background if the criteria specified in JobInfo.Builder() are met such as when the device is charging, idle, connected to internet etc. It will also try to batch these jobs together to save system resources. It also comes with back-off and retry logic if a job fails for some reason.
But it is not suitable for non-deferrable work, such as downloading an asset on button click which should happen right away and not delayed.
The other disadvantage, and the one that bugs most developers is that it is only supported on API versions 21 and higher. So, it would not work on android devices running on versions less than 21 which is 15% at the time.
GCM Network Manager
GCM Network Manager comes with all the goodness of Job Scheduler with the additional benefit of backward compatibility. Internally, GCM Network Manager uses Job Scheduler for API version > 21. For versions < 21, it uses Google Play Services’ scheduling engine.
It also has the ability to schedule one-off tasks as well as Periodic Tasks. Hence, it removes the extra task of rescheduling the Job from the developer, required in Job Scheduler.
But it has some demerits:
- Since it uses the Play Services’ scheduling engine, it will only work on devices with play services installed.
- When play services are updated, the jobs are wiped out. The developer has to take care of scheduling the job again.
- Not suitable for non-deferrable tasks or tasks supposed to run at a specific time.
- Google deprecated GCM on 10th April 2018 and it will be completely removed by 11th April 2019, hence it is advisable to not use GCM Network Manager any further.
Let’s have a look at Firebase Job Dispatcher which solves our problems.
Firebase Job Dispatcher
Firebase Job Dispatcher is an android library for scheduling background jobs. It supports backward compatibility till API version 9.
Just like GCM Network Manager, it uses Google Play Services’ scheduling engine to schedule jobs. If the device does not have play services installed, it uses Alarm Manager. For android devices running API version 21 or higher, it uses Job Scheduler.
So far so good. It manages backward compatibility, runs on devices with no Google Play Services and has one-off as well as periodic tasks.
So, why bother with Work Manager when Firebase Job Dispatcher has it all.
This is because, when these APIs are used incorrectly it leads to battery drain. So, to save power, android has released many power saving features such as Doze Mode, Doze on-the-go, limits on background services, App Standby Buckets etc. So, as a developer, it becomes our responsibility to take advantage of all of these so as to ensure our app remains battery efficient on all API levels.
This means a lot of spaghetti if-else code. So, let me introduce you all to the latest addition to scheduling API in android development:
As I’ve already mentioned, work manager is according to me one of the best APIs that Google has released for android in recent years. It ticks all the boxes you expect from a scheduling API, has a high level of abstraction so that you don’t have to worry about granular details such as power consumption, handling back-off and rescheduling.
Work Manager is suitable for deferrable, guaranteed background work. The keywords to focus on here are deferrable and guaranteed.
Work Manager in android will not run your tasks immediately but will differ it to be executed at a point in time when the constraints you mention are met and also taking into account battery constraints. It also guarantees that the work will be executed even if your device restarts.
Here is a great diagram which outlines when is it perfect to use Work Manager in your android applications:
As you can see, it is suited for deferrable tasks which need not run at a precise time in the future like an Alarm or Reminder.
Benefits of using Work Manager:
- Backward compatible up to API 14
- Add constraints like networks, charging.
- Can schedule one-off or periodic tasks.
- Can chain tasks together.
- Guarantees execution even if device restarts.
- Executes tasks at an optimized time in future considering battery, network availability.
- It is a part of Android Jetpack libraries and is recommended by Google 😛
It is suitable for tasks such as sending crash reports to a background service, syncing data with a web service, crunching your app’s assets etc.
In the next post in this series on Work Manager, we’ll be integrating Work Manager in an android application and have a practical look at how to set up and use Work Manager in android. So, stay tuned!
*Important*: I’ve created a SLACK workspace for mobile developers where we can share our learnings about everything latest in Tech, especially in Android Development, RxJava, Kotlin, Flutter, and overall mobile development in general.
Like what you read? Don’t forget to share this post on Facebook, Whatsapp, and LinkedIn.
If you want to stay updated with all the latest articles, subscribe to the weekly newsletter by entering your email address in the form on the top right section of this page.