Posted by Ian Lake, Developer Advocate
Android notifications are often a make-or-break interaction between your Android
app and users. To provide a better user experience, notifications on Android N
have received a visual refresh, improved support for custom views, and expanded
functionality in the forms of Direct Reply, a new MessagingStyle
,
and bundled notifications.
Same notification, new look
The first and most obvious change is that the default look and feel of notifications has significantly changed. Many of the fields that were spread around the notifications have been collapsed into a new header row with your app’s icon and name anchoring the notification. This change ensured that the title, text, and large icon are given the most amount of space possible and, as a result, notifications are generally slightly larger now and easier to read.
Given the single header row, it is more important than ever that the information
there is useful. When you target Android N, by default the time will be
hidden - if you have a time critical notification such as a messaging
app, you can re-enable it with setShowWhen(true)
. In addition, the
subtext will take precedence over any content info you set: only if you target a
previous version of Android will both appear. In all cases, ensure that the
subtext is relevant and useful - don’t add an account email address as your
subtext if the user only has one account, for example.
Notification actions have also received a redesign and are now in a visually separate bar below the notification.
You’ll note that the icons are not present in the new notifications; instead more room is provided for the labels themselves in the constrained space of the notification shade. However, the notification action icons are still required and continue to be used on older versions of Android and on devices such as Android Wear.
If you’ve been building your notification with NotificationCompat.Builder
and the standard styles available to you there, you’ll get the new look and feel
by default with no code changes required.
Better Support for Custom Views
If you’re instead building your notification from custom
RemoteViews
, adapting to any new style has been challenging. With
the new header, expanding behavior, actions, and large icon positioning as
separate elements from the main text+title of the notification, we’ve introduced
a new DecoratedCustomViewStyle
and
DecoratedMediaCustomViewStyle
to provide all of these elements,
allowing you to focus only on the content portion with the new
setCustomContentView()
method.
This also ensures that future look and feel changes should be significantly easier to adapt to as these styles will be updated alongside the platform with no code changes needed on the app side.
Direct Reply
While notification actions have already been able to launch an
Activity
or do background work with a Service
or
BroadcastReceiver
, Direct Reply allows you to
build an action that directly receives text input inline with
the notification actions.
Direct Reply uses the same RemoteInput
API - originally introduced for Android Wear - to mark an Action
as being able to directly receive input from the user.
The RemoteInput
itself contains information like the key which will
be used to later retrieve the input and the hint text which is displayed before
the user starts typing.
// Where should direct replies be put in the intent bundle (can be any string) private static final String KEY_TEXT_REPLY = "key_text_reply"; // Create the RemoteInput specifying this key String replyLabel = getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY) .setLabel(replyLabel) .build();
Once you’ve constructed the RemoteInput
, it can be attached to your
Action via the aptly named addRemoteInput()
method. You might consider also calling
setAllowGeneratedReplies(true)
to enable Android Wear
2.0 to generate Smart
Reply choices when available and make it easier for users to quickly
respond.
// Add to your action, enabling Direct Reply for it NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.reply, replyLabel, pendingIntent) .addRemoteInput(remoteInput) .setAllowGeneratedReplies(true) .build();
Keep in mind that the pendingIntent
being passed into your
Action
should be an Activity
on Marshmallow and lower
devices that don’t support Direct Reply (as you’ll want to dismiss the lock
screen, start an Activity
, and focus the input field to have the
user type their reply) and should be a Service
(if you need to do
work on a separate thread) or BroadcastReceiver
(which runs on the
UI thread) on Android N devices so as the process the text input in the
background even from the lock screen. (There is a separate user control to
enable/disable Direct Reply from a locked device in the system settings.)
Extracting the text input in your
Service
/BroadcastReceiver
is then possible with the
help of the RemoteInput.getResultsFromIntent()
method:
private CharSequence getMessageText(Intent intent) { Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { return remoteInput.getCharSequence(KEY_TEXT_REPLY); } return null; }
After you’ve processed the text, you must update the notification. This is the trigger which hides the Direct Reply UI and should be used as a technique to confirm to the user that their reply was received and processed correctly.
For most templates, this should involve using the new
setRemoteInputHistory()
method which appends the reply to the
bottom of the notification. Additional replies should be appended to the history
until the main content is updated (such as the other person replying).
However, if you’re building a messaging app and expect back and forth
conversations, you should use MessagingStyle
and append the
additional message to it.
MessagingStyle
We’ve optimized the experience for displaying an ongoing conversation and using
Direct Reply with the new MessagingStyle
.
This style provides built-in formatting for multiple messages added via the
addMessage()
method. Each message supports passing in the text
itself, a timestamp, and the sender of the message (making it easy to support
group conversations).
builder.setStyle(new NotificationCompat.MessagingStyle("Me") .setConversationTitle("Team lunch") .addMessage("Hi", timestampMillis1, null) // Pass in null for user. .addMessage("What's up?", timestampMillis2, "Coworker") .addMessage("Not much", timestampMillis3, null) .addMessage("How about lunch?", timestampMillis4, "Coworker"));
You’ll note that this style has first-class support for specifically denoting
messages from the user and filling in their name (in this case with “Me”) and
setting an optional conversation title. While this can be done manually with a
BigTextStyle
, by using this style Android Wear 2.0 users will get
immediate inline responses without kicking them out of the expanded notification
view, making for a seamless experience without needing to build a full Wear app.
Bundled Notifications
Once you’ve built a great notification by using the new visual designs, Direct
Reply, MessagingStyle
, and all of our previous best
practices, it is important to think about the overall notification
experience, particularly if you post multiple notifications (say, one per
ongoing conversation or per new email thread).
Bundled notifications offer the best of both worlds: a single summary notification for when users are looking at other notifications or want to act on all notifications simultaneously and the ability to expand the group to act on individual notifications (including using actions and Direct Reply).
If you’ve built stacking
notifications for Android Wear, the API used here is exactly the same.
Simply add setGroup()
to each individual notification to bundle those notifications together. You’re
not limited to one group, so bundle notifications appropriately. For an email
app, you might consider one bundle per account for instance.
It is important to also create a summary notification. This
summary notification, denoted by setGroupSummary(true)
,
is the only notification that appears on Marshmallow and lower
devices and should (you guessed it) summarize all of the individual
notifications. This is an opportune time to use the InboxStyle
,
although using it is not a requirement. On Android N and higher devices, some
information (such as the subtext, content intent, and delete intent) is
extracted from the summary notification to produce the collapsed notification
for the bundled notifications so you should continue to generate a summary
notification on all API levels.
To improve the overall user experience on Android N devices, posting 4 or more notifications without a group will cause those notifications to be automatically bundled.
N is for Notifications
Notifications on Android have been a constant area of progressive enhancement. From the single tap targets of the Gingerbread era to expandable notifications, actions, MediaStyle, and now features such as Direct Reply and bundled notifications, notifications play an important part of the overall user experience on Android.
With many new tools to use (and NotificationCompat
to help with backward compatibility), I’m excited to see how you use them to
#BuildBetterApps
Follow the Android Development Patterns Collection for more!