다중 재개

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() 콜백을 호출해야 하는지 확인합니다. 이렇게 하면 서버 및 클라이언트 측 간의 수명 주기 상태와 상단에서 재개된 상태의 통신에서 특정한 분리가 가능합니다.