blob: 09dd5f43b03f0ce6f7276ce20573424e6d107383 [file] [log] [blame]
page.title=Notifications
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#Design">Design Considerations</a></li>
<li><a href="#CreateNotification">Creating a Notification</a>
<ol>
<li><a href="#Required">Required notification contents</a></li>
<li><a href="#Optional">Optional notification contents and settings</a></li>
<li><a href="#Actions">Notification actions</a></li>
<li><a href="#Priority">Notification priority</a></li>
<li><a href="#SimpleNotification">Creating a simple notification</a></li>
<li><a href="#ApplyStyle">Applying an expanded layout to a notification</a></li>
<li><a href="#Compatibility">Handling compatibility</a></li>
</ol>
</li>
<li><a href="#Managing">Managing Notifications</a>
<ol>
<li><a href="#Updating">Updating notifications</a></li>
<li><a href="#Removing">Removing notifications</a></li>
<li><a href="#direct">Replying to notifications</a></li>
<li><a href="#bundle">Bundling notifications</a></li>
</ol>
</li>
<li><a href="#NotificationResponse">Preserving Navigation when Starting an Activity</a>
<ol>
<li><a href="#DirectEntry">Setting up a regular activity PendingIntent</a></li>
<li><a href="#ExtendedNotification">Setting up a special activity PendingIntent</a></li>
</ol>
</li>
<li><a href="#Progress">Displaying Progress in a Notification</a>
<ol>
<li><a href="#FixedProgress">Displaying a fixed-duration progress indicator</a></li>
<li><a href="#ActivityIndicator">Displaying a continuing activity indicator</a></li>
</ol>
</li>
<li><a href="#metadata">Notification Metadata</a></li>
<li><a href="#Heads-up">Heads-up Notifications</a></li>
<li><a href="#lockscreenNotification">Lock Screen Notifications</a>
<ol>
<li><a href="#visibility">Setting Visibility</a></li>
<li><a href="#controllingMedia">Controlling Media Playback on the Lock Screen</a></li>
</ol>
</li>
<li><a href="#CustomNotification">Customizing Notifications</a>
<ol>
<li><a href="#custom">Custom Views</a></li>
<li><a href="#style">Messaging Style</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.NotificationManager}</li>
<li>{@link android.support.v4.app.NotificationCompat}</li>
</ol>
<h2>Videos</h2>
<ol>
<li>
<a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s">
Notifications in 4.1</a>
</li>
</ol>
<h2>See also</h2>
<ol>
<li>
<a href="https://material.google.com/patterns/notifications.html">Material Design: Notifications</a>
</li>
</ol>
</div>
</div>
<p>
A notification is a message you can display to the user outside of your application's
normal UI. When you tell the system to issue a notification, it first appears as an icon in the
<strong>notification area</strong>. To see the details of the notification, the user opens the
<strong>notification drawer</strong>. Both the notification area and the notification drawer
are system-controlled areas that the user can view at any time.
</p>
<img
id="figure1"
src="{@docRoot}images/ui/notifications/notification_area.png"
height="" alt="" />
<p class="img-caption">
<strong>Figure 1.</strong> Notifications in the notification area.
</p>
<img id="figure2" src="{@docRoot}images/ui/notifications/notification_drawer.png"
width="280px" alt="" />
<p class="img-caption">
<strong>Figure 2.</strong> Notifications in the notification drawer.
</p>
<p class="note"><strong>Note:</strong> Except where noted, this guide refers to the
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class
in the version 4 <a href="{@docRoot}tools/support-library/index.html">Support Library</a>.
The class {@link android.app.Notification.Builder Notification.Builder} was added in Android
3.0 (API level 11).</p>
<h2 id="Design">Design Considerations</h2>
<p>Notifications, as an important part of the Android user interface, have their own design guidelines.
The material design changes introduced in Android 5.0 (API level 21) are of particular
importance, and you should review the <a href="{@docRoot}training/material/index.html">Material
Design</a> training for more information. To learn how to design notifications and their interactions,
read the <a href="https://material.google.com/patterns/notifications.html">Notifications</a> design guide.</p>
<h2 id="CreateNotification">Creating a Notification</h2>
<p>You specify the UI information and actions for a notification in a
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object.
To create the notification itself, you call
{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},
which returns a {@link android.app.Notification} object containing your specifications. To issue the
notification, you pass the {@link android.app.Notification} object to the system by calling
{@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.</p>
<h3 id="Required">Required notification contents</h3>
<p>
A {@link android.app.Notification} object <em>must</em> contain the following:
</p>
<ul>
<li>
A small icon, set by
{@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
</li>
<li>
A title, set by
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
</li>
<li>
Detail text, set by
{@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
</li>
</ul>
<h3 id="Optional">Optional notification contents and settings</h3>
<p>
All other notification settings and contents are optional. To learn more about them,
see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Actions">Notification actions</h3>
<p>
Although they're optional, you should add at least one action to your notification.
An action allows users to go directly from the notification to an
{@link android.app.Activity} in your application, where they can look at one or more events
or do further work.
</p>
<p>
A notification can provide multiple actions. You should always define the action that's
triggered when the user clicks the notification; usually this action opens an
{@link android.app.Activity} in your application. You can also add buttons to the notification
that perform additional actions such as snoozing an alarm or responding immediately to a text
message; this feature is available as of Android 4.1. If you use additional action buttons, you
must also make their functionality available in an {@link android.app.Activity} in your app; see
the section <a href="#Compatibility">Handling compatibility</a> for more details.
</p>
<p>
Inside a {@link android.app.Notification}, the action itself is defined by a
{@link android.app.PendingIntent} containing an
{@link android.content.Intent} that starts
an {@link android.app.Activity} in your application. To associate the
{@link android.app.PendingIntent} with a gesture, call the appropriate method of
{@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start
{@link android.app.Activity} when the user clicks the notification text in
the notification drawer, you add the {@link android.app.PendingIntent} by calling
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
</p>
<p>
Starting an {@link android.app.Activity} when the user clicks the notification is the most
common action scenario. You can also start an {@link android.app.Activity} when the user
dismisses a notification. In Android 4.1 and later, you can start an
{@link android.app.Activity} from an action button. To learn more, read the reference guide for
{@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Priority">Notification priority</h3>
<p>
If you wish, you can set the priority of a notification. The priority acts
as a hint to the device UI about how the notification should be displayed.
To set a notification's priority, call {@link
android.support.v4.app.NotificationCompat.Builder#setPriority(int)
NotificationCompat.Builder.setPriority()} and pass in one of the {@link
android.support.v4.app.NotificationCompat} priority constants. There are
five priority levels, ranging from {@link
android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) to {@link
android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); if not set, the
priority defaults to {@link
android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).
</p>
<p> For information about setting an appropriate priority level, see "Correctly
set and manage notification priority" in the <a
href="https://material.google.com/patterns/notifications.html">Notifications</a> Design
guide.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="SimpleNotification">Creating a simple notification</h3>
<p>
The following snippet illustrates a simple notification that specifies an activity to open when
the user clicks the notification. Notice that the code creates a
{@link android.support.v4.app.TaskStackBuilder} object and uses it to create the
{@link android.app.PendingIntent} for the action. This pattern is explained in more detail
in the section <a href="#NotificationResponse">
Preserving Navigation when Starting an Activity</a>:
</p>
<pre>
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
</pre>
<p>That's it. Your user has now been notified.</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ApplyStyle">Applying an expanded layout to a notification</h3>
<p>
To have a notification appear in an expanded view, first create a
{@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options
you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle
Builder.setStyle()} with an expanded layout object as its argument.
</p>
<p>
Remember that expanded notifications are not available on platforms prior to Android 4.1. To
learn how to handle notifications for Android 4.1 and for earlier platforms, read the
section <a href="#Compatibility">Handling compatibility</a>.
</p>
<p>
For example, the following code snippet demonstrates how to alter the notification created
in the previous snippet to use the expanded layout:
</p>
<pre>
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Event tracker")
.setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
new NotificationCompat.InboxStyle();
String[] events = new String[6];
// Sets a title for the Inbox in expanded layout
inboxStyle.setBigContentTitle("Event tracker details:");
...
// Moves events into the expanded layout
for (int i=0; i &lt; events.length; i++) {
inboxStyle.addLine(events[i]);
}
// Moves the expanded layout object into the notification object.
mBuilder.setStyle(inBoxStyle);
...
// Issue the notification here.
</pre>
<h3 id="Compatibility">Handling compatibility</h3>
<p>
Not all notification features are available for a particular version, even though
the methods to set them are in the support library class
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
For example, action buttons, which depend on expanded notifications, only appear on Android
4.1 and higher, because expanded notifications themselves are only available on
Android 4.1 and higher.
</p>
<p>
To ensure the best compatibility, create notifications with
{@link android.support.v4.app.NotificationCompat NotificationCompat} and its subclasses,
particularly {@link android.support.v4.app.NotificationCompat.Builder
NotificationCompat.Builder}. In addition, follow this process when you implement a notification:
</p>
<ol>
<li>
Provide all of the notification's functionality to all users, regardless of the version
they're using. To do this, verify that all of the functionality is available from an
{@link android.app.Activity} in your app. You may want to add a new
{@link android.app.Activity} to do this.
<p>
For example, if you want to use
{@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} to
provide a control that stops and starts media playback, first implement this
control in an {@link android.app.Activity} in your app.
</p>
</li>
<li>
Ensure that all users can get to the functionality in the {@link android.app.Activity},
by having it start when users click the notification. To do this,
create a {@link android.app.PendingIntent}
for the {@link android.app.Activity}. Call
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()} to add the {@link android.app.PendingIntent} to the notification.
</li>
<li>
Now add the expanded notification features you want to use to the notification. Remember
that any functionality you add also has to be available in the {@link android.app.Activity}
that starts when users click the notification.
</li>
</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Managing">Managing Notifications</h2>
<p>
When you need to issue a notification multiple times for the same type of event, you
should avoid making a completely new notification. Instead, you should consider updating a
previous notification, either by changing some of its values or by adding to it, or both.
</p>
<p>
For example, Gmail notifies the user that new emails have arrived by increasing its count of
unread messages and by adding a summary of each email to the notification. This is called
"stacking" the notification; it's described in more detail in the
<a href="https://material.google.com/patterns/notifications.html">Notifications</a> Design guide.
</p>
<p class="note">
<strong>Note:</strong> This Gmail feature requires the "inbox" expanded layout, which is part
of the expanded notification feature.
</p>
<p>
The following section describes how to update notifications and also how to remove them.
</p>
<h3 id="Updating">Updating notifications</h3>
<p>
To set up a notification so it can be updated, issue it with a notification ID by
calling {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.
To update this notification once you've issued
it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object,
build a {@link android.app.Notification} object from it, and issue the
{@link android.app.Notification} with the same ID you used previously. If
the previous notification is still visible, the system updates it from the contents of
the {@link android.app.Notification} object. If the previous notification has been dismissed, a
new notification is created instead.
</p>
<p>
The following snippet demonstrates a notification that is updated to reflect the
number of events that have occurred. It stacks the notification, showing a summary:
</p>
<pre>
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is
// updated.
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
...
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Removing">Removing notifications</h3>
<p>
Notifications remain visible until one of the following happens:
</p>
<ul>
<li>
The user dismisses the notification either individually or by using "Clear All" (if
the notification can be cleared).
</li>
<li>
The user clicks the notification, and you called
{@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when
you created the notification.
</li>
<li>
You call {@link android.app.NotificationManager#cancel(int) cancel()} for a specific
notification ID. This method also deletes ongoing notifications.
</li>
<li>
You call {@link android.app.NotificationManager#cancelAll() cancelAll()}, which removes
all of the notifications you previously issued.
</li>
</ul>
<!--------------------------------------------------------------- -->
<h2 id="direct">Replying to notifications</h2>
<p>
Starting in Android 7.0 (API level 24),
users can respond directly to text messages or update task lists
from within the notification
dialog. On a handheld, the inline reply action appears as an additional
button
displayed in the notification. When a user replies via keyboard, the system
attaches the text response to the intent
you had specified for the notification action and sends the intent to your
handheld app.
</p>
<img id="fig-reply-button" src="{@docRoot}images/android-7.0/inline-reply.png"
srcset="{@docRoot}images/android-7.0/inline-reply.png 1x,
{@docRoot}images/android-7.0/inline-reply_2x.png 2x"
width="400">
<p class="img-caption">
<strong>Figure 1.</strong> The <strong>Reply</strong> action button.
</p>
<h3>Adding inline reply actions</h3>
<p>To create a notification action that supports direct reply:
</p>
<ol>
<li>Create an instance of {@link android.support.v4.app.RemoteInput.Builder}
that you can add to your notification
action. This class's constructor accepts a string that the system uses as the key
for the text input. Later, your handheld app uses that key to retrieve the text
of the input.
<pre>
// Key for the string that's delivered in the action's intent.
private static final String KEY_TEXT_REPLY = "key_text_reply";
String replyLabel = getResources().getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel(replyLabel)
.build();
</pre>
</li>
<li>Attach the {@link android.support.v4.app.RemoteInput}
object to an action using <code>addRemoteInput()</code>.
<pre>
// Create the reply action and add the remote input.
Notification.Action action =
new Notification.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label), replyPendingIntent)
.addRemoteInput(remoteInput)
.build();
</pre>
</li>
<li>Apply the action to a notification and issue the notification.
<pre>
// Build the notification and add the action.
Notification newMessageNotification =
new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(getString(R.string.title))
.setContentText(getString(R.string.content))
.addAction(action))
.build();
// Issue the notification.
NotificationManager notificationManager =
NotificationManager.from(mContext);
notificationManager.notify(notificationId, newMessageNotification);
</pre>
</li>
</ol>
<p> The system prompts the user to input a response when they trigger the
notification action. </p>
<img id="fig-user-input" src="{@docRoot}images/android-7.0/inline-type-reply.png"
srcset="{@docRoot}images/android-7.0/inline-type-reply.png 1x,
{@docRoot}images/android-7.0/inline-type-reply_2x.png 2x"
width="300">
<p class="img-caption">
<strong>Figure 2.</strong> The user inputs text from the notification shade.
</p>
<h3>
Retrieving user input from the inline reply
</h3>
<p>
To receive user input from the notification interface to the activity you
declared in the reply action's intent:
</p>
<ol>
<li>Call {@link android.support.v4.app.RemoteInput#getResultsFromIntent
getResultsFromIntent()} by passing the notification action’s intent as the
input parameter. This method returns a {@link android.os.Bundle} that
contains the text response.
<pre>
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
</pre>
</li>
<li>Query the bundle using the result key (provided to the {@link
android.support.v4.app.RemoteInput.Builder} constructor). You can complete
this process and retrieve the input text by creating a method, as in the
following code snippet:
<pre>
// Obtain the intent that started this activity by calling
// Activity.getIntent() and pass it into this method to
// get the associated string.
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(KEY_TEXT_REPLY);
}
return null;
}
</pre>
</li>
<li>Build and issue another notification, using the same notification ID that
you provided for the previous notification. The progress indicator
disappears from the notification interface to inform users of a successful
reply. When working with this new notification, use the context that gets
passed to the receiver's {@code onReceive()} method.
<pre>
// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification =
new Notification.Builder(context)
.setSmallIcon(R.drawable.ic_message)
.setContentText(getString(R.string.replied))
.build();
// Issue the new notification.
NotificationManager notificationManager =
NotificationManager.from(context);
notificationManager.notify(notificationId, repliedNotification);
</pre>
</li>
</ol>
<p>
For interactive apps, such as chats, you can include additional
context when handling retrieved text. For example, these apps could show
multiple lines of chat history. When the user responds via {@link
android.support.v4.app.RemoteInput}, you can update the reply history
using the {@code setRemoteInputHistory()} method.
</p>
<p>
The notification must be either updated or cancelled after the app has
received remote input. When the user replies to a remote update
using Direct Reply,
do not cancel the notification. Instead, update the notification
to display the user's reply.
For notifications using {@code MessagingStyle}, you should add
the reply as the latest message. When using other templates, you can
append the user's reply to the remote-input history.
</p>
<!-------------------------------------------------------------------------- -->
<h2 id="bundle">Bundling notifications</h2>
<p>
Starting in Android 7.0 (API level 24),
Android provides developers with a new way to represent
a queue of notifications: <i>bundled notifications</i>. This is similar to the
<a href="{@docRoot}training/wearables/notifications/stacks.html">Notification
Stacks</a> feature in Android Wear. For example, if your app
creates notifications
for received messages, when more than one message is received, bundle the
notifications together as a single group. You can
use the {@link android.support.v4.app.NotificationCompat.Builder#setGroup
Builder.setGroup()} method to bundle similar notifications.</p>
<p>
A notification group imposes a hierarchy on the notifications comprising it.
At the top of that hierarchy is a parent notification that displays summary
information for the group. The user can progressively
expand the notification group, and the system shows more information as the
user drills deeper. When the user expands the bundle, the system reveals more
information for all its child notifications; when the user
expands one of those notifications, the system reveals its entire content.
</p>
<img id="fig-bundles" src="{@docRoot}images/android-7.0/bundles.png"
srcset="{@docRoot}images/android-7.0/bundles.png 1x,
{@docRoot}images/android-7.0/bundles_2x.png 2x"
width="300">
<p class="img-caption">
<strong>Figure 3.</strong> The user can progressively expand the notification
group.
</p>
<p class="note">
<strong>Note:</strong> If the same app sends four or more notifications
and does not specify a grouping, the
system automatically groups them together.
</p>
<p>To learn how to add notifications to a group, see
<a href="{@docRoot}training/wearables/notifications/stacks.html#AddGroup">Add
Each Notification to a Group</a>.</p>
<h3 id="best-practices">Best practices for bundled notifications</h3>
<p>This section provides guidelines about when to use notification groups instead
of the {@link android.app.Notification.InboxStyle InboxStyle}
notifications available in Android 6.0 and previous versions.</p>
<h3>When to use bundled notifications</h3>
<p>You should use notification groups only if all of the following conditions are
true for your use case:</p>
<ul>
<li>The child notifications are complete notifications and can be displayed
individually without the need for a group summary.</li>
<li>There is a benefit to surfacing the child notifications individually. For
example:
</li>
<ul>
<li>They are actionable, with actions specific to each child.</li>
<li>There is more information to the child that the user wants to read.</li>
</ul>
</ul>
<p>Examples of good use cases for notification groups include: a messaging app
displaying a list of incoming messages, or an email app displaying a list of
received emails.</p>
<p>
Examples of cases where a single notification is preferable
include individual messages from a single person, or a list representation of
single-line text items. You can use
({@link android.app.Notification.InboxStyle InboxStyle} or
{@link android.app.Notification.BigTextStyle BigTextStyle}) to accomplish
this.
</p>
<h3 id ="post">Displaying bundled notifications</h3>
<p>
The app should always post a group summary, even if the group contains just a
single child. The system will suppress the summary and directly display the
child notification if it only contains a single notification. This ensures
that the system can provide a consistent experience when the user swipes away
children of a group.
</p>
<h3>Peeking notifications</h3>
<p>While the system usually displays child notifications as a group, you can set
them to temporarily appear as
<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#Heads-up">
heads-up notifications</a>. This feature is especially useful because it allows
immediate access to the most recent child and the actions associated with it.
</p>
<h3>Backwards compatibility</h3>
<p>
Both notification groups and remote input have been a part of the {@link
android.app.Notification} API since Android 5.0 (API level 21) to support
Android Wear devices. If you've already built notifications with these APIs,
the only action you must take is to verify that the app behavior corresponds
to the guidelines described above, and to consider implementing {@code
setRemoteInputHistory()}.
</p>
<p>
In order to support backward compatibility, the same APIs are available with
the support library's {@link android.support.v4.app.NotificationCompat}
class, allowing you to build notifications that works on versions of Android
less than 5.0 (API level 21).
On handhelds and tablets, users only see the summary notification,
so an app should still have an inbox style or an equivalent notification
representative for the whole information content of the group. As Android
Wear devices allow users to see all child notifications even on older
platform levels, you should build child notifications regardless of API
level.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="NotificationResponse">Preserving Navigation when Starting an Activity</h2>
<p>
When you start an {@link android.app.Activity} from a notification, you must preserve the
user's expected navigation experience. Clicking <i>Back</i> should take the user back through
the application's normal work flow to the Home screen, and clicking <i>Recents</i> should show
the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you
should start the {@link android.app.Activity} in a fresh task. How you set up the
{@link android.app.PendingIntent} to give you a fresh task depends on the nature of the
{@link android.app.Activity} you're starting. There are two general situations:
</p>
<dl>
<dt>
Regular activity
</dt>
<dd>
You're starting an {@link android.app.Activity} that's part of the application's normal
workflow. In this situation, set up the {@link android.app.PendingIntent} to
start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack
that reproduces the application's normal <i>Back</i> behavior.
<p>
Notifications from the Gmail app demonstrate this. When you click a notification for
a single email message, you see the message itself. Touching <b>Back</b> takes you
backwards through Gmail to the Home screen, just as if you had entered Gmail from the
Home screen rather than entering it from a notification.
</p>
<p>
This happens regardless of the application you were in when you touched the
notification. For example, if you're in Gmail composing a message, and you click a
notification for a single email, you go immediately to that email. Touching <i>Back</i>
takes you to the inbox and then the Home screen, rather than taking you to the
message you were composing.
</p>
</dd>
<dt>
Special activity
</dt>
<dd>
The user only sees this {@link android.app.Activity} if it's started from a notification.
In a sense, the {@link android.app.Activity} extends the notification by providing
information that would be hard to display in the notification itself. For this situation,
set up the {@link android.app.PendingIntent} to start in a fresh task. There's no need to
create a back stack, though, because the started {@link android.app.Activity} isn't part of
the application's activity flow. Clicking <i>Back</i> will still take the user to the
Home screen.
</dd>
</dl>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="DirectEntry">Setting up a regular activity PendingIntent</h3>
<p>
To set up a {@link android.app.PendingIntent} that starts a direct entry
{@link android.app.Activity}, follow these steps:
</p>
<ol>
<li>
Define your application's {@link android.app.Activity} hierarchy in the manifest.
<ol style="list-style-type: lower-alpha;">
<li>
Add support for Android 4.0.3 and earlier. To do this, specify the parent of the
{@link android.app.Activity} you're starting by adding a
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
element as the child of the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>.
<p>
For this element, set
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
Set
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="&lt;parent_activity_name&gt;"</code>
where <code>&lt;parent_activity_name&gt;</code> is the value of
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
for the parent
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element. See the following XML for an example.
</p>
</li>
<li>
Also add support for Android 4.1 and later. To do this, add the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
attribute to the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element of the {@link android.app.Activity} you're starting.
</li>
</ol>
<p>
The final XML should look like this:
</p>
<pre>
&lt;activity
android:name=".MainActivity"
android:label="&#64;string/app_name" &gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
&lt;activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity"&gt;
&lt;meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/&gt;
&lt;/activity&gt;
</pre>
</li>
<li>
Create a back stack based on the {@link android.content.Intent} that starts the
{@link android.app.Activity}:
<ol style="list-style-type: lower-alpha;">
<li>
Create the {@link android.content.Intent} to start the {@link android.app.Activity}.
</li>
<li>
Create a stack builder by calling {@link android.app.TaskStackBuilder#create
TaskStackBuilder.create()}.
</li>
<li>
Add the back stack to the stack builder by calling
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
For each {@link android.app.Activity} in the hierarchy you've defined in the
manifest, the back stack contains an {@link android.content.Intent} object that
starts the {@link android.app.Activity}. This method also adds flags that start the
stack in a fresh task.
<p class="note">
<strong>Note:</strong> Although the argument to
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
is a reference to the started {@link android.app.Activity}, the method call
doesn't add the {@link android.content.Intent} that starts the
{@link android.app.Activity}. Instead, that's taken care of in the next step.
</p>
</li>
<li>
Add the {@link android.content.Intent} that starts the {@link android.app.Activity}
from the notification, by calling
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
Pass the {@link android.content.Intent} you created in the first step as the
argument to
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
</li>
<li>
If you need to, add arguments to {@link android.content.Intent} objects on the
stack by calling {@link android.support.v4.app.TaskStackBuilder#editIntentAt
TaskStackBuilder.editIntentAt()}. This is sometimes necessary to ensure that the
target {@link android.app.Activity} displays meaningful data when the user navigates
to it using <i>Back</i>.
</li>
<li>
Get a {@link android.app.PendingIntent} for this back stack by calling
{@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
You can then use this {@link android.app.PendingIntent} as the argument to
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()}.
</li>
</ol>
</li>
</ol>
<p>
The following code snippet demonstrates the process:
</p>
<pre>
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ExtendedNotification">Setting up a special activity PendingIntent</h3>
<p>
The following section describes how to set up a special activity
{@link android.app.PendingIntent}.
</p>
<p>
A special {@link android.app.Activity} doesn't need a back stack, so you don't have to
define its {@link android.app.Activity} hierarchy in the manifest, and you don't have
to call
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a
back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options,
and create the {@link android.app.PendingIntent} by calling
{@link android.app.PendingIntent#getActivity getActivity()}:
</p>
<ol>
<li>
In your manifest, add the following attributes to the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element for the {@link android.app.Activity}
<dl>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
</dt>
<dd>
The activity's fully-qualified class name.
</dd>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
</dt>
<dd>
Combined with the
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag
that you set in code, this ensures that this {@link android.app.Activity} doesn't
go into the application's default task. Any existing tasks that have the
application's default affinity are not affected.
</dd>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
</dt>
<dd>
Excludes the new task from <i>Recents</i>, so that the user can't accidentally
navigate back to it.
</dd>
</dl>
<p>
This snippet shows the element:
</p>
<pre>
&lt;activity
android:name=".ResultActivity"
...
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true"&gt;
&lt;/activity&gt;
...
</pre>
</li>
<li>
Build and issue the notification:
<ol style="list-style-type: lower-alpha;">
<li>
Create an {@link android.content.Intent} that starts the
{@link android.app.Activity}.
</li>
<li>
Set the {@link android.app.Activity} to start in a new, empty task by calling
{@link android.content.Intent#setFlags setFlags()} with the flags
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
and
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
</li>
<li>
Set any other options you need for the {@link android.content.Intent}.
</li>
<li>
Create a {@link android.app.PendingIntent} from the {@link android.content.Intent}
by calling {@link android.app.PendingIntent#getActivity getActivity()}.
You can then use this {@link android.app.PendingIntent} as the argument to
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()}.
</li>
</ol>
<p>
The following code snippet demonstrates the process:
</p>
<pre>
// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());
</pre>
</li>
</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Progress">Displaying Progress in a Notification</h2>
<p>
Notifications can include an animated progress indicator that shows users the status
of an ongoing operation. If you can estimate how long the operation takes and how much of it
is complete at any time, use the "determinate" form of the indicator
(a progress bar). If you can't estimate the length of the operation, use the
"indeterminate" form of the indicator (an activity indicator).
</p>
<p>
Progress indicators are displayed with the platform's implementation of the
{@link android.widget.ProgressBar} class.
</p>
<p>
To use a progress indicator on platforms starting with Android 4.0, call
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. For
previous versions, you must create your own custom notification layout that
includes a {@link android.widget.ProgressBar} view.
</p>
<p>
The following sections describe how to display progress in a notification using
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3>
<p>
To display a determinate progress bar, add the bar to your notification by calling
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(max, progress, false)} and then issue the notification. As your operation proceeds,
increment <code>progress</code>, and update the notification. At the end of the operation,
<code>progress</code> should equal <code>max</code>. A common way to call
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
is to set <code>max</code> to 100 and then increment <code>progress</code> as a
"percent complete" value for the operation.
</p>
<p>
You can either leave the progress bar showing when the operation is done, or remove it. In
either case, remember to update the notification text to show that the operation is complete.
To remove the progress bar, call
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(0, 0, false)}. For example:
</p>
<pre>
...
mNotifyManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
&#64;Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr &lt;= 100; incr+=5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(5*1000);
} catch (InterruptedException e) {
Log.d(TAG, "sleep failure");
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
mNotifyManager.notify(ID, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ActivityIndicator">Displaying a continuing activity indicator</h3>
<p>
To display an indeterminate activity indicator, add it to your notification with
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
(the first two arguments are ignored), and issue the notification. The result is an indicator
that has the same style as a progress bar, except that its animation is ongoing.
</p>
<p>
Issue the notification at the beginning of the operation. The animation will run until you
modify your notification. When the operation is done, call
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}
and then update the notification to remove the activity indicator.
Always do this; otherwise, the animation will run even when the operation is complete. Also
remember to change the notification text to indicate that the operation is complete.
</p>
<p>
To see how activity indicators work, refer to the preceding snippet. Locate the following lines:
</p>
<pre>
// Sets the progress indicator to a max value, the current completion
// percentage, and "determinate" state
mBuilder.setProgress(100, incr, false);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
</pre>
<p>
Replace the lines you've found with the following lines:
</p>
<pre>
// Sets an activity indicator for an operation of indeterminate length
mBuilder.setProgress(0, 0, true);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
</pre>
<h2 id="metadata">Notification Metadata</h2>
<p>Notifications may be sorted according to metadata that you assign with the
following {@link android.support.v4.app.NotificationCompat.Builder} methods:</p>
<ul>
<li>{@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}
tells the system how to handle your app notifications when the device is in Priority mode
(for example, if your notification represents an incoming call, instant message, or alarm).</li>
<li>{@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()} causes
notifications with the priority field set to {@code PRIORITY_MAX} or {@code PRIORITY_HIGH} to
appear in a small floating window if the notification also has sound or vibration.</li>
<li>{@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}
allows you to add a list of people to a notification. Your app can use this to signal to the
system that it should group together notifications from the specified people, or rank notifications
from these people as being more important.</li>
</ul>
<div class="figure" style="width:230px">
<img src="{@docRoot}images/ui/notifications/heads-up.png"
alt="" width="" height="" id="figure3" />
<p class="img-caption">
<strong>Figure 3.</strong> Fullscreen activity showing a heads-up notification
</p>
</div>
<h2 id="Heads-up">Heads-up Notifications</h2>
<p>With Android 5.0 (API level 21), notifications can appear in a small floating window
(also called a <em>heads-up notification</em>) when the device is active
(that is, the device is unlocked and its screen is on). These notifications
appear similar to the compact form of your notification, except that the
heads-up notification also shows action buttons. Users can act on, or dismiss,
a heads-up notification without leaving the current app.</p>
<p>Examples of conditions that may trigger heads-up notifications include:</p>
<ul>
<li>The user's activity is in fullscreen mode (the app uses
{@link android.app.Notification#fullScreenIntent}), or</li>
<li>The notification has high priority and uses ringtones or
vibrations</li>
</ul>
<h2 id="lockscreenNotification">Lock Screen Notifications</h2>
<p>With the release of Android 5.0 (API level 21), notifications may now appear on the lock
screen. Your app can use this functionality to provide media playback controls and other common
actions. Users can choose via Settings whether to display notifications on the lock screen, and
you can designate whether a notification from your app is visible on the lock screen.</p>
<h3 id="visibility">Setting Visibility</h3>
<p>Your app can control the level of detail visible in notifications displayed on a secure
lock screen. You call {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}
and specify one of the following values:</p>
<ul>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC} shows the notification's
full content.</li>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET} doesn't show any part of
this notification on the lock screen.</li>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} shows basic information,
such as the notification's icon and the content title, but hides the notification's full content.</li>
</ul>
<p>When {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} is set, you can also
provide an alternate version of the notification content which hides certain details. For example,
an SMS app might display a notification that shows <em>You have 3 new text messages</em>, but hides the
message contents and senders. To provide this alternative notification, first create the replacement
notification using {@link android.support.v4.app.NotificationCompat.Builder}. When you create the
private notification object, attach the replacement notification to it through the
{@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}
method.</p>
<h3 id="controllingMedia">Controlling Media Playback on the Lock Screen</h3>
<p>
In Android 5.0 (API level 21) the lock screen no longer displays media
controls based on the {@link android.media.RemoteControlClient}, which is
now deprecated. Instead, use the {@link
android.support.v7.app.NotificationCompat.MediaStyle} template with the
{@link
android.support.v4.app.NotificationCompat.Builder#addAction(android.support.v4.app.NotificationCompat.Action)
addAction()} method, which converts actions into clickable icons.
</p>
<p>
To display media playback controls on the lock screen in Android 5.0, set
the visibility to {@link
android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, as described
above. Then add the actions and set the {@link
android.support.v7.app.NotificationCompat.MediaStyle} template, as described
in the following sample code:
</p>
<pre>
Notification notification = new NotificationCompat.Builder(context)
// Show controls on lock screen even when user hides sensitive content.
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_stat_player)
// Add media control buttons that invoke intents in your media service
.addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
.addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
.addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
// Apply the media style template
.setStyle(new NotificationCompat.MediaStyle()
.setShowActionsInCompactView(1 /* #1: pause button */)
.setMediaSession(mMediaSession.getSessionToken()))
.setContentTitle("Wonderful music")
.setContentText("My Awesome Band")
.setLargeIcon(albumArtBitmap)
.build();
</pre>
<p class="note"><strong>Note:</strong> The deprecation of {@link android.media.RemoteControlClient}
has further implications for controlling media. See
<a href="{@docRoot}about/versions/android-5.0.html#MediaPlaybackControl">Media Playback Control</a>
for more information about the new APIs for managing the media session and controlling playback.</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="CustomNotification">Custom Notification Layouts</h2>
<p>
The notifications framework allows you to define a custom notification layout, which
defines the notification's appearance in a {@link android.widget.RemoteViews} object.
Custom layout notifications are similar to normal notifications, but they're based on a
{@link android.widget.RemoteViews} defined in a XML layout file.
</p>
<p>
The height available for a custom notification layout depends on the notification view. Normal
view layouts are limited to 64 dp, and expanded view layouts are limited to 256 dp.
</p>
<p>
To define a custom notification layout, start by instantiating a
{@link android.widget.RemoteViews} object that inflates an XML layout file. Then,
instead of calling methods such as
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set
content details in the custom notification, use the methods in
{@link android.widget.RemoteViews} to set the values of the view's children:
</p>
<ol>
<li>
Create an XML layout for the notification in a separate file. You can use any file name
you wish, but you must use the extension <code>.xml</code>
</li>
<li>
In your app, use {@link android.widget.RemoteViews} methods to define your notification's
icons and text. Put this {@link android.widget.RemoteViews} object into your
{@link android.support.v4.app.NotificationCompat.Builder} by calling
{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Avoid
setting a background {@link android.graphics.drawable.Drawable} on your
{@link android.widget.RemoteViews} object, because your text color may become unreadable.
</li>
</ol>
<p>
The {@link android.widget.RemoteViews} class also includes methods that you can use to easily
add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
to your notification's layout. For more information about creating custom layouts for your
notification, refer to the {@link android.widget.RemoteViews} reference documentation.
</p>
<p class="caution">
<strong>Caution:</strong> When you use a custom notification layout, take special care to
ensure that your custom layout works with different device orientations and resolutions. While
this advice applies to all View layouts, it's especially important for notifications because
the space in the notification drawer is very restricted. Don't make your custom layout too
complex, and be sure to test it in various configurations.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h4>Using style resources for custom notification text</h4>
<p>
Always use style resources for the text of a custom notification. The background color of the
notification can vary across different devices and versions, and using style resources
helps you account for this. Starting in Android 2.3, the system defined a style for the
standard notification layout text. If you use the same style in applications that target Android
2.3 or higher, you'll ensure that your text is visible against the display background.
</p>
<!-- ------------------------------------------------------------------------ -->
<h3 id="custom"> Custom Views</h3>
<p>
Starting from Android 7.0 (API level 24),
you can customize notification views and
still obtain system decorations like notification headers, actions, and
expandable layouts.
</p>
<p>To enable this capability, Android provides the following APIs to style your
custom view:</p>
<dl>
<dt>
{@code DecoratedCustomViewStyle()}</dt>
<dd> Styles notifications other than media
notifications.</dd>
<dt>
{@code DecoratedMediaCustomViewStyle()}</dt>
<dd> Styles media notifications.</dd>
</dl>
<p>To use this API, call the {@code setStyle()} method, passing to it
the desired custom view style.</p>
<p>This snippet shows how to construct a custom notification object with the
{@code DecoratedCustomViewStyle()} method.</p>
<pre>
Notification notification = new Notification.Builder()
.setSmallIcon(R.drawable.ic_stat_player)
.setLargeIcon(albumArtBitmap))
.setCustomContentView(contentView);
.setStyle(new Notification.DecoratedCustomViewStyle())
.build();
</pre>
<!-- ----------------------------------------------------------------------- -->
<h3 id="style">Messaging Style</h3>
<p>
Starting in Android 7.0 (API level 24),
Android provides an API for customizing the style of a notification.
Using the <code>MessagingStyle</code> class, you can change several of the
labels displayed on the notification, including the conversation title,
additional messages, and the content view for the notification.
</p>
<p>
The following code snippet demonstrates how to customize a notification's
style using the <code>MessagingStyle</code> class.
</p>
<pre>
Notification notification = new Notification.Builder()
.setStyle(new Notification.MessagingStyle("Me")
.setConversationTitle("Team lunch")
.addMessage("Hi", timestamp1, null) // Pass in null for user.
.addMessage("What's up?", timestamp2, "Coworker")
.addMessage("Not much", timestamp3, null)
.addMessage("How about lunch?", timestamp4, "Coworker"))
.build();
</pre>