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} &lt;meta-data&gt;
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} &lt;meta-data&gt;
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} &lt;meta-data&gt;
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} &lt;meta-data&gt; 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} &lt;meta-data&gt; 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