2025년 3월 27일부터 AOSP를 빌드하고 기여하려면 aosp-main
대신 android-latest-release
를 사용하는 것이 좋습니다. 자세한 내용은 AOSP 변경사항을 참고하세요.
다중 재개
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
Android 9 이하에서는 다음과 같은 경우 앱이 PAUSED
상태로 전환되었습니다.
- 앱이 계속 보이는 상태에서 앱 상단에서 새로운 투명한 활동이 실행되어 중지되지 않은 경우
- 활동이 포커스를 잃었지만 겉으로 드러나 사용자와 상호작용할 수 있게 된 경우 (예: 멀티 윈도우 모드에서는 여러 활동이 표시되어 터치 입력을 동시에 수신할 수 있음)
이러한 상황은 앱이 일시중지를 실행해야 하는 시간에서 차이가 있지만 앱 수준에서는 구분할 수 없습니다.
Android 10에서는 표시된 스택에서 상단에 포커스를 맞출 수 있는 모든 활동이 RESUMED
상태로 상주합니다. 이렇게 하면 UI 새로고침 및 사용자와의 상호작용을 멈추기 위해 onStop()
대신 onPause()
를 사용하는 앱의 멀티 윈도우 및 MD 모드와의 호환성이 개선됩니다. 이는 다음을 의미합니다.
- 화면 분할의 활동이 둘 다 재개됩니다.
- 자유 형식 윈도잉 모드에서 상단에 보이는 모든 활동이 재개됩니다.
- 여러 화면의 활동을 동시에 재개할 수 있습니다.

그림 1. 폴더블 기기의 다중 재개

그림 2. 데스크톱 모드의 다중 재개
활동은 다음과 같이 포커스를 맞출 수 없거나 일부가 가려지는 경우 PAUSED
상태로 상주할 수 있습니다.
- 런처가 측면에 위치한 최소화된 화면 분할에서는 상단 활동에 포커스를 맞출 수 없기 때문에 활동이 재개되지 않습니다.
- PIP 모드에서는 활동에 포커스를 맞출 수 없으므로 활동이 재개되지 않습니다.
- 같은 스택에서 활동이 다른 투명한 활동에 의해 가려지는 경우
이러한 접근 방식은 활동이 RESUMED
상태인 경우에만 사용자의 입력을 수신할 수 있음을 앱에 나타냅니다. Android 10 이전에는 활동이 PAUSED
상태에서도 입력을 수신할 수 있었습니다(예: Android 9를 실행하는 기기에서 화면 분할의 활동을 둘 다 동시에 터치하려고 시도하는 경우).
이전 Android 버전에서 재개된 신호를 보존하고 앱이 독점 액세스 또는 싱글톤 리소스의 액세스를 획득해야 할 때 통신하기 위해 Android 10에는 새로운 콜백이 포함됩니다.
Activity#onTopResumedActivityChanged(boolean onTop)
호출되면 이 콜백이 Activity#onResume()
및 Activity#onPause()
사이에 호출됩니다. 이 콜백은 건너뛸 수 있는 선택사항이므로 활동이 시스템 최상단에 위치하지 않고도 RESUMED
에서 PAUSED
상태로 전환될 수 있습니다. 멀티 윈도우 모드에 있는 경우를 예로 들 수 있습니다.
이 콜백은 선택사항이므로 활동 수명 주기의 일부가 아니며 아주 가끔만 사용해야 합니다.
이전 활동이 메서드 호출을 처리하는 데 너무 많은 시간을 소비하여 500밀리초의 시간 제한에 도달하지 않는 이상 이전에 상단에서 재개된 활동은 다음에 상단에서 재개된 활동이 onTopResumedActivity(true)
를 수신하기 전에 onTopResumedActivity(false)
의 실행을 수신하고 마무리합니다.
호환성
다중 재개를 구현할 때 호환성을 유지하려면 다음과 같은 해결 방법을 고려해 보세요.
단일 앱 프로세스에서 재개된 여러 활동
- 문제. Android 9 이하에서는 시스템에서 한 번에 한 개의 활동만 재개됩니다. 활동 간의 모든 전환 시에는 다른 활동을 재개하기 전에 현재의 활동을 일시중지해야 합니다. Flutter 또는 Android의 LocalActivityManager와 같은 일부 앱과 프레임워크는 이러한 사실을 활용하며 싱글톤에서 재개된 활동에 관한 상태를 저장합니다.
- 해결 방법. Android 9 이하에서는 같은 프로세스의 두 활동이 전부 재개되는 경우 시스템에서 Z-order가 더 높은 활동 하나만 재개합니다.
Android 10을 타겟팅하는 앱은 동시에 재개되고 있는 여러 활동을 지원할 수 있습니다.
동시 카메라 액세스
- 문제. 이러한 문제는 Android 9 이하에서도 존재합니다. 예를 들어 전체 화면 및 재개된 활동은 PIP 모드 상단의 일시중지된 활동의 카메라 포커스를 잃을 수 있지만 멀티 윈도우 및 다중 표시 모드의 광범위한 채택으로 노출 범위를 높일 수 있습니다.
RESUME
상태에 적용된 변경사항으로 인해 앱은 재개 중인 경우에도 카메라 연결이 끊길 수 있습니다. 이를 해결하려면 앱은 충돌 없이 카메라 연결 끊김을 처리해야 합니다. 연결이 끊기면 앱은 연결 해제된 콜백을 가져오며 API에 관한 모든 호출이 CameraAccessException
을 반환하기 시작합니다.
resizeableActivity=false
는 독점적인 카메라 액세스를 보장하지 않습니다. 이는 카메라를 사용 중인 다른 앱이 다른 디스플레이에서 열릴 수 있기 때문입니다.
- 해결 방법. 개발자는 앱이 카메라에서 연결 해제되는 시점에 대한 논리를 포함해야 합니다. 카메라에서 연결이 해제된 앱은 카메라 가용성 콜백을 주시하며 재연결 및 계속적인 카메라 사용을 위한 시도를 해야 합니다. Android 10에는 기존의
CameraManager#AvailabilityCallback#onCameraAvailable()
콜백 외에 CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()
가 추가되었습니다. 이는 재개된 여러 활동 간에 포커스(및 카메라 우선순위)가 전환되는 경우에 적용됩니다. 앱 개발자는 이러한 콜백을 둘 다 사용하여 카메라 액세스를 시도하기에 적합한 시점을 파악해야 합니다.
다중 재개
Android 10에서는 활동 수명 주기 상태가 가시성 및 Z-order에 의해 결정됩니다. 활동에 관한 가시성 업데이트 이후의 올바른 상태를 보장하고 어떤 수명 주기 상태가 적용 가능한지 평가하려면 다른 위치에서 ActivityRecord#makeActiveIfNeeded()
메서드를 호출하세요. Android 10에서는 활동이 RESUMED
또는 PAUSED
를 의미하며, 이러한 두 인스턴스에서만 작동합니다.
Android 10에서는 활동 재개가 시스템의 단일 위치 대신 각 스택에서 따로 추적됩니다. 이는 멀티 윈도우 모드에서 여러 활동 전환을 동시에 실행할 수 있기 때문입니다. 자세한 내용은 ActivityStack#mInResumeTopActivity
를 참고하세요.
상단에서 재개된 활동 콜백
상단 활동의 변경으로 이어질 수 있는 작업(예: 활동 실행, 재개 또는 Z-order 변경) 후에는 ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
가 호출됩니다. 이 메서드는 최상단에서 재개된 활동이 변경되었는지 확인하고 필요한 경우 업데이트를 실행합니다. 이전에 상단에서 재개된 활동에 의해 상단에서 재개된 상태가 해제되지 않은 경우에는 top-resumed-state-loss 메시지가 여기로 전송되고 서버 측에서 시간 제한이 예약됩니다(ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
). 상단에서 재개된 상태 보고서는 이전 활동에서 상태를 해제했거나 시간 제한에 도달하면 다음 활동으로 전송됩니다. 다음 내용이 어떻게 사용되는지 확인하세요.
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
상단에서 재개된 상태 변경을 클라이언트에 보고할 수 있도록 새로운 TopResumedActivityChangeItem
트랜잭션 항목이 추가되었습니다. 이 항목은 Android 9의 ActivityLifecycler
아키텍처를 활용합니다.
상단에서 재개된 상태는 클라이언트 측에 저장되며 활동이 RESUMED
또는 PAUSED
로 전환될 때마다 onTopResumedActivityChanged()
콜백을 호출해야 하는지 확인합니다. 이렇게 하면 서버 및 클라이언트 측 간의 수명 주기 상태와 상단에서 재개된 상태의 통신에서 특정한 분리가 가능합니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","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(UTC)"],[],[],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."]]