Home | History | Annotate | Download | only in notify-user
      1 page.title=Preserving Navigation when Starting an Activity
      2 page.tags=notifications
      3 helpoutsWidget=true
      4 
      5 trainingnavtop=true
      6 
      7 @jd:body
      8 
      9 <div id="tb-wrapper">
     10 <div id="tb">
     11 
     12 <!-- table of contents -->
     13 <h2>This lesson teaches you to</h2>
     14 <ol>
     15   <li><a href="#DirectEntry">Set up a regular activity PendingIntent</a></li>
     16   <li><a href="#ExtendedNotification">Set up a special activity PendingIntent</a></li>
     17 </ol>
     18 
     19 <!-- other docs (NOT javadocs) -->
     20 <h2>You should also read</h2>
     21 
     22 <ul>
     23     <li>
     24         <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a> API Guide
     25     </li>
     26     <li>
     27         <a href="{@docRoot}guide/components/intents-filters.html">
     28         Intents and Intent Filters
     29         </a>
     30     </li>
     31     <li>
     32         <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design Guide
     33     </li>
     34 </ul>
     35 
     36 
     37 </div>
     38 </div>
     39 <p>
     40     Part of designing a notification is preserving the user's expected navigation experience. 
     41     For a detailed discussion of this topic, see the
     42     <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#NotificationResponse">Notifications</a>
     43     API guide.
     44     There are two general situations:
     45 </p>
     46 <dl>
     47     <dt>
     48         Regular activity
     49     </dt>
     50     <dd>
     51         You're starting an {@link android.app.Activity} that's part of the application's normal
     52         workflow. 
     53     </dd>
     54     <dt>
     55         Special activity
     56     </dt>
     57     <dd>
     58         The user only sees this {@link android.app.Activity} if it's started from a notification.
     59         In a sense, the {@link android.app.Activity} extends the notification by providing
     60         information that would be hard to display in the notification itself.
     61     </dd>
     62 </dl>
     63 <!-- ------------------------------------------------------------------------------------------ -->
     64 <h2 id="DirectEntry">Set Up a Regular Activity PendingIntent</h2>
     65 <p>
     66     To set up a {@link android.app.PendingIntent} that starts a direct entry
     67     {@link android.app.Activity}, follow these steps:
     68 </p>
     69 <ol>
     70     <li>
     71         Define your application's {@link android.app.Activity} hierarchy in the manifest. The final XML should look like this:
     72         </p>
     73 <pre>
     74 &lt;activity
     75     android:name=".MainActivity"
     76     android:label="&#64;string/app_name" &gt;
     77     &lt;intent-filter&gt;
     78         &lt;action android:name="android.intent.action.MAIN" /&gt;
     79         &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
     80     &lt;/intent-filter&gt;
     81 &lt;/activity&gt;
     82 &lt;activity
     83     android:name=".ResultActivity"
     84     android:parentActivityName=".MainActivity"&gt;
     85     &lt;meta-data
     86         android:name="android.support.PARENT_ACTIVITY"
     87         android:value=".MainActivity"/&gt;
     88 &lt;/activity&gt;
     89 </pre>
     90     </li>
     91     <li>
     92         Create a back stack based on the {@link android.content.Intent} that starts the
     93         {@link android.app.Activity}. For example:
     94 </p>
     95 <pre>
     96 int id = 1;
     97 ...
     98 Intent resultIntent = new Intent(this, ResultActivity.class);
     99 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    100 // Adds the back stack
    101 stackBuilder.addParentStack(ResultActivity.class);
    102 // Adds the Intent to the top of the stack
    103 stackBuilder.addNextIntent(resultIntent);
    104 // Gets a PendingIntent containing the entire back stack
    105 PendingIntent resultPendingIntent =
    106         stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    107 ...
    108 NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    109 builder.setContentIntent(resultPendingIntent);
    110 NotificationManager mNotificationManager =
    111     (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    112 mNotificationManager.notify(id, builder.build());
    113 </pre>
    114 <!-- ------------------------------------------------------------------------------------------ -->
    115 <h2 id="ExtendedNotification">Set Up a Special Activity PendingIntent</h2>
    116 
    117 <p>
    118     A special {@link android.app.Activity} doesn't need a back stack, so you don't have to
    119     define its {@link android.app.Activity} hierarchy in the manifest, and you don't have
    120     to call
    121     {@link android.support.v4.app.TaskStackBuilder#addParentStack  addParentStack()} to build a
    122     back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options,
    123     and create the {@link android.app.PendingIntent} by calling
    124     {@link android.app.PendingIntent#getActivity getActivity()}:
    125 </p>
    126 <ol>
    127     <li>
    128         In your manifest, add the following attributes to the
    129 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
    130         element for the {@link android.app.Activity}:
    131         <dl>
    132             <dt>
    133 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
    134             </dt>
    135             <dd>
    136                 The activity's fully-qualified class name.
    137             </dd>
    138             <dt>
    139 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
    140             </dt>
    141             <dd>
    142                 Combined with the
    143                 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag
    144                 that you set in code, this ensures that this {@link android.app.Activity} doesn't
    145                 go into the application's default task. Any existing tasks that have the
    146                 application's default affinity are not affected.
    147             </dd>
    148             <dt>
    149 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
    150             </dt>
    151             <dd>
    152                 Excludes the new task from <i>Recents</i>, so that the user can't accidentally
    153                 navigate back to it.
    154             </dd>
    155         </dl>
    156         <p>
    157             This snippet shows the element:
    158         </p>
    159 <pre>
    160 &lt;activity
    161     android:name=".ResultActivity"
    162 ...
    163     android:launchMode="singleTask"
    164     android:taskAffinity=""
    165     android:excludeFromRecents="true"&gt;
    166 &lt;/activity&gt;
    167 ...
    168 </pre>
    169     </li>
    170     <li>
    171         Build and issue the notification:
    172         <ol style="list-style-type: lower-alpha;">
    173             <li>
    174                 Create an {@link android.content.Intent} that starts the
    175                 {@link android.app.Activity}.
    176             </li>
    177             <li>
    178                 Set the {@link android.app.Activity} to start in a new, empty task by calling
    179                 {@link android.content.Intent#setFlags setFlags()} with the flags
    180                 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
    181                 and
    182                 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
    183             </li>
    184             <li>
    185                 Set any other options you need for the {@link android.content.Intent}.
    186             </li>
    187             <li>
    188                 Create a {@link android.app.PendingIntent} from the {@link android.content.Intent}
    189                 by calling {@link android.app.PendingIntent#getActivity getActivity()}.
    190                 You can then use this {@link android.app.PendingIntent} as the argument to
    191                 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
    192                 setContentIntent()}.
    193             </li>
    194         </ol>
    195     <p>
    196         The following code snippet demonstrates the process:
    197     </p>
    198 <pre>
    199 // Instantiate a Builder object.
    200 NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    201 // Creates an Intent for the Activity
    202 Intent notifyIntent =
    203         new Intent(new ComponentName(this, ResultActivity.class));
    204 // Sets the Activity to start in a new, empty task
    205 notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 
    206         Intent.FLAG_ACTIVITY_CLEAR_TASK);
    207 // Creates the PendingIntent
    208 PendingIntent notifyIntent =
    209         PendingIntent.getActivity(
    210         this,
    211         0,
    212         notifyIntent,
    213         PendingIntent.FLAG_UPDATE_CURRENT
    214 );
    215 
    216 // Puts the PendingIntent into the notification builder
    217 builder.setContentIntent(notifyIntent);
    218 // Notifications are issued by sending them to the
    219 // NotificationManager system service.
    220 NotificationManager mNotificationManager =
    221     (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    222 // Builds an anonymous Notification object from the builder, and
    223 // passes it to the NotificationManager
    224 mNotificationManager.notify(id, builder.build());
    225 </pre>
    226     </li>
    227 </ol>
    228