Android:launchMode=“singleTask”中的错误? ->活动堆栈未保留
我的主要活动 A
在清单中设置了 android:launchMode="singleTask"
。现在,每当我从那里开始另一个活动时,例如 B
并按手机上的 HOME BUTTON
返回主屏幕,然后再次返回我的应用程序,或者通过按应用程序的按钮或长按HOME BUTTON
来显示我最近的应用程序,它不会保留我的活动堆栈并直接返回A
而不是预期的活动<代码>B。
这里有两种行为:
Expected: A > B > HOME > B
Actual: A > B > HOME > A (bad!)
我是否缺少某个设置或者这是一个错误?如果是后者,在错误修复之前是否有解决方法?
仅供参考:此问题已在此处讨论过。然而,目前似乎还没有任何真正的解决方案。
My main activity A
has as set android:launchMode="singleTask"
in the manifest. Now, whenever I start another activity from there, e.g. B
and press the HOME BUTTON
on the phone to return to the home screen and then again go back to my app, either via pressing the app's button or pressing the HOME BUTTON
long to show my most recent apps it doesn't preserve my activity stack and returns straight to A
instead of the expected activity B
.
Here the two behaviors:
Expected: A > B > HOME > B
Actual: A > B > HOME > A (bad!)
Is there a setting I'm missing or is this a bug? If the latter, is there a workaround for this until the bug is fixed?
FYI: This question has already been discussed here. However, it doesn't seem that there is any real solution to this, yet.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
这不是一个错误。当启动现有的
singleTask
活动时,堆栈中位于该活动之上的所有其他活动都将被销毁。当您按
HOME
并再次启动 Activity 时,ActivityManger
会调用 Intent因此结果是 A > B>首页> A.
当A的launchMode为“Standard”时,情况有所不同。包含A的任务将来到前台并保持与之前相同的状态。
您可以创建一个“标准”活动,例如。 C 作为启动器并在 C 的 onCreate 方法中启动Activity(A)
OR
只需删除
launchMode="singleTask"
并设置FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
每当向 A 调用意图时标记This is not a bug. When an existing
singleTask
activity is launched, all other activities above it in the stack will be destroyed.When you press
HOME
and launch the activity again,ActivityManger
calls an intentSo the result is A > B > HOME > A.
It's different when A's launchMode is "Standard". The task which contains A will come to the foreground and keep the state the same as before.
You can create a "Standard" activity eg. C as the launcher and startActivity(A) in the onCreate method of C
OR
Just remove the
launchMode="singleTask"
and setFLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
flag whenever call an intent to A来自 http://developer.android.com/guide/topics/manifest
singleTask
上的 /activity-element.html这意味着当action.MAIN和category.LAUNCHER标志从启动器瞄准您的应用程序时,系统宁愿将意图路由到现有的ActivityA,而不是创建新任务并将新的ActivityA设置为根。它宁愿拆除 ActivityA 所在的现有任务之上的所有活动,并调用它的 onNewIntent()。
如果您想捕获 singleTop 和 singleTask 的行为,请使用 singleTask launchMode 创建一个名为 SingleTaskActivity 的单独“委托”活动,该活动只需在其 onCreate() 中调用 singleTop 活动,然后自行完成。 singleTop 活动仍将具有 MAIN/LAUNCHER 意图过滤器以继续充当应用程序的主 Launcher 活动,但是当其他活动希望调用此 singleTop 活动时,它必须调用 SingleTaskActivity 以保留 singleTask 行为。传递给 singleTask 活动的意图也应该传递给 singleTop Activity,因此,由于我想要同时拥有 singleTask 和 singleTop 启动模式,因此类似以下内容对我有用。
并且您的 singleTop 活动将继续具有其 singleTop 启动模式。
祝你好运。
From http://developer.android.com/guide/topics/manifest/activity-element.html on
singleTask
This means when the action.MAIN and category.LAUNCHER flags targets your application from the Launcher, the system would rather route the intent to the existing ActivityA as opposed to creating a new task and setting a new ActivityA as the root. It would rather tear down all activities above existing task ActivityA lives in, and invoke it's onNewIntent().
If you want to capture both the behavior of singleTop and singleTask, create a separate "delegate" activity named SingleTaskActivity with the singleTask launchMode which simply invokes the singleTop activity in its onCreate() and then finishes itself. The singleTop activity would still have the MAIN/LAUNCHER intent-filters to continue acting as the application's main Launcher activity, but when other activities desire calling this singleTop activity it must instead invoke the SingleTaskActivity as to preserve the singleTask behavior. The intent being passed to the singleTask activity should also be carried over to the singleTop Activity, so something like the following has worked for me since I wanted to have both singleTask and singleTop launch modes.
And your singleTop activity would continue having its singleTop launch mode.
Good luck.
Stefan,你找到这个问题的答案了吗?我为此编写了一个测试用例,并且看到了相同的(令人困惑的)行为...我将粘贴下面的代码,以防有人出现并看到一些明显的东西:
AndroidManifest.xml:
ActivityA.java:
ActivityB.java:
我尝试过更改 minSdkVersion 无效。这似乎是一个错误,至少根据文档,其中声明如下:
如上所述,“singleTask”或“singleInstance”活动的实例永远不会超过一个,因此该实例应处理所有新意图。 “singleInstance”活动始终位于堆栈顶部(因为它是任务中唯一的活动),因此它始终能够处理意图。但是,“singleTask”活动在堆栈中可能有也可能没有位于其上方的其他活动。如果是,则它无法处理该意图,并且该意图将被丢弃。 (即使意图被放弃,它的到来也会导致任务到达前台,并保留在那里。)
Stefan, you ever find an answer to this? I put together a testcase for this and am seeing the same (perplexing) behavior...I'll paste the code below in case anyone comes along and sees something obvious:
AndroidManifest.xml:
ActivityA.java:
ActivityB.java:
I tried changing minSdkVersion to no avail. This just seems to be a bug, at least according to the documentation, which states the following:
As noted above, there's never more than one instance of a "singleTask" or "singleInstance" activity, so that instance is expected to handle all new intents. A "singleInstance" activity is always at the top of the stack (since it is the only activity in the task), so it is always in position to handle the intent. However, a "singleTask" activity may or may not have other activities above it in the stack. If it does, it is not in position to handle the intent, and the intent is dropped. (Even though the intent is dropped, its arrival would have caused the task to come to the foreground, where it would remain.)
我认为这就是您想要的行为:
由于某些我不明白的迟钝原因,singleTask 在主屏幕上重置堆栈。
解决方案是不使用 singleTask 并使用 standard 或 singleTop 来代替启动器活动(尽管迄今为止我只尝试过 singleTop)。
因为应用程序彼此之间具有亲和力,所以启动这样的活动:
将导致您的活动堆栈按原样重新出现,而不会在旧活动上启动新活动(这是我之前的主要问题)。 标志是重要的:
和:
如果没有它们,启动的活动只会被推到旧堆栈的顶部或其他一些不良行为(当然在这种情况下)
我相信没有收到最新意图的问题可以这样解决(在我的脑海中):
尝试一下出去!
I think this is the behaviour you want:
singleTask resets the stack on home press for some retarded reason that I don't understand.
The solution is instead to not use singleTask and use standard or singleTop for launcher activity instead (I've only tried with singleTop to date though).
Because apps have an affinity for each other, launching an activity like this:
will cause your activty stack to reappear as it was, without it starting a new activity upon the old one (which was my main problem before). The flags are the important ones:
And:
Without them the launched activity will just be pushed ontop of the old stack or some other undesirable behaviour (in this case of course)
I believe the problem with not receiving the latest Intent can be solved like this (out of my head):
Try it out!
我发现仅当启动器活动的启动模式设置为 singleTask 或 singleInstance 时才会出现此问题。
因此,我创建了一个新的启动器 Activity,其启动模式为 standard 或 singleTop。并使这个启动器活动调用我的旧主要活动,其启动模式是单任务。
LauncherActivity(标准/无历史记录)-> MainActivity (singleTask)。
将启动屏幕设置为启动器活动。在我调用主要活动后立即终止了启动器活动。
优点:可以将 MainActivity 的启动模式保持为 singleTask,以确保始终不超过一个 MainActivity。
I've found this issue happens only if the launcher activity's launch mode is set to singleTask or singleInstance.
So, I've created a new launcher activity whose launch mode is standard or singleTop. And made this launcher activity to call my old main activity whose launch mode is single task.
LauncherActivity (standard/no history) -> MainActivity (singleTask).
Set splash screen to launcher activity. And killed launcher activity right after I call the main activity.
Pros: Can keep the MainActivity's launch mode as singleTask to make sure there always is no more than one MainActivity.
如果 A 和 B 属于同一个
Application
,请尝试从您的
Activities
中删除并进行测试,因为我认为默认行为是您所描述的预期行为。If both A and B belong to the same
Application
, try removingfrom your
Activities
and test because I think the default behavior is what you described as expected.每当您按下主页按钮返回主屏幕时,活动堆栈都会杀死一些先前启动和正在运行的应用程序。
要验证这一事实,请尝试在应用程序中从 A 转到 B 后从通知面板启动应用程序,然后使用后退按钮返回......您会发现您的应用程序处于与您相同的状态留下了它。
Whenever you press the home button to go back to your home screen the activity stack kills some of the previously launched and running apps.
To verify this fact try to launch an app from the notification panel after going from A to B in your app and come back using the back button ..........you will find your app in the same state as you left it.
当使用 singleTop 启动模式时,请确保在启动下一个活动(使用 startActivity(Intent) 方法,如 B)时调用 finish()(在当前活动上,如 A)。这样当前的活动就会被破坏。
A-> B->暂停应用程序并单击启动器图标“Starts A”
在 A 的 oncreate 方法中,您需要进行检查,
这样在启动应用程序时我们将检查根任务,之前的根任务是 B 而不是 A。因此,此检查会销毁活动 A 并将我们带到当前的活动 B堆栈顶部。
希望它对你有用!
When using launch mode as singleTop make sure to call finish() (on current activity say A) when starting the next activity (using startActivity(Intent) method say B). This way the current activity gets destroyed.
A -> B -> Pause the app and click on launcher Icon, Starts A
In oncreate method of A, you need to have a check,
This way when launching app we are checking for root task and previously root task is B but not A. So this check destroys the activity A and takes us to activity B which is currently top of the stack.
Hope it works for you!.
这就是我最终解决这个奇怪行为的方法。在 AndroidManifest 中,这是我添加的内容:
This is how I finally solved this weird behavior. In AndroidManifest, this is what I added:
在 android 清单活动中添加以下内容,它将添加新任务到视图顶部,从而销毁之前的任务。
android:launchMode="singleTop" 如下
Add below in android manifest activity, it will add new task to top of the view destroying earlier tasks.
android:launchMode="singleTop" as below
我被这个问题困住了,找到了解决方案
从清单中删除 launchMode
每当启动 Activity
Intent.FLAG_ACTIVITY_CLEAR_TOP 或 Intent.FLAG_ACTIVITY_SINGLE_TOP
时添加这些标志这对我有用
I was stuck on the issue figured out a solution
remove launchMode from manifest
add these flags whenever launching the activity
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
this worked for me
//尝试在您的主要活动中使用 launchMode="singleTop" 来维护应用程序的单个实例。去体现并改变。
//Try to use launchMode="singleTop" in your main activity to maintain single instance of your application. Go to manifest and change.