1c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell/* 2c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Copyright (C) 2012 The Android Open Source Project 3c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 4c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * you may not use this file except in compliance with the License. 6c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * You may obtain a copy of the License at 7c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 8c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * http://www.apache.org/licenses/LICENSE-2.0 9c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 10c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Unless required by applicable law or agreed to in writing, software 11c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * See the License for the specific language governing permissions and 14c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * limitations under the License. 15c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 16c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 17c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellpackage android.support.v4.app; 18c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 19c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.app.Activity; 20c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.app.PendingIntent; 21f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powellimport android.content.ComponentName; 22c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.Context; 23c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.Intent; 24c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.pm.PackageManager.NameNotFoundException; 25c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.os.Build; 260306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powellimport android.os.Bundle; 27575e098da5bc16ff8b95ca080284253fd206fe12Adam Powellimport android.support.v4.content.ContextCompat; 28c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.support.v4.content.IntentCompat; 29c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.util.Log; 30c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 31c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport java.util.ArrayList; 32c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport java.util.Iterator; 33c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 34c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell/** 35c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Utility class for constructing synthetic back stacks for cross-task navigation 36c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * on Android 3.0 and newer. 37c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 38c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for 39c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * app navigation using the back key changed. The back key's behavior is local 40c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * to the current task and does not capture navigation across different tasks. 41c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Navigating across tasks and easily reaching the previous task is accomplished 42c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * through the "recents" UI, accessible through the software-provided Recents key 43c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * on the navigation or system bar. On devices with the older hardware button configuration 44c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the recents UI can be accessed with a long press on the Home key.</p> 45c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 46c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p>When crossing from one task stack to another post-Android 3.0, 47c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the application should synthesize a back stack/history for the new task so that 48c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the user may navigate out of the new task and back to the Launcher by repeated 49c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * presses of the back key. Back key presses should not navigate across task stacks.</p> 50c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 51c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p>TaskStackBuilder provides a backward-compatible way to obey the correct conventions 52c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * around cross-task navigation on the device's version of the platform. On devices running 53c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Android 3.0 or newer, calls to the {@link #startActivities()} method or sending the 54c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link PendingIntent} generated by {@link #getPendingIntent(int, int)} will construct 55c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the synthetic back stack as prescribed. On devices running older versions of the platform, 56c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * these same calls will invoke the topmost activity in the supplied stack, ignoring 57c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the rest of the synthetic stack and allowing the back key to navigate back to the previous 58c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * task.</p> 59c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 60c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <div class="special reference"> 61c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <h3>About Navigation</h3> 62c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * For more detailed information about tasks, the back stack, and navigation design guidelines, 63c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * please read 64c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a> 65c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * from the developer guide and <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> 66c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * from the design guide. 67c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * </div> 68c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 69c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class TaskStackBuilder implements Iterable<Intent> { 70c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private static final String TAG = "TaskStackBuilder"; 71c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 726f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes public interface SupportParentable { 736f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes Intent getSupportParentActivityIntent(); 746f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes } 756f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes 76c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell interface TaskStackBuilderImpl { 77c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, 780306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell int flags, Bundle options); 79c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 80c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 81c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell static class TaskStackBuilderImplBase implements TaskStackBuilderImpl { 82c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, 830306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell int flags, Bundle options) { 84f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell Intent topIntent = new Intent(intents[intents.length - 1]); 85c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 86c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return PendingIntent.getActivity(context, requestCode, topIntent, flags); 87c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 88c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 89c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 90c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell static class TaskStackBuilderImplHoneycomb implements TaskStackBuilderImpl { 91c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, 920306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell int flags, Bundle options) { 93f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 94f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | 95f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); 96c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return TaskStackBuilderHoneycomb.getActivitiesPendingIntent(context, requestCode, 97c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell intents, flags); 98c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 99c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 100c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 1010306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell static class TaskStackBuilderImplJellybean implements TaskStackBuilderImpl { 1020306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, 1030306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell int flags, Bundle options) { 104f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 105f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | 106f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); 1070306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell return TaskStackBuilderJellybean.getActivitiesPendingIntent(context, requestCode, 1080306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell intents, flags, options); 1090306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 1100306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 1110306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell 112c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private static final TaskStackBuilderImpl IMPL; 113c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 114c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell static { 115c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell if (Build.VERSION.SDK_INT >= 11) { 116c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell IMPL = new TaskStackBuilderImplHoneycomb(); 117c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } else { 118c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell IMPL = new TaskStackBuilderImplBase(); 119c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 120c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 121c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 122c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private final ArrayList<Intent> mIntents = new ArrayList<Intent>(); 123c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private final Context mSourceContext; 124c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 125c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private TaskStackBuilder(Context a) { 126c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell mSourceContext = a; 127c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 128c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 129c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 130c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Return a new TaskStackBuilder for launching a fresh task stack consisting 131c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * of a series of activities. 132c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 133c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param context The context that will launch the new task stack or generate a PendingIntent 134c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return A new TaskStackBuilder 135c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 1360306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public static TaskStackBuilder create(Context context) { 137c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return new TaskStackBuilder(context); 138c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 139c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 140c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 1410306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * Return a new TaskStackBuilder for launching a fresh task stack consisting 1420306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * of a series of activities. 1430306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 1440306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @param context The context that will launch the new task stack or generate a PendingIntent 1450306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @return A new TaskStackBuilder 1460306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 1470306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @deprecated use {@link #create(Context)} instead 1480306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell */ 149d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette @Deprecated 1500306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public static TaskStackBuilder from(Context context) { 1510306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell return create(context); 1520306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 1530306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell 1540306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell /** 155c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Add a new Intent to the task stack. The most recently added Intent will invoke 156c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the Activity at the top of the final task stack. 157c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 158c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param nextIntent Intent for the next Activity in the synthesized task stack 159c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return This TaskStackBuilder for method chaining 160c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 161c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public TaskStackBuilder addNextIntent(Intent nextIntent) { 162c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell mIntents.add(nextIntent); 163c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return this; 164c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 165c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 166c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 167f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * Add a new Intent with the resolved chain of parents for the target activity to 168f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * the task stack. 169f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * 170f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * <p>This is equivalent to calling {@link #addParentStack(ComponentName) addParentStack} 171f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * with the resolved ComponentName of nextIntent (if it can be resolved), followed by 172f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * {@link #addNextIntent(Intent) addNextIntent} with nextIntent.</p> 173f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * 174f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * @param nextIntent Intent for the topmost Activity in the synthesized task stack. 175f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * Its chain of parents as specified in the manifest will be added. 176f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * @return This TaskStackBuilder for method chaining. 177f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell */ 178f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell public TaskStackBuilder addNextIntentWithParentStack(Intent nextIntent) { 179f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell ComponentName target = nextIntent.getComponent(); 180f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell if (target == null) { 181f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell target = nextIntent.resolveActivity(mSourceContext.getPackageManager()); 182f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 183f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell if (target != null) { 184f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell addParentStack(target); 185f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 186f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell addNextIntent(nextIntent); 187f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return this; 188f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 189f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 190f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell /** 191c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Add the activity parent chain as specified by manifest <meta-data> elements 192c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * to the task stack builder. 193c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 194c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivity All parents of this activity will be added 195c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return This TaskStackBuilder for method chaining 196c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 197c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public TaskStackBuilder addParentStack(Activity sourceActivity) { 1986f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes Intent parent = null; 1996f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes if (sourceActivity instanceof SupportParentable) { 2006f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes parent = ((SupportParentable) sourceActivity).getSupportParentActivityIntent(); 2016f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes } 2026f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes if (parent == null) { 2036f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes parent = NavUtils.getParentActivityIntent(sourceActivity); 2046f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes } 2056f9952fd5a1dc66c584b26b9062ba6efd69ebcc7Chris Banes 206f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell if (parent != null) { 207f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell // We have the actual parent intent, build the rest from static metadata 208f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell // then add the direct parent intent to the end. 209f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell ComponentName target = parent.getComponent(); 210f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell if (target == null) { 211f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell target = parent.resolveActivity(mSourceContext.getPackageManager()); 212c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 213f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell addParentStack(target); 214f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell addNextIntent(parent); 215c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 216c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return this; 217c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 218c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 219c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 220c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Add the activity parent chain as specified by manifest <meta-data> elements 221c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * to the task stack builder. 222c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 223c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivityClass All parents of this activity will be added 224c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return This TaskStackBuilder for method chaining 225c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 226c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public TaskStackBuilder addParentStack(Class<?> sourceActivityClass) { 227f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return addParentStack(new ComponentName(mSourceContext, sourceActivityClass)); 228f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 229f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 230f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell /** 231f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * Add the activity parent chain as specified by manifest <meta-data> elements 232f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * to the task stack builder. 233f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * 234f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * @param sourceActivityName Must specify an Activity component. All parents of 235f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * this activity will be added 236f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell * @return This TaskStackBuilder for method chaining 237f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell */ 238f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell public TaskStackBuilder addParentStack(ComponentName sourceActivityName) { 239c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell final int insertAt = mIntents.size(); 240c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell try { 241f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell Intent parent = NavUtils.getParentActivityIntent(mSourceContext, sourceActivityName); 242c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell while (parent != null) { 243c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell mIntents.add(insertAt, parent); 244c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell parent = NavUtils.getParentActivityIntent(mSourceContext, parent.getComponent()); 245c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 246c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } catch (NameNotFoundException e) { 247c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell Log.e(TAG, "Bad ComponentName while traversing activity parent metadata"); 248c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throw new IllegalArgumentException(e); 249c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 250c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return this; 251c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 252c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 253c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 254c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return the number of intents added so far. 255c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 256c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public int getIntentCount() { 257c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return mIntents.size(); 258c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 259c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 260c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 261c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Get the intent at the specified index. 262c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Useful if you need to modify the flags or extras of an intent that was previously added, 263c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * for example with {@link #addParentStack(Activity)}. 264c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 265c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param index Index from 0-getIntentCount() 266c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return the intent at position index 2670306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 2680306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @deprecated Renamed to editIntentAt to better reflect intended usage 269c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 270d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette @Deprecated 271c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public Intent getIntent(int index) { 2720306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell return editIntentAt(index); 2730306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 2740306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell 2750306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell /** 2760306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * Return the intent at the specified index for modification. 2770306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * Useful if you need to modify the flags or extras of an intent that was previously added, 2780306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * for example with {@link #addParentStack(Activity)}. 2790306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 2800306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @param index Index from 0-getIntentCount() 2810306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @return the intent at position index 2820306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell */ 2830306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public Intent editIntentAt(int index) { 284c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return mIntents.get(index); 285c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 286c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 2870306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell /** 2880306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @deprecated Use editIntentAt instead 2890306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell */ 290d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette @Deprecated 291c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public Iterator<Intent> iterator() { 292c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return mIntents.iterator(); 293c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 294c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 295c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 296c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Start the task stack constructed by this builder. The Context used to obtain 297c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * this builder must be an Activity. 298c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 299c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p>On devices that do not support API level 11 or higher the topmost activity 300c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * will be started as a new task. On devices that do support API level 11 or higher 301c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the new task stack will be created in its entirety.</p> 302c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 303c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public void startActivities() { 3040306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell startActivities(null); 3050306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 3060306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell 3070306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell /** 3080306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * Start the task stack constructed by this builder. The Context used to obtain 3090306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * this builder must be an Activity. 3100306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 3110306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * <p>On devices that do not support API level 11 or higher the topmost activity 3120306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * will be started as a new task. On devices that do support API level 11 or higher 3130306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * the new task stack will be created in its entirety.</p> 3140306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 3150306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @param options Additional options for how the Activity should be started. 3160306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * See {@link android.content.Context#startActivity(Intent, Bundle) 3170306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell */ 3180306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public void startActivities(Bundle options) { 319c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell if (mIntents.isEmpty()) { 320c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throw new IllegalStateException( 321c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell "No intents added to TaskStackBuilder; cannot startActivities"); 322c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 323c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 324c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]); 325f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 326c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | 327c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); 328575e098da5bc16ff8b95ca080284253fd206fe12Adam Powell if (!ContextCompat.startActivities(mSourceContext, intents, options)) { 329f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell Intent topIntent = new Intent(intents[intents.length - 1]); 330c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 331c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell mSourceContext.startActivity(topIntent); 332c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 333c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 334c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 335c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 336c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far. 337c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 338c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param requestCode Private request code for the sender 339c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT}, 340c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT}, 341c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by 342c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the 343c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * intent that can be supplied when the actual send happens. 344c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return The obtained PendingIntent 345c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 346c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public PendingIntent getPendingIntent(int requestCode, int flags) { 3470306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell return getPendingIntent(requestCode, flags, null); 3480306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 3490306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell 3500306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell /** 3510306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far. 3520306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 3530306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @param requestCode Private request code for the sender 3540306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT}, 3550306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT}, 3560306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by 3570306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the 3580306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * intent that can be supplied when the actual send happens. 3590306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @param options Additional options for how the Activity should be started. 3600306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * See {@link android.content.Context#startActivity(Intent, Bundle) 3610306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @return The obtained PendingIntent 3620306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell */ 3630306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options) { 36456a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell if (mIntents.isEmpty()) { 36556a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell throw new IllegalStateException( 36656a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell "No intents added to TaskStackBuilder; cannot getPendingIntent"); 36756a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell } 36856a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell 369c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]); 370f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 37156a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | 37256a1f598b89d0e65dbd2a2678b66a43f5b7638c2Adam Powell IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); 373f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell // Appropriate flags will be added by the call below. 3740306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags, options); 3750306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell } 3760306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell 3770306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell /** 3780306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * Return an array containing the intents added to this builder. The intent at the 3790306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * root of the task stack will appear as the first item in the array and the 3800306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * intent at the top of the stack will appear as the last item. 3810306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * 3820306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell * @return An array containing the intents added to this builder. 3830306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell */ 3840306ebc908d5dcf148aa319a9734b419eacb23b5Adam Powell public Intent[] getIntents() { 385f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell Intent[] intents = new Intent[mIntents.size()]; 386f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell if (intents.length == 0) return intents; 387f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 388f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 389f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | 390f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); 391f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell for (int i = 1; i < intents.length; i++) { 392f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell intents[i] = new Intent(mIntents.get(i)); 393f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 394f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return intents; 395c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 396c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell} 397