Blog Infos
Author
Published
Topics
,
Published

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.

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)

Job Offers

Job Offers


    Mobile Engineer

    OLX Group
    Remote, Portugal, Spain, Romania, Poland
    • Full Time
    apply now

    Kotlin Multiplatform Mobile Developer

    Touchlab
    Remote
    • Full Time
    apply now

    Senior Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now
Load more listings

OUR VIDEO RECOMMENDATION

, ,

From Scoped Storage to Photo Picker: Everything to know about Storage

Persistence is a core element of every mobile app. Android provides different APIs to access or expose files with different tradeoffs.
Watch Video

From Scoped Storage to Photo Picker: Everything to know about Storage

Yacine Rezgui
Android developer advocate
Google

From Scoped Storage to Photo Picker: Everything to know about Storage

Yacine Rezgui
Android developer ad ...
Google

From Scoped Storage to Photo Picker: Everything to know about Storage

Yacine Rezgui
Android developer advocat ...
Google

Jobs

@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?

This article was originally published on proandroiddev.com on February 28, 2022

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
Modern mobile applications are already quite serious enterprise projects that are developed by hundreds…
READ MORE
blog
Ask yourself a fairly standard question for any interview to fill an Android position:…
READ MORE
blog
Hey Android Devs, in this article we will go through a step by step…
READ MORE
blog
In this article, we will learn about WorkManager best practices including performant component initialization…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu