Android N: Introducing upgraded Notifications
After writing about the new Picture-in-Picture feature for Android N, I decided to take a deep dive into another of the new features we saw released in the Developer Preview - notifications. Android N sees some great new additions to the notifications API, so lets take a look at some of these new features and how we can implement them into our Android applications.
To get a good grip of these new notification features I created Notifi, a simple Android project to demo all of the samples found in this article.
In Android N, notifications have been given a pretty big upgrade. We now have much more control over the look and feel of the notifications that can be used by our applications, and have also been given a bunch of new capabilities to enhance the experience for our user when dealing with these notifications. So what’s new? Well, this update introduces us to:
- New system layout templates for notifications mean that by default they’re simpler and cleaner - making them feel much less cluttered.
- Bundling now means that notifications will no longer flood the users status bar - related notifications can now be shown under a single expandable notification group if desired.
- Using the new inline reply action our users can respond to textual actions from the notification itself, without the need to open our application and become distracted from what they’re currently engaged in.
- Custom views allow us to sensibly style our notifications to make them look exactly how we please.
That all sounds great doesn’t it? So let’s get on with it and take a look at the implementation details for all of these.
Android N sees the introduction of some new templates used when displaying notifications. These new templates rearrange the components which previously existed on previous SDK versions, making them look both simpler and cleaner. These new templates are automatically used by the system, so there’s no need to change your code for creating a notification.
Just like before we can implement a simple notification like so:
Previously, displaying a notification using the code above (on a device pre-N) would look like this:
Now on Android N, the new templates (with no changes to the code used above!) means our notifications now look like so:
This new style of notification template not only looks cleaner, but I feel it helps to bring more focus onto the visual aspects and create less clutter in the small space that is available for notification content. Again, there’s nothing you need to change in your code - the system will automatically use this new look and feel by default.
Note: Remember you can and some style to your notification and set the colour used by your notification by simply using the setColor() method on your Builder instance:
Using this will set the colour for the notification icon and title, as well as any actions you add to your notification.
With Android N, we now have the ability to bundle our notifications — this groups related notification items so that we can display multiple notifications under a single notification header. When you’re sending multiple related notifications in your application, you should be sure to group them so that you avoid flooding the users status bar with notifications. This can be pretty annoying for the user, so grouping any relevant notifications can help to improve the experience for your user.
So to implement bundled notifications we must begin by setting one of our notifications as the ‘group summary’ notification, this group summary notification will not appear in the stack of notifications but will be the only notification that is displayed on the device until expanded, acting as a header for our notification stack. Following notifications in the group will be what makes up the body of this notification stack.
Note: You must set a notification as the group summary, otherwise your notifications will not appear as part of a group.
Next, we can group our notifications by simply assigning a group ID string using the setGroup() method when building a notification instance, like so:
This tells the notification manager that these notifications all belong to the same group, the system will then group these notifications into a bundle for us - it’s really as easy as that! This is a great way of reducing notifications shown in our users status bar, we can now group them under one notification to be viewed at the same time. Producing a result like below:
Actions for Bundled Notifications
And if that wasn’t enough, just like standard notifications we can also still use actions for notifications that are part of a bundle. At first, these will be collapsed as part of the notification and not visible to the user - however, the user can reveal these actions by clicking the reveal arrow on the desired notification, as shown below:
These actions are handled exactly the same way as they are in the standard approach for notifications, so no extra work is needed. All we need to do is create our new Action instances and assign them to our notification like so:
Using the RemoteInput API (which we’ve actually had since API level 4!), we can now show notifications in Android N that allow the user to respond directly from the notification without the need to open our app to do so. This is done by the display of an inline reply action, which essentially displays an additional button in our notification that allows the user to reveal a textual input field. This is great as it allows our user to interact almost frictionlessly with our application without having to open it, allowing them to remain undistracted from their current task and responding as they please.
When the user decides to interact with the inline reply action, the text that is submitted by the user is attached to our actions specified intent and is then sent to our app (be it activity, service etc), where we can retrieve said content and deal with it accordingly.
Adding inline actions
So we’ve now learnt a little about this new inline reply action, but how can we implement it?! Well, in order to add a inline reply action to our notification, we need to begin by creating a new RemoteInput instance:
The RemoteInput builder requires the use of an identification key (KEY_TEXT_REPLY in my case) that we can later use in our application to retrieve the text that has been entered in our inline reply action by the user. After that, we can then simply set the label to be used for the inline reply action which is displayed as the hint when the input field is in focus (and empty!). The submit icon for the inline reply action is automatically displayed within the notification for us by the system.
Next, we need to create the PendingIntent instances that we wish to launch when our actions are interacted with by the user. We do this just like we normally do when creating PendingIntents for use with our notification:
So now we have these PendingIntents, we actually need to make use of them! This is where our remoteInput instance also comes into play. We need to begin by creating our actions, so let’s take a look at our replyAction instance below:
Here we create our action as normal and then use the addRemoteInput() method to attach our remoteInput instance to it. This is declaring that when this action is interacted with, we want to display the inline reply action to the user in our notification. The input data for this inline reply will be included in our replyIntent Intent once the inline reply has been submitted by the user.
After that, we can simply add our actions to our Notification Builder like below (again, this is still the same as our previous approach Pre-N), no additional code is needed for the inline reply action implementation.
Once we’ve implemented the above, the outcome of the implementation will give us the result below:
Receiving data from inline actions
So we’ve implemented the inline reply action and it looks great, but for it to be useful we need to actually retrieve the data submitted by the user. This is dead easy to do:
Here, we use the RemoteInput API to retrieve the input results from the intent. At this point, if results exist then we can retrieve our data from the bundle. We do so here by using the key we previously used to store the data, which is our KEY_TEXT_REPLY that we mentioned in the previous section.
Styling the inline reply
We can also set the colour of our inline reply action by making use of the setColor() method when building our notification. Doesn’t it look great?
You can also see this sets the colour for all of the components in our notification. Which can easily be achieved like so:
Heads up notifications behave just as before in Marshmallow, however they now use the updated templates used by the system in Android N. This gives us a new notification look and feel as shown below:
The great thing about heads-up notifications in Android N is that we can now use Custom Layouts to declare how our notification should be displayed. We’ll cover that in the next section!
Custom View notifications
As in previous versions of Android, we can still make use of custom layouts to use with our notifications. This means we can use our own layout resources to declare the look and feel of the notification (just don’t get carried away!). This is great for:
- Displaying components that weren’t previously supported by the Notifications API
- Display more meaningful and glanceable information in your notification, fedding the user more meaningful knowledge without the need to open your app
- Adding branding to your notification to match the look and feel of your application
But with saying that, you should ensure to keep the design of your notifications to a minimum. We don’t want to overwhelm the user with information, especially in such a small space. Allow the user to benefit from your notification, whilst still keeping the detail and design to a minimum.
So, with that in mind I think we’re ready to create a custom layout for our notifications! It’s fairly simple to do so, we can make use of the RemoteViews class to construct our custom notification.
We begin by creating a new instance of this RemoteViews class, passing in the package name of our application (the system needs this when dealing with notifications) and the layout itself which we wish to use for the notification. We can then use the methods provided by the RemoteView class to set the data / resources used by the views in our layout. From the RemoteView class, I’ve made use of the following methods:
- setImageViewResource(viewId, resource) - The resource of our image and the view ID which we wish to use our image resource with.
- setTextViewText(viewId, text) - The text that we wish to display in the given text view, referenced by its ID.
The class allows us to set data values, resources, listeners and more for our views. Be sure to check out the documentation for the complete list!
So now we’ve created a RemoteViews instance, we need to use it with a notification to display our desired look and feel.
In the previous section we declared the layout in the RemoteViews instance along with the data to use for those views, so when building our notification all we need to do is pass our RemoteViews instance to the setCustomContentView() method of our builder. In this exampe, we provide custom view for the collapsed (normal) state of our notification:
Setting a Custom Content View for the collapsed state of our notification will simply display our notification for this state alone. We haven’t set an expanded state, so the notification won’t be expandable and will be displayed as below:
Similar to above, we can also provide a custom view for the expanded (larger) state of our notification by passing a RemoteViews instance to the setCustomBigContentView() method:
If we use the setCustomBigContentView() method without setting a collapsed layout using the setCustomContentView() method, then our notification will simply collapse to a state that only displays the application name, as below:
As a best practice, if you provide an expanded size notification layout then you should provide a collapsed layout. This is because the empty collapsed state above provides no context to the user, which goes against the point of a notification! If you’re only going to use a single size (collapsed or expanded) then you should just use the collapsed state by itself.
Using both Collapsed and Expanded Views
If we wish for our notification to be both expandable and collapsable, then we can provide RemoteView instances for both states by making calls to both setCustomContentView() and setCustomBigContentView() methods.
Now we’ve set both a collapsed and expanded view for our notification, the user can expand our notification to view more information about the notification.
Custom Heads-up Views
We can also use custom layouts when it comes to heads-up notifications. Using the same approach in the previous section to create a heads-up notification, we can use a custom view by simply passing a RemoteViews instance in a call to the setCustomContentView() method.
And that’s it!
So we’ve taken a look at this new notifications in Android N and how to implement them — so now it’s time to build this into your existing / new applications ready for Android N! I think these are some great additions to the Android platform, not only are notifications more powerful (and prettier) but I’m looking forward to seeing better notification experiences within applications. If you have any questions, please feel free to tweet me or leave a response below!
p.s don’t forget to hit the recommend button if you enjoyed this article :)
The latest Tweets from Joe Birch (@hitherejoe). Android, photography, bass and a lot of running. Android Developer…twitter.com
Check out my other projects at hitherejoe.com