Search code examples
androidandroid-appcompatandroid-fragmentactivityup-button

Up Button not working if the activity extends AppCompatActivity


I launched Activity B via deep link and I'm expecting Activity A to be launched on Up Button click.

Here's my manifest

<activity
    android:name=".ui.activity.B"
    android:label="@string/title_activity_search"
    android:parentActivityName=".ui.activity.A" >

    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".ui.activity.A"/>
        ...
        <!-- deep link -->
        ...     
</activity>

B Activity code is here.

public class B extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
Toolbar vToolbar = ((Toolbar) findViewById(R.id.toolbar));
        setSupportActionBar(vToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

You can copy/past this code and it works if Activity B extends FragmentActivity. But I need this to be working with AppCompatActivity. What am I doing wrong?


Solution

  • You're opening your Activity from another application. So there is no other Activity available in the stack. Thus you should not get the parent Activity to come up in the front when you press the up button. If the target parent activity is in the task's back stack, it is brought forward. From the developers documentation.

    However, using navigateUpFromSameTask() is suitable only when your app is the owner of the current task (that is, the user began this task from your app). If that's not true and your activity was started in a task that belongs to a different app, then navigating Up should create a new task that belongs to your app, which requires that you create a new back stack.

    So in your case you need to do something like this stated in the documentation.

    If your activity provides any intent filters that allow other apps to start the activity, you should implement the onOptionsItemSelected() callback such that if the user presses the Up button after entering your activity from another app's task, your app starts a new task with the appropriate back stack before navigating up.

    You can do so by first calling shouldUpRecreateTask() to check whether the current activity instance exists in a different app's task. If it returns true, then build a new task with TaskStackBuilder. Otherwise, you can use the navigateUpFromSameTask() method as shown above.

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            Intent upIntent = NavUtils.getParentActivityIntent(this);
            if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
                // This activity is NOT part of this app's task, so create a new task
                // when navigating up, with a synthesized back stack.
                TaskStackBuilder.create(this)
                        // Add all of this activity's parents to the back stack
                        .addNextIntentWithParentStack(upIntent)
                        // Navigate up to the closest parent
                        .startActivities();
            } else {
                // This activity is part of this app's task, so simply
                // navigate up to the logical parent activity.
                NavUtils.navigateUpTo(this, upIntent);
            }
            return true;
        }
        return super.onOptionsItemSelected(item);
    }