最近使用屏幕(也称为概览屏幕、最近任务列表或最近应用屏幕)是系统级 UI,它列出最近访问的 活动 和 任务。用户可以通过列表进行导航,选择要恢复的任务,或通过滑动将其从列表中删除。
最近使用屏幕使用 以文档为中心的模型(在 Android 5.0(API 级别 21)中引入),其中包含不同文档的同一活动的多个实例可以作为最近使用屏幕中的任务出现。例如,Google Drive 可能具有针对多个 Google 文档的每个任务。每个文档都作为最近使用屏幕中的一个任务出现
另一个常见示例是,当用户使用其浏览器时,他们点击共享 > Gmail。Gmail 应用的撰写屏幕会出现。此时点击最近使用按钮会显示 Chrome 和 Gmail 作为单独的任务运行
通常,您让系统定义您的任务和活动在最近使用屏幕中的表示方式。您无需修改此行为。但是,您的应用可以确定活动在最近使用屏幕中的显示方式和时间。
使用 ActivityManager.AppTask
类可以管理任务,使用 Intent
类的活动标记可以指定何时在“最近使用”屏幕中添加或移除活动。此外,还可以使用 <activity>
属性在清单中设置行为。
在“最近使用”屏幕中添加任务
使用 Intent
类的标记添加任务可以更好地控制何时以及如何打开或重新打开“最近使用”屏幕中的文档。使用 <activity>
属性时,可以选择始终在新任务中打开文档,或者为文档重用现有任务。
使用 Intent 标记添加任务
为活动创建新文档时,需要调用 startActivity()
方法,并向其传递启动该活动的 Intent。为了插入逻辑断点,使系统将活动视为“最近使用”屏幕中的新任务,请在启动该活动的 Intent
的 addFlags()
方法中传递 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; } }
当主活动启动新活动时,系统将在现有任务中搜索匹配该活动 Intent 组件名称和 Intent 数据的任务。如果未找到任务,或者 Intent 包含 FLAG_ACTIVITY_MULTIPLE_TASK
标记,系统将使用该活动作为根创建新任务。
如果系统找到 Intent 组件名称和 Intent 数据匹配的任务,它会将该任务置于最前面,并将新的 Intent 传递给 onNewIntent()
。新活动获取 Intent,并在“最近使用”屏幕中创建新文档,如下例所示
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>
属性 android:documentLaunchMode
。该属性有四个值,在用户使用应用程序打开文档时会产生以下效果
intoExisting
- 活动会为文档重用现有任务。这与设置
FLAG_ACTIVITY_NEW_DOCUMENT
标记(不设置FLAG_ACTIVITY_MULTIPLE_TASK
标记)相同,如 使用 Intent 标记添加任务 部分所述。 always
- 活动会为文档创建新任务,即使文档已打开。使用此值与设置
FLAG_ACTIVITY_NEW_DOCUMENT
和FLAG_ACTIVITY_MULTIPLE_TASK
标记相同。 none
- 活动不会为文档创建新任务。“最近使用”屏幕将像默认情况下一样处理活动。它会显示应用程序的单个任务,并从用户上次调用的活动继续执行。
never
- 活动不会为文档创建新任务。设置此值会覆盖
FLAG_ACTIVITY_NEW_DOCUMENT
和FLAG_ACTIVITY_MULTIPLE_TASK
标记的行为。如果 Intent 中设置了这两个标记,并且“最近使用”屏幕显示了应用程序的单个任务,它将从用户上次调用的活动继续执行。
移除任务
默认情况下,文档任务会在其活动完成时自动从“最近使用”屏幕退出。可以使用 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(); }
保留已完成的任务
如果希望在活动完成时仍保留任务在“最近使用”屏幕中,请在启动该活动的 Intent 的 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。
任何应用程序都可以通过提供网络 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")); } }