在 Android 9(及更低版本)中,應用在以下情況下進入PAUSED
狀態:
- 在應用程序頂部啟動了一個新的半透明活動,而應用程序仍然可見(因此沒有停止)。
- 該活動失去了焦點,但沒有被遮擋並且可以與用戶進行交互。例如,在多窗口模式下,可以看到多個活動並同時接收觸摸輸入。
這些情況在應用程序必須執行的暫停量上有所不同,但在應用程序級別無法區分。
在 Android 10 中,可見堆棧中的所有頂部可聚焦 Activity 都處於RESUMED
狀態。這提高了使用onPause()
而不是onStop()
來停止刷新 UI 和與用戶交互的應用程序與多窗口和 MD 模式的兼容性。這表示:
- 分屏中的兩個活動都恢復了。
- 自由形式窗口模式中的所有頂部可見活動都將恢復。
- 可以同時恢復多個屏幕上的活動。
圖 1.可折疊設備上的多份簡歷
圖 2.桌面模式下的多簡歷
當活動無法聚焦或被部分遮擋時,它們可以處於PAUSED
狀態,例如:
- 在最小化的分屏中(側面有啟動器),頂部活動不會恢復,因為它不可聚焦。
- 在畫中畫模式下,活動不會恢復,因為它不可聚焦。
- 當活動被同一堆棧中的其他透明活動覆蓋時。
這種方法向應用表明,Activity 只能在RESUMED
狀態下接收來自用戶的輸入。在 Android 10 之前,Activity 也可以在PAUSED
狀態下接收輸入(例如,嘗試在運行 Android 9 的設備上同時觸摸分屏中的兩個 Activity)。
為了保留以前 Android 版本的恢復信號(並在應用程序應該獲得對獨占訪問或單例資源的訪問權時進行通信),Android 10 包含一個新的回調:
Activity#onTopResumedActivityChanged(boolean onTop)
調用時,會在Activity#onResume()
和Activity#onPause()
之間調用此回調。此回調是可選的,可以跳過,因此活動可以從RESUMED
狀態轉到PAUSED
狀態,而不會成為系統中的最頂層。例如,在多窗口模式下。因為這個回調是可選的,所以它不是活動生命週期的一部分,應該很少使用。
上一個最開始恢復的活動在下一個最開始恢復的活動收到onTopResumedActivity(true)
之前接收並完成onTopResumedActivity(false)
的執行,除非上一個活動花費太多時間來處理方法調用並達到 500 毫秒超時。
兼容性
為了在實施多簡歷時保持兼容性,請考慮這些解決方案。
在一個應用進程中恢復多個活動
- 問題。在 Android 9 及更低版本中,一次只能恢復系統中的一項活動。活動之間的所有轉換都涉及在恢復另一個活動之前暫停一個活動。一些應用程序和框架(例如 Flutter 或 Android 的 LocalActivityManager)使用這一事實,並將有關恢復活動的狀態存儲在單例中。
- 解決方案。在 Android 9 及更低版本中,如果來自同一進程的兩個 Activity 都被恢復,則係統只會恢復 Z 順序較高的 Activity。面向 Android 10 的應用可以支持同時恢復多個活動。
同時訪問相機
- 問題。這些問題也存在於 Android 9 及更低版本中。例如,在畫中畫模式下,全屏和恢復的活動可能會將相機焦點轉移到頂部的暫停活動,但隨著多窗口和多顯示模式的更廣泛採用而變得更加暴露。
- 由於對
RESUME
狀態進行了更改,即使在 resumed 時,應用程序也可能與相機斷開連接。為了解決這個問題,應用程序必須在不崩潰的情況下處理相機斷開連接。斷開連接時,應用程序會收到一個斷開連接的回調,並且對 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()
。此方法檢查最頂層恢復的活動是否已更改,並在需要時執行更新。如果先前的 top-resumed 活動尚未釋放 top-resumed 狀態,則將向其發送 top-resumed-state-loss 消息,並在服務器端安排超時( ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
)。在前一個活動釋放狀態之後,或者當遇到超時時(參見用法:
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
添加了一個新的TopResumedActivityChangeItem
事務項以向客戶端報告最高恢復狀態更改,並利用 Android 9 中的ActivityLifecycler
架構。
top-resumed 狀態存儲在客戶端,每次活動轉換為RESUMED
或PAUSED
時,它還會檢查是否應調用onTopResumedActivityChanged()
回調。這使得生命週期狀態的通信和服務器端和客戶端之間的頂部恢復狀態能夠進行一定的解耦。