WorkManager and push notifications
This is another article in the series of articles about Android Jetpack.
I created this design pattern for a professional project I was involved in. I am not using it in my GitHub profile.
Definitions
In this article I will use the terms ‘push notification’ and ‘notification’ interchangeably, as this is really the same things.
When Firebase Cloud Messaging is meant, I will make it explicit in the article.
WorkManager
To add WokrManager to your project, please refer to Jetpack documentation. In this article a basic understanding of Jetpack is assumed.
Creating notification channels
I use one extention function to create all notification channels:
You can call it from onCreate
function inside your Application
class:
Because it is an extention function, an instance of your application Context
will be automatically passed to it.
If you want to use a more advanced design pattern to initialize your application, together with dependency retrieval, you can create an instance of the class Bootstrap
I explain in the article ‘Testing with dependency retrieval’ in this blog.
This is the part of your Bootstrap
class that calls the function creating the channels:
The function creating each individual channel is private within the same file that defines the function createNotificationChannels
, so you can’t create each channel individually, you can only create them simultaneously. This is one of such functions:
This is the function that creates every channel:
Worker
This is the Worker
class that shows the notification:
Context
will be supplied by WorkManager itself, and params
, which are also supplied my WorkManager, can be ignored in case of hardcoded messages, and are used in this article only for Firebase Cloud Messaging.
The extension function notify()
, used above, needs to be written by yourself. You can use your favourite implementation of the code that creates notifications, but it will probably similar to the extenion functions that create the channels, that are explained above.
For exact description of Worker
as well as WorkManager
, please see Jetpack documentation. This article just describes how to use WorkManager
specifically for notifications, assuming that you already know the basics of architecture components of Android Jetpack.
To implement specific Worker
for every particular notification, just extend the abstract class defined above, like this:
Scheduling
This section will describe how to schedule a notification for some time in the future (here: 24 hors), how to test it manually, by reducing the time to just a couple of minutes in debug builds, and how to prevent the notification from showing during the “do not disturb” hours.
To schedule one notification, you call this extention function on your Fragment
:
This in turn calls this extension function on the Context
. It expent a type parameter that extents the abstract class AbstractNotificationWorker
explained above:
The extention function delay
used above requires an extra explanation, at it contains the code that decides if the code is run after the required time measured in hours (in production builds), or in minutes (in debug builds), and prevent displaying notifications at nighttime.
The above function calculates by how many hours the notification needs to be shifted so that it does not appear between 23:00 and 7:00. The effect of the shift will be that the notification will be then shifted to some time after 7:00, but before 8:00.
It then checks whether this is a debug build, or one of the debug flavors. If so, then instead of waiting several hours for the notification to show up, it will wait the same amoutd of minutes. (But either way it will not show up at nighttime).
Canceling the scheduled notifications
These couple of functions cancel the scheduled notifications:
Firebase Cloud Messaging
This section will explain how to use design patterns already described above in conjunction with Firebase Cloud Messaging.
If you want to create a separate notification channel for this, creation of notification channels is also desrbibed in the preceding sections.
To handle Firebase Cloud Messaging you need to set up a service in your AndroidManifest.xml
:
Please note that this is the only time you have to set up a Service
in order to use notifications. All other times notificiations have been handled by WorkManager, and WorkManager
will be used for handling cloud messaging as well, but this time the notification will be scheduled from a Service
.
This is the body of the Service
:
You do not need to use the Service
’s Context
to display the notification, as WorkManager
provides its own Context
.
This is the function scheduling the notification. It works similar to the way described above:
The difference is that now it needs to set up InputData
, as now it doesn’t use hardcoded notification text. All other notifications described previously in this article used hardcoded text:
The message is retrieved using the code params.inputData.getString(MESSAGE)!!
. Setting targetActivity
to null will inform the AbstractNotificationWorker
that it doesn’t have to set any target activity in the message activity it is going to display, but if you set here any oter value, you will be driven to that activity (by a PendingIntent
) when you tap on the notification.
Because of the way I wrote the code in this section, cloud messages will be displayed with but a 10 seconds delay, regardless of whether it is day or night, but you can just as well use the code explained previously to create an extra delay when cloud messages are received at nighttime.
Donations
If you’ve enjoyed this article, consider donating some bitcoin: bc1qncxh5xs6erq6w4qz3a7xl7f50agrgn3w58dsfp (you can also look at donations page).