A fusion between WorkManager and AlarmManager
Android’s WorkManager
has been around for a while. However my own expectations about it were a little higher. I wished that the WorkManager
could fire events at exact timing. But since it was made to respect doze mode, I should respect that too. That means that if the phone is idle, the WorkManager
won’t run.
Let’s explore my case:
Once the user logs into my app, I need to schedule five alarms for him. But the alarm times come from a server and not locally. So basically I need some background work to do:
Sync timing -> Save to database -> Schedule Alarms. (btw on the time alarm will fire, it’s just a notification to be shown)
Now this has to happen every day at 00:01. The data coming from the server hold the alarm timings for a year, but certainly I can’t schedule alarms from current moment till the end of the year. It would drain phones battery. So I need to start a WorkManager
to save data to my local Room database and after that I need to repeatedly schedule alarms every day.
On with the show:
First of all, if anyone is curious why I chose WorkManager
over JobScheduler
or even BroadcastReceiver
:
1- Don’t have to register anything in the Manifest file.
2- Don’t have to worry about internet connection, phone reboot, etc.
3- I faced lots of deprecated methods and constants without it.
Let’s start:
So the WorkManager
has a few things to set up. Since I will get data from API, I need my worker to be started if and only if there is internet connection which is specified by the setRequiredNetworkType(NetworkType.CONNECTED)
method in the Constraint.Builder()
. After that I need to specify how many times will my worker run. On my case there is no comment needed looking at the name OneTimeWorkRequestBuilder
which has a worker of mine. After setting my defined constraints I can start my DataSyncWorker
.
Let’s check the class now:
Since I love coroutines and I am using them everywhere, I am using the WorkManager
by extending CoroutineWorker
. So the method where all my sync happens is named doWork
which btw is a suspending method handled by the Android framework itself.
And now, let’s jump into my OfflineScheduler
:
Looks like I’m done scheduling my notifications at current timing for today and also tomorrows timing alarm, which will schedule other alarms:
Once the alarm has been set, Android “waits” until the time comes and brings my code here:
And another one which was scheduled for the midnight, which basically will trigger my OfflineScheduler
code again:
And it will fire and fire until the end of time 💪.
There are two more things:
First of all, for the classes extending BroadCastReceiver
to work, need to be registered to Manifest
file.
And second of all how do I schedule my notifications when the phone reboots? 👀
So I made another Receiver
which only needs to be registered on the Manifest
and nothing more:
Now this one needs a small modification achieved by a boolean flag. What happens if my worker has never started and I request to schedule local data (which never arrived)? A total disaster.
And pretty much that’s it. That’s the best combination I could do to solve my case, and if you have other suggestions about my case, feel free to comment.