1 page.title=Providing Proper Back Navigation 2 page.tags="back navigation","NavUtils","TaskStackBuilder" 3 4 trainingnavtop=true 5 6 @jd:body 7 8 <div id="tb-wrapper"> 9 <div id="tb"> 10 11 <h2>This lesson teaches you to:</h2> 12 <ol> 13 <li><a href="#SynthesizeBackStack">Synthesize a new Back Stack for Deep Links</a></li> 14 <li><a href="#back-fragments">Implement Back Navigation for Fragments</a></li> 15 <li><a href="#back-webviews">Implement Back Navigation for WebViews</a></li> 16 </ol> 17 18 <h2>You should also read</h2> 19 <ul> 20 <li><a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a></li> 21 <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack</a></li> 22 <li><a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a></li> 23 </ul> 24 25 </div> 26 </div> 27 28 29 <p><em>Back</em> navigation is how users move backward through the history of screens 30 they previously visited. All Android devices provide a <em>Back</em> button for this 31 type of navigation, so <strong>your app should not add a Back button to the UI</strong>.</p> 32 33 <p>In almost all situations, the system maintains a back stack of activities while the user 34 navigates your application. This allows the system to properly navigate backward when the user 35 presses the <em>Back</em> button. However, there are a few cases in which your app should manually 36 specify the <em>Back</em> behavior in order to provide the best user experience.</p> 37 38 <div class="note design"> 39 <p><strong>Back Navigation Design</strong></p> 40 <p>Before continuing with this document, you should understand the 41 concepts and principles for <em>Back</em> navigation as described in 42 the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design 43 guide.</p> 44 </div> 45 46 <p>Navigation patterns that require you to manually specify the <em>Back</em> behavior include:</p> 47 <ul> 48 <li>When the user enters a deep-level activity directly from a <a 49 href="{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a>, an <a 50 href="{@docRoot}guide/topics/appwidgets/index.html">app widget</a>, or the <a 51 href="{@docRoot}training/implementing-navigation/nav-drawer.html">navigation drawer</a>.</li> 52 <li>Certain cases in which the user navigates between <a 53 href="{@docRoot}guide/components/fragments.html">fragments</a>.</li> 54 <li>When the user navigates web pages in a {@link android.webkit.WebView}.</li> 55 </ul> 56 57 <p>How to implement proper <em>Back</em> navigation in these situations is described 58 in the following sections.</p> 59 60 61 62 <h2 id="SynthesizeBackStack">Synthesize a new Back Stack for Deep Links</h2> 63 64 <p>Ordinarily, the system incrementally builds the back stack as the user navigates from one 65 activity to the next. However, when the user enters your app with a <em>deep link</em> that 66 starts the activity in its own task, it's necessary for you to synthesize a new 67 back stack because the activity is running in a new task without any back stack at all.</p> 68 69 <p>For example, when a notification takes the user to an activity deep in your app hierarchy, 70 you should add activities into your task's back stack so that pressing <em>Back</em> navigates 71 up the app hierarchy instead of exiting the app. This pattern is described further in the 72 <a href="{@docRoot}design/patterns/navigation.html#into-your-app" 73 >Navigation</a> design guide.</p> 74 75 76 <h3 id="SpecifyParent">Specify parent activities in the manifest</h3> 77 78 <p>Beginning in Android 4.1 (API level 16), you can declare the logical parent of each 79 activity by specifying the <a 80 href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 81 android:parentActivityName}</a> attribute 82 in the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code 83 <activity>}</a> element. This allows the system to facilitate navigation patterns 84 because it can determine the logical <em>Back</em> or <em>Up</em> navigation path with this 85 information.</p> 86 87 <p>If your app supports Android 4.0 and lower, include the 88 <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with your app and 89 add a <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 90 element inside the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code 91 <activity>}</a>. Then specify the parent activity as the value 92 for {@code android.support.PARENT_ACTIVITY}, matching the <a 93 href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 94 android:parentActivityName}</a> attribute.</p> 95 96 <p>For example:</p> 97 98 <pre> 99 <application ... > 100 ... 101 <!-- The main/home activity (it has no parent activity) --> 102 <activity 103 android:name="com.example.myfirstapp.MainActivity" ...> 104 ... 105 </activity> 106 <!-- A child of the main activity --> 107 <activity 108 android:name="com.example.myfirstapp.DisplayMessageActivity" 109 android:label="@string/title_activity_display_message" 110 android:parentActivityName="com.example.myfirstapp.MainActivity" > 111 <!-- The meta-data element is needed for versions lower than 4.1 --> 112 <meta-data 113 android:name="android.support.PARENT_ACTIVITY" 114 android:value="com.example.myfirstapp.MainActivity" /> 115 </activity> 116 </application> 117 </pre> 118 119 <p>With the parent activity declared this way, you can use the 120 {@link android.support.v4.app.NavUtils} APIs to synthesize a new back stack by identifying which 121 activity is the appropriate parent for each activity.</p> 122 123 124 125 <h3 id="CreateBackStack">Create back stack when starting the activity</h3> 126 127 <p>Adding activities to the back stack begins upon the event that takes the user into your app. 128 That is, instead of calling {@link android.content.Context#startActivity startActivity()}, use the 129 {@link android.support.v4.app.TaskStackBuilder} APIs to define each activity that should 130 be placed into a new back stack. Then begin the target activity by calling {@link 131 android.support.v4.app.TaskStackBuilder#startActivities startActivities()}, or create the 132 appropriate {@link android.app.PendingIntent} by calling {@link 133 android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.</p> 134 135 <p>For example, when a notification takes the user to an activity deep in your app hierarchy, 136 you can use this code to create a {@link android.app.PendingIntent} 137 that starts an activity and inserts a new back stack into the target task:</p> 138 139 <pre> 140 // Intent for the activity to open when user selects the notification 141 Intent detailsIntent = new Intent(this, DetailsActivity.class); 142 143 // Use TaskStackBuilder to build the back stack and get the PendingIntent 144 PendingIntent pendingIntent = 145 TaskStackBuilder.create(this) 146 // add all of DetailsActivity's parents to the stack, 147 // followed by DetailsActivity itself 148 .addNextIntentWithParentStack(upIntent) 149 .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 150 151 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 152 builder.setContentIntent(pendingIntent); 153 ... 154 </pre> 155 156 <p>The resulting {@link android.app.PendingIntent} specifies not only the activity to 157 start (as defined by {@code detailsIntent}), but also the back stack that should be inserted 158 into the task (all parents of the {@code DetailsActivity} defined by {@code detailsIntent}). 159 So when the {@code DetailsActivity} starts, pressing <em>Back</em> 160 navigates backward through each of the {@code DetailsActivity} class's parent activities.</p> 161 162 <p class="note"><strong>Note:</strong> In order for the {@link 163 android.support.v4.app.TaskStackBuilder#addNextIntentWithParentStack addNextIntentWithParentStack()} 164 method to work, 165 you must declare the logical parent of each activity in your manifest file, using the 166 <a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 167 android:parentActivityName}</a> attribute (and corresponding <a 168 href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> element) 169 as described above.</p> 170 171 172 173 174 175 <h2 id="back-fragments">Implement Back Navigation for Fragments</h2> 176 177 <p>When using fragments in your app, individual {@link android.app.FragmentTransaction} 178 objects may represent context changes that should be added to the back stack. For example, if you 179 are implementing a <a href="descendant.html#master-detail">master/detail flow</a> on a handset by 180 swapping out fragments, you should ensure that pressing the <em>Back</em> button on a detail 181 screen returns the user to the master screen. To do so, call {@link 182 android.app.FragmentTransaction#addToBackStack addToBackStack()} before you commit 183 the transaction:</p> 184 185 <pre> 186 // Works with either the framework FragmentManager or the 187 // support package FragmentManager (getSupportFragmentManager). 188 getSupportFragmentManager().beginTransaction() 189 .add(detailFragment, "detail") 190 // Add this transaction to the back stack 191 .addToBackStack() 192 .commit(); 193 </pre> 194 195 <p>When there are {@link android.app.FragmentTransaction} objects on the back stack and the user 196 presses the <em>Back</em> button, 197 the {@link android.app.FragmentManager} pops the most recent transaction off the back stack and 198 performs the reverse action (such as removing a fragment if the transaction added it).</p> 199 200 <p class="note"><strong>Note:</strong> You <strong>should not add transactions to the back 201 stack</strong> when the transaction is for horizontal navigation (such as when switching tabs) 202 or when modifying the content appearance (such as when adjusting filters). For more information, 203 about when <em>Back</em> navigation is appropriate, 204 see the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design guide.</p> 205 206 <p>If your application updates other user interface elements to reflect the current state of your 207 fragments, such as the action bar, remember to update the UI when you commit the transaction. You 208 should update your user interface after the back stack changes in addition to 209 when you commit the transaction. You can listen for when a {@link android.app.FragmentTransaction} 210 is reverted by setting up an {@link android.app.FragmentManager.OnBackStackChangedListener}:</p> 211 212 <pre> 213 getSupportFragmentManager().addOnBackStackChangedListener( 214 new FragmentManager.OnBackStackChangedListener() { 215 public void onBackStackChanged() { 216 // Update your UI here. 217 } 218 }); 219 </pre> 220 221 222 223 <h2 id="back-webviews">Implement Back Navigation for WebViews</h2> 224 225 <p>If a part of your application is contained in a {@link android.webkit.WebView}, it may be 226 appropriate for <em>Back</em> to traverse browser history. To do so, you can override {@link 227 android.app.Activity#onBackPressed onBackPressed()} and proxy to the 228 {@link android.webkit.WebView} if it has history state:</p> 229 230 <pre> 231 {@literal @}Override 232 public void onBackPressed() { 233 if (mWebView.canGoBack()) { 234 mWebView.goBack(); 235 return; 236 } 237 238 // Otherwise defer to system default behavior. 239 super.onBackPressed(); 240 } 241 </pre> 242 243 <p>Be careful when using this mechanism with highly dynamic web pages that can grow a large 244 history. Pages that generate an extensive history, such as those that make frequent changes to 245 the document hash, may make it tedious for users to get out of your activity.</p> 246 247 <p>For more information about using {@link android.webkit.WebView}, read <a 248 href="{@docRoot}guide/webapps/webview.html">Building Web Apps in WebView</a>. 249