从另一个应用程序启动时,应用程序将失去记住其堆栈的能力

发布于 2024-10-22 07:20:53 字数 941 浏览 1 评论 0原文

现在我已经对此进行了更多研究,我正在重写它以使其更加清晰。如果您正在寻找更多信息,可以在旧版本中找到一些信息。

发生了什么:(

这是指未设置任何 launchMode 的应用程序 设置,使用默认值也是如此)

  1. 您从市场或安装程序启动应用程序。这 启动应用程序的根/主要活动 FLAG_ACTIVITY_NEW_TASK 标志并且没有类别。现在的 应用程序堆栈是 [ A ]

  2. 然后您将继续执行应用程序中的下一个活动。现在的 此任务中的堆栈是 [ A > B]

  3. 然后按主页键,然后重新启动同一应用程序 通过按主屏幕或应用程序托盘中的图标。

  4. 此时预计将显示活动 B,因为 那就是你离开的地方。然而,显示了 A 并且任务堆栈是 [A> B> A ] A 的第二个实例是通过 以下标志:FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_RESET_IF_NEEDED 和 FLAG_ACTIVITY_BROUGHT_TO_FRONT。它 还有 android.intent.category.LAUNCHER 类别。

此时,如果您按返回键,它将返回到 B,因为它 当你离开它的时候。

查看文档似乎 FLAG_ACTIVITY_BROUGHT_TO_FRONT 只能为以下活动设置: 使用 singleTask 或 singleTop 启动模式。然而,这 应用程序尚未设置任何启动模式,因此正在使用 默认标准启动模式。

我认为在这种情况下这不会发生?

我还应该注意,一旦进入这种奇怪的状态,每次从主屏幕或应用程序托盘启动应用程序时都会发生这种情况。如果任务完成(重新启动 电话,强制停止应用程序,或一路回击 stack)将修复此问题,并且将不再错误地启动它。 仅当您从安装程序或市场启动应用程序并且 然后尝试从启动器启动它。

综上所述,为什么会发生这种情况?有办法预防吗?

Now that I have researched this even more I am rewriting this to make it clearer. If you are looking for more info, there is some available in older edits.

What is happening:

(This refers to an application that has not set any launchMode
settings and so is using the defaults)

  1. You launch an app from the Market or from the Installer. This
    launches the root/main activity of the application with the
    FLAG_ACTIVITY_NEW_TASK flag and no categories. Right now the
    applications stack is [ A ]

  2. Then you proceed to the next activity in the application. Now the
    stack in this task is [ A > B ]

  3. Then you press the home key and then relaunch the same application
    by pressing it's icon from either the home screen or the app tray.

  4. What is expected at this point is that activity B will show, since
    that is where you left off. However A is shown and the tasks stack is
    [ A > B > A ] This second instance of A is launched with the
    following flags: FLAG_ACTIVITY_NEW_TASK,
    FLAG_ACTIVITY_RESET_IF_NEEDED, and FLAG_ACTIVITY_BROUGHT_TO_FRONT. It
    also has the android.intent.category.LAUNCHER category.

At this point, if you hit the back key, it will return you to B, as it
was when you left it.

Looking at the documentation it seems as if
FLAG_ACTIVITY_BROUGHT_TO_FRONT should only be set for activities that
use the singleTask or singleTop launchModes. However, this
application has not set any launchModes and is therefore using the
default standard launchMode.

I assume this is not suppose to happen in this case?

I should also note, that once it gets into this weird state, then it happens everytime the app is launched from the home screen or app tray. If the task is finished (restarting the
phone, force stopping the app, or hitting back all the way through the
stack) will fix this issue and will no longer launch it incorrectly.
It only happens if you launch the app from the installer or market and
then try to launch it from the launcher.

So in summary, why is this happening? Is there a way to prevent it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傾城如夢未必闌珊 2024-10-29 07:20:53

这是我迄今为止想出的解决方法。我见过的其他一些解决方法涉及查看当前正在运行的任务。然而,我真的不想仅仅为了解决问题而向用户请求另一个许可(GET_TASKS)。

如果您发现其中有任何漏洞,请告诉我。

在主/根活动的 onCreate 方法中,检查意图是否已
FLAG_ACTIVITY_BROUGHT_TO_FRONT 设置,如果是,则调用 finish()。这
然后将 A 的额外实例从堆栈中弹出 [ A > B> ] 变为
[A> B] 从用户的角度来看,它进入了
他们期待的活动。

到目前为止,它似乎在我所有的测试中都有效。我唯一担心的是如果
有一些奇怪的情况,某人的启动器总是会标记
使用 FLAG_ACTIVITY_BROUGHT_TO_FRONT 启动,即使应用程序不是
已经在执行一项任务,因此会将他们完全锁定
因为它会调用 finish() 并且堆栈中没有任何内容
返回到.

--

根据此处评论中的要求,您可以如何检查意图是否为特定标志:

int flags = intent.getFlags();
boolean hasFlag = flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT == Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT;

--

另外我应该注意,在进行此修复后,我仍然看到有时会出现此问题。这似乎不是一个完美的解决方案。

Here is a workaround I have come up with so far. Some other workarounds I have seen involved looking at the currently running tasks. However, I really did not want to have to ask for another permission (GET_TASKS) from the user just to make a work around.

Please let me know if you see any holes in this.

In the main/root activity's onCreate method, check if the intent has
the FLAG_ACTIVITY_BROUGHT_TO_FRONT set and if so, call finish(). This
then pops the extra instance of A off the stack [ A > B > A ] becomes
[ A > B ] and from the users perspective, it launches into the
activity they were expecting.

It seems to work in all of my tests so far. My only worry is that if
there is some weird case where someones launcher would always flag a
launch with FLAG_ACTIVITY_BROUGHT_TO_FRONT even if the app wasn't
already in a task, and therefore would completely lock them out
because it would call finish() and not have anything in the stack to
return to.

--

As requested in the comments here is how you can check if an intent a specific flag:

int flags = intent.getFlags();
boolean hasFlag = flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT == Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT;

--

Also I should note that I am still seeing this problem occur sometimes with this fix in place. It doesn't seem to be a perfect solution.

感受沵的脚步 2024-10-29 07:20:53

重写 onConfigurationChanged() 应该可以帮助您保留状态。

http://developer.android.com/reference/android/app/Activity。 html

配置更改

如果设备的配置(由 Resources.Configuration 类定义)发生更改,则显示用户界面的任何内容都需要更新以匹配该配置。由于 Activity 是与用户交互的主要机制,因此它包含对处理配置更改的特殊支持。

除非您另外指定,否则配置更改(例如屏幕方向、语言、输入设备等的更改)将导致您当前的 Activity 被销毁,经历 onPause()、onStop( ) 和 onDestroy()(视情况而定)。如果该 Activity 位于前台或对用户可见,则一旦在该实例中调用 onDestroy(),就会创建该 Activity 的一个新实例,并使用前一个实例从 onSaveInstanceState(Bundle) 生成的 SaveInstanceState。

这样做是因为任何应用程序资源(包括布局文件)都可以根据任何配置值进行更改。因此,处理配置更改的唯一安全方法是重新检索所有资源,包括布局、可绘制对象和字符串。因为活动必须已经知道如何保存其状态并从该状态重新创建自己,所以这是让活动使用新配置重新启动的便捷方法。

在某些特殊情况下,您可能希望根据一种或多种类型的配置更改绕过 Activity 的重新启动。这是通过其清单中的 android:configChanges 属性完成的。对于您所说的在那里处理的任何类型的配置更改,您将收到对当前活动的 onConfigurationChanged(Configuration) 方法的调用,而不是重新启动。但是,如果配置更改涉及任何您不处理的内容,则该 Activity 仍将重新启动,并且不会调用 onConfigurationChanged(Configuration)。”

Overriding of onConfigurationChanged() should help you to retain the state.

http://developer.android.com/reference/android/app/Activity.html

Configuration Changes

If the configuration of the device (as defined by the Resources.Configuration class) changes, then anything displaying a user interface will need to update to match that configuration. Because Activity is the primary mechanism for interacting with the user, it includes special support for handling configuration changes.

Unless you specify otherwise, a configuration change (such as a change in screen orientation, language, input devices, etc) will cause your current activity to be destroyed, going through the normal activity lifecycle process of onPause(), onStop(), and onDestroy() as appropriate. If the activity had been in the foreground or visible to the user, once onDestroy() is called in that instance then a new instance of the activity will be created, with whatever savedInstanceState the previous instance had generated from onSaveInstanceState(Bundle).

This is done because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources, including layouts, drawables, and strings. Because activities must already know how to save their state and re-create themselves from that state, this is a convenient way to have an activity restart itself with a new configuration.

In some special cases, you may want to bypass restarting of your activity based on one or more types of configuration changes. This is done with the android:configChanges attribute in its manifest. For any types of configuration changes you say that you handle there, you will receive a call to your current activity's onConfigurationChanged(Configuration) method instead of being restarted. If a configuration change involves any that you do not handle, however, the activity will still be restarted and onConfigurationChanged(Configuration) will not be called."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文