为啥即使另一个活动在顶部,launchMode="singleTask" 的启动器活动总是被推到后台堆栈的顶部? [复制]
Posted
技术标签:
【中文标题】为啥即使另一个活动在顶部,launchMode="singleTask" 的启动器活动总是被推到后台堆栈的顶部? [复制]【英文标题】:Why is launcher activity with launchMode="singleTask" always pushed to top of backstack even if another activity was on top? [duplicate]为什么即使另一个活动在顶部,launchMode="singleTask" 的启动器活动总是被推到后台堆栈的顶部? [复制] 【发布时间】:2020-07-21 20:54:06 【问题描述】:由于某些要求,我的启动器活动将 launchMode 属性设置为 singleTask。
<activity
android:name=".map.MapsActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/MapScreenTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
我面临的问题是,如果我打开另一个活动 -> 按主页 -> 在启动器应用程序中单击应用程序图标 -> 它会打开 MapActivity 而不是之前打开的活动。
但是,如果我通过最近菜单导航到应用程序,则不会发生这种情况。然后新打开的活动保持在顶部。
有人能解释一下这里发生的关于后台堆栈的情况吗?为什么 ActivityManagerService 没有考虑到应用程序进程已经存在,却决定启动启动器应用程序并清除后台堆栈,而不是简单地将应用程序向前推进?
可以在此处创建的一个小示例应用程序中观察到此问题 - https://github.com/abhiank/SingleTaskActivity
【问题讨论】:
你试过This thread..的任何解决方案吗? @ADM。太感谢了。尽管进行了所有搜索,我都不敢相信我没有找到这个线程。所以,最终的解决方案是有一个辅助活动来启动主要活动,因为 singleTask 只是简单地杀死它上面的所有其他活动。 是的,这让我想到这是一个明显的问题,以前应该问过。所以我挖了一点。如果您有解决方案,请添加答案并接受以关闭 Bounty。 是的。我想我应该挖得更深。好吧,这并不是真正的解决方案。只是一个hacky的解决方法。我认为最好是我们将此线程标记为重复并引用该线程。 一般来说,使用特殊的launchMode
会导致比它解决的问题更多。请说明您认为需要这种特殊启动模式的原因。
【参考方案1】:
我认为这是SingleTask
启动模式的期望行为。将启动器活动保持为SingleTask
有其后果。
我想不出这个问题的确切解决方案,但一些解决方法可以解决这个问题。
添加下面我在评论中提到的链接。
Android: bug in launchMode="singleTask"? -> activity stack not preserved
【讨论】:
这是不正确的。singleTask
的期望行为如下所述:developer.android.com/guide/components/activities/… 如果您查看“图 4”,它甚至明确显示包含 2 个活动的任务,其中根 Activity
声明为 launchMode="singleTask"
谢谢@DavidWasser 我会读一读..
实际上,我刚刚找到了一个非常详细的答案,该答案涵盖了这个主题的很多内容(尽管不是专门针对 launchMode="singleTask"
的行为。看看这里:***.com/a/29376250/769265
【参考方案2】:
我认为,当您再次单击应用程序图标时,它会在您之前打开的 Activity 之上打开 Launcher Activity。你可以做的就是应用一个简单的检查除了这个之外的backstack中是否有任何活动,然后完成这个启动器活动,它会显示之前打开的屏幕。试试下面的链接。 https://***.com/a/38450232/3497972
也检查这些链接,当应用程序在后台启动时,它们还有其他方式来维护屏幕
How to make an android app return to the last open activity when relaunched?
Android app restarts when opened by clicking app icon
Determine when application icon is clicked to launch the app in android
What is the difference between launch app from "recent apps" and tapping app icon
【讨论】:
感谢您的回答。我尝试了您链接中的问题提到的答案。但是,onCreate 永远不会被调用,因为如果它在 backstack 中,则带有“singleTask”的活动。我尝试将相同的代码放入 onNewIntent() 并调用它,但是,到那时 isTaskRoot() 已经是真的了。这意味着在调用 onNewIntent 之前,backstack 已经被清除并且这个活动已经被放在顶部。再次感谢您的链接。这个问题也和我面临同样的问题。 @abhiank 用更多链接更新了答案,这也有其他方法,可能会帮助你,通过它们 再次感谢这些链接。有趣的读物。但是,它们都没有用。其中大多数是关于从安装程序“打开”按钮与启动器图标单击打开的应用程序有关的问题。我希望您的最后一个链接能够深入研究从最近恢复应用程序时会发生什么不同的情况,但可惜,它没有所需的信息。【参考方案3】:当您的主要活动仅由您自己的应用程序中的其他活动启动时,有一些解决方案:
您可以从清单中的主要活动定义中删除launchMode
属性。只需将Intent.FLAG_ACTIVITY_NEW_TASK
传递给打开MainActivity
的每个意图,例如:
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
请注意,您自己的应用程序中Intent.FLAG_ACTIVITY_NEW_TASK
或launchMode="singleTask"
的行为只能与清单中活动定义的taskAffinity
属性结合使用。
希望对你有所帮助。
【讨论】:
感谢您的回答。不过,这对我不起作用。我无法控制启动器活动的意图。这由启动器应用程序和活动管理器服务控制。另外,我不需要在新任务中打开活动。我可以在默认任务中打开主要活动。我只想了解为什么具有单个任务的启动器活动总是被推到后台堆栈的顶部。 Intent.FLAG_ACTIVITY_NEW_TASK 和 launchMode="singleTask" 具有相同的行为。我建议的本质是通过意图标志而不是属性来设置“singleTask”模式。当然,如果您的应用程序将被其他应用程序使用(向其发送意图),我的解决方案将不适用于您,否则您将完全控制您的主要活动的意图。启动器应用的意图怎么样,不需要控制它,这种方法效果很好。 我明白了。但是,问题是我无法控制打开启动器活动的意图。启动器活动只是由活动管理器服务打开。 我的意思是,如果您的主要活动充当其他应用程序的助手。假设情况:用户想从某个应用程序发送电子邮件,当他这样做时,Android 系统会维护此操作,其结果将是一些活动(来自当前应用程序或另一个应用程序,没关系,只是可以执行的活动此任务),用户可以使用它完成他的发送电子邮件任务。现在,如果您的主要活动不是上述“某些活动”,那么我的解决方案效果很好,否则您当然应该得到另一个解决方案。 你是说我使用了一个常见的活动,即启动器活动并用它来启动我的主要活动?【参考方案4】:在我看来,您正在看到这个长期存在的令人讨厌的 Android 错误
Re-launch of Activity on Home button, but...only the first time
要测试是否是这种情况,请终止您的应用程序(设置->应用程序->您的应用程序->强制退出)。然后通过点击主屏幕上的应用程序图标启动您的应用程序。做任何你需要做的事情来启动另一个Activity
到任务中。按主页。现在再次点击主屏幕上的图标。这应该会将您的任务以您离开时的相同状态带到前台。
【讨论】:
嘿@David,感谢您的回答。但是,这不是我面临的错误。这个错误实际上是这个 - ***.com/questions/2417468/… 链接的问题描述了基本相同的错误。这个问题的答案是完全错误的,但如果有错误,那就是我描述的错误。您是否按照我的建议进行了测试? 我试过了。这不是正在发生的情况。这些是单独的错误。就我而言,主要活动不调用 onCreate 。首先为 Activity B 调用 onDestroy,然后为 onDetachedFromWindow 调用,最后为 mainActivity 调用 onNewIntent。而在 newIntent 中,isTaskRoot() 始终为真。实际上,在这一点上,我认为这不能称为错误。似乎 singleTask 的活动以这种方式表现。唯一的解决方案是有一个委托活动。以上是关于为啥即使另一个活动在顶部,launchMode="singleTask" 的启动器活动总是被推到后台堆栈的顶部? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
当使用 startActivityForResult 启动活动时,LaunchMode "singleTop" 会被忽略
设置 launchMode="singleTask" 与设置活动 launchMode="singleTop"
在所有内容之上显示一个 UIAlertController 并保持在顶部,即使推送另一个视图(iOS 13)