The previous article Android Activity Launch Mode Standard SingleTop Example has introduced the two android activity launch modes Standard and SingleTop. This article will introduce the other two android activity launch modes SingleTask and SingleInstance which are more difficult to understand.
1. Activity Launch Mode SingleTask.
If you can not watch the above video, you can see it on the youtube URL https://youtu.be/_ReQFBVQPCY
- When you request an instance of activity that configured with the singleTask launch mode, if one instance has existed in the current back stack, then that instance will be pop up to the top of the back stack and all other activity instances above it will be removed from the back stack.
- The below example has three activities, ActivityLaunchModeFirstActivity, ActivityLaunchModeSecondActivity, ActivityLaunchModeThirdActivity.
- Only the second activity is configured in singleTask launch mode in AndroidManifest.xml file.
<activity android:name=".ActivityLaunchModeFirstActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ActivityLaunchModeSecondActivity" android:launchMode="singleTask" /> <activity android:name=".ActivityLaunchModeThirdActivity"></activity>
- When clicking the button to start or restart another activity, the code will print out all the activities that exist in the current task back stack, below are the example source files.
- activity_launch_mode_first.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/firstActivityIdTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20dp"/> <Button android:id="@+id/startSecondActivityButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Second Activity"/> </LinearLayout>
- ActivityLaunchModeFirstActivity.java
package com.dev2qa.example; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.dev2qa.example.util.ActivityManagerUtil; public class ActivityLaunchModeFirstActivity extends AppCompatActivity { private static final String TAG = "ACTIVITY_ID"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launch_mode_first); ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), TAG); // Create Task and activity related id info. StringBuffer strBuf = new StringBuffer(); strBuf.append("Task Id : "); strBuf.append(this.getTaskId()); strBuf.append(" , Activity Id : "); strBuf.append(this.toString()); // Set above info in TextView object. TextView firstActivityIdTextView = (TextView)findViewById(R.id.firstActivityIdTextView); firstActivityIdTextView.setText(strBuf.toString()); // Log above info in logcat console. Log.d(TAG, strBuf.toString()); // When click this button, start a new instance of second activity. Button startSecondActivityButton = (Button)findViewById(R.id.startSecondActivityButton); startSecondActivityButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(ActivityLaunchModeFirstActivity.this, ActivityLaunchModeSecondActivity.class); startActivity(intent); } }); } // When activity restart, print activity info in back stack again. @Override protected void onRestart() { super.onRestart(); ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), TAG); } }
- activity_launch_mode_second.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/secondActivityIdTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20dp"/> <Button android:id="@+id/startThirdActivityFromSecondActivityButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Third Activity"/> </LinearLayout>
- ActivityLaunchModeSecondActivity.java
package com.dev2qa.example; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.dev2qa.example.util.ActivityManagerUtil; public class ActivityLaunchModeSecondActivity extends AppCompatActivity { private static final String TAG = "ACTIVITY_ID"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launch_mode_second); ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), TAG); // Create Task and activity related id info. StringBuffer strBuf = new StringBuffer(); strBuf.append("Task Id : "); strBuf.append(this.getTaskId()); strBuf.append(" , Activity Id : "); strBuf.append(this.toString()); // Set above info in TextView object. TextView secondActivityIdTextView = (TextView)findViewById(R.id.secondActivityIdTextView); secondActivityIdTextView.setText(strBuf.toString()); // Log above info in logcat console. Log.d(TAG, strBuf.toString()); // When click this button, start a new instance of First activity. Button startThirdActivityFromSecondActivityButton = (Button)findViewById(R.id.startThirdActivityFromSecondActivityButton); startThirdActivityFromSecondActivityButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(ActivityLaunchModeSecondActivity.this, ActivityLaunchModeThirdActivity.class); startActivity(intent); } }); } @Override protected void onRestart() { super.onRestart(); ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), TAG); } }
- activity_launch_mode_third.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/thirdActivityIdTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20dp"/> <Button android:id="@+id/startSecondActivityFromThirdActivityButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Second Activity"/> </LinearLayout>
- ActivityLaunchModeThirdActivity.java
package com.dev2qa.example; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.dev2qa.example.util.ActivityManagerUtil; public class ActivityLaunchModeThirdActivity extends AppCompatActivity { private static final String TAG = "ACTIVITY_ID"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launch_mode_third); ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), TAG); // Create Task and activity related id info. StringBuffer strBuf = new StringBuffer(); strBuf.append("Task Id : "); strBuf.append(this.getTaskId()); strBuf.append(" , Activity Id : "); strBuf.append(this.toString()); // Set above info in TextView object. TextView thirdActivityIdTextView = (TextView)findViewById(R.id.thirdActivityIdTextView); thirdActivityIdTextView.setText(strBuf.toString()); // Log above info in logcat console. Log.d(TAG, strBuf.toString()); // When click this button, start a new instance of second activity. Button startSecondActivityFromThirdActivityButton = (Button)findViewById(R.id.startSecondActivityFromThirdActivityButton); startSecondActivityFromThirdActivityButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(ActivityLaunchModeThirdActivity.this, ActivityLaunchModeSecondActivity.class); startActivity(intent); } }); } @Override protected void onRestart() { super.onRestart(); ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), TAG); } }
- ActivityManagerUtil.java. This class is the util class that provides a method to print out all activities info in the current task.
package com.dev2qa.example.util; import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.util.Log; import java.util.List; public class ActivityManagerUtil { public static void printCurrentTaskActivityList(Context context, String tagName) { ActivityManager activityManager = (ActivityManager) context.getSystemService( context.ACTIVITY_SERVICE ); List<ActivityManager.AppTask> appTaskList = activityManager.getAppTasks(); if(appTaskList!=null) { int size = appTaskList.size(); for(int i=0;i<size;i++) { ActivityManager.AppTask appTask = appTaskList.get(i); ActivityManager.RecentTaskInfo recentTaskInfo = appTask.getTaskInfo(); int taskId = recentTaskInfo.persistentId; int activityNumber = recentTaskInfo.numActivities; ComponentName origActivity = recentTaskInfo.origActivity; ComponentName baseActivity = recentTaskInfo.baseActivity; ComponentName topActivity = recentTaskInfo.topActivity; Log.d(tagName, "Task Id : " + taskId); Log.d(tagName, "Activity Number : " + activityNumber); if(origActivity!=null) { Log.d(tagName, "Original Activity : " + origActivity.toString()); } if(baseActivity!=null) { Log.d(tagName, "Base Activity : " + baseActivity.toString()); } if(topActivity!=null) { Log.d(tagName, "Top Activity : " + topActivity.toString()); } Log.d(tagName, "************************************************"); } } } }
2. Activity Launch Mode SingleInstance.
If you can not watch the above video, you can see it on the youtube URL https://youtu.be/6v0t4OE1j2s
- This launch mode will make the activity saved in a new task back stack. And the back stack contains only one activity, it is like a global activity.
- Change AndroidManifest.xml to below.
<activity android:name=".ActivityLaunchModeFirstActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ActivityLaunchModeSecondActivity" android:launchMode="singleInstance" /> <activity android:name=".ActivityLaunchModeThirdActivity"></activity>
- Run the above example code again, you will get the below result. You can see the task id for the second activity has been changed. But the first and the third activity still exist in the same task back stack.
Task Id : 516 Activity Number : 1 Base Activity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeFirstActivity} Top Rctivity : ComponentInf0{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeFirstActivity} ******************************************************** Task Id: 517 Activity Number: 1 Base Activity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeSecondActivity} Top Rctivity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeSecondActivity} ******************************************************** Task Id: 516 Activity Number: 2 Base Activity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeFirstActivity} Top Rctivity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeThirdActivity} ******************************************************** Task Id: 517 Activity Number: 1 Base Activity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeSecondActivity} Top Rctivity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeSecondActivity} ******************************************************** Task Id: 516 Activity Number: 3 Base Activity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeFirstActivity} Top Rctivity : ComponentInfo{com.dev2qa.example/com.dev2qa.example.ActivityLaunchModeThirdActivity} ********************************************************