Custom Notification using Work Manager for Android

Ali Baha-Abadi
ProAndroidDev
Published in
4 min readFeb 28, 2022

--

By Ali Baha

Notifications provide short, timely information about events in your app while it’s not in use. This article shows you how to fetch data that includes your notification contents every 15 minutes using Work Manager and create a notification to show.

Photo by Volodymyr Hryshchenko on Unsplash

We have to do 3 steps to send the notification, LET’S DO IT.

1. Create a notification channel

First of all, you need to add the Supportive library:

dependencies {    def core_version = "1.6.0"    def work_version = "2.7.1"    implementation "androidx.core:core:$core_version"    implementation "androidx.work:work-runtime-ktx:$work_version"    implementation 'androidx.hilt:hilt-work:1.0.0'

kapt 'androidx.hilt:hilt-compiler:1.0.0'
}

Then for sending notifications we need to create a channel. We can create different channels to separate notification types, and users can turn them on and off as they want. For instance, sometimes they don’t need social notifications but need to be aware of the application’s latest news notifications.

To create a channel, you just need to do this as Google says:

private fun createNotificationChannel() {    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.channel_name)
val descriptionText = getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
// Register the channel with the system
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}

You may wonder what the ‘importance’ parameter is. This parameter determines how to interrupt the user for any notification that belongs to this channel. For more information about what the different levels mean, read about notification importance levels.

2. Create a worker

We need to fetch data from the server to get notifications if they are available. We can create a function and call it every 15 minutes, but wait! what if users leave the app? Then our application is in the background or even killed, So, how do we fetch data in those situations?! That’s where the Work Manager comes in. Let’s see how Work Manager helps us fetch the data while the app is in the background.

First, create an Instance of Work Manager.

val workManager = WorkManager.getInstance(application.applicationContext!!)

Second, set constraints.

val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(false)
.build()

Third, set data to pass to the worker.

val data = Data.Builder()
data.putString(ENDPOINT_REQUEST, endPoint)

Then, create the work.

val work = PeriodicWorkRequestBuilder<FetchDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.setInputData(data.build())
.build()

As we want to fetch data every 15 minutes from the server we should use PeriodicWorkRequestBuilder.

Finally, enqueue worker

workManager
.enqueue(work)

Wait, where do we call our function to fetch data? That’s fairly simple: We put it in a class called ‘FetchDataWorker’. Our class should extend the Worker class to override the doWork() method. Rather than extending Worker, we extend CoroutineWorker to call suspend functions, as we want to collect data in a Flow. (read more here)

@HiltWorker
class FetchDataWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
private val notificationViewModel: NotificationViewModel
) : CoroutineWorker(appContext, workerParams) {

override suspend fun doWork(): Result {
val endPoint = inputData.getString(NotificationCore.ENDPOINT_REQUEST)

if (endPoint != null) {
getData(endPoint)
}

val outputData = Data.Builder()
.putString(NotificationCore.NOTIFICATION_DATA, "Hi Da")
.build()

return Result.success(outputData)
}

You know what? I LOVE HILT. Why? Because it makes life easier. We need to call a function from notificationViewModel and we inject it into our worker class using hilt. Personally, I don’t even want to think about using the view model without the hilt in our worker class. Make sure to read more here.

3. Create a notification

Wow, we are ready to send notifications, look’s amazing.

In getData(endPoint) function we fetched data, our data should have three important attributes:

Id, title, and content.

This is how we send notifications.

val notifyIntent = Intent(this, ResultActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
notifyIntent.putExtra(NOTIFICATION_EXTRA, true)
notifyIntent.putExtra(NOTIFICATION_ID, notificationId)
val notifyPendingIntent = PendingIntent.getActivity(
this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT
)

val builder = NotificationCompat
.Builder(context, Channel_ID_DEFAULT)
.setSmallIcon(notificationImage)
.setContentTitle(notificationTitle)
.setContentText(notificationContent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(notifyPendingIntent)
.setAutoCancel(true)

with(NotificationManagerCompat.from(context)) {
notify(notificationId, builder.build())
}

We create a PendingIntent to start an activity when the user clicks on the notification. We can pass value using putExtra to our intent. To get extras when a notification is clicked, do this in your activity:

override fun onResume() {
super.onResume()
checkIntent(intent)
}

private fun checkIntent(intent: Intent?) {
intent?.let {
if (it.hasExtra(NotificationCore.NOTIFICATION_EXTRA)) {

val id = it.getStringExtra(NotificationCore.NOTIFICATION_ID)

}
}
}
}

Done. :)

My Notification Module Repository In Github

Don’t forget to give my repo a star and clap this article if you found it useful and I’ll be thankful if you share this article with your friends.

Which one do you prefer?

Also, there are other ways to send notifications like Firebase or OneSignal, but Which one do you prefer? Your own custom notifications library or third-party libraries?

--

--