Android: Activity launch mode

A task is the stack ("Last in, First out") which contains a collection of activity instances. Normally, when a user starts an app a new task will be created, and the first activity instance is called as a root of the task. The Android system can hold multiple tasks at the same time and only one task is in the foreground. Similar to a double click of the home key on iOS, if you long press the HOME key on Android you'll be presented with a list of your currently running applications. You can select any one of these applications (which are currently running in the background) in order to bring it to the foreground and interact with the app! Of course, because background tasks do tend to use up your processor cycles you should try to keep your backgrounded apps to a minimum to ensure your phone performs optimally.
Now let's look at the launch mode of an activity. Launch mode allows you to define how a new instance or the existing instance of an activity is associated with the current task. The activity launch mode has four valid values:
<activity android:launchMode = ["standard" | "singleTop" | "singleTask" | "singleInstance"] ../>
The 'standard' is the default value. The four values fall into two groups:
  • 'standard' and 'singleTop' can instantiate multiple activity instances and the instance will stay in the same task.
  • For 'singleTask' or 'singleInstance', the activity class uses the singleton pattern, and that instance will be the root activity of a new task. Let's examine each value:

"standard":

Multiple instances of the activity class can be instantiated and multiple instances can be added to the same task or different tasks. This is the common mode for most of the activities.

"singleTop":

The difference from 'standard' is, if an instance of activity already exists at the top of the current task and system routes intent to this activity, no new instance will be created because it will fire off an onNewIntent() method instead of creating a new object. Let's take the Twitter-oauth integration as example. Suppose we have the following NewsDetailActivity declared:
1 2 3 4 5 6 7 8
<activity android:name=".NewsDetailActivity" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="oauth" android:host="twitt"></data>
</intent-filter>
</activity>
So if a user goes to this activity in the current task (let's say Task #1), a new instance of NewsDetailActivity will be pushed to the top. Now start the oAuth process and the Android system routes the intent to the default Android Browser application, whose launch mode is 'singleTask'; that means a new Task begins for the browser activity, let's say Task #2. Hence the 'NewDetailActivity' is still on top of the Task #1.
After the user finishes the authorization on Twitter's page, the customized callback url 'oauth://twitter' will be invoked. Because NewsDetailActivity declares support for that data type, the system routes the intent to the 'NewsDetailActivity'. Since NewsDetailActivity's launch mode is 'singleTop', and the top instance on Task #1 will be reused, its onNewIntent() method will be invoked to continue oAuth's last step. Here is the code for that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Uri uri = intent.getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String verifier = uri.getQueryParameter("oauth_verifier");
try {
//load other persisted data goes here
....
//get the request-token from prefs and request the access token
TwitterFactory twitter = new TwitterFactory().getInstance();
requestToken = prefsManager.getRequestToken();
prefsManager.clearTwitterRequestToken();
twitter4j.auth.AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier);
// save the access token
prefsManager.saveTwitterOauth(accessToken.getToken(), accessToken.getTokenSecret(), accessToken
.getScreenName());
//other logics to do the post to twitter
....
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}

"singleTask":

A new task will always be created and a new instance will be pushed to the task as the root one. However, if any activity instance exists in any tasks, the system routes the intent to that activity instance through the onNewIntent() method call. In this mode, activity instances can be pushed to the same task. And if the user clicks the BACK key from the singleTask activity, the system will return the user to the previous activity.
This mode is useful for activities that act as the entry points. For example, in a tab-based Twitter client, we can declare the main TabActivity as singleTask. This is also useful if you only want a single instance of the activity to be created. One example of singleTask is the Browser application. Let's take a Twitter-client-application as example, where the main activity is a TabActivity and has three tabs: tweets, replies and messages. And we want to suppose auto-refresh and notification function when app is running.
In AndroidManifest.xml, we have:
1 2
<activity android:name=".MainTabActivity" android:launchMode="singleTask" android:alwaysRetainTaskState="true" android:windowSoftInputMode="adjustPan">
</activity>
Suppose we have the notification for new tweet/replies/messages, and we hope that clickong on the notification will take the user to the current TabActivity, and switch to corresponding tabs. (Here we suppose the app is not closed before user clicks the notification). Because the MainTabActivity's launch mode is singleTask, system routes the intent to the MainTabActivity by calling its onNewIntent() method. And in this method, we can determine which tab to switch to according to the bundle data in the intent.

"singleInstance":

Same as 'singleTask', except that the no activities instance can be pushed into the same task of the singleInstance's. That means, the activity with launch mode is always in a single activity instance task. This is a very specialized mode and should only be used in the applications that are implemented entirely as one activity.

Comments

Post a Comment

Popular posts from this blog

How to draw an overlay on a SurfaceView used by Camera on Android?

Android TCP Connection Chat application

Create EditText with dropdown in android