从Android应用程序安装程序和主屏幕启动应用程序时出现活动堆栈排序问题

从Android应用程序安装程序和主屏幕启动应用程序时出现活动堆栈排序问题,android,android-activity,android-intent,task,flags,Android,Android Activity,Android Intent,Task,Flags,仅出于测试目的,我允许通过URL下载和安装我的应用程序APK。一旦下载到手机上,它就可以通过Android应用程序安装程序启动,用户可以选择将其安装到自己的设备上,然后运行它 考虑我们是否以上述方式下载并运行应用程序。我的应用程序中的主/启动器活动是登录页面(活动a)。一旦用户通过身份验证,他们将被带到应用程序的主要区域,例如活动B。因此,现在此任务的当前活动堆栈是A>B 然后我按下手机上的home(主页)按钮,进入Android主屏幕。我通过菜单中的图标重新启动我的应用程序,并进入活动A,而不

仅出于测试目的,我允许通过URL下载和安装我的应用程序APK。一旦下载到手机上,它就可以通过Android应用程序安装程序启动,用户可以选择将其安装到自己的设备上,然后运行它

考虑我们是否以上述方式下载并运行应用程序。我的应用程序中的主/启动器活动是登录页面(
活动a
)。一旦用户通过身份验证,他们将被带到应用程序的主要区域,例如
活动B
。因此,现在此任务的当前活动堆栈是
A>B

然后我按下手机上的home(主页)按钮,进入Android主屏幕。我通过菜单中的图标重新启动我的应用程序,并进入
活动A
,而不是
活动B
。活动堆栈现在是
A>B>A
,或者现在有两个单独的任务,分别具有活动堆栈
A>B
,和
A
。当我重新启动应用程序时,我想要的是回到
活动B
。在此状态下按back(后退)将使我返回到
活动B

只有当我首先通过安装程序打开应用程序时,这种不希望出现的行为才会发生,而不是通过主屏幕/菜单打开应用程序时

我研究了每个机制是如何启动这些活动的。使用应用程序安装程序时,我们会看到以下日志:

INFO/ActivityManager(XXXX): Starting activity: Intent { dat=file:///mnt/sdcard/download/[my app].apk cmp=com.android.packageinstaller/.InstallAppProgress (has extras) }
INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=[my package]/[Activity A] }
通过启动器/主屏幕:

INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=[my package]/[Activity A] }
当使用安装程序启动时,我们看到它使用的是标志
0x10000000
,但当使用启动器启动时,我们看到它使用的是
0x10200000
。它还使用了意图类别

从中,我们可以看到以下标志:

public static final int FLAG_ACTIVITY_NEW_TASK
Constant Value: 268435456 (0x10000000)

public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
Constant Value: 2097152 (0x00200000)
如果需要,标志
flag\u ACTIVITY\u RESET\u TASK\u(从启动器启动应用程序时使用)通常会阻止创建新任务(如果已经存在),并将恢复上次使用的活动。这是理想的行为。为什么它在这种情况下不起作用?我能做些什么来确保我的应用程序始终返回到上一个活动,而不管它是否是通过应用程序安装程序/启动器启动的

如果我使用
singleTask
,每当我运行应用程序时(这也是不可取的),它总是会将我带回主活动(
活动A

以下是我发现的一个问题,其中有人遇到了类似的问题(没有公认的答案):

编辑:在启动程序活动的
onCreate()
中检查标志
flag\u ACTIVITY\u将\u带到前面的
(如果设置了,则完成)似乎可以修复主要症状,但显然根本问题仍然存在。有更完整的解决方案吗


EDIT2:从Android Market下载/运行应用程序时也会出现相同的结果,因此上面的一些细节可能不相关。

我认为根本问题是,启动器和安装程序使用的
意图不同。只要您获得不同的意图标志,您将获得不同的启动行为。你可以随意改变发射模式,你可能会得到一致的结果,但从根本上说,这些不同的意图会产生不同的结果


您的修复程序(或类似程序)可能是您的最佳选择。

您的问题可能源于这样一个事实,即应用程序安装程序不使用启动器类别,启动器也不使用

此错误已在其他地方记录:


添加了antonyt提供的答案:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
        // Activity was brought to front and not created,
        // Thus finishing this will get us to the last viewed activity
        finish();
        return;
    }

    // Regular activity creation code...
}

这似乎是许多应用程序都不希望看到的一个基本问题——事实上,我已经看到Android Facebook应用程序表现出这种行为——因此,我们所能做的只是上述解决方法(或类似方法),这相当令人失望。这可能被视为一种行为缺陷:另一方面,它确实允许您区分安装程序启动和应用程序图标启动,您可以使用它们启动欢迎屏幕,该屏幕仅在有人单击安装程序运行按钮时显示。现在,我想我可能真的会使用它:)@Femi但是,请记住,并不是每个人都会通过安装和运行选项第一次启动该应用程序,当他们开始使用它时,他们可能仍然会感激一句问候语。:)非常正确:我的应用程序中已经有了检查第一次运行的逻辑,这只是又一个钩子。我试图检测类别是否设置在用于启动活动的意图中(通常不是由安装程序设置的,只有启动器设置的)-如果缺少,我添加类别和标志,然后重新启动(startActivity()/finish())带着这个修改过的意图。尽管现在看来意图一致,但这种不良行为仍在发生。你对此有什么想法吗?检查旗子的活动,把旗子带到前线,效果很好。你能把它作为一个答案吗?另一个可复制的场景:从市场上推出应用程序基本上与2019年的情况相同,但仍处于崩溃状态!thnx用于代码,我还学习了一种新的方法来编写if条件,但您应该添加这样一种情况,即某些启动器总是使用flag_ACTIVITY_将某个启动标记到前面,即使应用程序尚未处于任务中,因此会完全锁定它们,因为它会调用finish()而且在堆栈中没有任何东西可以返回。在进行此项检查时,似乎要记住一件很重要的事情。@VishwasSharma-您提出的问题听起来像是Android平台的bug。为什么Android会同意锁定的情况?锁定的情况将由上面代码中的检查引入(虽然不太可能发生),而不是由Android引入,如果您知道应用程序是如何启动的,您应该已经知道,如果您从菜单启动应用程序,它将以不同的意图标志启动,如果你从launcher菜单启动它,那么我