防止由单个活动组成的Android应用程序的多个实例

23

我有一个Android应用程序,它由单个Activity组成。如何确保在给定时间内只存在一个应用程序(== Activity)的实例? 我遇到了这样一种情况,通过多次点击应用程序图标,我成功打开了多个应用程序实例(这并不总是发生)。

3个回答

42

像这样更改您的清单:

    <activity
        android:name="com.yourpackage.YourActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

包含android:launchMode="singleTask",这将使得无法同时启动多个Activity实例。有关更多信息,请参见activity文档


5
它是否比"singleInstance"更受青睐? - Daniel L.
阅读文档中关于两者之间的区别,并决定哪个更适合您的用例... 我不知道您的应用程序的任何其他信息,因此无法回答。 - FoamyGuy
5
android:launchMode="singleTask"无效,android:launchMode="singleInstance"有效。 - xevser
非常感谢!现在是2022年,我遇到了同样的问题。我实现了一个应用程序主题更改对话框,每次重新启动应用程序时(确保它不在“最近使用”中,即不在后台运行),当当前主题与设备的默认主题不匹配时,就会创建相同活动的新实例。我尝试了很多方法来解决这个问题,但都没有成功。最终,我找到了这个方法,我的问题现在已经解决了。顺便说一下,“singleTask”和“singleInstance”都适用于我。:) - Shubham Nanche

15

接受的答案达到了其目的,但这并不是做这件事的最佳方式。

相反,我建议在每个活动中使用静态的AtomicInteger,如下所示:

//create a counter to count the number of instances of this activity
public static AtomicInteger activitiesLaunched = new AtomicInteger(0);

@Override
protected void onCreate(Bundle pSavedInstanceState) {

        //if launching will create more than one 
        //instance of this activity, bail out
        if (activitiesLaunched.incrementAndGet() > 1) { finish(); }

        super.onCreate(pSavedInstanceState);

}

@Override
protected void onDestroy() {

        //remove this activity from the counter
        activitiesLaunched.getAndDecrement();

        super.onDestroy();

}



那么,被接受的答案有什么问题吗?

声明您的活动应使用singleInstance模式启动会开始干扰活动和任务的默认行为,这可能会产生一些不良影响。

Android 文档建议仅在必要时(在此情况下不需要)打断此行为:

警告:大多数应用程序不应中断活动和任务的默认行为。如果您确定需要修改默认行为,则要小心,并确保测试活动在启动时和从其他活动和任务导航回到该活动时的可用性以及返回按钮的使用情况进行测试。务必测试可能与用户预期行为冲突的导航行为。


您提出的解决方案是否适用于具有多个活动的应用程序?我最终得到了一个空白的活动,并且在某些情况下,应用程序根本无法启动。 - Luboš Staráček
应该可以。那是我几年前使用它时没有问题的。当然,现在可能你的代码其他地方有问题吧?试着排除这种可能性:创建一个新项目,包含两个基本活动,只显示文本(“Activity 1”和“Activity 2”)。然后在这个控制环境中实现这个方法并进行测试,看看是否仍然会出现奇怪的问题。 - Hunter S
我的使用情境是从任何第三方应用程序中以Intent.ACTION_VIEW的操作启动我的应用程序,而我的应用程序在后台运行。好的,我将在一些琐碎的代码上尝试一下,看看它是否可以工作。 - Luboš Staráček
1
这应该是被接受的答案。singleTop launchMode 在我开发的应用中接收通知时引起了很多问题。 - Justin Ebby
1
这个答案解决了我的问题!忘记了原子整数,这个方法非常好用。 - Gastón Saillén
显示剩余5条评论

0

我发现我的应用程序的用户经常会出现内存不足的情况,而我一直在努力弄清楚原因。在尝试解决问题时,我发现我可以通过重复点击图标然后返回主屏幕,再次点击图标,再返回主屏幕等方式打开多个应用程序实例。我可以看到内存使用量不断增加,直到最终应用程序崩溃。在崩溃之前,我可以点击“关闭”菜单选项,之前的实例就会回到前台,这种情况会发生多次,就像我启动应用程序一样。

我的解决方案是在清单文件中添加android:launchMode="singleInstance"。从那以后,我就无法打开多个实例或使应用程序崩溃了。


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