ca.loconet.android Tip

Android development can be a lot of fun but it can also be frustrating at times, specially with the many small gotchas that the framework and documentation have. As I work on a personal project for the Android platform, I will post some thoughts and tips about my adventures in the platform. Hopefully it will help someone or people out there can point out better solutions!

Using the app icon as an action item

For those of us targeting Honeycomb (or working with compatibility libraries) , one of the cool features we have at our disposal is the ActionBar. One of the standard elements of the ActionBar is the app icon presented on the top let corner of the application. This icon is supposed to act as a button that allows the user to go to the home Activity from anywhere in the application. According to the documentation, the following piece of code should be the standard way of having a the activity handle the selection of the app icon:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
    case android.R.id.home:
      // app icon in Action Bar clicked; go home
      Intent intent = new Intent(this, HomeActivity.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      startActivity(intent);
      return true;
   default:
     return super.onOptionsItemSelected(item);
  }
}

Of interest is the intent Intent.FLAG_ACTIVITY_CLEAR_TOP flag. According to the documentation:

If you respond to the application icon by returning to the home activity, you should include the FLAG_ACTIVITY_CLEAR_TOP flag in the Intent. With this flag, if the activity you’re starting already exists in the current task, then all activities on top of it are destroyed and it is brought to the front. You should favor this approach, because going “home” is an action that’s equivalent to “going back” and you should usually not create a new instance of the home activity. Otherwise, you might end up with a long stack of activities in the current task.

What the documentation fails to mention, is that under default conditions, this approach alone will have the framework re-create your home Activity. Let’s say HomeActivity starts ActivityB, the activity stack should look like: HomeActivity, ActivityB. If ActivityB now handles the app icon with the code above, it will tell the system to destroy the activities on top of it. Unfortunately, in this case, the target HomeActivity itself will also be destroyed and its onCreate() will be called again. This is something not entirely clear if you are only reading the ActionBar fundamentals.

FLAG_ACTIVITY_CLEAR_TOP’s documentation is a bit more clear on this point:

For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.

The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be “multiple” (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance’s onNewIntent().

So, the trick is to OR the flag with FLAG_ACTIVITY_SINGLE_TOP:


intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

From the docs on FLAG_ACTIVITY_SINGLE_TOP:

If set, the activity will not be launched if it is already running at the top of the history stack

2 thoughts on “ca.loconet.android Tip

  1. Thanks for the helpful article!

    The use of
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

    does not seem to do the trick either. I end up still able to use “Back” to navigate backwards through the stack. In essence, it appears as though the new instance is added to the stack in the same way that I would add any new Intent. “Back” still takes the user back through the stack, stepping through all of the previously visited Activities. Here is the code I am using:

    private void home() {
    Intent intent = new Intent(this, Main.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    startActivity(intent);
    }

    An ideas?

    Michael

  2. Hey Michael,

    I’m very likely misunderstanding the problem you are seeing. In my case, “back” takes me back to whatever activity was active before the target activity. So for example, let’s say the activity stack looks like this, A->B->C, if I then trigger the “Go Home” code from “C” and “Home” is defined as “A”, it will take me to A (without creating a new instance of A). If then I hit the ‘back’ button it takes me out of the application and onto the HC “desktop” which is what I would expect it to do.

    Do let me know if you solved your issue, I’m curious as to what is going on. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>