Skip to content

Commit 6ceca58

Browse files
author
Dianne Hackborn
committed
Update notification documentation to follow current guidelines.
The documentation is now consistent with the current UI guidelines for handling notifications, and includes complete sample code showing the correct way to do this. Change-Id: I68f0afc62c2af164c3205535e62093679e2a256a
1 parent d3be0a7 commit 6ceca58

File tree

3 files changed

+154
-103
lines changed

3 files changed

+154
-103
lines changed

core/java/android/app/Notification.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ public class Notification implements Parcelable
113113
* {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
114114
* that you take care of task management as described in the
115115
* <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
116-
* Stack</a> document.
116+
* Stack</a> document. In particular, make sure to read the notification section
117+
* <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#HandlingNotifications">Handling
118+
* Notifications</a> for the correct ways to launch an application from a
119+
* notification.
117120
*/
118121
public PendingIntent contentIntent;
119122

@@ -765,7 +768,9 @@ public Builder setContent(RemoteViews views) {
765768
* Supply a {@link PendingIntent} to send when the notification is clicked.
766769
* If you do not supply an intent, you can now add PendingIntents to individual
767770
* views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
768-
* RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.
771+
* RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to
772+
* read {@link Notification#contentIntent Notification.contentIntent} for
773+
* how to correctly use this.
769774
*/
770775
public Builder setContentIntent(PendingIntent intent) {
771776
mContentIntent = intent;

docs/html/guide/practices/ui_guidelines/activity_task_design.jd

Lines changed: 14 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ parent.link=index.html
4040
<li><a href=#reusing_tip>Handle case where no activity matches</a></li>
4141
<li><a href=#activity_launching_tip>Consider how to launch your activities</a></li>
4242
<li><a href=#activities_added_to_task_tip>Allow activities to add to current task</a></li>
43-
<li><a href=#notifications_get_back_tip>Notifications should let user easily get back</li>
43+
<li><a href=#notifications_get_back_tip>Notifications and App Widgets should provide consistent back behavior</li>
4444
<li><a href=#use_notification_tip>Use the notification system</a></li>
4545
<li><a href=#taking_over_back_key>Don't take over BACK key unless you absolutely need to</a></li>
4646
</ol>
@@ -1063,110 +1063,23 @@ MAIN and
10631063
</p>
10641064

10651065

1066-
<h3 id="notifications_get_back_tip">Notifications should let the user easily get back to the previous activity</h3>
1066+
<h3 id="notifications_get_back_tip">Notifications and App Widgets should provide consistent back behavior</h3>
10671067
<p>
1068-
Applications that are in the background or not running can have
1069-
services that send out notifications to the user letting them know about
1070-
events of interest. Two examples are Calendar, which can send out notifications of
1071-
upcoming events, and Email, which can send out notifications when new
1072-
messages arrive. One of the user interface guidelines is that when the
1073-
user is in activity A, gets a notification for activity B and
1074-
picks that notification, when they press the BACK key, they should
1075-
go back to activity A.&nbsp;
1068+
Notifications and app widgets are two common ways that a user can launch
1069+
your app through something besides its main icon in Launcher. You must
1070+
take care when implementing these so that the user has a consistent experience
1071+
with the back button, not causing surprises in where they return to or the
1072+
state the application ends up in.
10761073
</p>
10771074

10781075
<p>
1079-
The following scenario shows how the activity stack should work
1080-
when the user responds to a notification.
1081-
</p>
1082-
1083-
<ol>
1084-
<li>
1085-
User is creating a new event in Calendar. They realize they
1086-
need to copy part of an email message into this event
1087-
</li>
1088-
<li>
1089-
The user chooses Home &gt; Gmail
1090-
</li>
1091-
<li>
1092-
While in Gmail, they receive a notification from Calendar for an upcoming meeting
1093-
</li>
1094-
<li>
1095-
So they choose that notification, which takes them to a
1096-
dedicated Calendar activity that displays brief details of the
1097-
upcoming meeting
1098-
</li>
1099-
<li>
1100-
The user chooses this short notice to view further details
1101-
</li>
1102-
<li>
1103-
When done viewing the event, the user presses the BACK
1104-
key. They should be taken to Gmail, which is where they were
1105-
when they took the notification
1106-
</li>
1107-
</ol>
1108-
1109-
<p>
1110-
This behavior doesn't necessarily happen by default.
1111-
</p>
1112-
1113-
<p>
1114-
Notifications generally happen primarily in one of two ways:
1115-
</p>
1116-
1117-
<ul>
1118-
<li>
1119-
<b>The chosen activity is dedicated for notification only</b> -
1120-
For example, when the user receives a
1121-
Calendar notification, choosing that
1122-
notification starts a special activity that displays a list
1123-
of upcoming calendar events &mdash; this view is available only
1124-
from the notification, not through the Calendar's own user
1125-
interface. After viewing this upcoming event, to ensure that
1126-
the user pressing the BACK key will return to the activity
1127-
the user was in when they picked the notification, you would
1128-
make sure this dedicated activity does not have the same
1129-
task affinity as the Calendar or any other activity. (You do
1130-
this by setting task affinity to the empty string, which
1131-
means it has no affinity to anything.) The explanation for
1132-
this follows.
1133-
1134-
<p>
1135-
Because of the way tasks work, if the taskAffinity of the
1136-
dedicated activity is kept as its default, then pressing the
1137-
BACK key (in step 6, above) would go to Calendar, rather
1138-
than Gmail. The reason is that, by default, all activities
1139-
in a given application have the same task
1140-
affinity. Therefore, the task affinity of the dedicated
1141-
activity matches the Calendar task, which is already running
1142-
in step 1. This means in step 4, choosing the notification
1143-
brings the existing Calendar event (in step 1) forward and
1144-
starts the dedicated activity on top of it. This is not
1145-
what you want to have happen. Setting the dedicated
1146-
activity's taskAffinity to empty string fixes this.
1147-
</p>
1148-
</li>
1149-
1150-
<li>
1151-
<b>The chosen activity is not dedicated, but always comes to
1152-
the foreground in its initial state</b> - For example, in
1153-
response to a notification, when the Gmail application comes
1154-
to the foreground, it always presents the list of conversations.
1155-
You can ensure this happens by setting a "clear top" flag in the
1156-
intent that the notification triggers. This ensures that when the
1157-
activity is launched, it displays its initial activity, preventing
1158-
Gmail from coming to the foreground in whatever state the user last
1159-
happened to be viewing it. (To do this, you put {@link
1160-
android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP
1161-
FLAG_ACTIVITY_CLEAR_TOP} in the intent you pass to startActivity()).
1162-
</li>
1163-
</ul>
1164-
1165-
<p>
1166-
There are other ways to handle notifications, such as bringing the
1167-
activity to the foreground, set to display specific data, such as
1168-
displaying the text message thread for the person who just sent a
1169-
new text message.
1076+
The
1077+
<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#HandlingNotifications">Handling
1078+
Notifications</a> section of the developer guide's
1079+
<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
1080+
documentation provides an overview of how to write code to correctly handle
1081+
notification. This dicussion applies equally to handling interactions with
1082+
app widgets.
11701083
</p>
11711084

11721085
<p>

docs/html/guide/topics/ui/notifiers/notifications.jd

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ user clicks it</li>
1616
<h2>In this document</h2>
1717
<ol>
1818
<li><a href="#Basics">The Basics</a></li>
19+
<li><a href="#HandlingNotifications">Responding to Notifications</a></li>
1920
<li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
2021
<li><a href="#CreateANotification">Creating a Notification</a>
2122
<ol>
@@ -123,6 +124,138 @@ mNotificationManager.notify(HELLO_ID, notification);
123124
</ol>
124125

125126

127+
<h2 id="HandlingNotifications">Responding to Notifications</h2>
128+
129+
<p>A central part of the user's experience with a notification revolves around
130+
how it interacts with the application's UI flow. You must implement
131+
this correctly to provide a consistent user experience within your app.</p>
132+
133+
<p>Two typical examples of notifications are provided by Calendar, which can send out
134+
notifications of upcoming events, and Email, which can send out notifications
135+
when new messages arrive. These represent the two recommended patterns for handling
136+
notifications: either launching into an activity that is separate from the
137+
main application, or launching an entirely new instance of the application
138+
showing the appropriate point for the notification.</p>
139+
140+
<p>The following scenario shows how the activity stack should work
141+
in these two typical notification flows, first handling a Calendar notification:
142+
</p>
143+
144+
<ol>
145+
<li>User is creating a new event in Calendar. They realize they
146+
need to copy part of an email message into this event.
147+
</li>
148+
<li>
149+
The user chooses Home &gt; Email.
150+
</li>
151+
<li>
152+
While in Email, they receive a notification from Calendar for an upcoming
153+
meeting.
154+
</li>
155+
<li>
156+
So they choose that notification, which takes them to a
157+
dedicated Calendar activity that displays brief details of the
158+
upcoming meeting.
159+
</li>
160+
<li>
161+
The user has seen enough to know they have a meeting coming up,
162+
so they press the BACK button. They are now returned to Email, which
163+
is where they were when they took the notification.
164+
</li>
165+
</ol>
166+
167+
<p>Handling an Email notification:</p>
168+
169+
<ol>
170+
<li>
171+
The user is currently in Email composing a message, and needs to
172+
check a date in their calendar.
173+
</li>
174+
<li>
175+
The user chooses Home &gt; Calendar.
176+
</li>
177+
<li>
178+
While in Calendar, they receive a notification from Email about a new
179+
message.
180+
</li>
181+
<li>
182+
They select the notification, which brings them to Email with the message
183+
details displayed. This has replaced what they were previously doing
184+
(writing an e-mail), but that message is still saved in their drafts.
185+
</li>
186+
<li>
187+
The user presses BACK once to go to the message list (the typical flow in the
188+
Email app), and press BACK again to return to Calendar as they left it.
189+
</li>
190+
</ol>
191+
192+
<p>In an Email style of notification, the UI launched by the notification
193+
shows the main application in a state representing that notification.
194+
For example, when the Email application comes to the foreground from its
195+
notification, it displays either the conversion list or a specific
196+
conversation depending on whether there are multiple or only one new
197+
email. To achieve this, we want to completely replace whatever current
198+
state the application is in with a new activity stack representing the
199+
new notification state.</p>
200+
201+
<p>The following code illustrates how to show this kind of notification. Of
202+
most interest is the <code>makeMessageIntentStack()</code> method, which constructs
203+
an array of intents representing the app's new activity stack for this state.
204+
(If you are using fragments, you may need to initialize your fragment and
205+
app state so that pressing BACK will switch the UI back to its parent state.)
206+
The core of this is the {@link android.content.Intent#makeRestartActivityTask
207+
Intent.makeRestartActivityTask()} method, which constructs the root activity
208+
of the stack with the appropriate flags, such as
209+
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK}.</p>
210+
211+
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
212+
app_notification}
213+
214+
<p>In a Calendar style of notification, the UI launched by the notification
215+
is a dedicated activity that is not part of the normal application flow.
216+
For example, when the user receives a Calendar notification, choosing that
217+
notification starts a special activity that displays a list
218+
of upcoming calendar events &mdash; this view is available only
219+
from the notification, not through the Calendar's normal user
220+
interface.</p>
221+
222+
<p>The code for posting this type of notification is very straight-forward; it
223+
is like the above, but the {@link android.app.PendingIntent} is for just a single
224+
activity, our dedicated notification activity.</p>
225+
226+
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
227+
interstitial_notification}
228+
229+
<p>This is not enough, however. Normally Android considers all activities within
230+
an application to be part of that application's UI flow, so simply launching the
231+
activity like this can cause it to be mixed with your normal application back stack
232+
in undesired ways. To make it behave correctly, in the manifest declaration
233+
for the activity the attributes
234+
<code>android:launchMode="singleInstance"</code> and
235+
<code>android:excludeFromRecents="true"</code>
236+
must be set. The full activity declaration for this sample is:</p>
237+
238+
{@sample development/samples/ApiDemos/AndroidManifest.xml interstitial_affinity}
239+
240+
<p>Because of the use of <code>singleInstance</code>, you must be careful about launching
241+
any other activities from this one. These activities will be launched
242+
in their own task, and care must be taken to make sure this interacts
243+
well with the current state of your application's task. This is essentially
244+
the same as switching to the main application as described for the Email style
245+
notification shown before. Given the <code>makeMessageIntentStack()</code>
246+
method previously shown, handling a click here would look something like this:</p>
247+
248+
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageInterstitial.java
249+
app_launch}
250+
251+
<p>If you don't want to use the <code>singleInstance</code> launch mode for
252+
this activity, an alternative approach is to use <code>android:taskAffinity=""</code>.
253+
This tells Android that the activity should not be treated as part of the
254+
main application flow, so it will not get mixed together with that. All of the
255+
other issues discussed here do still apply, though this would allow you to start
256+
additional activities that are part of this notification task instead of switching
257+
to and replacing the main application task.</p>
258+
126259
<h2 id="ManageYourNotifications">Managing your Notifications</h2>
127260

128261
<p>The {@link android.app.NotificationManager} is a system service that manages all

0 commit comments

Comments
 (0)