希望有人能帮我弄清楚,如果不是解决方案,至少可以解释一种行为。
The Problem:
在一些设备上,按下启动器图标会导致当前任务被恢复,而在其他设备上,它会导致初始启动意图被触发(有效地重新启动应用程序)。这一切为什么要发生?
细节:
当你按下“启动器图标”时,应用程序会正常启动--也就是说,我假设你的第一个Activity
的名字是动作android.intent.action.MAIN
和类别android.intent.category.LAUNCHER
。然而,情况并不总是如此:
在大多数设备上,如果您在应用程序运行后按下启动器图标,则会恢复该进程中当前正在运行的活动(而不是初始Activity
)。它恢复的方式与您从操作系统菜单的“最近的任务”中选择它的方式相同。这是我希望在所有设备上实现的行为。
但是,在选定的其他设备上会发生不同的行为:
Activity
。我假设启动器图标总是启动“启动器”意图。Activity
(与Xoom相同)-但是,在安装后重新启动设备后,启动器图标将恢复应用程序。我假设这些设备在设备启动时将“已安装的应用程序”添加到一个查询表中,从而允许启动器图标正确地恢复运行任务-我读过很多类似于我的问题的答案,但简单地在Activity
中添加android:alwaysRetainTaskState="true"
或使用launchMode="singleTop"
不是解决问题的方法。
编辑:
在最近一次启动此应用程序后,我们发现在第一次重启后,所有设备上都开始出现这种行为。这对我来说似乎很疯狂,但通过重启过程,我实际上找不到哪里出了问题。
发布于 2014-04-17 20:47:44
啊哈!(tldr;参见底部以粗体显示的语句)
我找到问题了..。我认为。
所以,我将从一个假设开始。当您按下启动程序时,它会启动默认的Activity
,或者,如果由上一次启动启动的Task
是打开的,它会将其带到最前面。换句话说,如果你在导航的任何阶段创建了一个新的Task
,并对旧的创建了finish
,那么启动器现在将不再恢复你的应用。
如果这个假设是真的,我很确定这应该是一个错误,因为每个Task
都在相同的过程中,并且与第一个创建的简历候选人一样有效?
然后,通过从几个Intents
中删除这些标志,修复了我的问题
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
虽然很明显FLAG_ACTIVITY_NEW_TASK
创建了一个新的Task
,但我并不欣赏上面的假设是有效的。我确实认为这是一个罪魁祸首,并将其删除以进行测试,但我仍然有问题,所以我将其驳回。然而,我仍然有以下条件:
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
我的闪屏正在使用上面的标志启动我的应用程序中的“主”Activity
。毕竟,如果我“重启”了我的应用,而Activity
还在运行,我宁愿保留它的状态信息。
您会注意到,在documentation中没有提到要启动一个新的Task
如果设置了
,并且正在启动的活动已经在当前任务中运行,则不是启动该活动的新实例,而是关闭它上面的所有其他活动,并且此意图将作为新意图传递给(现在在顶部)旧活动。
例如,考虑由活动A、B、C、D组成的任务。如果D使用解析为活动B的组件的意图调用startActivity(),则C和D将完成,而B接收给定的意图,导致堆栈现在为: A、B。
在上面的例子中,当前运行的activity B实例将在其onNewIntent()方法中接收您在此处启动的新意图,或者使用新意图完成并重新启动它自己。如果它已将其启动模式声明为"multiple“(默认值),并且您没有以相同的目的设置FLAG_ACTIVITY_SINGLE_TOP,那么它将完成并重新创建;对于所有其他启动模式,或者如果设置了FLAG_ACTIVITY_SINGLE_TOP,则此意图将被传递到当前实例的onNewIntent()。
这种启动模式也可以与FLAG_ACTIVITY_NEW_TASK配合使用,以达到良好的效果:如果用于启动任务的根activity,它会将该任务当前正在运行的任何实例带到前台,然后将其清除到根状态。例如,当从通知管理器启动活动时,这特别有用。
因此,我有如下描述的情况:
A
用FLAG_ACTIVITY_CLEAR_TOP
启动了B
,A
完成了。B
希望重新启动服务,因此将用户发送到具有服务重新启动逻辑和UI的A
(No flags).A
使用FLAG_ACTIVITY_CLEAR_TOP启动B
,A
完成。在此阶段,第二个FLAG_ACTIVITY_CLEAR_TOP
标志是重新启动任务堆栈中的B
。我假设这一定会破坏Task
并开始一个新的,导致我的问题,如果你问我,这是一个很难发现的情况!
所以,如果我所有的假设都是正确的:
Launcher
仅恢复最初创建的Activity
**,,如果重新启动唯一剩余的,它还将重新创建新的**发布于 2014-04-22 20:51:16
你所遇到的行为是由一个问题引起的,这个问题存在于一些安卓启动程序中,从API1开始。你可以在这里找到关于这个错误的详细信息和可能的解决方案:https://code.google.com/p/android/issues/detail?id=2373。
在三星设备和其他使用定制启动器/皮肤的制造商上,这是一个相对常见的问题。我还没有见过这个问题发生在一个现成的Android启动程序上。
基本上,应用程序实际上并没有完全重新启动,但当应用程序由启动程序恢复时,您的启动活动正在启动并添加到活动堆栈的顶部。当您恢复应用程序并显示启动活动时,您可以通过单击back按钮来确认这一点。然后,您应该被带到您恢复应用程序时预期显示的活动。
我选择实现的解决方法是检查启动初始活动的intent中的Intent.CATEGORY_LAUNCHER类别和Intent.ACTION_MAIN操作。如果存在这两个标志,并且活动不在任务的根位置(意味着应用程序已经在运行),则在初始活动上调用finish()。这个确切的解决方案可能对你不起作用,但类似的东西应该对你起作用。
以下是我在initial/launch活动的onCreate()中执行的操作:
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
发布于 2016-07-13 04:01:46
这个问题在2016年仍然是相关的。今天,一位QA测试员报告说,我的一个应用程序重启,而不是从Android M的股票启动程序恢复。
实际上,系统正在将启动的活动添加到当前的task-stack中,但对于用户来说,似乎发生了重启,他们的工作已经丢失。顺序是:
<代码>H110从应用程序抽屉启动应用程序:活动A出现!任务堆栈:A -> B -> A(用户可以按“Back”按钮从这里转到活动“B”)
注意:通过ADB部署的调试APK不会出现此问题,仅在从Play Store下载或侧面加载的APK中出现。在后一种情况下,步骤5中的启动意图包含标志Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
,但不在调试用例中。一旦应用程序从启动程序中冷启动,问题就会消失。我怀疑任务是带有错误(更准确地说,是非标准的)意图的种子,这会阻止正确的启动行为,直到任务完全清除。
我尝试了各种activity launch modes,但这些设置与用户期望的标准行为偏离太多:在活动B处继续任务。请参阅页面底部“启动任务”下guide to Tasks and Back Stack中预期行为的以下定义:
这类意图过滤器使活动的图标和标签显示在应用程序启动器中,使用户可以启动活动并在活动启动后随时返回到它创建的任务。
我发现this answer是相关的,并将以下代码插入到根活动(A)的'onCreate‘方法中,这样当用户打开应用程序时,它就会适当地恢复。
/**
* Ensure the application resumes whatever task the user was performing the last time
* they opened the app from the launcher. It would be preferable to configure this
* behavior in AndroidMananifest.xml activity settings, but those settings cause drastic
* undesirable changes to the way the app opens: singleTask closes ALL other activities
* in the task every time and alwaysRetainTaskState doesn't cover this case, incredibly.
*
* The problem happens when the user first installs and opens the app from
* the play store or sideloaded apk (not via ADB). On this first run, if the user opens
* activity B from activity A, presses 'home' and then navigates back to the app via the
* launcher, they'd expect to see activity B. Instead they're shown activity A.
*
* The best solution is to close this activity if it isn't the task root.
*
*/
if (!isTaskRoot()) {
finish();
return;
}
更新:将此解决方案从解析意图标志转移到查询活动是否直接位于任务的根。意图标志很难用打开主活动的所有不同方式进行预测和测试(从主页启动、从“向上”按钮启动、从Play Store启动等)。
https://stackoverflow.com/questions/19545889
复制相似问题