因为一个多任务的需求,所以想到了使用 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); } }
参考资料: