다중 창 지원

Android 7.0은 둘 이상의 앱을 동시에 표시하기 위한 지원을 추가합니다. 핸드헬드 기기에서 두 개의 앱을 화면 분할 모드에서 나란히 또는 상하로 실행할 수 있습니다. TV 기기에서 앱이 PIP(Picture-In-Picture) 모드를 사용하는 경우 사용자가 다른 앱과 상호작용하는 동안에 계속 동영상을 재생할 수 있습니다.

앱이 Android 7.0(API 레벨 24) 이상을 대상으로 할 경우 앱이 다중 창 표시를 처리하는 방법을 구성할 수 있습니다. 예를 들어, 액티비티의 최소 허용 치수를 지정할 수 있습니다. 또한 앱에 대해 다중 창 표시를 비활성화할 수도 있으며, 이 경우 시스템은 앱을 전체 화면 모드에서만 표시합니다.

개요

Android에서는 여러 앱이 동시에 화면을 공유할 수 있습니다. 예를 들어, 사용자가 화면을 분할하여 왼쪽에서는 웹페이지를 보고 오른쪽에서는 이메일을 작성할 수 있습니다. 사용자 환경은 Android OS 버전과 기기 종류에 따라 달라집니다.

  • Android 7.0에서 실행되는 핸드헬드 기기는 화면 분할 모드를 제공합니다. 이 모드에서 시스템은 화면을 두 개의 앱으로 채우고, 이 앱을 나란히 또는 상하로 표시합니다. 사용자가 두 앱을 구분하는 분할선을 드래그하여 한 앱을 다른 앱보다 더 크게 만들 수 있습니다.
  • Android 8.0부터 앱이 PIP(Picture-In-Picture) 모드로 배치될 수 있으므로, 사용자가 검색을 수행하거나 다른 앱과 상호작용하는 중에도 앱이 계속해서 콘텐츠를 표시할 수 있습니다.
  • 더 큰 기기를 제조하는 업체는 자유 형식 모드를 선택할 수 있으며, 이 경우 사용자가 각 액티비티의 크기를 자유롭게 조정할 수 있습니다. 제조업체가 이 기능을 활성화하면, 기기는 화면 분할 모드뿐만 아니라 자유 형식 모드를 제공합니다.

그림 1. 화면 분할 모드에서 나란히 실행 중인 두 앱.

사용자가 다음과 같이 다중 창 모드로 전환할 수 있습니다.

  • 사용자가 Overview 화면을 열고 액티비티 제목을 길게 누르면, 이 액티비티를 화면의 강조 표시된 부분으로 드래그하여 다중 창 모드에 둘 수 있습니다.
  • 사용자가 Overview 버튼을 길게 누르면, 기기가 현재 액티비티를 다중 창 모드에 두고 Overview 화면을 엽니다. 이 화면에서 사용자는 화면을 공유할 다른 액티비티를 선택할 수 있습니다.

사용자는 여러 액티비티가 화면을 공유하는 동안 하나의 액티비티에서 다른 액티비티로 데이터를 드래그 앤 드롭할 수 있습니다.

다중 창 수명 주기

다중 창 모드는 액티비티 수명 주기를 변경하지 않습니다.

다중 창 모드에서는 사용자가 가장 최근에 상호작용했던 액티비티만 지정된 시간에 활성화됩니다. 이 액티비티가 최상위로 간주되고 RESUMED 상태의 유일한 액티비티가 됩니다. 그 외에 보이는 모든 액티비티는 STARTED이지만 RESUMED가 아닙니다. 그러나 시스템은 화면에 표시되지만 다시 시작되지 않은 액티비티에 표시되지 않은 액티비티보다 더 높은 우선순위를 부여합니다. 사용자가 눈에 보이는 액티비티 중 하나와 상호작용하면, 해당 액티비티가 다시 시작되고 이전의 최상위 액티비티가 STARTED 상태에 들어갑니다.

참고: 다중 창 모드에서 앱은 사용자에게 보이더라도 RESUMED 상태가 아닐 수 있습니다. 앱은 최상위 상태가 아닐 때에도 작업을 계속해야 할 수 있습니다. 예를 들어 이 상태의 동영상 재생 앱은 동영상을 계속 보여주어야 합니다. 그러므로 동영상을 재생하는 액티비티는 ON_PAUSE 수명 주기 이벤트가 발생하더라도 이에 반응하여 동영상 재생을 멈추지 않아야 합니다. 그 대신 액티비티는 ON_START에 응답하여 재생을 시작하고 ON_STOP에 응답하여 재생을 일시 정지해야 합니다. Lifecycle 패키지를 사용하지 않고 수명 주기 이벤트를 직접 처리할 경우 onStop() 핸들러에서 동영상 재생을 일시 정지했다고 onStart()에서 재생을 다시 시작합니다.

사용자가 앱을 다중 창 모드에 놓으면 시스템은, 구성 변경 처리에 지정된 대로 구성 변경을 액티비티에 알려줍니다. 이 동작은 사용자가 앱의 크기를 조정하거나 앱을 전체 화면 모드로 다시 전환할 때도 발생합니다. 기본적으로 이 변경에서 액티비티-수명 주기 관계는 기기 모드가 세로 모드에서 가로 모드로 전환되었음을 시스템이 앱에 알려줄 때와 동일합니다(단순 스왑 대신 기기 치수가 변경되는 경우는 제외). 런타임 변경 처리에서 설명한 대로, 액티비티 스스로 구성 변경을 처리하거나, 시스템이 액티비티를 소멸시키고 새 치수로 다시 액티비티를 생성하도록 할 수 있습니다.

사용자가 창의 크기를 조정하여 한쪽 치수를 더 크게 만드는 경우, 시스템은 사용자 작업에 맞게 액티비티의 크기를 조정하고 필요한 경우 구성 변경을 수행합니다. 앱이 새로 노출되는 영역에 그릴 때 지연이 발생하는 경우, 시스템은 windowBackground 특성 또는 기본 windowBackgroundFallback 스타일 특성에 지정된 색으로 이 영역을 임시로 채웁니다.

앱을 다중 창 모드로 구성

앱이 API 레벨 24 이상을 대상으로 하는 경우, 앱의 액티비티가 다중 창 표시를 지원하는지 여부와 지원 방법을 설정할 수 있습니다. 매니페스트에서 특성을 설정하여 크기와 레이아웃을 제어할 수 있습니다. 루트 액티비티의 특성 설정은 작업 스택 내의 모든 액티비티에 적용됩니다. 예를 들어, 루트 액티비티의 android:resizeableActivity가 true로 설정된 경우, 작업 스택에 있는 모든 액티비티의 크기를 조정할 수 있습니다.

참고: API 레벨 23 이하를 대상으로 하는 여러 방향을 사용하는 앱을 빌드하고 사용자가 이 앱을 다중 창 모드로 사용하는 경우, 시스템이 앱의 크기를 강제로 조절합니다. 앱이 예상치 못하게 동작할 수 있음을 사용자에게 경고하는 대화 상자가 표시됩니다. 시스템은 고정 방향 앱의 크기는 조정하지 않습니다. 사용자가 다중 창 모드 하에서 고정 방향 앱을 열려고 시도하면, 앱이 전체 화면을 차지합니다.

android:resizeableActivity

매니페스트의 <activity> 또는 <application> 요소에서 이 특성을 설정하여 다중 창 표시를 활성화하거나 비활성화합니다.

android:resizeableActivity=["true" | "false"]

이 특성을 true로 설정하면, 액티비티를 분할 화면 모드와 자유 형식 모드로 시작할 수 있습니다. 이 특성을 false로 설정하면, 액티비티가 다중 창 모드를 지원하지 않습니다. 이 값이 false이고 사용자가 다중 창 모드에서 액티비티를 시작하려고 시도하면, 액티비티가 전체 화면을 차지합니다.

앱이 API 레벨 24를 대상으로 하지만 이 특성 값을 지정하지 않은 경우 이 특성의 기본값은 true가 됩니다.

android:supportsPictureInPicture

이 특성을 매니페스트의 <activity> 노드에 설정하여 액티비티가 PIP(Picture-in-Picture) 표시를 지원하는지 여부를 나타냅니다. android:resizeableActivity가 false인 경우 이 특성이 무시됩니다.

android:supportsPictureInPicture=["true" | "false"]

레이아웃 특성

Android 7.0에서 <layout> 매니페스트 요소는 다중 창 모드에서 액티비티가 동작하는 방식에 영향을 미치는 여러 특성을 지원합니다.

android:defaultWidth
자유형식 모드에서 시작될 때 액티비티의 기본 너비.
android:defaultHeight
자유형식 모드에서 시작될 때 액티비티의 기본 높이.
android:gravity
자유 형식 모드에서 시작될 때 액티비티의 초기 배치. 적합한 값은 Gravity 참조 문서를 참조하세요.
android:minHeight, android:minWidth
화면 분할 및 자유 형식 모드에서 액티비티의 최소 높이 및 최소 너비. 사용자가 화면 분할 모드에서 디바이더를 이동하여 액티비티를 지정된 최솟값보다 더 작게 만드는 경우, 시스템은 이 액티비티를 사용자가 요청한 크기로 자릅니다.

예를 들어 다음 코드는 액티비티가 자유 형식 모드로 표시될 때 이 액티비티의 기본 크기와 위치 및 최소 크기를 지정하는 방법을 보여줍니다.

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end"
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

앱을 다중 창 모드에서 실행

Android 7.0부터 시스템에서 다중 창 모드로 실행할 수 있는 앱을 지원하는 기능을 제공합니다.

다중 창 모드에서 비활성화되는 기능

기기가 다중 창 모드에 있는 경우 일부 기능이 비활성화되거나 무시되는데, 그 이유는 기기 화면을 다른 액티비티 또는 앱과 공유하는 액티비티에 적합하지 않기 때문입니다. 이러한 기능에는 다음이 포함됩니다.

  • 일부 시스템 UI 사용자 지정 옵션이 비활성화됩니다. 예를 들어, 앱이 전체 화면 모드에서 실행되지 않을 경우에는 상태 표시줄을 숨길 수 없습니다.
  • 시스템이 android:screenOrientation 특성의 변경을 무시합니다.

다중 창 변경 알림 및 쿼리

Activity는 다중 창 표시를 지원하는 다음과 같은 메서드를 제공합니다.

isInMultiWindowMode()
액티비티가 다중 창 모드에 있는지를 알아내려면 이 메서드를 호출하세요.
isInPictureInPictureMode()
액티비티가 PIP 모드에 있는지를 알아내려면 호출합니다.

참고: PIP 모드는 다중 창 모드의 특별한 케이스입니다. myActivity.isInPictureInPictureMode()가 true를 반환하면 myActivity.isInMultiWindowMode()도 역시 true를 반환합니다.

onMultiWindowModeChanged()
시스템은 액티비티가 다중 창 모드로 들어가거나 이 모드에서 나올 때마다 이 메서드를 호출합니다. 시스템은 액티비티가 다중 창 모드로 들어갈 때는 true 값을 메서드에 전달하고, 액티비티가 다중 창 모드에서 나올 때는 false 값을 전달합니다.
onPictureInPictureModeChanged()
시스템은 액티비티가 PIP 모드로 들어가거나 이 모드에서 나올 때마다 이 메서드를 호출합니다. 시스템은 액티비티가 PIP 모드로 들어갈 때는 true 값을 메서드에 전달하고, 액티비티가 PIP에서 나올 때는 false 값을 전달합니다.

Fragment 클래스는 위와 같은 여러 메서드의 버전을 노출합니다(예: Fragment.onMultiWindowModeChanged()).

PIP 모드로 들어가기

액티비티를 PIP 모드에 두려면, 새로운 메서드인 Activity.enterPictureInPictureMode()를 호출합니다. 기기가 PIP 모드를 지원하지 않으면 이 메서드는 영향을 주지 않습니다. 자세한 내용은 PIP 문서를 참조하세요.

다중 창 모드에서 새 액티비티 시작

새 액티비티를 시작하는 경우, 가능하면 이 새 액티비티가 현재 액티비티에 인접하여 표시되어야 함을 시스템에 알려줄 수 있습니다. 이를 위해 인텐트 플래그 FLAG_ACTIVITY_LAUNCH_ADJACENT를 사용합니다. 이 플래그를 전달하면 다음과 같은 동작이 요청됩니다.

  • 기기가 화면 분할 모드에 있는 경우, 시스템은 시작한 액티비티 옆에 새 액티비티를 만들려고 시도하므로, 두 액티비티가 화면을 공유합니다. 시스템이 이 작업을 수행할 수 있다고 보장되지는 않지만, 가능하면 액티비티를 인접하게 만듭니다.
  • 기기가 화면 분할 모드에 있으면, 이 플래그가 영향을 미치지 않습니다.

기기가 자유 형식 모드에 있고 새 액티비티를 시작 중인 경우, ActivityOptions.setLaunchBounds()를 호출하여 이 새 액티비티의 치수와 화면 위치를 지정할 수 있습니다. 기기가 다중 창 모드에 있지 않으면, 이 메서드가 영향을 미치지 않습니다.

참고: 작업 스택 내에서 액티비티를 시작하는 경우, 이 액티비티는 화면상의 액티비티를 대체하여 모든 다중 창 속성을 상속합니다. 새 액티비티를 다중 창 모드에서 별도 창으로 시작하려면, 새 작업 스택에서 액티비티를 시작해야 합니다.

드래그 앤 드롭 지원

사용자는 두 액티비티가 화면을 공유하는 동안 한 액티비티에서 다른 액티비티로 데이터를 드래그 앤 드롭할 수 있습니다. (Android 7.0 이전에는 사용자가 단일 액티비티 내에서만 데이터를 드래그 앤 드롭할 수 있었습니다.) 이러한 이유로, 앱이 현재 지원하지 않는 경우에는 드래그 앤 드롭 기능을 앱에 추가하는 것이 좋습니다.

DragAndDropPermissions
드롭을 수신하는 앱에 부여되는 권한을 지정하기 위한 토큰 객체.
View.startDragAndDrop()
View.startDrag()의 별칭입니다. 액티비티 간의 드래그 앤 드롭을 활성화하려면, 플래그 DRAG_FLAG_GLOBAL을 전달합니다. 수신자 액티비티에 URI 권한을 부여해야 하는 경우, 플래그 DRAG_FLAG_GLOBAL_URI_READ 또는 DRAG_FLAG_GLOBAL_URI_WRITE를 적절하게 전달합니다.
View.cancelDragAndDrop()
현재 진행 중인 드래그 작업을 취소합니다. 드래그 작업을 발생시킨 앱에 의해서만 호출될 수 있습니다.
View.updateDragShadow()
현재 진행 중인 드래그 작업의 드래그 그림자를 대체합니다. 드래그 작업을 발생시킨 앱에 의해서만 호출될 수 있습니다.
Activity.requestDragAndDropPermissions()
DragEvent에 포함된 ClipData로 전달되는 콘텐츠 URI의 권한을 요청합니다.

앱의 다중 창 지원 테스트

앱이 API 레벨 24 이상을 대상으로 하는지 여부와 관계없이, Android 7.0 이상을 실행 중인 기기에서 사용자가 앱을 다중 창 모드로 시작하려고 시도하는 경우에 앱이 다중 창 모드에서 어떻게 작동하는지 확인해야 합니다.

테스트 기기 구성

기기가 Android 7.0 이상을 실행한다면 분할 화면 모드를 자동으로 지원합니다.

앱이 API 레벨 23 이하를 대상으로 하는 경우

앱이 API 레벨 23 이하를 대상으로 하고 사용자가 앱을 다중 창 모드에서 사용하려고 시도하는 경우, 이 앱이 고정 방향을 선언하지 않으면 시스템이 앱의 크기를 강제로 조정합니다.

앱이 고정 방향을 선언하지 않은 경우 Android 7.0 이상이 실행 중인 기기에서 앱을 시작해야 하며, 앱을 화면 분할 모드에 두도록 시도해야 합니다. 앱의 크기를 강제로 조정하는 경우 사용자 환경이 적절한지 확인하세요.

앱이 고정 방향을 선언하는 경우, 앱을 다중 창 모드에 두도록 시도해야 합니다. 이때 앱이 전체 화면 모드에 남아있는지 확인하세요.

다중 창 모드를 지원하는 경우

앱이 API 레벨 24 이상을 대상으로 하고 다중 창 지원을 비활성화하지 않은 경우, 분할 모드와 자유 형식 모드에서 모두 다음의 동작을 확인하세요.

  • 앱을 전체 화면 모드에서 시작한 다음, Overview 버튼을 길게 눌러서 다중 창 모드로 전환합니다. 앱이 적절히 전환되는지 확인합니다.
  • 앱을 다중 창 모드에서 직접 시작하고, 이 앱이 적절히 시작되는지 확인합니다. 다중 창 모드에서 앱을 시작하려면, Overview 버튼을 누르고 앱의 제목 표시줄을 길게 누른 다음 화면의 강조 표시된 영역 중 하나로 제목 표시줄을 끌어서 놓습니다.
  • 분할선을 끌어서 화면 분할 모드에서 앱의 크기를 조정합니다. 작동 중단 없이 앱 크기가 조정되는지 확인하고, 필요한 UI 요소가 표시되는지 확인합니다.
  • 앱에 최소 치수를 지정한 경우, 이 치수 아래로 앱 크기를 조정해 봅니다. 지정된 최솟값보다 더 작게 앱 크기를 조정할 수 없는지 확인합니다.
  • 모든 테스트를 통해 앱의 성능이 적절한지 확인합니다. 예를 들어, 앱 크기를 조정한 후 UI를 업데이트하기에 지연이 너무 길지 않은지 확인합니다.

테스트 검사 목록

다중 창 모드에서 앱의 성능을 확인하려면, 다음 작업을 시도해 보세요. 별다른 설명이 없다면 화면 분할 및 다중 창 모드에서 모두 이 작업들을 시도해야 합니다.

  • 다중 창 모드에 들어갔다 나옵니다.
  • 자신의 앱에서 다른 앱으로 전환하고, 앱이 표시는 되지만 활성화되지 않은 동안에 적절히 동작하는지 확인합니다. 예를 들어 앱이 동영상을 재생 중인 경우, 사용자가 다른 앱과 상호작용하는 동안에 이 동영상이 계속 재생되는지 확인합니다.
  • 화면 분할 모드에서 분할선을 이동하여 앱을 크거나 작게 바꾸어 봅니다. 앱을 나란히 또는 상하로 놓은 구성에서 이 작업을 시도해 봅니다. 앱의 작동이 중단되지 않는지, 필수 기능이 표시되는지, 그리고 크기 조정 작업이 너무 오래 걸리지 않는지 확인합니다.
  • 빠르게 연속해서 여러 가지 크기 조정 작업을 수행합니다. 앱의 작동이 중단되거나 메모리가 누수되지 않는지 확인합니다. 앱의 메모리 사용량을 확인하는 방법에 대한 자세한 내용은 Android Studio의 메모리 프로파일러를 참조하세요.
  • 여러 가지 다른 창 구성에서 앱을 정상적으로 사용하고, 이 앱이 제대로 작동하는지 확인합니다. 텍스트를 읽을 수 있는지 확인하고, 해당 UI 요소가 상호작용하기에 너무 작지 않은지 확인합니다.

다중 창 지원을 비활성화한 경우

android:resizeableActivity="false"를 설정하여 다중 창 지원을 비활성화한 경우, Android 7.0 이상을 실행 중인 기기에서 앱을 시작해야 하며, 앱을 자유 형식 및 화면 분할 모드로 둬야 합니다. 이때 앱이 전체 화면 모드에 남아있는지 확인하세요.

Android의 다중 창 지원에 대한 자세한 내용은 Android N에서 다중 창을 준비하기 위한 5가지 팁다중 창 플레이그라운드 샘플 앱을 참조하세요.