是啥让 singleTask 活动有 2 个实例?

Posted

技术标签:

【中文标题】是啥让 singleTask 活动有 2 个实例?【英文标题】:What makes a singleTask activity have 2 instances?是什么让 singleTask 活动有 2 个实例? 【发布时间】:2019-07-09 18:20:34 【问题描述】:

根据docs,singleTask 活动不能有多个实例。我的应用程序的唯一活动是 singleTask,它同时有 2 个实例。

重现问题的步骤

步骤 1

android Studio 3.3.1 中创建一个新项目,Add No Activity,将其命名为 singleTaskBug,(包 com.example.singletaskbug),使用 Java 语言,最低 API 级别为 21,不支持即时应用。

第二步

通过编辑 AndroidManifest.xml 手动添加新活动,然后在 appjavacom.example.singletaskbug 中创建一个新的 Java 类,命名为 LauncherActivity

AndroidManifest.xml的内容:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".LauncherActivity"
        android:excludeFromRecents="true"
        android:launchMode="singleTask">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />

        </intent-filter>

    </activity>
</application>

LauncherActivity.java的内容:

package com.example.singletaskbug;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;

public class LauncherActivity extends Activity 

    static int instanceCounter = 0;
    final int instanceId;
    final String TAG = "STB";

    public LauncherActivity() 
        instanceId = ++instanceCounter;
        Log.d(TAG, "Constructed instance " + instanceId + ".");
    

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Created instance " + instanceId + ".");
    

    @Override
    protected void onNewIntent(Intent intent) 
        super.onNewIntent(intent);
        Log.d(TAG, "New intent to instance " + instanceId + ".");
    

    @Override
    protected void onDestroy() 
        Log.d(TAG, "Destroyed instance " + instanceId + ".");
        super.onDestroy();
    

第三步

转到RunEdit Configurations... 并在Launch Options 部分将Launch: 设置为Specified ActivityActivity: com.example.singletaskbug.LauncherActivity,然后单击OKRun 'app' Shift F10.

第四步

等到活动变得可见。现在在测试设备(在我的情况下为 API 21)上,转到设置以将此应用程序设置为默认启动器。然后按主页按钮。此时你会在 Logcat 中看到:

02-15 17:22:01.906 26429-26429/com.example.singletaskbug D/STB: Constructed instance 1.
02-15 17:22:01.916 26429-26429/com.example.singletaskbug D/STB: Created instance 1.
02-15 17:22:24.228 26429-26429/com.example.singletaskbug D/STB: Constructed instance 2.
02-15 17:22:24.248 26429-26429/com.example.singletaskbug D/STB: Created instance 2.

【问题讨论】:

听起来很奇怪。您能够复制此代码的最少代码量是多少? 我将在几分钟内添加更多代码和分步说明。 我从零开始创建了一个新的Android Studio项目,bug就在那里,所以我希望它会很容易重现。 我认为这是一个类似的问题(6个月前问过,没有解决方案):***.com/questions/51455763/… 基本上我们必须假设 代码是正确的(并且不是错误)并且文档是错误的(或具有误导性/措辞不当),因为代码已经存在(正在使用)并且文档有错误,就像代码一样。我知道,我提出了有关文档的问题并已更改它们(例如 raw assets )。 【参考方案1】:

一个 Android 应用程序可以有多个任务。每个任务可以有多个活动。 singleTasksingleInstance 控制任务内部 Activity 的行为(其唯一性),但可能会发生一个 App 有两个或多个任务内部具有相同 Activity 的情况。

这是这里实际看到的,一个有两个任务的应用程序,里面有一个LauncherActivity,每个任务一个。作为解决方法,请确保应用程序中始终存在一项任务。在LauncherActivityonCreate上添加:

val appTasks = getSystemService(ActivityManager::class.java).appTasks
if (appTasks.size >= 2) 
    appTasks.dropLast(1).forEach  it.finishAndRemoveTask() 
    appTasks.last().moveToFront()
    return

【讨论】:

以上是关于是啥让 singleTask 活动有 2 个实例?的主要内容,如果未能解决你的问题,请参考以下文章

弄清楚是啥让 VS2008 中的 C++ 类抽象

如果数据大小超过可用内存,是啥让 Spark 快速?

SingleTask 活动在同一个进程中多次创建

launchMode 为 singleTask 的 Activity 的两个实例

android singleTask 活动不作为根?

在 PyTorch 中,是啥让张量具有非连续内存?