「最近使用」畫面也稱為「總覽」畫面、最近任務清單或最近使用的應用程式畫面,是系統層級的 UI,會列出最近存取的活動和工作。使用者可以瀏覽清單、選取要繼續執行的工作,或滑動工作來從清單中移除。
「最近使用」畫面採用以文件為中心的模型 (Android 5.0 (API 級別 21) 中推出),其中包含不同文件的相同活動的多個執行個體,可做為工作顯示在「最近使用」畫面上。舉例來說,Google 雲端硬碟可能為多個 Google 文件各建立一項工作。每份文件都會以工作形式顯示在「最近」畫面中:
另一個常見的例子是使用者透過瀏覽器輕觸「分享」 >「Gmail」,Gmail 應用程式的「撰寫」畫面隨即顯示。這時輕觸「最近」按鈕,會顯示 Chrome 和 Gmail 分別以獨立工作執行的畫面:
一般來說,您會讓系統定義工作和活動在「最近」畫面中的顯示方式。您不需要修改這項行為。不過,應用程式可以決定活動在「最近」畫面中的顯示方式和時間。
ActivityManager.AppTask 類別可讓您管理工作,而 Intent 類別的活動旗標則可讓您指定活動新增至「最近」畫面或從該畫面移除的時間。此外,您也可以使用 <activity> 屬性在資訊清單中設定行為。
在「最近使用」畫面中新增工作
使用 Intent 類別的旗標新增工作,可進一步控管文件在「最近」畫面中開啟或重新開啟的時間和方式。使用 <activity> 屬性時,您可以選擇一律在新工作開啟文件,或是重複使用文件的現有工作。
使用 Intent 旗標新增工作
為活動建立新文件時,請呼叫 startActivity() 方法,並將啟動活動的意圖傳遞至該方法。如要插入邏輯中斷點,讓系統將活動視為「最近」畫面中的新工作,請在啟動活動的 Intent 的 addFlags() 方法中,傳遞 FLAG_ACTIVITY_NEW_DOCUMENT 旗標。
如果您在建立新文件時設定 FLAG_ACTIVITY_MULTIPLE_TASK 標記,系統一律會建立新工作,並將目標活動做為根層級。這項設定可讓您在多個工作開啟同一份文件。下列程式碼示範主要活動如何執行這項操作,並從可組合函式啟動新活動:
private fun newDocumentIntent(context: Context): Intent = Intent(context, NewDocumentActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++) } @Composable fun CreateDocumentButton() { val context = LocalContext.current Button( onClick = { val intent = newDocumentIntent(context) // Add FLAG_ACTIVITY_MULTIPLE_TASK if needed based on state context.startActivity(intent) } ) { Text("Create New Document") } }
當主要活動啟動新活動時,系統會搜尋現有工作,找出意圖與活動的意圖元件名稱和意圖資料相符的工作。如果找不到工作,或意圖包含 FLAG_ACTIVITY_MULTIPLE_TASK 旗標,系統會建立新工作,並將活動設為根層級。
如果系統找到意圖與意圖元件名稱和意圖資料相符的任務,就會將該任務帶到前景,並將新意圖傳遞至 onNewIntent()。新活動會取得意圖,並在「最近」畫面中建立新文件,如下列範例所示:
class DocumentCentricActivity : ComponentActivity() { private var documentState by mutableStateOf( DocumentState( count = 0, textResId = R.string.hello_new_document_counter ) ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val initialCount = intent.getIntExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0) documentState = documentState.copy(count = initialCount) setContent { MaterialTheme { DocumentScreen( count = documentState.count, textResId = documentState.textResId ) } } } override fun onNewIntent(newIntent: Intent) { super.onNewIntent(newIntent) // If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this Activity is reused. documentState = documentState.copy( textResId = R.string.reusing_document_counter ) } data class DocumentState(val count: Int, @StringRes val textResId: Int) companion object { const val KEY_EXTRA_NEW_DOCUMENT_COUNTER = "KEY_EXTRA_NEW_DOCUMENT_COUNTER" } } @Composable fun DocumentScreen(count: Int, @StringRes textResId: Int) { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.Center ) { // UI reacts to whichever string resource ID was passed down Text(text = stringResource(id = textResId)) Spacer(modifier = Modifier.height(8.dp)) Text(text = "Counter: $count") } }
在上述程式碼中,Activity 會處理 OS 層級的路由 (onCreate 和 onNewIntent),而 @Composable 函式只負責根據提供的狀態算繪 UI。
使用活動屬性新增工作
活動也可以在資訊清單中指定一律在新工作啟動,方法是使用 <activity> 屬性 android:documentLaunchMode。這個屬性有四個值,當使用者透過應用程式開啟文件時,會產生以下效果:
intoExisting- 活動會重複使用文件的現有工作。這與未設定
FLAG_ACTIVITY_MULTIPLE_TASK旗標,但設定FLAG_ACTIVITY_NEW_DOCUMENT旗標的效果相同,如「使用 Intent 旗標新增工作」一節所述。 always- 即使文件已開啟,活動仍會為文件建立新的工作。使用這個值與同時設定
FLAG_ACTIVITY_NEW_DOCUMENT和FLAG_ACTIVITY_MULTIPLE_TASK旗標的效果相同。 none- 活動不會為文件建立新任務。「最近使用」畫面會以預設方式處理活動。也就是為應用程式顯示單一任務,並從使用者上次叫用的任意活動繼續執行。
never- 活動不會為文件建立新任務。設定這個值會覆寫
FLAG_ACTIVITY_NEW_DOCUMENT和FLAG_ACTIVITY_MULTIPLE_TASK標記的行為。如果意圖中已設定這類標記,且「最近使用」畫面會顯示應用程式的單一任務,無論使用者上次叫用哪一項活動,都能繼續執行該任務。
移除工作
根據預設,文件工作會在活動結束時自動從「最近使用」畫面中退出。您可以使用 ActivityManager.AppTask 類別、Intent 旗標或 <activity> 屬性覆寫這個行為。
您隨時可以設定 <activity> 屬性 android:excludeFromRecents 為 true,完全從「最近使用」畫面中排除工作。
您可以將 <activity> 屬性 android:maxRecents 設為整數值,藉此設定應用程式可在「最近使用」畫面中顯示的任務數量上限。達到任務數量上限時,最近最少使用的任務會從「最近使用」畫面消失。預設值為 16,最大值為 50 (低記憶體裝置為 25)。值不得小於 1。
使用 AppTask 類別移除工作
在「最近」畫面中建立新工作時,您可以呼叫 finishAndRemoveTask() 方法,指定何時移除工作並完成所有相關聯的活動:
@Composable fun RemoveTaskButton() { val context = LocalContext.current Button( onClick = { // It is good practice to remove a document from the overview stack if not needed anymore. (context as? Activity)?.finishAndRemoveTask() } ) { Text("Remove from Recents") } }
保留完成的工作
如果您想在「最近使用」畫面中保留任務,即使活動已完成,請在啟動活動的意圖的 addFlags() 方法中,傳遞 FLAG_ACTIVITY_RETAIN_IN_RECENTS 旗標。
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()) }
如要達到相同效果,請將 <activity> 屬性 android:autoRemoveFromRecents 設為 false。文件活動的預設值為 true,一般活動則為 false。使用這項屬性會覆寫 FLAG_ACTIVITY_RETAIN_IN_RECENTS 旗標。
啟用最近瀏覽的網址分享功能 (僅限 Pixel)
在搭載 Android 12 以上版本的 Pixel 裝置上,使用者可以直接從「最近使用」畫面分享最近瀏覽的網頁內容連結。使用者在應用程式中瀏覽內容後,可以滑動至「最近使用」畫面,找出瀏覽內容的應用程式,然後輕觸連結按鈕複製或分享網址。
任何應用程式都能提供網頁 UI 並覆寫 onProvideAssistContent(),為使用者啟用「最近」連結,如下例所示:
class MainActivity : ComponentActivity() { // Track the current URL as state so the UI can update it during navigation private var currentWebUri by mutableStateOf("https://example.com/home") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { AppTheme { // Pass a lambda to your Compose UI so it can update the URL state // as the user navigates through your app. MainScreen( onPageChanged = { newUrl -> currentWebUri = newUrl } ) } } } override fun onProvideAssistContent(outContent: AssistContent) { super.onProvideAssistContent(outContent) // The system calls this when the user enters the Recents screen. // Provide the active URI tracked by the Compose state. outContent.webUri = Uri.parse(currentWebUri) } }