Blog Infos
Author
Published
Topics
Published

In this article, we will discuss everything about notifications and show you how you can use different notifications with examples.

Topics to cover:
  1. Notification Channels
  2. Requesting Notification Permission
  3. Simple Notification
  4. Add Action in a Notification
  5. Add direct reply action in the Notification
  6. Add Progress Bar in Notification
  7. Starting an activity from a Notification
  8. Expanded Notification
  9. Time-sensitive Notification
  10. Notification Groups
  11. Notification Badge
  12. Custom Notification
  13. Bubbles
What is a Notification in android?

A notification is a message that android provides outside your app’s UI to provide information about reminders, alerts, communication from other people, or other timely information from your app.

Before starting, create a new Android Project.

You can check out the code here.

1. Notification Channels :

It is a representation of settings that applies to a group of notifications. You can consider it like different categories of notifications which you can configure separately. You can give different categories of notifications with different behavior.

Starting from Android 8.0(Oreo) you need to assign notifications with a notification channel.

Note: if you don’t provide a channel. you will not get notification from android 8 and above. so please make sure to provide a channel.

Let’s see how we create a notification channel:

  1. Create an object of NotificationChannel and give it a unique id, a name, and an importance level. You can pass a description text that will be shown in the system settings for that notification channel.
fun createNotificationChannel() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
"channel_id_1",
"channel1",
NotificationManager.IMPORTANCE_DEFAULT
)
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

make sure to guard it with version check as it is only applicable from Android 8 onwards.

2. Now register this channel using NotificationManger.

fun createNotificationChannel() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
"channel_id_1",
"channel1",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationChannel.description = "My first notification channel"
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(notificationChannel)
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

3. Now call this method in onCreate() as you should register Notification Channels before showing notifications to users.

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
...
}
createNotificationChannel()
}
view raw MainActivity.kt hosted with ❤ by GitHub

Now, run the app and check the settings of the app.

now, you see a notification channel has been created. If you click on the channel you will find different settings of that channel which I mentioned earlier.

So, the user can enable/disable sound, vibrations, etc.

2. Requesting Notification Permission :

Starting from Android 13 and above. you need to ask runtime permission to show a notification. You need to ask for POST_NOTIFICATIONS permission.

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

add this permission in your Manifest.xml file.

Now, ask this permission to enable.

I am using the accompanist library for easy handling of permission provided by google.

implementation "com.google.accompanist:accompanist-permissions:0.27.1"

Now, ask for permission

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NotificationsSampleAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
RequestNotificationPermission()
}
}
}
}
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@OptIn(ExperimentalPermissionsApi::class)
@Composable
private fun RequestNotificationPermission() {
val notificationPermissionState =
rememberPermissionState(android.Manifest.permission.POST_NOTIFICATIONS)
if (notificationPermissionState.status.isGranted) {
Text("Notification permission Granted")
} else {
Column {
val textToShow = if (notificationPermissionState.status.shouldShowRationale) {
"The notification permission is important for this app. Please grant the permission."
} else {
"notifications not available"
}
Text(textToShow)
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = { notificationPermissionState.launchPermissionRequest() }) {
Text("Request permission")
}
}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

You, have to check for the Android version as you should show this for Android 13 and above. for below API 33, it is always granted.

Now, click on the button

Accept it otherwise you can send notifications to the user.

There are a few exemptions where you don’t need to ask this permission;

  1. If it is related to Media Sessions.
  2. If your app is configured to self-manage phone calls
3. Simple Notification :

First, I will show you the anatomy of a notification.

  1. Small icon: This is required and set with setSmallIcon().
  2. App name: This is provided by the system.
  3. Timestamp: This is provided by the system but you can override it with setWhen() or hide it with setShowWhen(false).
  4. Large icon: This is optional (usually used only for contact photos; do not use it for your app icon) and set with setLargeIcon().
  5. Title: This is optional and set with setContentTitle().
  6. Text: This is optional and set with setContentText().

Let’s create a simple notification

Step 1: Make sure you are able to import NotificationCompat. if not please add this dependency.

def core_version = "1.6.0"
dependencies {
    implementation "androidx.core:core:$core_version"
}

Step 2: Not you need to create NotificationCompat Builder which helps us to create a notification by adding different fields which are required.

Note: NotificationCompat is used for accessing notification features with backward compatibility. so that you don’t need to add version checks.

val builder = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(com.google.accompanist.permissions.R.drawable.notification_bg)
.setContentTitle(textTitle)
.setContentText(textContent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
view raw Notification.kt hosted with ❤ by GitHub

You need to have the channel id with you. so that notifications can fall into that particular channel which is required from Android 8 and above. you need to set the priority of notifications for Android 7 and below.

Step 3: Now, you need to hand over this notification to the Android system as showing a notification is not part of your app. Make sure to pass a unique notification id for that notification.

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

You are done

You will see a notification like this.

Updating a Notification:

To update this notification after you’ve issued it, call NotificationManagerCompat.notify() again, passing it a notification with the same ID you used previously. If the previous notification has been dismissed, a new notification is created instead.

Remove a notification:

You can add setAutoCancel to true or use NotificationManagerCompat and call cancel() with notification id

Set lock screen visibility:

To control the level of detail visible in the notification from the lock screen.

you need to call setVisibility() and for Android 8 and above

notificationChannel.lockscreenVisibility = Notification.VISIBILITY_SECRET

There are types of VISIBILITY

  • VISIBILITY_PUBLIC that show the notification’s full content.
  • VISIBILITY_SECRET doesn’t show any part of this notification on the lock screen.
  • VISIBILITY_PRIVATE shows basic information, such as the notification’s icon and the content title, but hides the notification’s full content.
4. Add Action in a Notification :

You can add up to 3 actions in a notification.

Let’s see how we can add an action

Step 1: You need a PendingIntent that will contain an Intent it can be an activity, broadcast receiver, etc.

private fun addAction(context: Context,action: String): PendingIntent {
val intent = Intent(context, MyBroadCastReceiver::class.java)
intent.action = action
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
view raw Notification.kt hosted with ❤ by GitHub

I have created a BroadCastReceiver and registered it in Manifest.xml

<receiver android:name=".broadcast_receiver.MyBroadCastReceiver"/>

Step 2: Create MyBroadCastReceiver.kt

class MyBroadCastReceiver: BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
val actionString = p1?.action
Log.i("MyBroadCastReceiver",actionString?:"")
}
}

Step 3: call addAction() on NotificationCompat Builder

builder.addAction(R.drawable.ic_launcher_background ,"Click",addAction(context,"Click Action"))

Now, check the output

When You click it you will get a log with the action string received.

5. Add direct reply action in the Notification :

You might have seen direct replies in Chat Apps where you can add any reply to a conversation. we will be creating that direct reply action.

Step 1: You need to create a RemoteInput. it is used to take response from a user as this input is not part of your app which is why it is Remote like RemoteViews.

private fun createRemoteInput(): RemoteInput{
return RemoteInput.Builder(KEY_TEXT_REPLY).run {
setLabel("Add Reply")
build()
}
}
view raw Notification.kt hosted with ❤ by GitHub

You need to pass a String Key which we will use later to get the response.

Step 2: Now we will create a PendingIntent as we did above.

val replyIntent = Intent(context, MyBroadCastReceiver::class.java)
replyIntent.action = "reply_action"
val replyPendingIntent: PendingIntent =
PendingIntent.getBroadcast(context,
1234,
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
)
view raw Notification.kt hosted with ❤ by GitHub

Step 3: Now create Action Builder which will help us to create a relation between the RemoteInput and PendingIntent.

NotificationCompat.Action.Builder(
        androidx.core.R.drawable.notification_action_background,
        "Reply", replyPendingIntent)
        .addRemoteInput(createRemoteInput())
        .build()

Step 4: Add action to the notification

.addAction(replyAction(context))

Let’s see the output

You can see the RemoteInput.

now, when you click send icon. it will keep loading as we have to respond to this response.

Step 5: Now, we will handle fetching reply text and update notification.

private fun getMessageText(intent: Intent): CharSequence? {
return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(Notification.KEY_TEXT_REPLY)
}

to get the reply you need to pass the broadcast receiver’s intent and fetch the text.

override fun onReceive(p0: Context?, p1: Intent?) {
val actionString = p1?.action
if(actionString == "reply_action"){
val repliedNotification = android.app.Notification.Builder(p0!!, NotificationChannels.CHANNEL1)
.setSmallIcon(androidx.core.R.drawable.notification_bg_low_normal)
.setContentText(getMessageText(p1))
.build()
NotificationManagerCompat.from(p0).apply {
this.notify(12313, repliedNotification)
}
}
}

here we are fetching the message and updating the same notification using id.

Now, once you click send icon. it will update the notification.

6. Add Progress Bar in Notification :

Now, We will work on showing progress in Notification. You might have seen this on your phone.

Step 1: Create a NotificationBuilder

val builder = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1).apply {
setContentTitle("Picture Download")
setContentText("Download in progress")
setSmallIcon(com.google.accompanist.permissions.R.drawable.notification_bg)
priority = NotificationCompat.PRIORITY_LOW
}
view raw Notification.kt hosted with ❤ by GitHub

Step 2: In builder, you need to setProgress() with the maximum and current progress of the task if you don’t know the progress of the task you can use an indeterminate progress bar.

val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 0
val notificationManagerCompat = NotificationManagerCompat.from(context)
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
notificationManagerCompat.notify(1234, builder.build())
CoroutineScope(Dispatchers.Default).launch {
for (i in PROGRESS_CURRENT..PROGRESS_MAX step 10) {
builder.setProgress(PROGRESS_MAX, i, false)
notificationManagerCompat.notify(1234, builder.build());
delay(1000)
}
delay(10000)
builder.setContentText("Download complete")
.setProgress(0, 0, false)
notificationManagerCompat.notify(1234, builder.build())
}
view raw Notification.kt hosted with ❤ by GitHub

so, to update progress. you need to run a background task and update the progress.

if you call the method. you will see this output.

If you want to show an indeterminate progress bar just call

setProgress(0,0,true)

7. Starting an activity from a Notification :

So, here we will see how we can start an activity with a proper navigation experience for the user. To preserve this navigation experience, you should start the activity with a fresh task. It also depends on the activity you show on the tap of notification.

Regular activity:

This is an activity that exists as a part of your app’s normal UX flow. So when the user arrives in the activity from the notification, the new task should include a complete back stack, allowing them to press Back and navigate up the app hierarchy.

Special activity:

The user only sees this activity if it’s started from a notification. In a sense, this activity extends the notification UI by providing information that would be hard to display in the notification itself. So this activity does not need a back stack. It is specially created for Notification.

First, we take a look at regular activity pending intent.

TaskStackBuilder: it provides a way to obey the correct conventions around cross-task navigation.

To start a “regular activity” from your notification, set up the PendingIntent using TaskStackBuilder so that it creates a new back stack as follows.

Step 1: Define the natural hierarchy for your activities by adding the android:parentActivityName attribute to each <activity> element in your app manifest file.

<activity
android:name=".MainActivity2"
android:exported="false"
android:label="@string/title_activity_main2"
android:parentActivityName=".MainActivity"
android:theme="@style/Theme.NotificationSampleApp">
<meta-data
android:name="android.app.lib_name"
android:value="" />
view raw manifest.xml hosted with ❤ by GitHub

Step 2: To start an activity that includes a back stack of activities, you need to create an instance of TaskStackBuilder and call addNextIntentWithParentStack(), passing it the Intent for the activity, you want to start.

val resultIntent = Intent(context, MainActivity2::class.java)
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(resultIntent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
view raw Notification.kt hosted with ❤ by GitHub

Step 3: Create notification builder and setContentIntent with resultIntent.

fun createNotificationWithBackStack(context: Context){
val resultIntent = Intent(context, MainActivity2::class.java)
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(resultIntent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
val builder = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(com.google.accompanist.permissions.R.drawable.notification_bg)
.setContentTitle("textTitle")
.setContentIntent(resultPendingIntent)
.setContentText("textContent")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(VISIBILITY_SECRET)
.addAction(
R.drawable.ic_launcher_background,
"Click",
addAction(context, "click_action")
)
.addAction(replyAction(context))
.setAutoCancel(true)
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.notify(12345, builder.build())
}
view raw Notification.kt hosted with ❤ by GitHub

Here, When you tap on the notification. you can see no new task has been created but now for Special activities you will see a new task will there.

Let’s start opening a special activity

Step 1: Go to Manifest.xml and add this in MainActivity2.

android:taskAffinity=""
android:excludeFromRecents="true"

task affinity combined with ACTIVITY_NEW_TASK will help not to open activity in an existing task.

excludeFromRecents: this will help you not to find this recent UI after navigating back.

Step 2: Now, create a PendingIntent with intent having flag ACTIVITY_NEW_TASK.

val notifyIntent = Intent(context, MainActivity2::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val notifyPendingIntent = PendingIntent.getActivity(
    context, 0, notifyIntent,
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

Step 3: notify

fun createNotificationWithSpecialActivity(context: Context){
val notifyIntent = Intent(context, MainActivity2::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val notifyPendingIntent = PendingIntent.getActivity(
context, 0, notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val builder = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(com.google.accompanist.permissions.R.drawable.notification_bg)
.setContentTitle("textTitle")
.setContentIntent(notifyPendingIntent)
.setContentText("textContent")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(VISIBILITY_SECRET)
.addAction(
R.drawable.ic_launcher_background,
"Click",
addAction(context, "click_action")
)
.addAction(replyAction(context))
.setAutoCancel(true)
with(NotificationManagerCompat.from(context)) {
notify(123456, builder.build())
}
}
view raw Notification.kt hosted with ❤ by GitHub

So, now you can see the new task and once you press back you will not see the new task in recent.

Job Offers

Job Offers


    Senior Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now

    Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now

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

8. Expanded Notification :

If you think your app notification should show more information than Simple Notification. Then we can use Expanded Notification. It is not a new type of notification we will just add style and a few more settings to the notification.

Now, to add a large image in a notification follow this

fun createNotificationWithLargeIcon(context: Context){
val icon = BitmapFactory.decodeResource(
context.resources,
R.drawable.aquarium
)
val notification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(R.drawable.desk)
.setContentTitle("imageTitle")
.setContentText("imageDescription")
.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(icon))
.build()
with(NotificationManagerCompat.from(context)) {
notify(1234567, notification)
}
}
view raw Notification.kt hosted with ❤ by GitHub

Here, I am using a few images. you can use yours.

You just have to add a style name BigPictureStyle() and add your bitmap.

you will see something like this

you can add this icon as a thumbnail like this

val notification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
    .setSmallIcon(R.drawable.desk)
    .setContentTitle("imageTitle")
    .setContentText("imageDescription")
    .setStyle(NotificationCompat.BigPictureStyle()
        .bigPicture(icon).bigLargeIcon(null))
    .setLargeIcon(icon)
    .build()

bigLargIcon is null because we don’t want to see this thumbnail in expanded form.

You can add Large Text as well

fun createNotificationWithLargeText(context: Context){
val icon = BitmapFactory.decodeResource(
context.resources,
R.drawable.aquarium
)
val notification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(R.drawable.desk)
.setContentTitle("Joe")
.setContentText("Lending Money")
.setLargeIcon(icon)
.setStyle(NotificationCompat.BigTextStyle()
.bigText("long long long long long long long long long long text "))
.build()
with(NotificationManagerCompat.from(context)) {
notify(12544567, notification)
}
}
view raw Notification.kt hosted with ❤ by GitHub

Next up is, showing conversation text.

fun createNotificationWithConversationText(context: Context){
val message1 = NotificationCompat.MessagingStyle.Message("Hi, there",
12345L,
"Martin")
val message2 = NotificationCompat.MessagingStyle.Message("Hello",
12345L,
"You")
val notification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(R.drawable.desk)
.setStyle(NotificationCompat.MessagingStyle("Arun")
.addMessage(message1)
.addMessage(message2))
.build()
with(NotificationManagerCompat.from(context)) {
notify(12544567, notification)
}
}
view raw Notification.kt hosted with ❤ by GitHub

Simple, use MessageStyle and call addMessage() with the message object.

One last is adding media controls as we see in music player apps.

fun createNotificationWithMediaControl(context: Context){
val icon = BitmapFactory.decodeResource(
context.resources,
R.drawable.aquarium
)
val mediaSession = MediaSessionCompat(context,"myTag")
val notification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.desk)
.addAction(R.drawable.previous, "Previous", null)
.addAction(R.drawable.pause, "Pause", null)
.addAction(R.drawable.next, "Next", null)
.setStyle(androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0,1,2)
.setMediaSession(mediaSession.sessionToken))
.setContentTitle("music_land")
.setContentText("Creative Awesome Band")
.setLargeIcon(icon)
.build()
with(NotificationManagerCompat.from(context)) {
notify(12544567, notification)
}
}
view raw Notification.kt hosted with ❤ by GitHub

we need to add this dependency

implementation "androidx.media:media:1.6.0"

So, here as you can see we have added 3 actions in the expanded and collapsed forms of notification.

Simply, add actions as we do in notifications but when adding actions in the collapsed form you use MediaStyle().

For collapsed form, you call setActionsInCompatView() and setMediaSessionToken.

9. Time-sensitive Notification :

When you want to get the user’s attention for some urgent message. you should show time-sensitive notifications.

Step 1: For Android 8 and above you need to set notification channel priority as HIGH and below set notification of priority.

val notificationChannel = NotificationChannel(
    CHANNEL1,
    "channel1",
    NotificationManager.IMPORTANCE_HIGH
)

Step 2: Everything is the same except for one thing

fun createFullScreenIntentNotification(context: Context){
val fullScreenIntent = Intent(context, MainActivity2::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(context, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
val notificationBuilder =
NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(R.drawable.desk)
.setContentTitle("Incoming call")
.setContentText("+9178458787XXX")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(fullScreenPendingIntent, true)
val incomingCallNotification = notificationBuilder.build()
with(NotificationManagerCompat.from(context)) {
notify(1445457, incomingCallNotification)
}
}
view raw Notification.kt hosted with ❤ by GitHub

just setFullScreenIntent instead of setContentIntent.

But if you want to open full-screen intent. use this code for API 27 and above.

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
}
...
}

and for Api 26 and below

val flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_FULLSCREEN
window.addFlags(flags)

You will see a heads-up notification.

If you lock the screen. you will see your activity opens

10. Notification Groups :

You would have seen this on your phone.

Grouping notifications is very common in new android phones.

If your app sends notifications. you can group them and add a summary notification to them.

you can do this as follows:

Step 1: Create a Notification as always by adding setGroup().setGroup will help to associate similar notifications in a group that you want to be grouped.

val newMessageNotification1 = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
    .setSmallIcon(R.drawable.email)
    .setContentTitle("Arun")
    .setContentText("Ooo")
    .setLargeIcon(icon)
    .setGroup(GROUP_KEY_WORK_EMAIL)
    .build()

Step 2: you need to create a summary notification that will help the user to get an idea about the child notifications.

val summaryNotification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setContentTitle("Summary")
.setContentText("Two new messages")
.setSmallIcon(R.drawable.email)
.setStyle(NotificationCompat.InboxStyle()
.addLine("Arun Ooo")
.addLine("Alex Outside")
.setBigContentTitle("2 new messages")
.setSummaryText("arun@example.com"))
.setGroup(GROUP_KEY_WORK_EMAIL)
.setGroupSummary(true)
.build()
view raw Notification.kt hosted with ❤ by GitHub

just add the same group string and setGroupSummary to true.

You need to add InboxStyle to support API 24 and below.

See, this is a summary notification. if you expand it you will see this.

11. Notification Badge :

From Android 8 and above android phone now supports notifications badges.

These dots appear by default in launcher apps that support them and there’s nothing your app needs to do. However, there might be situations in which you don’t want the notification dot to appear or you want to control exactly which notifications appear there.

currently, you see a badge.

Disabling a notification badge.

notificationChannel.setShowBadge(false)

Modify Notification Count:

you can change the message count by:

notification.setNumber(messageCount)
12. Custom Notification :

You can create your custom layout notifications but it is not recommended as your app notification will differ from other notifications.

But still to show follow this:

Step 1: create your notification layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_gravity="center"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="TITLE"
android:id="@+id/notification_title"
style="@style/TextAppearance.Compat.Notification.Title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="TEXT"
android:id="@+id/notification_text"
style="@style/TextAppearance.Compat.Notification.Title" />
</LinearLayout>

Step 2: Create an instance of remote view as showing your notification layout is not your app job.

fun createCustomNotification(context: Context){
val notificationLayout = RemoteViews(context.packageName, R.layout.notification_small)
val notificationLayoutExpanded = RemoteViews(context.packageName, R.layout.notification_small)
val customNotification = NotificationCompat.Builder(context, NotificationChannels.CHANNEL1)
.setSmallIcon(R.drawable.notification_icon)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutExpanded)
.build()
with(NotificationManagerCompat.from(context)) {
notify(1445457, customNotification)
}
}
view raw Notification.kt hosted with ❤ by GitHub

use DecoratedCustomViewStyle() and setCustomContentView() with your remote view.

12. Bubbles :

Finally, we have come to the last part.

This is a new feature in Android 11.

Using this feature you can communicate with people in a floating window.

Let’s see how we can develop this:

Step 1: First, you need to create an instance of Person.

val person = androidx.core.app.Person.Builder()
    .setName(simpleMessage.sender)
    .setIcon(icon)
    .setImportant(true)
    .build()

Step 2: Now, create an instance of BubbleMetadata.

BubbleMetadata is used to encapsulate the information needed to display a notification as a bubble.

you can configure various properties for when the bubble is expanded.

private fun createBubbleMetadata(
contentUri: Uri,
icon: IconCompat
): NotificationCompat.BubbleMetadata {
val bubbleIntent =
PendingIntent.getActivity(
context,
REQUEST_BUBBLE,
Intent(context, MainActivity3::class.java)
.setAction(Intent.ACTION_VIEW)
.setData(contentUri),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
)
val builder = NotificationCompat.BubbleMetadata.Builder(bubbleIntent, icon)
return builder
.setDesiredHeightResId(R.dimen.bubble_height)
.setAutoExpandBubble(true)
.setSuppressNotification(true)
.build()
}
view raw Notification.kt hosted with ❤ by GitHub

here as you can see we need the pendingIntent and icon they can’t be null for BubbleMetadata.you can set the height of the floating window.

Step 3: Create an instance of ShotcutInfoCompat.

ShotcutInfoCompat: this helps you access the features of ShortcutInfo.

A shortcut is basically an action that your app can perform and these shortcuts can be available in the phone launcher.

private fun createDynamicShortcut(
message: SimpleMessage,
icon: IconCompat,
person: androidx.core.app.Person
): ShortcutInfoCompat {
return ShortcutInfoCompat.Builder(context, message.id.toString())
.setLongLived(true)
.setIntent(
Intent(context, MainActivity3::class.java)
.setAction(Intent.ACTION_VIEW)
.setData(createContentUri(message.text))
)
.setShortLabel(message.sender)
.setIcon(icon)
.setPerson(person)
.build()
}
view raw Notification.kt hosted with ❤ by GitHub

Step 4: Now you need to publish this shortcut via ShortcutManager.

private fun addDynamicShortcut(shortcut: ShortcutInfo) {
if (atLeastAndroid11()) {
shortcutManager.pushDynamicShortcut(shortcut)
} else {
shortcutManager.addDynamicShortcuts(listOf(shortcut))
}
}
view raw Notification.kt hosted with ❤ by GitHub

Step 5: Now, create a notification builder and pass bubbleMetadata and shortcut id. you need to take care of backward compatibility as well

private fun getNotificationBuilder(): NotificationCompat.Builder {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder(context, CHANNEL_NEW_BUBBLE)
} else {
NotificationCompat.Builder(context)
}
}
view raw Notification.kt hosted with ❤ by GitHub
with(builder) {
setContentTitle(
context.resources.getString(
R.string.message_from,
simpleMessage.sender
)
)
setSmallIcon(R.drawable.ic_stat_notification)
setCategory(android.app.Notification.CATEGORY_MESSAGE)
setContentIntent(
PendingIntent.getActivity(
context,
REQUEST_CONTENT,
Intent(context, MainActivity3::class.java)
.setAction(Intent.ACTION_VIEW)
.setData(contentUri),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
)
)
setShowWhen(true)
}
view raw Notification.kt hosted with ❤ by GitHub

Step 6: call the method by passing data.

BubbleNotificationView(context).showNotification(
    Message(
        123,
        "Arun",
        "Hello",
        R.drawable.ic_base_person
    )
)

Step 7: Make sure to add these properties resizeable and embedded. On devices running Android 10, notifications are not shown as bubbles unless you explicitly set documentLaunchMode to "always"

<activity
android:name=".MainActivity3"
android:allowEmbedded="true"
android:resizeableActivity="true"
android:documentLaunchMode="always"
android:theme="@style/Theme.AppCompat.Light"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
view raw manifest.xml hosted with ❤ by GitHub

Now, if you run the app.

https://gfycat.com/achingshorttermhoki

Now, we have come to the end of the article.

You can check out the code here.

Thank You for reading.

Thanks to Mario Sanoguera de Lorenzo

This article was originally published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
Notifications are a very important part of Android apps, showing relevant information, informing when…
READ MORE
blog
Icons are a crucial part of every app and software. They are more than…
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