Archive for June, 2011

ca.loconet.android Tip

Posted in Android, Software on June 12th, 2011 by loconet – 2 Comments

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