Up Navigation Broken on Jellybean

Intended usage of Up navigation

1) No, you are not trying to misuse the ActionBar here. If you are going from A -> B -> C then pressing Up from C should take you to B and NOT A. This is mentioned here as

"The Up button is used to navigate within an app based on the hierarchical relationships between screens. For instance, if screen A displays a list of items, and selecting an item leads to screen B (which presents that item in more detail), then screen B should offer an Up button that returns to screen A."

2)Your implementation is not working as intended because you forgot to do the following as mentioned here:

    @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_displaymessage);

getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// If your minSdkVersion is 11 or higher, instead use:
// getActionBar().setDisplayHomeAsUpEnabled(true);
}

I however do not recommend that you use the above technique to handle your Up Navigation as the above method will not work for ICS and below. The reason it won't work is because NavUtils behaves differently for Pre JellyBean and Post JellyBean as explained in this SO.

A better way is to do this is to handle the Up action manually in the Child Activity:

    @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
startActivity(new Intent(this, ParentActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_SINGLE_TOP));
default:
return super.onOptionsItemSelected(item);
}
}

And best part of this manual approach is that it works for ALL Api Levels.

NavUtils.shouldUpRecreateTask fails on JellyBean

I still don't know why shouldUpRecreateTask fails - looking at the source code for it doesn't help much. But the solution is quite simple - I just add an extra flag value to the Intent that is attached to the notification, and check this in onCreate(). If it is set, then the Activity has been invoked from the notification, so the back stack has to be recreated.

The code looks like this:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
fromNotification = b.getInt("fromNotification") == 1;
setContentView(R.layout.threadlist);
}

@Override
public boolean onHomeButtonPressed() {
if(fromNotification) {
// This activity is not part of the application's task, so create a new task
// with a synthesized back stack.
TaskStackBuilder tsb = TaskStackBuilder.from(this)
.addNextIntent(new Intent(this, COPAme.class));
tsb.startActivities();
}
// Otherwise, This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
finish();
return true;
}

How can I return to a parent activity correctly?

You declared activity A with the standard launchMode in the Android manifest. According to the documentation, that means the following:

The system always creates a new instance of the activity in the target
task and routes the intent to it.

Therefore, the system is forced to recreate activity A (i.e. calling onCreate) even if the task stack is handled correctly.

To fix this problem you need to change the manifest, adding the following attribute to the A activity declaration:

android:launchMode="singleTop"

Note: calling finish() (as suggested as solution before) works only when you are completely sure that the activity B instance you are terminating lives on top of an instance of activity A. In more complex workflows (for instance, launching activity B from a notification) this might not be the case and you have to correctly launch activity A from B.



Related Topics



Leave a reply



Submit