自 2025 年 3 月 27 日起,我們建議您使用 android-latest-release
而非 aosp-main
建構及貢獻 AOSP。詳情請參閱「Android 開放原始碼計畫變更」。
多視窗運作
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
在 Android 9 (和以下版本) 中,應用程式會在下列情況下進入 PAUSED
狀態:
- 在應用程式仍可見 (因此未停止) 的情況下,在應用程式頂端啟動新的半透明活動。
- 活動失去焦點,但未遭遮蔽,且使用者可以與其互動。舉例來說,在多視窗模式下,系統可同時顯示多個活動並接收觸控輸入內容。
這兩種情況的差異在於應用程式必須執行的「暫停」時間長短,但無法在應用程式層級做出區隔。
在 Android 10 中,可聚焦的活動會在可見堆疊中處於 RESUMED
狀態。對於使用 onPause()
而非 onStop()
來停止重新整理 UI 和與使用者互動的應用程式,這可提升與多視窗和 MD 模式的相容性。因此:
- 分割畫面中的兩個活動都會恢復。
- 系統會重新啟用任意形式視窗模式中所有顯示在頂端的活動。
- 多個螢幕上的活動可同時重新啟動。

圖 1. 在摺疊式裝置上使用多視窗運作

圖 2. 在電腦模式下支援多視窗運作
如果活動無法聚焦或部分遮蔽,就會處於 PAUSED
狀態,例如:
- 在已最小化的分割畫面 (側邊有啟動器) 中,頂端活動不會復原,因為無法聚焦。
- 在子母畫面模式中,活動無法聚焦,因此不會繼續執行。
- 當活動遭到相同堆疊中其他透明活動覆蓋時。
這種做法會向應用程式指出,活動只能在 RESUMED
狀態下接收使用者輸入內容。在 Android 10 之前,活動也可以在 PAUSED
狀態下接收輸入內容 (例如,在執行 Android 9 的裝置上,嘗試同時觸碰分割畫面中的兩個活動)。
為保留先前 Android 版本的「resumed」信號 (並在應用程式應取得專屬存取權或單例資源存取權時進行通訊),Android 10 包含了新的回呼:
Activity#onTopResumedActivityChanged(boolean onTop)
在呼叫時,系統會在 Activity#onResume()
和 Activity#onPause()
之間呼叫此回呼。這個回呼是選用功能,可略過,因此活動可以從 RESUMED
轉換為 PAUSED
狀態,而不必成為系統中最上層的活動。例如在多視窗模式下。由於這個回呼為選用項目,因此並非 Activity 生命週期的一部分,因此應盡量少用。
上一個頂層暫停活動會在下一個頂層暫停活動接收 onTopResumedActivity(true)
之前,接收並完成 onTopResumedActivity(false)
的執行作業,除非上一個活動花費太多時間處理方法呼叫,並達到 500 毫秒的逾時限制。
相容性
如要在實作多視窗同時執行時維持相容性,請考慮採用下列解決方案。
在單一應用程式程序中重新啟用多個活動
- 問題:在 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 中,active 代表 RESUMED
或 PAUSED
,且只適用於這兩個例項。
在 Android 10 中,系統會在各個堆疊中個別追蹤活動的復原作業,而非在系統中的單一位置。這是因為在多視窗模式中,可以同時執行多個活動轉場。詳情請參閱 ActivityStack#mInResumeTopActivity
。
頂層暫停活動回呼
在可能導致頂層活動變更的動作 (例如活動啟動、重新啟動或 Z 順序變更) 後,系統會叫用 ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
。這個方法會檢查最上層的重新啟用活動是否已變更,並視需要執行更新。如果先前的頂層暫停活動未釋出頂層暫停狀態,系統會傳送頂層暫停狀態遺失訊息,並在伺服器端排定逾時時間 (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
)。頂層暫停狀態的報告會在先前活動釋出狀態後,或在達到逾時時間時傳送至下一個活動 (請參閱以下項目的用法:
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
我們新增了 TopResumedActivityChangeItem
交易項目,用於向用戶端回報頂層暫停狀態變更,並利用 Android 9 的 ActivityLifecycler
架構。
頂層暫停狀態會儲存在用戶端,每次活動切換至 RESUMED
或 PAUSED
時,也會檢查是否應叫用 onTopResumedActivityChanged()
回呼。這樣一來,生命週期狀態和伺服器與用戶端之間的頂端暫停狀態,就能在通訊中進行特定解耦。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Multi-resume\n\nIn Android 9 (and lower), apps were entered into the `PAUSED` state when:\n\n- A new, translucent activity launched on top of the app, while the app was still visible (and, therefore, wasn't stopped).\n- The activity lost focus, but was unobscured and could be interacted with by the user. For example, in multi-window mode, a number of activities can be visible and receive touch input simultaneously.\n\nThese situations differ in the amount of *pausing* an app must do but can't be\ndistinguished at the app level.\n\nIn Android 10, all top-focusable activities in visible stacks reside in\nthe `RESUMED` state. This improves compatibility with\n[Multi-Window](/docs/core/display/multi-window) and MD modes for apps that use\n`onPause()` instead of `onStop()` to stop refreshing the UI and interacting\nwith the user. This means:\n\n- Both activities in split-screen are resumed.\n- All top-visible activities in free-form windowing mode are resumed.\n- Activities on multiple screens can be resumed at the same time.\n\n**Figure 1.** Multi-resume on a foldable device\n\n**Figure 2.** Multi-resume in desktop mode\n\nActivities can reside in the `PAUSED` state when they cannot be focused upon or are\npartially occluded, such as:\n\n- In a minimized split-screen (with launcher on side), the top activity isn't resumed because it's not focusable.\n- In a picture-in-picture mode, the activity isn't resumed because it's not focusable.\n- When activities are covered by other transparent activities in the same stack.\n\nThis approach indicates to apps that an activity can receive input from a\nuser only in the `RESUMED` state. Before Android 10,\nactivities could also receive input in the `PAUSED` state (for example, try touching\nboth activities in split-screen simultaneously on a device running Android 9).\n\nTo preserve the *resumed* signal from previous Android releases (and\nto communicate when apps should obtain access to exclusive-access or singleton\nresources), Android 10 includes a new callback: \n\n```text\nActivity#onTopResumedActivityChanged(boolean onTop)\n```\n\nWhen invoked, this callback is called between `Activity#onResume()`\nand `Activity#onPause()`. This callback is optional and can be skipped,\nso an activity can go from a `RESUMED` to a `PAUSED` state\nwithout becoming the topmost in the system. For example, in multi-window mode.\nBecause this callback is optional, it's not part of the [Activity\nLifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle) and should be rarely used.\n\nThe previous top-resumed activity receives and finishes execution of\n`onTopResumedActivity(false)` before the next top-resumed activity\nreceives `onTopResumedActivity(true)` unless the previous activity\ntakes too much time to handle the method call and hits the 500 ms timeout.\n\nCompatibility\n-------------\n\nTo maintain compatibility when implementing multi-resume, consider these\nsolutions.\n\n### Multiple resumed activities in one app process\n\n- Issue. In Android 9 and lower, only one activity in the system is resumed at a time. All transitions between activities involve pausing an activity before resuming another. Some apps and frameworks (such as Flutter, or Android's LocalActivityManager) use this fact, and store state about the resumed activity in singletons.\n- Solution. In Android 9 and lower, if two activities from the same process are both resumed, the system only resumes the activity that's higher in Z-order. Apps targeting Android 10 can support multiple activities being resumed at the same time.\n\n### Simultaneous camera access\n\n- **Issues** . These issues are also present in Android 9 and lower. For example, a fullscreen and resumed activity can lose camera focus to a paused activity on top in picture-in-picture mode but become more exposed with wider adoption of multi-window and multi-display modes.\n - Due to changes made to the `RESUME` state, apps may be disconnected from the camera *even while resumed* . To address this, apps must handle a camera disconnect without crashing. When disconnected, apps get a disconnected callback and all calls into the API start throwing `CameraAccessException`.\n - `resizeableActivity=false` isn't a guarantee of exclusive camera access, because other apps using the camera can be opened on other displays.\n- **Solutions.** Developers should include logic for when an app is disconnected from the camera. If an app is disconnected from the camera, it should watch camera availability callbacks to try to reconnect and continue camera use. In addition to the existing `CameraManager#AvailabilityCallback#onCameraAvailable()` callback, Android 10 added `CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()`, which covers the case when focus (and camera priority) switches between several resumed activities. App developers should use both of these callbacks to determine a good time to try to get access to the camera.\n\n### Multi-resume\n\nIn Android 10, the activity lifecycle state is determined by visibility and\nZ-order. To ensure that the correct state after visibility updates on an\nactivity and evaluate which lifecycle state is applicable, invoke the\n`ActivityRecord#makeActiveIfNeeded()` method from different\nlocations. In Android 10, active means either `RESUMED` or\n`PAUSED` and works only in these two instances.\n\nIn Android 10, resuming an activity is separately tracked in each stack\ninstead of in the single location in the system. This is because several\nactivity transitions can be performed simultaneously in multi-window modes. For\ndetails, see `ActivityStack#mInResumeTopActivity`.\n\n### Top-resumed activity callback\n\nAfter actions that can result in a top activity change (such as activity\nlaunch, resuming, or Z-order change),\n`ActivityStackSupervisor#updateTopResumedActivityIfNeeded()` is invoked. This\nmethod checks if the topmost resumed activity changed and performs the update if\nneeded. If the previous top-resumed activity hasn't release the top-resumed\nstate, then a top-resumed-state-loss message is sent to it and a timeout is\nscheduled on the server side\n(`ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()`).\nA report of the top-resumed state is sent to the next activity after the previous\none released the state, or when a timeout was hit (see usages of: \n\n```text\nActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()\n```\n\nA new `TopResumedActivityChangeItem` transaction item was added\nto report top-resumed state changes to clients and leverages the\n`ActivityLifecycler` architecture from Android 9.\n\nThe top-resumed state is stored on the client side, and each time the\nactivity transitions to `RESUMED` or `PAUSED` it also\nchecks whether the `onTopResumedActivityChanged()` callback should be\ninvoked. This enables certain decoupling in the communication of lifecycle states\nand the top-resumed state between the server and client sides."]]