当前位置: 首页 > 知识库问答 >
问题:

应用程序重新启动,而不是恢复

水麒
2023-03-14

希望有人能帮我找出,如果不是一个解决方案,至少是一个行为的解释。

问题:

在一些设备上,按下启动器图标会导致当前任务恢复,在其他设备上,会导致初始启动意图被激发(有效地重新启动应用程序)。为什么会这样?

细节:

当您按下“启动程序图标”时,应用程序会正常启动-也就是说,我假设,使用您的第一个活动的名称和操作android.Intent.action启动一个意图。MAIN和类别android.intent.category.LAUNCHER。然而,情况并非总是如此:

在大多数设备上,如果您在应用程序已经运行后按下启动器图标,则会恢复该进程中当前正在运行的活动(不是初始的活动)。它以与您从操作系统菜单中的“最近任务”中选择它相同的方式恢复。这是我想要在所有设备上的行为。

但是,在选定的其他设备上,会出现不同的行为:

>

  • 在摩托罗拉Xoom上,当您按下启动器图标时,无论当前运行什么,应用程序都将始终启动初始启动html" target="_blank">active。我假设启动器图标总是启动“LAUNCHER”意图。

    在Samsung Tab 2上,当您按下启动器图标时,如果您刚刚安装了该应用程序,它将始终启动初始活动(与Xoom相同) - 但是,在安装后重新启动设备后,启动器图标将恢复该应用程序。我假设这些设备在设备启动时将“已安装的应用程序”添加到查找表中,从而允许启动器图标正确恢复正在运行的任务?

    我已经阅读了许多答案,听起来类似于我的问题,但简单地添加android: alwaysRetainTaskState="true"或使用LaunchMode="singleTop"活动不是答案。

    编辑:

    在最近一次启动该应用程序后,我们发现首次重启后,所有设备上都开始出现这种行为。这对我来说似乎很疯狂,但在重新启动过程中,我无法真正找到问题所在。

  • 共有3个答案

    申屠弘图
    2023-03-14

    啊哈!(tldr;见底部粗体语句)

    我发现了问题…我想。

    所以,我将从一个假设开始。当您按下启动器时,它要么启动默认的活动,要么,如果先前启动启动的任务打开,它会将其带到前面。换句话说-如果在导航的任何阶段您创建了一个新的任务完成了旧的,启动器现在将不再恢复您的应用程序。

    如果这个假设是真的,我很确定这应该是一个错误,因为每个任务都在同一个过程中,并且与第一个创建的简历候选人一样有效?

    然后,我的问题通过从几个< code > intent 中删除这些标志得到了解决:

    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
    

    虽然很明显,FLAG_ACTIVITY_NEW_TASK创建了一个新任务,但我没有意识到上述假设是有效的。我确实认为这是罪魁祸首,并将其删除以进行测试,我仍然遇到问题,所以我将其驳回。但是,我仍然有以下条件:

    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    

    我的启动屏幕正在使用上述标志启动我的应用程序中的“main”active。毕竟,如果我“重启”了我的应用程序并且active仍在运行,我更愿意保留它的状态信息。

    您会注意到在文档中没有提到开始一个新的< code >任务:

    如果设置了,并且正在启动的活动已经在当前任务中运行,则不会启动该活动的新实例,而是关闭其上的所有其他活动,并且此 Intent 将作为新 Intent 传递到(现在位于顶部)旧活动。

    例如,考虑由活动a、B、C、D组成的任务。如果D调用startActivity()的意图解析为活动B的组件,则C和D将完成,B接收给定的意图,导致堆栈现在为:a、B。

    上例中当前正在运行的activity B的实例要么在onNewIntent()方法中接收您在这里启动的新意图,要么自己完成并以新意图重新启动。如果它已经声明其启动模式为“多”(默认),并且您没有以相同的意图设置FLAG_ACTIVITY_SINGLE_TOP,那么它将被完成并重新创建;对于所有其他启动模式,或者如果设置了FLAG_ACTIVITY_SINGLE_TOP,则此意图将被传递给当前实例的onNewIntent()。

    此启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合使用,以达到良好的效果:如果用于启动任务的根活动,则会将该任务的任何当前正在运行的实例带到前台,然后将其清除到其根状态。这尤其有用,例如,从通知管理器启动活动时。

    因此,我的情况如下所述:

    • A启动了BFLAG_ACTIVITY_CLEAR_TOPA完成了。
    • B 希望重新启动服务,因此将用户发送到具有服务重新启动逻辑和 UI(无标志)的 A
    • A 以FLAG_ACTIVITY_CLEAR_TOP启动 BA 完成。

    在这个阶段,第二个FLAG_ACTIVITY_CLEAR_TOP标志正在重新启动任务堆栈中的B。我假设这必须销毁任务并启动一个新的,从而导致我的问题,如果你问我,这是一个非常困难的情况!

    所以,如果我所有的推测都是正确的:

    • 启动器仅恢复最初创建的任务。
    • FLAG_ACTIVITY_CLEAR_TOP如果重新启动唯一剩余的活动,也将重新创建一个新的Task
    裴存
    2023-03-14

    这个问题在2016年仍然相关。今天,一位QA测试人员报告说,我的一个应用程序在Android M中重新启动,而不是从股票启动器恢复。

    实际上,系统正在将启动的活动添加到当前任务堆栈中,但在用户看来,好像发生了重新启动,他们丢失了工作。顺序是:

    1. 从play store(或侧加载apk)下载
    2. 从play store对话框启动应用程序:活动A出现[任务堆栈:A]
    3. 导航到活动B[任务堆栈:A-

    注意:通过 ADB 部署的调试 APK 不会出现此问题,只会显示在从 Play 商店下载或旁加载的 APK 中。在后一种情况下,步骤 5 中的启动意图包含Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT标志,但在调试情况下则不包含。从启动器冷启动应用程序后,问题就会消失。我怀疑任务的种子带有格式错误(更准确地说,非标准)意图,该意图会阻止正确的启动行为,直到任务完全清除为止。

    我尝试了各种活动启动模式,但这些设置与用户期望的标准行为相差太大:在活动 B 处恢复任务。请参阅页面底部“启动任务”下的任务和后退堆栈指南中的以下预期行为定义:

    这种类型的意向筛选器会导致活动图标和标签显示在应用程序启动器中,使用户能够启动活动并在启动后随时返回到该任务创建的任务。

    我发现这个答案是相关的,并在我的根活动(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启动等)

    宰父才
    2023-03-14

    您遇到的问题是由API 1以后的一些Android启动程序中存在的问题引起的。你可以在这里找到关于这个错误的细节以及可能的解决方案:https://code.google.com/p/android/issues/detail?id=2373.

    这是三星设备以及其他使用自定义启动器/皮肤的制造商上相对常见的问题。我还没有在股票Android启动器上看到这个问题。

    基本上,应用程序实际上并没有完全重新启动,但当应用程序由启动器恢复时,您的启动活动正在启动并添加到活动堆栈的顶部。当您恢复应用程序并显示启动活动时,您可以通过单击“上一步”按钮确认情况。然后,您将被带到恢复应用程序时预期显示的活动。

    我选择实现解决此问题的解决方法是在启动初始活动的意图中检查Intent.CATEGORY_LAUNCHER类别和Intent.ACTION_MAIN操作。如果存在这两个标志并且活动不在任务的根目录(意味着应用程序已经在运行),那么我在初始活动上调用完成()。这种确切的解决方案可能不适合您,但类似的解决方案应该适用。

    下面是我在初始/启动活动的onCreate()中所做的工作:

        if (!isTaskRoot()
                && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
                && getIntent().getAction() != null
                && getIntent().getAction().equals(Intent.ACTION_MAIN)) {
    
            finish();
            return;
        }
    
     类似资料:
    • 在Spring Boot中,在不重新启动应用程序的情况下更新前端部分?

    • 问题内容: 我愿意在应用程序中添加一个按钮,单击该按钮将重新启动该应用程序。我搜索谷歌,但没有发现任何有用的,除了这一个。但是,此处遵循的过程违反了Java的WORA概念。 是否有其他以Java为中心的方法来实现此功能?是否可以只派生另一个副本然后退出? 提前致谢。我感谢您的帮助。 @deporter我已经尝试过您的解决方案,但是它不起作用:( @mKorbel我写的,采取的概念下面的代码,你曾在

    • 语境 我试图使用JDBC在集群模式下使用quartz调度器。 问题 在开始使用集群模式下的jdbc之前,我只是用RAM存储测试了调度器。这没有问题,我能够重新启动调度程序(主类)没有任何错误。我现在遇到的问题是,当我停止执行(CTRL+C)然后重新启动它时,我总是得到错误消息: 我不明白这是怎么回事。quartz不支持重新启动调度程序吗?我的意思是,如果出现崩溃,调度程序在恢复后重新启动会发生什么

    • 问题内容: 如何重新启动Java AWT应用程序?我有一个附加了事件处理程序的按钮。我应该使用什么代码来重新启动应用程序? 我想做与应用程序中相同的事情。 问题答案: 当然,可以重新启动Java应用程序。 以下方法显示了一种重新启动Java应用程序的方法: 基本上,它执行以下操作: 查找Java可执行文件(我在这里使用了Java二进制文件,但这取决于您的要求) 查找应用程序(在我的情况下是一个ja

    • 问题内容: 如果JVM有机会在更多对象分配请求出现之前运行GC,那么JVM是否可以从OutOfMemoryError中恢复而无需重新启动? 各种JVM实现在这方面是否有所不同? 我的问题是关于JVM恢复,而不是用户程序试图通过捕获错误进行恢复。换句话说,如果将OOME抛出到应用程序服务器(jboss / websphere / ..)中,我是否必须重新启动它?或者,如果其他请求似乎没有问题,我可以

    • 下面是在没有fxml的情况下重新启动JavaFX应用程序的代码。 但是,我想用fxml实现这一点。 我不知道如何使用fxml应用此代码。 我的代码。 Main.java 控制器。JAVA 样品fxml 我想重新启动我的JavaFX应用程序。 我不知道如何使用fxml应用此代码。 如何使用fxml重新启动JavaFX应用程序?