Geek Culture
Published in

Geek Culture

Notifications in Android — PART 2

Notifications are important to get user attention. In the first part of this article, we talked about notifications, why we need them, how to create a notification, how to fire them, and their appearance on the device.

you can visit part 1 from here:

In this article, we will learn about:

  • Grouped notifications
  • Time-bound notifications
  • User action on buttons in the notification
  • Add a direct reply action
  • Retrieving user input data in the app

Grouped notifications

Let’s understand this with an example. In your WhatsApp, one day you are added to a new family group. Now when all your family members are sharing pictures of what they are doing, or family functions or puns. Your phone is bombarded with 100’s of notifications which is annoying.

To save your ass in Android 7, we got an update, Grouped notification. In which we can group redundant notification into a single notification, and when you expand it, can see each notification.

Create a group of notification

  • setGroup
    To create a notification group, create a unique key for the group, and then just call setGroup for every notification, you want in the group.
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
  • setSortKey()
    By default, notifications are sorted according to when they were posted, but you can change the order by calling setSortKey().
  • setGroupAlertBehavior()
    This method sets the group alert behavior for notification. Use this method to mute notification if alerts for this notification’s group should be handled by a different notification. This is, of course, applicable in group notification cases, otherwise, every single notification will send an alert to get user attention.
    There are 3 types of alert behavior:
  • setGroupSummary
    As discussed earlier group notification came in android 7. To support the older version we need to create an extra notification that acts as a summary.

Check the complete code below:

Time-bound notifications

In certain situations, your app might need user attention immediately like a phone call or alarm, when your app is in the background. To provide this behavior we need to do some setup.

Let’s take the example of a video call service in HealthifyMe App. When a coach wants to talk to the user, we are sending a video call notification

Step 1: Create notification Channel

We are setting the notification importance to high. And lock-screen visibility is also public, so it doesn’t matter your app is in the background or your device is locked, the user will get this notification on priority.

Step 2: Start ringtone and check Vibration
Now in video call case wee want a ringtone and vibration of the phone, this is optional according to your need.

Step 3: setFullScreenIntent()
This is optional as well, sometimes you don't want your notification to take full screen. In our case, we are making a video call so we want full screen.

Step 4: Display the notification to the user
When displaying your notification to the user, they can then choose to acknowledge or dismiss your app’s alert or reminder. For example, the user can choose whether to accept or reject an incoming phone call.

If your notification is an ongoing one, such as an incoming phone call, associate the notification with a foreground service. The following code snippet shows how to display a notification that’s associated with a foreground service:

startForeground(NOTIFICATION_ID_INCOMING_CALL, notification)

User action on buttons in the notification

Let’s take the same example where in full screen notification we have 2 buttons, one to accept call and another to decline call.

Step 1: Create a pending intent for decline call event. Where you are sending a broadcast with action as ACTION_DECLINE_CALL .

val declineCall = Intent().apply {
val declineCallIntent: PendingIntent =
PendingIntent.getBroadcast(this, 0, declineCall, PendingIntent.FLAG_UPDATE_CURRENT)

Step 2: Create pending intent for accept call

val acceptCall = Intent().apply {
val acceptCallIntent: PendingIntent =
PendingIntent.getBroadcast(this, 0, acceptCall, PendingIntent.FLAG_UPDATE_CURRENT)

Step 3: Add these as action while building a notification using addAction()

Step 4: Handle broadcast receiver
Wee are using broadcast here so things will run in background and nothing gets disturbed on main thread.

For more information about building a BroadcastReceiver to run background work, see the Broadcasts guide.

Stop the foreground service which you ran to show notification.

Add a direct reply action

Add a reply button

Step 1: Create an instance of remote builder.

private RemoteInput getReplyRemoteInput(Context context) {
// Key for the string that's delivered in the action's intent.
String replyLabel = context.getResources().getString(R.string.type_message);
return new RemoteInput.Builder(KEY_TEXT_REPLY)

Step 2: Create a pending intent for reply button.

private PendingIntent getReplyPendingIntent(Context context, Group group) {
Intent intent = new Intent(context, FirebaseSyncService.class);
intent.putExtra(FirebaseSyncService.ARG_GROUP, group);
return PendingIntent.getService(context,
intent, PendingIntent.FLAG_UPDATE_CURRENT);

Step 3: Attach the RemoteInput object to an action using addRemoteInput().

private NotificationCompat.Action getReplyAction(Context context, Group group) {
// Create the reply action and add the remote input.
return new NotificationCompat.Action.Builder(R.drawable.ic_send_white,
context.getString(R.string.reply_label), getReplyPendingIntent(context, group))

Step 4: Apply this action to notification

Retrive user message from reply

Step 1: Call RemoteInput.getResultsFromIntent()

private CharSequence getMessageText(Intent intent) {
if (intent == null)
return null;

Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(KEY_TEXT_REPLY);
return null;

Step 2: After you’ve processed the text, you must update the notification by calling NotificationManagerCompat.notify() with the same ID and tag (if used). This is necessary to hide direct reply UI and confirm to the user that their reply was received and processed correctly.

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)

// Issue the new notification.
NotificationManagerCompat.from(this).apply {
notificationManager.notify(notificationId, repliedNotification)


Notifications are double-edged swords. They can promote engagement but can also result in user annoyance. So getting it right is important for your overall experience. Let me know your thoughts about when we should and shouldn’t use them, and how they can improve user experience.


If you have any feedback please write me back at claps are really appreciated to help others find this article 😃 .



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store