我误解了FLAG_ACTIVITY_REORDER_TO_FRONT 标志。我认为活动 Y FLAG_ACTIVITY_REORDER_TO_FRONT 活动 C 将保留父项,因此 C 回压将转到 B。不,事实并非如此。 FLAG_ACTIVITY_REORDER_TO_FRONT 实际上使 C 转移到新的父 Y(即调用者),但由于父 Y 在 C 之上,所以 C 后压将无法转到 Y 并最小化/隐藏到背景。
我也误解了我的代码创建 2 个堆栈,但实际上它只是一个堆栈。我必须使用FLAG_ACTIVITY_MULTIPLE_TASK 使其成为多个堆栈。
我还需要在清单中定义正确的launchMode:
- 启动器活动 A 和 X 都必须定义为
singleInstance in
显现。
- 主页活动 B 和 Y 都必须定义为
singleTop
在清单中。
- 其他活动 C 和 Z ...等必须定义为
singleTask 在清单中。
Activity A 在启动主页 B 时必须设置标志 Intent.FLAG_ACTIVITY_MULTIPLE_TASK。
X 也应该在启动主页 Y 时设置标志Intent.FLAG_ACTIVITY_MULTIPLE_TASK。
如果选项卡任务之前已经开始,循环的有效标志来重新排序所有相同的任务活动(存储在全局堆栈列表中)是(moveTaskToBack(true); 单行也可以,但它不能回到前台):
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|Intent.FLAG_ACTIVITY_NEW_TASK
|Intent.FLAG_ACTIVITY_NO_ANIMATION);
p/s:以上在 Android 5 和 6 中不起作用,它只会将单个顶部活动重新排序到前面,所以我需要在清单中添加 android.permission.REORDER_TASKS 并执行此操作(更多信息,see this bug report):
ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (final Activity a : YStackClasses) {
if (IsBeforeAndroidNougat && (tasksManager != null)) {
tasksManager.moveTaskToFront(a.getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
} else {
//Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
}
}
如果选项卡任务从未启动,则应启动启动器活动而不设置任何特殊标志。
为了防止点击启动器由于singleInstance而刷新,我还必须检查A和B,把它放在setContentView和finish()/return;之前。
if (getIntent() != null && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
//figure out latest activity and it's home activity, and reorder to front, and its entire task stack will focus on top.
}
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK 将不再自动清除所有活动以刷新应用程序,解决方案是ActivityCompat.finishAffinity(desiredTask's Top Act);,它将删除顶部活动下方的所有活动而不影响其他任务堆栈。
如果类是重用的,比如 C1、C2,那么我必须使用startActivityForResult(intent, dummyResponse); 来强制它在同一个类之上创建新的活动。但是不要在 A 启动活动 B 时这样做,因为 startActivityForResult 需要单个任务并忽略 singleInstance 启动模式、see this thread。并且不要在onNewIntent() 内执行ForResult,这可能会导致页面在堆栈中生成两次(第二个页面不会立即生成,而是仅在返回时生成)。但是我可以在onNewIntent()的调用者中做ForResult来生效。
我还需要执行此操作以使 backpress 在家庭活动中按预期工作以隐藏应用程序并能够返回正确的任务页面。我不使用TASK_ON_HOME(当启动主页B类时)标志,因为它只是单个任务方向(即前台到固定活动而不是依赖于先前的顶级任务活动):
@Override //B class
public void onBackPressed() {
moveTaskToBack(true); //B task stack
if (YStackClasses.size() > 0) { //Y task stack
try {
YStackClasses.get(0).moveTaskToBack(true);
} catch (Exception e) {
e.printStackTrace();
}
}
super.onBackPressed();
}
请注意,即使由于崩溃而自动重新启动,应用程序堆栈也可能会缓存,因此有时您需要重新启动两次才能使其恢复到初始堆栈状态进行测试,否则您会得到错误的结论。
就是这样,这个答案可能缺少代码细节,但如果你遇到像我一样的“回压时隐藏到后台”问题,它应该会有所帮助,你可以了解实现预期的难度如果您在一个步骤中设置了错误的标志或在清单中的一项活动中定义了错误的launchMode,则行为。