A fusion between WorkManager and AlarmManager

Stavro Xhardha
ProAndroidDev
Published in
3 min readJul 8, 2019

--

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.

--

--