在 Android 9 (以下版本) 中,應用程式會在下列情況進入 PAUSED
狀態:
- 在應用程式上方啟動新的半透明活動,但應用程式仍可見 (因此不會停止)。
- 活動失去焦點,但未遭遮蔽,使用者可以與其互動。舉例來說,在多視窗模式下,多個活動可以同時顯示並接收觸控輸入。
在這些情況下,應用程式必須暫停的程度不同,但無法在應用程式層級區分。
在 Android 10 中,可見堆疊中所有可聚焦的頂端活動都處於 RESUMED
狀態。這項功能可提升應用程式與多視窗和 MD 模式的相容性,讓應用程式使用 onPause()
(而非 onStop()
) 停止重新整理 UI 並與使用者互動。因此:
- 分割畫面中的兩個活動都會繼續執行。
- 任意形式視窗模式中所有最上層的活動都會繼續執行。
- 多個螢幕上的活動可以同時繼續執行。
圖 1. 在摺疊式裝置上使用多視窗運作
圖 2. 電腦模式下的多視窗運作
如果活動無法聚焦或部分遮蔽,就會處於 PAUSED
狀態,例如:
- 在縮小的分割畫面 (啟動器位於側邊) 中,系統不會恢復頂端活動,因為該活動無法成為焦點。
- 在子母畫面模式中,活動不會繼續執行,因為無法聚焦。
- 活動遭同一堆疊中的其他透明活動遮蓋。
這種做法會向應用程式指出,活動只能在 RESUMED
狀態下接收使用者輸入內容。在 Android 10 之前,活動也可以在 PAUSED
狀態下接收輸入內容 (舉例來說,在執行 Android 9 的裝置上,嘗試同時觸控分割畫面中的兩個活動)。
為保留先前 Android 版本中的「已恢復」信號 (並在應用程式應取得專屬存取權或單例資源存取權時進行通訊),Android 10 包含新的回呼:
Activity#onTopResumedActivityChanged(boolean onTop)
呼叫時,這個回呼會在 Activity#onResume()
與 Activity#onPause()
之間呼叫。這個回呼是選用項目,可以略過,因此活動可以從 RESUMED
狀態進入 PAUSED
狀態,而不成為系統中最上層的活動。例如在多視窗模式下。由於這個回呼是選用項目,因此不屬於 Activity 生命週期,應盡量避免使用。
除非上一個活動處理方法呼叫的時間過長,導致達到 500 毫秒的逾時時間,否則上一個恢復執行的頂層活動會先接收並完成 onTopResumedActivity(false)
的執行作業,下一個恢復執行的頂層活動才會接收 onTopResumedActivity(true)
。
相容性
如要實作多視窗同時執行功能時維持相容性,請考慮下列解決方案。
單一應用程式程序中有多個已恢復的活動
- 問題。在 Android 9 以下版本中,系統一次只會恢復一項活動。所有活動之間的轉換都會暫停一個活動,然後繼續另一個活動。部分應用程式和架構 (例如 Flutter 或 Android 的 LocalActivityManager) 會使用這項事實,並在單例中儲存有關已恢復活動的狀態。
- 解決方法。在 Android 9 以下版本中,如果同一程序中的兩個活動都重新啟動,系統只會重新啟動 Z 順序較高的活動。以 Android 10 為目標的應用程式可支援多個活動同時恢復。
同時存取攝影機
- 問題。Android 9 以下版本也有這些問題。舉例來說,在子母畫面模式下,全螢幕且已恢復的活動可能會將相機焦點讓給頂端暫停的活動,但隨著多視窗和多螢幕模式的普及,這類活動的曝光度會更高。
- 由於
RESUME
狀態有所變更,應用程式可能會與攝影機中斷連線(即使已恢復連線)。為解決這個問題,應用程式必須處理相機中斷連線的情況,且不會當機。中斷連線時,應用程式會收到中斷連線回呼,且所有對 API 的呼叫都會開始擲回CameraAccessException
。 resizeableActivity=false
無法確保該應用程式可取得專屬相機存取權,原因在於其他畫面可能開啟了使用相機的其他應用程式。
- 由於
- 解決方案。開發人員應加入應用程式與攝影機中斷連線時的邏輯。如果應用程式與攝影機中斷連線,應用程式應監看攝影機可用性回呼,嘗試重新連線並繼續使用攝影機。除了現有的
CameraManager#AvailabilityCallback#onCameraAvailable()
回呼,Android 10 還新增了CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()
,可處理焦點 (和相機優先順序) 在多個已恢復活動之間切換的情況。應用程式開發人員應使用這兩個回呼,判斷適合存取相機的時間。
多視窗運作
在 Android 10 中,活動生命週期狀態取決於可見度和 Z 順序。如要確保活動在可見度更新後處於正確狀態,並評估適用的生命週期狀態,請從不同位置叫用 ActivityRecord#makeActiveIfNeeded()
方法。在 Android 10 中,「有效」是指 RESUMED
或 PAUSED
,且僅適用於這兩種情況。
在 Android 10 中,系統會分別追蹤每個堆疊中的活動恢復作業,而非在系統的單一位置追蹤。這是因為在多視窗模式下,可以同時執行多個活動轉換作業。詳情請參閱ActivityStack#mInResumeTopActivity
。
最常恢復的活動回呼
在可能導致頂端活動變更的動作 (例如啟動、恢復活動或變更 Z 順序) 之後,系統會叫用 ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
。這個方法會檢查最上層的重新啟用活動是否已變更,並視需要執行更新。如果先前恢復的最上層活動尚未釋出最上層恢復狀態,系統會將最上層恢復狀態遺失訊息傳送給該活動,並在伺服器端排定逾時 (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
)。先前活動釋出狀態後,或達到逾時時間時,系統會將最上層恢復狀態的報告傳送給下一個活動 (請參閱以下用法:
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
新增 TopResumedActivityChangeItem
交易項目,向用戶端回報恢復狀態的重大變化,並運用 Android 9 的 ActivityLifecycler
架構。
系統會在用戶端儲存最上層的恢復狀態,且每次活動轉換為 RESUMED
或 PAUSED
時,也會檢查是否應叫用 onTopResumedActivityChanged()
回呼。這可在伺服器和用戶端之間,針對生命週期狀態和最上層恢復狀態的通訊進行特定解耦。