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.content.ComponentName; 21c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.Context; 22c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.Intent; 23c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.pm.ActivityInfo; 24c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.pm.PackageManager; 25c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellimport android.content.pm.PackageManager.NameNotFoundException; 26f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powellimport android.support.v4.content.IntentCompat; 27f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powellimport android.util.Log; 28c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 29c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell/** 30c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * NavUtils provides helper functionality for applications implementing 31c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * recommended Android UI navigation patterns. For information about recommended 32c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * navigation patterns see 33c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a> 34c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * from the developer guide and <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> 35c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * from the design guide. 36c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 37c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powellpublic class NavUtils { 38c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private static final String TAG = "NavUtils"; 39c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static final String PARENT_ACTIVITY = "android.support.PARENT_ACTIVITY"; 40c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 4157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell interface NavUtilsImpl { 4257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell Intent getParentActivityIntent(Activity activity); 4357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell boolean shouldUpRecreateTask(Activity activity, Intent targetIntent); 4457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell void navigateUpTo(Activity activity, Intent upIntent); 4557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell String getParentActivityName(Context context, ActivityInfo info); 4657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 4757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 4857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell static class NavUtilsImplBase implements NavUtilsImpl { 4957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 5057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 5157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public Intent getParentActivityIntent(Activity activity) { 52f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell String parentName = NavUtils.getParentActivityName(activity); 53f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell if (parentName == null) return null; 54f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 55f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell // If the parent itself has no parent, generate a main activity intent. 56f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final ComponentName target = new ComponentName(activity, parentName); 57f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell try { 58f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final String grandparent = NavUtils.getParentActivityName(activity, target); 59f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final Intent parentIntent = grandparent == null 60f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell ? IntentCompat.makeMainActivity(target) 61f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell : new Intent().setComponent(target); 62f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return parentIntent; 63f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } catch (NameNotFoundException e) { 64f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell Log.e(TAG, "getParentActivityIntent: bad parentActivityName '" + parentName + 65f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell "' in manifest"); 66f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return null; 67f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 6857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 6957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 7057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 7157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public boolean shouldUpRecreateTask(Activity activity, Intent targetIntent) { 7257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell String action = activity.getIntent().getAction(); 7357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return action != null && !action.equals(Intent.ACTION_MAIN); 7457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 7557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 7657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 7757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public void navigateUpTo(Activity activity, Intent upIntent) { 7857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 7957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell activity.startActivity(upIntent); 8057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell activity.finish(); 8157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 8257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 8357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 8457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public String getParentActivityName(Context context, ActivityInfo info) { 8557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell if (info.metaData == null) return null; 8657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell String parentActivity = info.metaData.getString(PARENT_ACTIVITY); 8757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell if (parentActivity == null) return null; 8857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell if (parentActivity.charAt(0) == '.') { 8957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell parentActivity = context.getPackageName() + parentActivity; 9057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 9157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return parentActivity; 9257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 9357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 9457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 9557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell static class NavUtilsImplJB extends NavUtilsImplBase { 9657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 9757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 9857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public Intent getParentActivityIntent(Activity activity) { 9957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell // Prefer the "real" JB definition if available, 10057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell // else fall back to the meta-data element. 10157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell Intent result = NavUtilsJB.getParentActivityIntent(activity); 10257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell if (result == null) { 103f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell result = superGetParentActivityIntent(activity); 10457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 10557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return result; 10657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 10757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 108f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell Intent superGetParentActivityIntent(Activity activity) { 109f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return super.getParentActivityIntent(activity); 110f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell } 111f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 11257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 11357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public boolean shouldUpRecreateTask(Activity activity, Intent targetIntent) { 11457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return NavUtilsJB.shouldUpRecreateTask(activity, targetIntent); 11557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 11657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 11757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 11857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public void navigateUpTo(Activity activity, Intent upIntent) { 11957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell NavUtilsJB.navigateUpTo(activity, upIntent); 12057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 12157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 12257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell @Override 12357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell public String getParentActivityName(Context context, ActivityInfo info) { 12457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell String result = NavUtilsJB.getParentActivityName(info); 12557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell if (result == null) { 12657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell result = super.getParentActivityName(context, info); 12757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 12857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return result; 12957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 13057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 13157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 13257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell private static final NavUtilsImpl IMPL; 13357ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 13457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell static { 13557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell final int version = android.os.Build.VERSION.SDK_INT; 13657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell if (version >= 16) { 13757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell IMPL = new NavUtilsImplJB(); 13857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } else { 13957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell IMPL = new NavUtilsImplBase(); 14057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 14157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell } 14257ff0548ba991652576d81adaaa8baf4c028de39Adam Powell 143c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 144c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Returns true if sourceActivity should recreate the task when navigating 'up' 145c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * by using targetIntent. 146c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 147c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p>If this method returns false the app can trivially call 148c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link #navigateUpTo(Activity, Intent)} using the same parameters to correctly perform 149c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * up navigation. If this method returns false, the app should synthesize a new task stack 150c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * by using {@link TaskStackBuilder} or another similar mechanism to perform up navigation.</p> 151c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 152c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivity The current activity from which the user is attempting to navigate up 153c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param targetIntent An intent representing the target destination for up navigation 154c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return true if navigating up should recreate a new task stack, false if the same task 155c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * should be used for the destination 156c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 157c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static boolean shouldUpRecreateTask(Activity sourceActivity, Intent targetIntent) { 15857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return IMPL.shouldUpRecreateTask(sourceActivity, targetIntent); 159c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 160c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 161c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 162c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Convenience method that is equivalent to calling 163c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <code>{@link #navigateUpTo(Activity, Intent) navigateUpTo}(sourceActivity, 164c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link #getParentActivityIntent(Activity) getParentActivityIntent} (sourceActivity))</code>. 165c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * sourceActivity will be finished by this call. 166c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 167c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p><em>Note:</em> This method should only be used when sourceActivity and the corresponding 168c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * parent are within the same task. If up navigation should cross tasks in some cases, see 169c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link #shouldUpRecreateTask(Activity, Intent)}.</p> 170c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 171c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivity The current activity from which the user is attempting to navigate up 172c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 173c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static void navigateUpFromSameTask(Activity sourceActivity) { 174c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell Intent upIntent = getParentActivityIntent(sourceActivity); 175c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 176c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell if (upIntent == null) { 177c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throw new IllegalArgumentException("Activity " + 178c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell sourceActivity.getClass().getSimpleName() + 179c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell " does not have a parent activity name specified." + 180c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell " (Did you forget to add the android.support.PARENT_ACTIVITY <meta-data> " + 181c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell " element in your manifest?)"); 182c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 183c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 184c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell navigateUpTo(sourceActivity, upIntent); 185c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 186c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 187c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 188c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Navigate from sourceActivity to the activity specified by upIntent, finishing sourceActivity 189c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * in the process. upIntent will have the flag {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} set 190c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * by this method, along with any others required for proper up navigation as outlined 191c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * in the Android Design Guide. 192c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 193c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * <p>This method should be used when performing up navigation from within the same task 194c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * as the destination. If up navigation should cross tasks in some cases, see 195c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * {@link #shouldUpRecreateTask(Activity, Intent)}.</p> 196c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 197c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivity The current activity from which the user is attempting to navigate up 198c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param upIntent An intent representing the target destination for up navigation 199c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 200c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static void navigateUpTo(Activity sourceActivity, Intent upIntent) { 20157ff0548ba991652576d81adaaa8baf4c028de39Adam Powell IMPL.navigateUpTo(sourceActivity, upIntent); 202c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 203c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 204c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 20557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * Obtain an {@link Intent} that will launch an explicit target activity 20657ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * specified by sourceActivity's {@link #PARENT_ACTIVITY} <meta-data> 20757ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * element in the application's manifest. If the device is running 20857ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * Jellybean or newer, the android:parentActivityName attribute will be preferred 20957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * if it is present. 210c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 211c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivity Activity to fetch a parent intent for 212c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return a new Intent targeting the defined parent activity of sourceActivity 213c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 214c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static Intent getParentActivityIntent(Activity sourceActivity) { 21557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell return IMPL.getParentActivityIntent(sourceActivity); 216c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 217c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 218c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 21957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * Obtain an {@link Intent} that will launch an explicit target activity 22057ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * specified by sourceActivityClass's {@link #PARENT_ACTIVITY} <meta-data> 221c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * element in the application's manifest. 222c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 223c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param context Context for looking up the activity component for sourceActivityClass 224c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivityClass {@link java.lang.Class} object for an Activity class 225c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return a new Intent targeting the defined parent activity of sourceActivity 226c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @throws NameNotFoundException if the ComponentName for sourceActivityClass is invalid 227c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 228c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static Intent getParentActivityIntent(Context context, Class<?> sourceActivityClass) 229c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throws NameNotFoundException { 230c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell String parentActivity = getParentActivityName(context, 231c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell new ComponentName(context, sourceActivityClass)); 232c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell if (parentActivity == null) return null; 233f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 234f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell // If the parent itself has no parent, generate a main activity intent. 235f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final ComponentName target = new ComponentName(context, parentActivity); 236f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final String grandparent = getParentActivityName(context, target); 237f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final Intent parentIntent = grandparent == null 238f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell ? IntentCompat.makeMainActivity(target) 239f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell : new Intent().setComponent(target); 240f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return parentIntent; 241c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 242c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 243c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 24457ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * Obtain an {@link Intent} that will launch an explicit target activity 24557ff0548ba991652576d81adaaa8baf4c028de39Adam Powell * specified by sourceActivityClass's {@link #PARENT_ACTIVITY} <meta-data> 246c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * element in the application's manifest. 247c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 248c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param context Context for looking up the activity component for the source activity 249c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param componentName ComponentName for the source Activity 250c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return a new Intent targeting the defined parent activity of sourceActivity 251c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @throws NameNotFoundException if the ComponentName for sourceActivityClass is invalid 252c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 253c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static Intent getParentActivityIntent(Context context, ComponentName componentName) 254c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throws NameNotFoundException { 255c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell String parentActivity = getParentActivityName(context, componentName); 256c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell if (parentActivity == null) return null; 257f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell 258f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell // If the parent itself has no parent, generate a main activity intent. 259f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final ComponentName target = new ComponentName( 260f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell componentName.getPackageName(), parentActivity); 261f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final String grandparent = getParentActivityName(context, target); 262f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell final Intent parentIntent = grandparent == null 263f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell ? IntentCompat.makeMainActivity(target) 264f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell : new Intent().setComponent(target); 265f19cb1f3facdb9f90ef1b26537ff303eaa3db77dAdam Powell return parentIntent; 266c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 267c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 268c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 269c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Return the fully qualified class name of sourceActivity's parent activity as specified by 270c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * a {@link #PARENT_ACTIVITY} <meta-data> element within the activity element in 271c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the application's manifest. 272c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 273c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param sourceActivity Activity to fetch a parent class name for 274c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return The fully qualified class name of sourceActivity's parent activity or null if 275c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * it was not specified 276c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 277c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static String getParentActivityName(Activity sourceActivity) { 278c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell try { 279c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return getParentActivityName(sourceActivity, sourceActivity.getComponentName()); 280c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } catch (NameNotFoundException e) { 281c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell // Component name of supplied activity does not exist...? 282c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throw new IllegalArgumentException(e); 283c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 284c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 285c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** 286c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * Return the fully qualified class name of a source activity's parent activity as specified by 287c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * a {@link #PARENT_ACTIVITY} <meta-data> element within the activity element in 288c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * the application's manifest. The source activity is provided by componentName. 289c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * 290c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param context Context for looking up the activity component for the source activity 291c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @param componentName ComponentName for the source Activity 292c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * @return The fully qualified class name of sourceActivity's parent activity or null if 293c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell * it was not specified 294c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell */ 295c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell public static String getParentActivityName(Context context, ComponentName componentName) 296c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell throws NameNotFoundException { 297c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell PackageManager pm = context.getPackageManager(); 298c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell ActivityInfo info = pm.getActivityInfo(componentName, PackageManager.GET_META_DATA); 29957ff0548ba991652576d81adaaa8baf4c028de39Adam Powell String parentActivity = IMPL.getParentActivityName(context, info); 300c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell return parentActivity; 301c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 302c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell 303c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell /** No instances! */ 304c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell private NavUtils() { 305c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell } 306c9cf2eb0a9b6694d0fda3dbc313844955db60820Adam Powell} 307