多視窗運作

在 Android 9(及更低版本)中,應用程式在以下情況下進入PAUSED狀態:

  • 在應用程式頂部啟動了一個新的半透明活動,同時該應用程式仍然可見(因此沒有停止)。
  • 該活動失去了焦點,但沒有被遮擋,並且可以由用戶進行互動。例如,在多視窗模式下,多個活動可以是可見的並且同時接收觸控輸入。

這些情況在應用程式必須執行的暫停量方面有所不同,但無法在應用程式層級進行區分。

在 Android 10 中,可見堆疊中的所有可頂部對焦的活動都處於RESUMED狀態。對於使用onPause()而不是onStop()來停止刷新 UI 並與用戶交互的應用程序,這提高了與多視窗和 MD 模式的兼容性。這意味著:

  • 分割畫面中的兩項活動均恢復。
  • 自由形式視窗模式下的所有頂部可見活動都將恢復。
  • 多個螢幕上的活動可以同時恢復。

圖 1.可折疊設備上的多重恢復

圖 2.桌面模式下的多重恢復

當活動無法集中註意力或部分被遮蔽時,活動可以處於PAUSED狀態,例如:

  • 在最小化分割畫面(側面有啟動器)中,頂部活動不會恢復,因為它無法聚焦。
  • 在畫中畫模式下,活動不會恢復,因為它不可聚焦。
  • 當活動被同一堆堆疊中的其他透明活動覆蓋時。

此方法向應用程式表明活動只能在RESUMED狀態下接收來自使用者的輸入。在 Android 10 之前,Activity 還可以在PAUSED狀態下接收輸入(例如,嘗試在運行 Android 9 的裝置上同時觸控分割畫面中的兩個 Activity)。

為了保留先前 Android 版本的恢復訊號(並在應用程式應取得獨佔存取或單例資源的存取權限時進行通訊),Android 10 包含一個新的回呼:

Activity#onTopResumedActivityChanged(boolean onTop)

呼叫時,此回呼會在Activity#onResume()Activity#onPause()之間呼叫。此回調是可選的並且可以跳過,因此活動可以從RESUMED狀態進入PAUSED狀態,而無需成為系統中的最頂層。例如,在多視窗模式下。由於此回調是可選的,因此它不是活動生命週期的一部分,因此應該很少使用。

前一個頂部恢復活動會在下一個頂部恢復活動接收onTopResumedActivity(false)之前接收並完成onTopResumedActivity(true)的執行,除非前一個活動花費太多時間來處理方法呼叫並達到 500 毫秒逾時。

相容性

為了在實施多重恢復時保持相容性,請考慮這些解決方案。

一個應用程式進程中的多個已恢復活動

  • 問題。在 Android 9 及更低版本中,一次僅恢復系統中的一項活動。活動之間的所有轉換都涉及在恢復另一個活動之前暫停一個活動。一些應用程式和框架(例如 Flutter 或 Android 的 LocalActivityManager)使用這一事實,並將有關已恢復活動的狀態儲存在單例中。
  • 解決方案。在 Android 9 及更低版本中,如果同一進程中的兩個 Activity 都已恢復,則係統僅恢復 Z 順序較高的 Activity。針對 Android 10 的應用程式可以支援同時恢復多個活動。

同時訪問相機

  • 問題。這些問題也存在於 Android 9 及更低版本。例如,全螢幕和恢復的活動可能會使相機焦點失去到畫中畫模式下頂部暫停的活動,但隨著多視窗和多顯示模式的廣泛採用,會變得更加暴露。
    • 由於對RESUME狀態的更改,即使在恢復時,應用程式也可能會與相機斷開連接。為了解決這個問題,應用程式必須處理相機斷開連接而不崩潰。斷開連接時,應用程式會收到斷開連接回調,並且對 API 的所有呼叫都會開始拋出CameraAccessException
    • resizeableActivity=false不能保證獨佔相機存取權限,因為使用相機的其他應用程式可以在其他顯示器上開啟。
  • 解決方案。開發人員應包含應用程式與相機斷開連接時的邏輯。如果應用程式與相機斷開連接,它應該監視相機可用性回調以嘗試重新連接並繼續使用相機。除了現有的CameraManager#AvailabilityCallback#onCameraAvailable()回呼之外,Android 10 還添加了CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged() ,它涵蓋了焦點(和相機優先權)在多個恢復的活動之間切換時的情況。應用程式開發人員應該使用這兩個回調來確定嘗試存取相機的最佳時機。

多重履歷

在 Android 10 中,Activity 生命週期狀態由可見性和 Z 順序決定。為了確保活動可見性更新後的正確狀態並評估適用的生命週期狀態,請從不同位置呼叫ActivityRecord#makeActiveIfNeeded()方法。在 Android 10 中,活動意味著RESUMEDPAUSED ,並且僅在這兩種情況下有效。

在 Android 10 中,恢復活動是在每個堆疊中單獨追蹤的,而不是在系統中的單一位置中追蹤的。這是因為在多視窗模式下可以同時執行多個活動轉換。有關詳細信息,請參閱ActivityStack#mInResumeTopActivity

頂部恢復活動回調

在可能導致頂級活動變更(例如活動啟動、復原或 Z 順序變更)的操作之後,將呼叫ActivityStackSupervisor#updateTopResumedActivityIfNeeded() 。此方法檢查最頂層恢復的活動是否發生更改,並在需要時執行更新。如果前一個頂級恢復活動尚未釋放頂級恢復狀態,則會向其發送頂級恢復狀態丟失訊息,並在伺服器端安排逾時( ActivityStackSupervisor#scheduleTopResumedStateLossTimeout() )。在前一個活動釋放狀態後,或當逾時時,頂部恢復狀態的報告將發送到下一個活動(請參閱以下用法:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

新增了新的TopResumedActivityChangeItem事務項,用於向客戶端報告頂部恢復狀態更改,並利用 Android 9 中的ActivityLifecycler架構。

頂部恢復狀態儲存在客戶端,每次 Activity 轉換為RESUMEDPAUSED時,它也會檢查是否應呼叫onTopResumedActivityChanged()回呼。這使得伺服器和客戶端之間的生命週期狀態和頂部恢復狀態的通訊能夠實現一定的解耦。