最近使用的屏幕

最近使用的屏幕(也称为概览屏幕、最近任务列表或最近应用屏幕)是一个系统级 UI,其中列出了最近访问的活动任务。用户可以通过列表导航,选择要恢复的任务,或通过滑动将其从列表中删除。

最近使用的屏幕使用以文档为中心的模型(在 Android 5.0(API 级别 21)中引入),其中同一活动包含不同文档的多个实例可以作为任务显示在最近使用的屏幕中。例如,Google 云端硬盘可能为多个 Google 文档中的每一个都有一个任务。每个文档都显示为最近使用的屏幕中的一个任务

最近使用的屏幕显示两个 Google 云端硬盘文档,每个文档都表示为一个单独的任务。

另一个常见示例是当用户使用其浏览器并点击共享 > Gmail时。Gmail 应用的撰写屏幕出现。此时点击最近使用的按钮会显示 Chrome 和 Gmail 作为单独的任务运行

最近使用的屏幕显示 Chrome 和 Gmail 作为单独的任务运行。

通常,您让系统定义您的任务和活动如何在最近使用的屏幕中表示。您无需修改此行为。但是,您的应用可以确定活动在最近使用的屏幕中显示的方式和时间。

ActivityManager.AppTask 类允许您管理任务,并且Intent 类的活动标志允许您指定何时将活动添加到最近使用的屏幕或从中删除。此外,<activity> 属性允许您在清单中设置行为。

将任务添加到最近使用的屏幕

使用Intent 类的标志添加任务可以让您更好地控制何时以及如何打开或重新打开最近使用的屏幕中的文档。当您使用<activity> 属性时,您可以在始终在新任务中打开文档或重用现有任务以用于文档之间进行选择。

使用 Intent 标志添加任务

当您为活动创建新文档时,您会调用 startActivity() 方法,并将启动该活动的意图传递给它。为了插入逻辑断点,以便系统在“最近使用的应用”屏幕中将您的活动视为新任务,请在启动该活动的 IntentaddFlags() 方法中传递 FLAG_ACTIVITY_NEW_DOCUMENT 标志。

如果在创建新文档时设置了 FLAG_ACTIVITY_MULTIPLE_TASK 标志,则系统始终会创建一个新任务,并将目标活动作为根活动。此设置允许在多个任务中打开同一文档。以下代码演示了主活动如何执行此操作

Kotlin

fun createNewDocument(view: View) {
    val newDocumentIntent = newDocumentIntent()
    if (useMultipleTasks) {
        newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
    }
    startActivity(newDocumentIntent)
}

private fun newDocumentIntent(): Intent =
        Intent(this, NewDocumentActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
                    android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
            putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++)
        }

Java

public void createNewDocument(View view) {
      final Intent newDocumentIntent = newDocumentIntent();
      if (useMultipleTasks) {
          newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
      }
      startActivity(newDocumentIntent);
  }

  private Intent newDocumentIntent() {
      boolean useMultipleTasks = checkbox.isChecked();
      final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
      newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
      newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++);
      return newDocumentIntent;
  }

}

当主活动启动一个新活动时,系统会在现有任务中搜索一个其意图与活动意图组件名称和意图数据匹配的任务。如果未找到任务,或者意图包含 FLAG_ACTIVITY_MULTIPLE_TASK 标志,则会创建一个新任务,并将该活动作为其根活动。

如果系统找到一个其意图与意图组件名称和意图数据匹配的任务,则会将该任务置于最前端,并将新意图传递给 onNewIntent()。新活动获取意图并在“最近使用的应用”屏幕中创建一个新文档,如下例所示

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_new_document)
    documentCount = intent
            .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0)
    documentCounterTextView = findViewById(R.id.hello_new_document_text_view)
    setDocumentCounterText(R.string.hello_new_document_counter)
}

override fun onNewIntent(newIntent: Intent) {
    super.onNewIntent(newIntent)
    /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this Activity
    will be reused. */
    setDocumentCounterText(R.string.reusing_document_counter)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_document);
    documentCount = getIntent()
            .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
    documentCounterTextView = (TextView) findViewById(
            R.id.hello_new_document_text_view);
    setDocumentCounterText(R.string.hello_new_document_counter);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
    is reused to create a new document.
     */
    setDocumentCounterText(R.string.reusing_document_counter);
}

使用 activity 属性添加任务

活动还可以在其清单中指定它始终启动到一个新任务中,方法是使用 <activity> 属性 android:documentLaunchMode。此属性有四个值,当用户使用应用程序打开文档时,会产生以下效果

intoExisting
活动为文档重用现有任务。这与设置 FLAG_ACTIVITY_NEW_DOCUMENT 标志而不设置 FLAG_ACTIVITY_MULTIPLE_TASK 标志相同,如 使用 Intent 标志添加任务 部分所述。
always
即使文档已打开,活动也会为文档创建一个新任务。使用此值与设置 FLAG_ACTIVITY_NEW_DOCUMENTFLAG_ACTIVITY_MULTIPLE_TASK 标志相同。
none
活动不会为文档创建新任务。“最近使用的应用”屏幕会像默认情况下一样处理该活动。它会显示应用程序的单个任务,该任务会从用户上次调用的活动恢复。
never
活动不会为文档创建新任务。设置此值会覆盖 FLAG_ACTIVITY_NEW_DOCUMENTFLAG_ACTIVITY_MULTIPLE_TASK 标志的行为。如果在意图中设置了这两个标志,并且“最近使用的应用”屏幕显示应用程序的单个任务,则它会从用户上次调用的活动恢复。

删除任务

默认情况下,文档任务在其活动完成时会自动退出“最近使用的应用”屏幕。您可以使用 ActivityManager.AppTask 类、Intent 标志或 <activity> 属性来覆盖此行为。

您可以通过将 <activity> 属性 android:excludeFromRecents 设置为 true 来完全从“最近使用的应用”屏幕中排除任务。

您可以通过将 <activity> 属性 android:maxRecents 设置为整数值来设置应用程序可以在“最近使用的应用”屏幕中包含的任务的最大数量。当达到最大任务数时,最近使用最少的任务会从“最近使用的应用”屏幕中消失。默认值为 16,最大值为 50(在内存不足的设备上为 25)。小于 1 的值无效。

使用 AppTask 类删除任务

在“最近使用的应用”屏幕中创建新任务的活动中,您可以通过调用 finishAndRemoveTask() 方法来指定何时删除任务并完成与其关联的所有活动

Kotlin

fun onRemoveFromOverview(view: View) {
    // It is good pratice to remove a document from the overview stack if not needed anymore.
    finishAndRemoveTask()
}

Java

public void onRemoveFromRecents(View view) {
    // The document is no longer needed; remove its task.
    finishAndRemoveTask();
}

保留已完成的任务

如果希望即使活动已完成也保留任务在“最近使用的应用”屏幕中,请在启动该活动的意图的 addFlags() 方法中传递 FLAG_ACTIVITY_RETAIN_IN_RECENTS 标志。

Kotlin

private fun newDocumentIntent() =
        Intent(this, NewDocumentActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
                    android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
            putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, getAndIncrement())
        }

Java

private Intent newDocumentIntent() {
    final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
    newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
      android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
    newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, getAndIncrement());
    return newDocumentIntent;
}

要实现相同的效果,请将 <activity> 属性 android:autoRemoveFromRecents 设置为 false。对于文档活动,默认值为 true,对于常规活动,默认值为 false。使用此属性会覆盖 FLAG_ACTIVITY_RETAIN_IN_RECENTS 标志。

启用最近使用的应用 URL 共享(仅限 Pixel)

在运行 Android 12 或更高版本的 Pixel 设备上,用户可以直接从“最近使用的应用”屏幕共享最近查看的网页内容的链接。在应用中访问内容后,用户可以滑动到“最近使用的应用”屏幕并找到他们查看内容的应用,然后点击链接按钮复制或共享 URL。

带有最近查看的网页内容共享链接的“最近使用的应用”屏幕。

任何应用都可以通过提供 Web UI 并覆盖 onProvideAssistContent() 来为用户启用最近使用的应用链接,如下例所示

Kotlin

class MainActivity : AppCompatActivity() {
    protected fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun onProvideAssistContent(outContent: AssistContent) {
        super.onProvideAssistContent(outContent)
        outContent.setWebUri(Uri.parse("https://example.com/myCurrentPage"))
    }
}

Java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onProvideAssistContent(AssistContent outContent) {
        super.onProvideAssistContent(outContent);

        outContent.setWebUri(Uri.parse("https://example.com/myCurrentPage"));
    }
}