Display Android notifications with a contact image on the left, like messaging apps
Android SDK
Recently, I had to work on a messaging app and I struggled to implement notifications with a contact image on the left, like any other messaging apps do, for Android versions starting from Android 11 (API 30).
A lot of documentation on this subject is not up to date.
When I read an updated one, it talked about using Shortcut
API to get a contact image on the left, so I thought it was not what I looked for, but spoil: it was!
In this article, we will look at all the steps to follow to implement a messaging-style notification to get the following result:
Before looking at the specific code to display a notification the way we want, we will sum up the basic way to display a notification.
For anyone having in mind the basic code to do that, you can jump to the next section.
To make our life easier, we will add the dependency on the AndroidX SDK Core
that provides Compat
classes and methods to avoid adding Android version checks in several places in our code.
We will display a notification with the following configuration:
- A title: The first line of the notification, displayed in bold. This information is optional.
- A text: The second line of the notification. The displayed string can take 2 lines before being truncated. This information is optional.
- A colored small icon. A small icon is mandatory otherwise your app will crash with an
IllegalArgumentException: Invalid notification (no valid small icon)
. AutoCancel
set totrue
will make the notification automatically disappear after the user has clicked on it.- Setting a category allows the system to determine if the notification can be displayed when the device is in
Do Not Disturb
. Here is the documentation.
We will get the following result:
Here is the code to build the notification:
- Starting from Android O (API 26), a notification must be linked to a notification channel to be displayed. It’s out of the scope of this article but you can find the
createNotificationChannelIfNeeded
implementation here and read the Android documentation here. - You can find the implementation of the
createPendingIntent
here. - We use the
Builder
of theNotificationCompat
class to build our notification. In the builder’s constructor, we have to pass thechannel id
used during the construction of the channel, in thecreateNotificationChannelIfNeeded
method. - To display the notification, we have to call the
notify
method ofNotificationManagerCompat
and pass theid
we want to give to the notification. Thisid
can be lately used to dismiss the notification or update it by notifying a new notification with the sameid
.
Now that we know how to display a notification, we will get to the main point of this article: display a notification with a contact icon on the left.
To build the notification we want, we have to set a NotificationCompat.Style
to the notification by calling NotificationCompat.Builder.setStyle
.
There are several styles (ex: BigPictureStyle to add a large image, BigTextStyle to add a large block of text, etc…). In our case, we want to show a conversation.
To do that, we have to instantiate a NotificationCompat.MessagingStyle
. The constructor is MessagingStyle(Person user)
.
Let’s see what a is Person
.
Create a Person
The Person
API is a simple API used to represent an entity. This entity can contain some information describing it. In our case, we set 2 information:
We will use the compat version of the androidx.core:core
SDK. The API has been introduced in Android API 28 and by using the compat version, it will manage Android version checks for us.
To get a Person
instance, we have to use the Person.Builder
class.
In this example, we get the user profile image in the Bitmap
format. We use the IconCompat.createWithBitmap
method to get an icon to match the Person
API.
In the context of a 1:1 conversation, the name and the icon used are linked to the other person, but in a conversation between several persons, a Person
can represent the conversation channel which can have a custom name and custom icon.
Create a MessagingStyle
Now that we have a Person
instance, we can create a NotificationCompat.MessagingStyle
instance.
We have to add one or more Message
s to our style to set the notification’s text.
The constructor of this Message
class takes:
- The text to display
- The timestamp when the notification is displayed
- A
Person
instance representing the message’s sender. In the case of a 1:1 conversation, you use the samePerson
instance that in theMessagingStyle
constructor, otherwise you create aPerson
instance representing the message’s sender.
To add the Message
to the style, we call addMessage
.
Now that we have our style, we just have to set it to the NotificationCompat.Builder
and display the notification.
By applying a style, data set by calling setContentTitle
and setContentText
are now ignored so we don’t need to call them anymore.
By executing this code on a device with API < 30, we got the expected notification UI, but on API ≥ 30, the result is the following:
To get good rendering for API ≥ 30, we will have to implement dynamic shortcuts!
At first glance, there is no link between displaying a user photo on the left of a notification and a dynamic shortcut, but starting from API 30, a notification has to be “linked”, by a common ID, to a shortcut to get the notification UI we want.
What is a Shortcut
App’s shortcuts are accessible after a long click on the app icon:
There are 2 types of shortcuts:
- Static shortcuts allow to open a specific screen of the app without any personalized information based on the usage of the app. The
Intent
used to open a screen will not contain custom data. For instance, you can open a camera screen or settings screen but not a conversation screen with a specific person. You can learn how to build a static shortcut here. - Dynamic shortcuts can be added and removed according to the app’s usage. The
Intent
used to open a screen can contain custom data to adapt the screen to a specific usage. For instance, you can open a conversation screen with a specific person by passing the “conversation id” that the screen should display.
Let’s create a dynamic shortcut
In our case, we will create a dynamic shortcut. Each time we need to display a notification, we will create a new shortcut. This is the required way to get the notification UI we want.
Both our dynamic shortcut and our notification will have to share a common ID to “create the bridge” between them and satisfy the system to get the good UI.
Let’s see how to create the shortcut:
- Create an Intent that will start your application and open the screen of the conversation linked to the received message.
- As for the notification, we will use a “compat” version of the API used to create a shortcut.
- Use
ShortcutInfoCompat.Builder
to create a shortcut. You have to pass a string “shortcutId” that will be used in the notification creation process. We will see how later. - Call
setLongLived
is optional. If you set it totrue
, it allows you to keep a shortcut pinned on the launcher even if it has been unpublished by the app. Pinned means placed on the launcher, like an app icon, to quickly access it. This case can occur when you reach the limit of 10 dynamic shortcuts and your shortcut is replaced by a new one. - Call
setIntent
to set theintent
you created earlier. - Call
setShortLabel
. It will be the name of the shortcut. In our case, we can use the name of the person in the conversation. The recommended maximum length is 10 characters. - Set the same
Person
used in theMessagingStyle
creation by callingsetPerson
. - If you set a picture to the
Person
instance, you can set it to the shortcut too by callingsetIcon
. - Finally, you call
build
to get aShortcutInfoCompat
instance. - The last step is to publish the shortcut. To do that, we call the static method
ShortcutManagerCompat.pushDynamicShortcut(Context, ShortcutInfoCompat)
. This method, only available in the “compat” version ofShortcutManager
, manages a lot of boilerplate code for us to easily publish our shortcut.
Indeed, in ShortcutManager
, there are only methods to add and remove shortcuts. This causes a problem because there is a limit to the number of dynamic shortcuts that can exist at a time. If you try to add a new one when the maximum number of shortcuts is reached, an exception is thrown. We would have to code the logic to check if the number is reached, get the list of existing shortcuts, find the oldest, and remove it. By using pushDynamicShortcut
, everything is done for us!
Link the notification to the shortcut
During the notification creation, you have to call a new method setShortcutId
, and pass the same ID used during the shortcut creation.
Now that the link is done, your notification will have the expected UI even for API ≥ 30! 🎉
In the context of messaging notifications, to provide a good experience to users, we want to avoid displaying one notification per message. A better experience would be to display a unique notification containing all messages from a contact.
MessagingStyle
allows that with the method addMessage
, which can be called several times on the same style. Each call will add a new text and all texts will be displayed in a chronological order i.e. the oldest first, the newest last.
It’s also possible to retrieve the current active notification (“active” means visible to the user) and extract the MessagingStyle
from it. With that, we can add a new message’s text and republish the notification to update it.
Get the current active notification
The first step is to get the current active notification:
We call getActiveNotifications()
which returns all visible notifications that have been published by the current application. It returns a list of StatusBarNotification
.
On a StatusBarNotification
, we can call getId()
to get the ID used to publish the notification. Like that, we can find the notification we are interested in by checking the ID.
To get the Notification
object, we call getNotification()
.
Retrieve the MessagingStyle from the notification and add the new message
Now that we have our Notification
object, we want to extract its style. We use the static method NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification
.
In this example, we retrieve the previous MessagingStyle
containing one or already several Message
s.
We create a new Message
and we add it to the MessagingStyle
.
Create or update a notification
Depending on whether there is already an active notification or not, we have to add our message to the existing MessagingStyle
or create one and add our Message
to it.
After that, you create a new Notification
, you apply MessagingStyle
to it and you publish it with the ID of the previous notification to update it if there was already one.
Related Posts
Leave a Reply Cancel reply
Categories
- ! Без рубрики (1)
- ++PU (1)
- 1 (1)
- 1w (1)
- 1win Brazil (1)
- 1win India (1)
- 1WIN Official In Russia (1)
- 1win Turkiye (1)
- 1xbet egypt (1)
- 2ankarafayansustasi.net_may (1)
- ankarafayansustasi.netsiteai apr (1)
- Artificial intelligence (1)
- Arts & Entertainment, Photography (1)
- belugasitesi_mAY (1)
- BH_TOPsitesi apr (1)
- BHsitesy_may (2)
- Blog (3)
- Bookkeeping (14)
- Bootcamp de programação (2)
- Bootcamp de programación (2)
- BT_TOPsitesi apr (1)
- casino (5)
- casinom-hub (1)
- casinom-hub.comsitesi apr (3)
- colombian mail order brides (1)
- Cryptocurrency exchange (2)
- Dinamobet_next (1)
- Disease & Illness, Colon Cancer (1)
- Dumanbet (1)
- Dumanbet_next (1)
- Finance, Insurance (1)
- FinTech (5)
- Forex Trading (11)
- Galabet (1)
- Health & Fitness, Fitness Equipment (1)
- Hitbet (1)
- Home & Family, Crafts (1)
- Home & Family, Gardening (1)
- Internet Business, Audio-Video Streaming (1)
- Internet Business, Ecommerce (1)
- Internet Business, Email Marketing (1)
- Internet Business, Internet Marketing (1)
- IT Вакансії (1)
- IT Образование (5)
- IT Освіта (1)
- latin women dating (1)
- mail order bride (1)
- Mars bahis (2)
- Matadorbet (1)
- minimiri.comsitesi apr (3)
- Mobile App Development (771)
- Mostbet Russia (1)
- New Post (1)
- News (1)
- PB_TOPsitesi apr (1)
- PBsitesi_may (1)
- Pusulabet (1)
- redmirepool.bizsitesi apr (2)
- redmirepoolsitesi_may (1)
- Reference & Education, College (1)
- Reference & Education, Sociology (1)
- Rokusitesi apr (1)
- Sober living (6)
- Society, Divorce (1)
- Software development (7)
- Superbetin (1)
- Tempobet_next (1)
- thelongeststride.comsitesi apr (1)
- tipobet-turkiyesitesi apr (1)
- Ultrabet (1)
- Uncategorized (1)
- Игра (2)
- казино (1)
- Криптовалюты (1)
- Новости Криптовалют (1)
- Финтех (7)
- Форекс Брокеры (9)
- Форекс обучение (2)