按HOME后重新启动应用程序时如何返回到最新启动的活动?

熟悉的场景:我有一个主要活动,当按下button时启动游戏活动。 如果用户按HOME键,然后再次启动我的应用程序,则应该显示游戏活动,这是他在使用应用程序时最后做的事情。

但是,发生的却是他再次获得主要活动。 我觉得Android正在创buildMainActivity的另一个实例,并将其添加到该应用程序的堆栈中,而不是只select顶部的任何东西,因为如果在重新启动应用程序后按BACK,我会进入游戏活动! 每次调用Main.onCreate方法,而不是调用GameActivity.onResume。

我的AndroidManifest.xml几乎是“裸露的骨头”:

 <activity android:name="MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="GameActivity" android:label="@string/app_name"> </activity> 

正如你所看到的,没有什么太花哨。

这就是新活动的推出方式,非常简单:

 Intent intent = new Intent(this, GameActivity.class); startActivity(intent); 

从理论上讲,这应该在Android中“开箱即用”,因为一个非常类似的问题的答案是: 在Android(使用singleTask启动模式)中维护标准应用程序活动回栈状态 ,但事实并非如此。

我一直在阅读和重新阅读关于活动和任务和堆栈的文档,并浏览所有相关的答案,但我不明白为什么这样一个简单的安装程序没有按预期工作。

Solutions Collecting From Web of "按HOME后重新启动应用程序时如何返回到最新启动的活动?"

  @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... } 

哦,我想我已经find了答案。

因为我是通过使用IntelliJ启动应用程序的,所以它似乎以不同于用户的方式启动应用程序,单击主屏幕小部件将启动。 在另一个SO问题的答案中解释了这个问题:

这是由于意图被用来启动应用程序是不同的。 Eclipse启动一个应用程序使用意向没有行动,没有类别。 启动器启动一个应用程序使用意图与android.intent.action.MAIN行动和android.intent.category.LAUNCHER类别。 安装程序使用android.intent.action.MAIN操作启动一个应用程序,并且没有类别。

参考: 应用程序总是从根活动新鲜开始,而不是恢复后台状态(已知错误)

所以我手动杀死了手机中的应用程序,并从主屏幕小部件再次重新启动。 然后打开GameActivity,并按下HOME。 现在,重新启动时,GameActivity仍然可见并保持其UI状态,就像我离开时一样。

而且我猜测,之前按快捷方式时创build活动的新实例的原因是由于启动活动使用了不同的Intent。

最简单的解决scheme是在onPause期间写出一个首选项,或者将你的状态序列化到一个持久化文件,然后在主入口点Activity的onResume中读取这个文件。 此活动将重build应用程序状态并重新启动正确的活动。

你看到这个,因为你的应用程序可能会被操作系统杀死退出。 你永远不知道,所以如果你想要真正的使用持久性,即无论如何回到最后一个活动,你需要将你的状态写入持久性存储。

我强烈build议使用isTaskRoot检查活动是否应完成,而不是FLAG_ACTIVITY_BROUGHT_TO_FRONT标志。

我喜欢萨钦的回答 ,但是有时会给我误报,我会在不应该的时候完成这个活动。 我发现重现这种误报的可靠方法是:

  1. 从主屏幕启动应用程序
  2. 按回家
  3. 再次从主屏幕启动应用程序
  4. 按“返回”返回到主屏幕
  5. 从“最近的应用程序”返回到应用程序

我开始寻找方法来检查我的任务的活动backstack,并find使用ActivityManager的答案。 这似乎可以工作,但这个答案指出了isTaskRoot的存在,这是一个简单,优雅的方式来检测这不会给出误报,不需要特别的权限,不使用方法documtation说的是用于debugging和任务pipe理应用程序,这是不支持这种types的使用。

我明白你来自哪里,但我认为操作系统不想做出任何假设。 另外,还有一个问题是你的应用程序已经被回收,因为内存需要其他的东西。 在那个原因,它将从您的MainActivity重新开始。

根据游戏的复杂程度,您可以在SharedPreferences中保存状态,也可以在Activity的onPause()方法中保存SqlLite数据库。 然后onResume()你可以将用户恢复到最后的状态,这可能包括“重新启动”你的GameActivity。

希望这可以帮助!

编辑:我在说的是,作为开发者,我们有责任向用户展示/保证返回到应用程序时显示正确的活动。 你的应用程序的内存总是有回收的可能性,然后android将重新启动你已经标记为MAIN和LAUNCHER意图的活动。 通过保存状态(活动ID),您可以将它们redirect到主活动…

我在我的应用程序中使用以下活动堆栈来解决问题:

LaunchActivity – > MainActivtiy – > SomeSubActivtiy

LaunchActivtiy只validation一些参数并启动MainActivtiy 。 原来, MainActivity必须与

 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 

MainActivity上的这些标志组合提供了所需的行为。