Merge "Update notification documentation to follow current guidelines." into ics-mr1

This commit is contained in:
Dianne Hackborn
2012-01-13 16:36:05 -08:00
committed by Android (Google) Code Review
3 changed files with 154 additions and 103 deletions

View File

@ -113,7 +113,10 @@ public class Notification implements Parcelable
* {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
* that you take care of task management as described in the
* <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
* Stack</a> document.
* Stack</a> document. In particular, make sure to read the notification section
* <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#HandlingNotifications">Handling
* Notifications</a> for the correct ways to launch an application from a
* notification.
*/
public PendingIntent contentIntent;
@ -765,7 +768,9 @@ public class Notification implements Parcelable
* Supply a {@link PendingIntent} to send when the notification is clicked.
* If you do not supply an intent, you can now add PendingIntents to individual
* views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
* RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.
* RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to
* read {@link Notification#contentIntent Notification.contentIntent} for
* how to correctly use this.
*/
public Builder setContentIntent(PendingIntent intent) {
mContentIntent = intent;

View File

@ -40,7 +40,7 @@ parent.link=index.html
<li><a href=#reusing_tip>Handle case where no activity matches</a></li>
<li><a href=#activity_launching_tip>Consider how to launch your activities</a></li>
<li><a href=#activities_added_to_task_tip>Allow activities to add to current task</a></li>
<li><a href=#notifications_get_back_tip>Notifications should let user easily get back</li>
<li><a href=#notifications_get_back_tip>Notifications and App Widgets should provide consistent back behavior</li>
<li><a href=#use_notification_tip>Use the notification system</a></li>
<li><a href=#taking_over_back_key>Don't take over BACK key unless you absolutely need to</a></li>
</ol>
@ -1063,110 +1063,23 @@ MAIN and
</p>
<h3 id="notifications_get_back_tip">Notifications should let the user easily get back to the previous activity</h3>
<h3 id="notifications_get_back_tip">Notifications and App Widgets should provide consistent back behavior</h3>
<p>
Applications that are in the background or not running can have
services that send out notifications to the user letting them know about
events of interest. Two examples are Calendar, which can send out notifications of
upcoming events, and Email, which can send out notifications when new
messages arrive. One of the user interface guidelines is that when the
user is in activity A, gets a notification for activity B and
picks that notification, when they press the BACK key, they should
go back to activity A.&nbsp;
Notifications and app widgets are two common ways that a user can launch
your app through something besides its main icon in Launcher. You must
take care when implementing these so that the user has a consistent experience
with the back button, not causing surprises in where they return to or the
state the application ends up in.
</p>
<p>
The following scenario shows how the activity stack should work
when the user responds to a notification.
</p>
<ol>
<li>
User is creating a new event in Calendar. They realize they
need to copy part of an email message into this event
</li>
<li>
The user chooses Home &gt; Gmail
</li>
<li>
While in Gmail, they receive a notification from Calendar for an upcoming meeting
</li>
<li>
So they choose that notification, which takes them to a
dedicated Calendar activity that displays brief details of the
upcoming meeting
</li>
<li>
The user chooses this short notice to view further details
</li>
<li>
When done viewing the event, the user presses the BACK
key. They should be taken to Gmail, which is where they were
when they took the notification
</li>
</ol>
<p>
This behavior doesn't necessarily happen by default.
</p>
<p>
Notifications generally happen primarily in one of two ways:
</p>
<ul>
<li>
<b>The chosen activity is dedicated for notification only</b> -
For example, when the user receives a
Calendar notification, choosing that
notification starts a special activity that displays a list
of upcoming calendar events &mdash; this view is available only
from the notification, not through the Calendar's own user
interface. After viewing this upcoming event, to ensure that
the user pressing the BACK key will return to the activity
the user was in when they picked the notification, you would
make sure this dedicated activity does not have the same
task affinity as the Calendar or any other activity. (You do
this by setting task affinity to the empty string, which
means it has no affinity to anything.) The explanation for
this follows.
<p>
Because of the way tasks work, if the taskAffinity of the
dedicated activity is kept as its default, then pressing the
BACK key (in step 6, above) would go to Calendar, rather
than Gmail. The reason is that, by default, all activities
in a given application have the same task
affinity. Therefore, the task affinity of the dedicated
activity matches the Calendar task, which is already running
in step 1. This means in step 4, choosing the notification
brings the existing Calendar event (in step 1) forward and
starts the dedicated activity on top of it. This is not
what you want to have happen. Setting the dedicated
activity's taskAffinity to empty string fixes this.
</p>
</li>
<li>
<b>The chosen activity is not dedicated, but always comes to
the foreground in its initial state</b> - For example, in
response to a notification, when the Gmail application comes
to the foreground, it always presents the list of conversations.
You can ensure this happens by setting a "clear top" flag in the
intent that the notification triggers. This ensures that when the
activity is launched, it displays its initial activity, preventing
Gmail from coming to the foreground in whatever state the user last
happened to be viewing it. (To do this, you put {@link
android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_CLEAR_TOP} in the intent you pass to startActivity()).
</li>
</ul>
<p>
There are other ways to handle notifications, such as bringing the
activity to the foreground, set to display specific data, such as
displaying the text message thread for the person who just sent a
new text message.
The
<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#HandlingNotifications">Handling
Notifications</a> section of the developer guide's
<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
documentation provides an overview of how to write code to correctly handle
notification. This dicussion applies equally to handling interactions with
app widgets.
</p>
<p>

View File

@ -16,6 +16,7 @@ user clicks it</li>
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#HandlingNotifications">Responding to Notifications</a></li>
<li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
<li><a href="#CreateANotification">Creating a Notification</a>
<ol>
@ -137,6 +138,138 @@ mNotificationManager.notify(HELLO_ID, notification);
</ol>
<h2 id="HandlingNotifications">Responding to Notifications</h2>
<p>A central part of the user's experience with a notification revolves around
how it interacts with the application's UI flow. You must implement
this correctly to provide a consistent user experience within your app.</p>
<p>Two typical examples of notifications are provided by Calendar, which can send out
notifications of upcoming events, and Email, which can send out notifications
when new messages arrive. These represent the two recommended patterns for handling
notifications: either launching into an activity that is separate from the
main application, or launching an entirely new instance of the application
showing the appropriate point for the notification.</p>
<p>The following scenario shows how the activity stack should work
in these two typical notification flows, first handling a Calendar notification:
</p>
<ol>
<li>User is creating a new event in Calendar. They realize they
need to copy part of an email message into this event.
</li>
<li>
The user chooses Home &gt; Email.
</li>
<li>
While in Email, they receive a notification from Calendar for an upcoming
meeting.
</li>
<li>
So they choose that notification, which takes them to a
dedicated Calendar activity that displays brief details of the
upcoming meeting.
</li>
<li>
The user has seen enough to know they have a meeting coming up,
so they press the BACK button. They are now returned to Email, which
is where they were when they took the notification.
</li>
</ol>
<p>Handling an Email notification:</p>
<ol>
<li>
The user is currently in Email composing a message, and needs to
check a date in their calendar.
</li>
<li>
The user chooses Home &gt; Calendar.
</li>
<li>
While in Calendar, they receive a notification from Email about a new
message.
</li>
<li>
They select the notification, which brings them to Email with the message
details displayed. This has replaced what they were previously doing
(writing an e-mail), but that message is still saved in their drafts.
</li>
<li>
The user presses BACK once to go to the message list (the typical flow in the
Email app), and press BACK again to return to Calendar as they left it.
</li>
</ol>
<p>In an Email style of notification, the UI launched by the notification
shows the main application in a state representing that notification.
For example, when the Email application comes to the foreground from its
notification, it displays either the conversion list or a specific
conversation depending on whether there are multiple or only one new
email. To achieve this, we want to completely replace whatever current
state the application is in with a new activity stack representing the
new notification state.</p>
<p>The following code illustrates how to show this kind of notification. Of
most interest is the <code>makeMessageIntentStack()</code> method, which constructs
an array of intents representing the app's new activity stack for this state.
(If you are using fragments, you may need to initialize your fragment and
app state so that pressing BACK will switch the UI back to its parent state.)
The core of this is the {@link android.content.Intent#makeRestartActivityTask
Intent.makeRestartActivityTask()} method, which constructs the root activity
of the stack with the appropriate flags, such as
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK}.</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
app_notification}
<p>In a Calendar style of notification, the UI launched by the notification
is a dedicated activity that is not part of the normal application flow.
For example, when the user receives a Calendar notification, choosing that
notification starts a special activity that displays a list
of upcoming calendar events &mdash; this view is available only
from the notification, not through the Calendar's normal user
interface.</p>
<p>The code for posting this type of notification is very straight-forward; it
is like the above, but the {@link android.app.PendingIntent} is for just a single
activity, our dedicated notification activity.</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
interstitial_notification}
<p>This is not enough, however. Normally Android considers all activities within
an application to be part of that application's UI flow, so simply launching the
activity like this can cause it to be mixed with your normal application back stack
in undesired ways. To make it behave correctly, in the manifest declaration
for the activity the attributes
<code>android:launchMode="singleInstance"</code> and
<code>android:excludeFromRecents="true"</code>
must be set. The full activity declaration for this sample is:</p>
{@sample development/samples/ApiDemos/AndroidManifest.xml interstitial_affinity}
<p>Because of the use of <code>singleInstance</code>, you must be careful about launching
any other activities from this one. These activities will be launched
in their own task, and care must be taken to make sure this interacts
well with the current state of your application's task. This is essentially
the same as switching to the main application as described for the Email style
notification shown before. Given the <code>makeMessageIntentStack()</code>
method previously shown, handling a click here would look something like this:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageInterstitial.java
app_launch}
<p>If you don't want to use the <code>singleInstance</code> launch mode for
this activity, an alternative approach is to use <code>android:taskAffinity=""</code>.
This tells Android that the activity should not be treated as part of the
main application flow, so it will not get mixed together with that. All of the
other issues discussed here do still apply, though this would allow you to start
additional activities that are part of this notification task instead of switching
to and replacing the main application task.</p>
<h2 id="ManageYourNotifications">Managing your Notifications</h2>
<p>The {@link android.app.NotificationManager} is a system service that manages all