How to Display Notifications in 2020


These days, most startup apps heavily rely on third-party libraries to send push notifications to a user, thus causing developers to usually not pay too much attention to Android notification changes.

For example, I was working on my side-project which sends a notification once the download is completed (was checking how DownloadManager works).

Back in 2016, you’d need to initialize NotificationManager and pending intent if notification contains custom action:

 1private lateinit var notificationManager: NotificationManager
 2private lateinit var pendingIntent: PendingIntent
 3
 4override fun onCreate(savedInstanceState: Bundle?) {
 5    ...
 6    notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
 7
 8    val intent = Intent(this, DetailActivity::class.java)
 9    pendingIntent =
10        PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
11}

And then after download is complete, you’d need to build the notification, include pendingIntent and send it to notification manager:

1val builder = NotificationCompat.Builder(context)
2    .setSmallIcon(R.drawable.ic_assistant_black_24dp)
3    .setContentTitle(getString(R.string.notification_title))
4    .setContentText(getString(R.string.notification_description))
5    .setPriority(NotificationCompat.PRIORITY_MAX)
6    .addAction(R.drawable.icon, getString(R.string.notification_button), pendingIntent)
7
8notificationManager.notify(1, builder.build())

After writing code and running the app, the notification wasn’t getting displayed. I thought maybe I was incorrectly implementing DownloadManager since I had just started playing around with it. So, after some debugging, I saw that the DownloadManager worked flawlessly and notificationBuilder did in-fact get called, but nothing was displayed πŸ€¦β€. The next obvious step was to google the issue. The first stackOverflow answer mentioned the following change in NotificationManager for Android O and above.

πŸ’‘So for the devices running on Android O and above, it’s required to create a channel for different kind of notifications where id, name and importance should be passed in constructor:

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            CHANNEL_ID,
            getString(R.string.notification_title),
            NotificationManager.IMPORTANCE_HIGH
        )
        notificationManager.createNotificationChannel(channel)
    }
}
The same channel id should be passed in notificationBuilder’s constructor alongside with context:
val builder = NotificationCompat.Builder(context, CHANNEL_ID)

Made the changes, the notification got displayed! But the action button didn’t work πŸ˜’. After another round of googling, I found out the addAction method in notificationBuilder now requires an Action class, which is basically a wrapper of the arguments addAction method used to accept.

The full code of sending and displaying notifications nowadays is below:

private lateinit var notificationManager: NotificationManager
private lateinit var action: NotificationCompat.Action

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            CHANNEL_ID,
            getString(R.string.notification_title),
            NotificationManager.IMPORTANCE_HIGH
        )
        notificationManager.createNotificationChannel(channel)
    }

    val intent = Intent(this, DetailActivity::class.java)
    val pendingIntent =
        PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    action = NotificationCompat.Action.Builder(
        R.drawable.icon, getString(R.string.notification_button), pendingIntent
    ).build()
}
...

private fun downloadCompleted() {
  val builder = NotificationCompat.Builder(context, CHANNEL_ID)
      .setSmallIcon(R.drawable.ic_assistant_black_24dp)
      .setContentTitle(getString(R.string.notification_title))
      .setContentText(getString(R.string.notification_description))
      .setPriority(NotificationCompat.PRIORITY_MAX)
      .addAction(action)

  notificationManager.notify(1, builder.build())
}

Hopefully, this article was helpful and stay tuned for another then-and-now article!


❀️ Was this post helpful?

If you like the article, help me keep writing and consider buying me a β˜• cup of coffee via


If you can't, do send some πŸ’– to @aida_isay and help to share this article.

Thank you for your support πŸ™Œ