…while maintaining backwards compatibility (cause that’s how we roll 🎸)
Each version of Android usually brings something new in the way notifications are displayed to the user, this allows new interactions and features without even the need of opening the application. Android Nougat (7.0) introduced grouping of notifications. Android Oreo (8.0) not only brought a cleaner look to the notification shade, but also introduced Notification Channels along with other updates to the Notifications APIs. Channels allow the app to categorise notifications it generates and hand over the power to the user to select what type of notifications they are interested in. A messaging application, for example, might allow the user to control the notifications they receive.
There are plenty of well documented sources out there that can teach you how to create, use and structure the channels of your app. In this blog post, I’m going through how I updated Memento Calendar’s Daily Reminder feature, introducing functionality that was not previously possible without Channels and enhancing the feature as a whole.
Daily Reminder before Channels
The Daily Reminder notifies the user about their Contacts’ special events, Name Days and the Bank holiday of the given day. This generated three separate notifications, which navigated the user to the corresponding part of the app when pressed. Each notification was present only if the user had chosen to display the specific type of events (contacts, name days or bank holidays), which was also the default option.
This approach works but it is not ideal. What happens if the user is only interested in one of the contacts celebrating? The notification does not deep link to each of the contact’s details screen, so they would have to open the app and dig up that specific one. Moreover it does not address the situation where the user only wants to be notified about events from a specific source, such as contacts, instead of name days.
Splitting out the Contacts’ Celebrations
Looking closer into the
NotificationBuilder class, we can see that it gives a lot of nice goodies. For starters,
setGroup() allows you to bundle notifications together. Instead of creating a summary notification for the events of all contacts, we could create a notification for each one and then let the OS put them all in a bundle for us.
That way, we can provide both an overview about which contacts’ celebrations are happening, but also a deep link to each of the contact’s profile page. We could even go one step further by providing dedicated Notification
Actions for each one of the contacts such as sending a text message, or calling them right straight from the notification. The best thing about this, is that the system will automatically give us the summary notification for free™️!
Make sure to use
setGroupAlertBehavior(GROUP_ALERT_SUMMARY)when grouping multiple notifications. Otherwise each one of the notifications will trigger a separate alarm (sound and/or vibration), spamming the user.
Ok the for free™ part️ was partially a lie. The automatic grouping of notifications into a summary one is supported from Android 7.0 (Nougat) onwards. For legacy versions, we need to create the summary ourselves.
In order for the feature to be consistent on both the latest and older versions of Android, we are going to use something called
InboxStyle. This notification style can provide this nice line-by-line styling which makes the Notification easier to read for multiple contacts that celebrate. By doing this, however, we lose the option to create deep links to each of the contacts separately. As notification grouping is not an option below Android 7.0, creating a single notification for each one would be too spammy for the notification shade. Finally, use
Spans when building the text for each line and some spacing to make each line easier to scan. I followed the styling of Android 8.0 making the contact name
TypeFace.BOLD and added two tabs (
\t\t ) between the contact name and the type of event.
Having all this in place, will cause the Daily Reminder to look something like this on both legacy and current version of the platform:
Daily Reminder as a group of Channels
Instead of creating a single Notification Channel for all notifications of the feature, I decided to create a notification Group instead. This way gives users full control over what notifications they would like to receive, whether they prefer just Contact celebrations, Bank Holidays or Name days, regardless of which events they choose to be visible within the app.
Notice how Contacts is the only Channel that actually produces sound. That is a conscious UX decision, as the user might want to call them or message them through the day. Seeing the notification as soon as possible is important. Bank Holidays and Name Days on the other hand does not require any direct follow up user actions so it can be silent, letting the user ignore it completely if they want to.
Sounds and vibrations can be distracting unless used right. A notification without sound or vibration is still valuable and lets the user handle the information at a later time. It is important to create the right channels for your app, but always be considerate of the right defaults you are going to give to each channel, depending on the context of use.
Prefer code to words? You can find a pure code version of this on Github 🔗.
Dealing with Notification Settings
Once a notification is published to a Notification Channel, it is up to the user to do any modifications to the ringtone, vibration or LED settings. This might feel weird in terms of UX in the beginning, but such behaviour change helps you focus on the unique features of your applications, such as what value you provide to the user by notifying instead of how.
In terms of designing the settings screen for the feature, things are now much much simpler: provide the user the options to control the feature, but leave the notification details to the platform.
Both versions allow the user to enable or disable the feature and change the time they would like to be notified. The difference is that while in legacy versions (prior to 8.0) we provide notification customisations, Android 8.0 (Oreo) onwards links to the Notification System settings instead.
On the technical side, this is pretty straightforward to achieve. We can use Android’s resource system, so that we load the right xml preference file for the right version of the OS we are running on. That should save you many headaches since in your preferences code you wouldn’t have to check which version of Android you are running on to add or remove specific options — the right ones will always be displayed on the screen.
Last but not least, make sure to remove any settings that are irrelevant to device’s given configuration on Legacy versions during Runtime. It doesn’t make sense for example to show vibration settings for a device without a vibrator motor (tablets anyone?).
I hope this blog post gave you some ideas on how to utilise existing and new Notification features in order to update your app’s Notifications. If you have any questions or comments, ask away on Twitter. 😄
More on the topic
If you are new to Android Oreo channels, checkout Joe Birch’s Exploring Android O Notification Channels blog post. Goes through in detail what are Channels both from a user (UX) and code (API) perspective.
Interested about the app that was showcased here? Checkout Memento Calendar on Github. It’s an open-source Birthdays and Name Days app where I try out all the things I am exploring.