因为一个多任务的需求,所以想到了使用 SingleInstance 方式启动多任务容器 Activity,保证一定情况内 Activity 不被销毁,可以随时切换回来操作。
基于面向百度编程可知 SingleInstance 会另开一个返回栈(Task)来启动该 Activity,但首先有两个问题需要解决:
1. 如何从SingleInstance 返回到上一个 Activity
2. ActivityResult的实现
这篇文章中我们先来解决第一个问题:
(1) 直接调用 moveTaskToBack(boolean nonRoot) 方法
@Override
public void onBackPressed() {
moveTaskToBack(true);
}
这个方法使用时看似方便,但是一旦用户通过概览屏幕(或者叫最新动态屏幕、最近任务列表或最近使用的应用)回到这个 SingleInstance,再点击返回按钮隐藏任务栈就会导致app直接返回到主页面。这里我们就需要想办法回到上一个 Activity 的返回栈。
(2) 通过遍历返回栈回到上一个 Activity
@Override
public void onBackPressed() {
moveTaskToBack(true);
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
assert manager != null;
List taskInfoList = manager.getRunningTasks(30);
for (ActivityManager.RunningTaskInfo task : taskInfoList) {
if (task.topActivity.getPackageName().equals(getPackageName()) && task.id != getTaskId()) {
manager.moveTaskToFront(task.id, 0);
break;
}
}
}
这种方法能够较好地解决返回问题,moveTaskToFront(int taskId, @MoveTaskFlags int flags)需要 REORDER_TASKS 权限。这里值得注意的是 ActivityManager#getRunningTasks(int maxNum) 这个方法在 Android 5.0 被弃用,API >= 21 时只能获取到当前APP的返回栈。
(3) 直接向 SingleInstance Activity 传递 TaskId
在 Intnet 跳转时直接传入该 Activity 所在的 TaskId
public void show(Context context) {
Intent intent = new Intent(context, MultiTaskActivity.class);
intent.putExtra(MultiTaskConstant.INTENT_EXTRA_TASK_ID, ((Activity)context).getTaskId());
context.startActivity(intent);
}
返回时直接通过 TaskId 回到上一个栈。
@Override
public void onBackPressed() {
moveTaskToBack(true);
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
assert manager != null;
int taskId = getIntent().getIntExtra(MultiTaskConstant.INTENT_EXTRA_TASK_ID, Integer.MIN_VALUE);
if (taskId > 0) {
manager.moveTaskToFront(taskId, 0);
}
}
参考资料:
