在启动器中点击应用图标后,应用完全重新启动

88

我正在尝试创建我的第一个Android应用的发布版本,以便发送给几个测试者。但是,我遇到了一个问题。当您退出应用程序然后通过其图标重新进入时,它会重新启动整个应用程序,而不是返回到它之前的位置。即使您在退出后立即重新进入,也会发生这种情况。但是,如果我按住Home按钮并通过最近使用的应用程序列表启动它,则不会发生这种情况。

我在网上搜索了其他人遇到过此问题,有一些人遇到了类似的问题,但是没有人能够给出确切的答案说明为什么会出现这种情况。旧问题中建议在清单文件中将启动模式设置为singletasksingleinstance,但这对我没有帮助。而且从我了解的情况来看,Android的默认行为是在这种情况下返回任务的先前状态,因此我不知道为什么需要特殊的清单选项才能使其做到这一点。

关于这个问题最奇怪的事情是,如果我使用eclipse和调试器将应用程序放在我的手机上,这个问题就不会发生。我甚至不需要连接调试器,只要我有一个调试版本的应用程序,这个问题就不会发生。但是,如果我使用发布版本(我使用Eclipse中的Android工具 - 导出已签名应用程序包菜单选项创建它),则会出现问题。 如果有人知道是什么原因引起了这个问题,我很想听听您的想法。


3
显然,如果我重新启动安装应用程序的设备,这个问题就会消失。虽然如此,但在我的应用程序中,如果用户在下载应用程序后在手机重启之前遇到这种情况,仍然会非常烦人。 - LayfieldK
能否提供堆栈跟踪或日志? - TryTryAgain
2
不,这只发生在我使用应用程序的发布版本时,所以我没有堆栈跟踪或日志。 - LayfieldK
3
我遇到了同样的问题,你最终找到解决方法了吗?或者是原因?甚至在重启设备后是否能够重新创建该行为?顺便说一句,我也发现强制停止应用程序可以清除该行为。 - kassim
2
这个问题的有效答案可以在这里找到:https://dev59.com/_2Ik5IYBdhLWcg3wI7EF - Mythul
显示剩余6条评论
15个回答

63

我遇到了一个应用程序的相同问题,我通过在AndroidManifest.xml文件中<activity>声明中添加标志"android:launchMode="singleTop""而不是"android:launchMode="singleTask""来解决这个问题。希望这能帮助到某些人。


3
如果我们想要用不同的数据打开同一活动两次,那么这种方法是危险的。 - hkaraoglu
7
如果您想使用不同的数据打开相同的活动,则可以在onNewIntent()中处理此操作。 - Tasneem
我还发现如果完全删除android:launchMode属性,它也能起作用。不确定是否默认为“Standard”,但任何想法都将有所帮助。我找到了这个很棒的解释,但现在已经很晚了,所以对我来说看起来像一种外语:https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en - Joshua Pinter
嗨,我应该在所有的活动中添加android:launchMode="singleTop"吗? - jmarkstar
在我的情况下,这不起作用。在我的应用程序中,我有一个功能来创建和共享某些内容的链接。如果应用程序在后台,并且用户单击共享的链接,则会打开应用程序的完全新实例,如果我的launchMode设置为'singleTop'或'singleInstance'。 - tech_human
当我将这个添加到我的项目中时,导航器停止工作了。我无法进入应用程序。 - Samiksha Jagtap

34

到目前为止,我发现这是一个基于你如何在真实设备上安装它的问题,具体而言:

  1. 如果你只是将APK文件复制并粘贴到设备的本地存储中,并从设备上安装它,无论它是否被签名或未签名或来自bin文件夹,它都会出现这种行为,应用程序会从菜单图标重新启动。

如果你使用以下选项之一进行安装,则不会出现此问题:

  1. 打开终端或命令提示符并进入sdk/tools/目录,然后键入

    adb install <FILE PATH OF .APK FILE>
    
    在Linux中,输入以下命令:
    ./adb install <FILE PATH OF .APK FILE>
    
  2. 只需在Eclipse中运行您的项目即可。

如果有可能分发正确的APK进行测试,我会很高兴。我已经尝试过导出已签名的APK,因为当您复制并粘贴一个APK并手动安装它时,它会显示异常行为。

更新:

我找到了解决方案。请按照以下两个步骤操作:

  1. AndroidMainifest.xml文件中的所有应用程序活动中的activity标记内设置android:launchMode="singleTask" = true
  2. 将此代码放置在启动器Activity的onCreate()中。
if (!isTaskRoot())
{
    final Intent intent = getIntent();
    final String intentAction = intent.getAction(); 
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
        finish();
        return;       
    }
}

这种行为是 Android 中的一个错误,不是特例。


2
我不建议这样做。launchMode 不应该仅仅被设置,它必须有一个目的,否则可能会导致奇怪的行为(从经验中说的;)) - Boy
如果您的应用程序支持诸如 Pin 锁定之类的功能,则在设置 android:launchMode="singleTask" 时应小心处理。 - Logan Guo

11
 // To prevent launching another instance of app on clicking app icon 
        if (!isTaskRoot()
                && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
                && getIntent().getAction() != null
                && getIntent().getAction().equals(Intent.ACTION_MAIN)) {

            finish();
            return;
        }

在调用setContentView之前,在您的启动活动中编写上述代码。这将解决问题。


这个方法可行。我在应用程序从Play商店“打开”按钮启动并将应用程序移至后台,然后单击应用程序图标时遇到了崩溃的问题。这个修复解决了我的问题。谢谢。 - karanatwal.github.io

8
您可以在AndroidManifest.xml中的启动器活动中使用singleTop作为launchMode。
       <activity
        android:name="<YOUR_ACTIVITY>"
        android:label="@string/app_name"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

4

将以下代码添加到你的第一个活动:

if (!isTaskRoot()) {
        finish();
        return;
}     
super.onCreate(savedInstanceState);

2
这对我的情况起作用,即具有处理应用程序所有入口点的启动屏幕,因此如果启动屏幕已经完成了它的工作并重定向到正确的位置,第一次就不需要再做一遍。 - Ahmed na

4

这是在Android中的默认行为。对于调试版本,由于某种原因它会有所不同。你可以通过将android:launchMode="singleInstance"添加到你想要在从图标启动后重新启动的活动中来解决此问题。


3
尝试使用 android:alwaysRetainTaskState,如下例所示:
<activity
    android:name="com.jsnider.timelineplanner.MainActivity"
    android:alwaysRetainTaskState="true"
    android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

3
你可以尝试在AndroidManifest.xml中为您的启动器活动设置android:alwaysRetainTaskState="true". 这将使您的应用程序保留其最后一次状态,即使用户离开并返回到该应用程序。
    <activity
        android:name=".YourMainActivity"
        android:alwaysRetainTaskState="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

具体详情请参见https://developer.android.com/guide/topics/manifest/activity-element.html#always


3

我发现我在activity属性中错误地发布了NoHistory = true

[Activity(NoHistory = true, ScreenOrientation = ScreenOrientation.Landscape)]

这个操作阻止了应用恢复到该活动并重新启动


2

我在2019年的Android电视上遇到了这个问题。除了“Original Answer”之外,是否有更好的解决方法?

if (!isTaskRoot()) {
    finish();
}

它可以运行,但看起来更像是一种hack而不是真正的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接