是什么让单个Task活动有2个实例?

问题描述 投票:0回答:2

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

重现问题的步骤

步骤1

在Android Studio 3.3.1中创建一个新项目,不添加Activity,命名为singleTaskBug,(包

com.example.singletaskbug
),使用Java语言,最低API级别21,不支持即时应用程序。

步骤2

通过编辑

AndroidManifest.xml
手动添加新活动,然后在
app
java
com.example.singletaskbug
中创建一个名为
LauncherActivity
的新 Java 类。

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();
    }
}

步骤3

转至

Run
Edit Configurations...
,并在
Launch Options
部分中将
Launch:
设置为
Specified Activity
Activity:
com.example.singletaskbug.LauncherActivity
,然后单击
OK
Run 'app'
ShiftF10

步骤4

等待活动变得可见。现在,在测试设备(在我的例子中为 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 android-activity android-task
2个回答
0
投票

一个Android应用程序可以有多个任务。每个任务可以有多个活动。

singleTask
singleInstance
控制任务内 Activity 的行为(其唯一性),但应用程序可能有两个或多个任务内部具有相同的
Activity

这就是这里实际看到的,一个有两个任务的应用程序,里面有一个

LauncherActivity
,每个任务一个。作为解决方法,请确保应用程序中始终有一项任务。在
LauncherActivity
onCreate
添加:

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

0
投票

令人烦恼的是,似乎没有任何一致的方法来告诉 Android 不允许多个活动。我们无法控制操作系统在以各种方式打开应用程序时可能设置的标志:启动器、“应用程序信息”设置窗口、最近的窗口、来自深层链接等......并且不同的制造商可能会抛出自己的处理方式融入其中只是为了让它变得更有趣。

我发现处理这个问题的最佳方法很简单,就是让它发生,并在操作系统发生后进行清理。在您的活动的

onCreate
中,您可以检查任何没有活动的应用程序任务并将其删除;这也会将它们从最近使用的窗口中删除。

getSystemService<ActivityManager>()?.appTasks?.forEach { appTask ->
    if (appTask.taskInfo.numActivities == 0) {
        appTask.finishAndRemoveTask()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.