멀티 윈도우 지원

Android 7.0에는 두 개 이상의 앱을 동시에 표시할 수 있는 지원 기능이 추가되었습니다. 휴대기기에서 두 앱을 화면 분할 모드로 양옆 또는 위아래로 나란히 볼 수 있습니다. TV 기기에서 앱이 PIP 모드를 사용하는 경우 사용자가 다른 앱과 상호작용하는 동안에 계속 동영상을 재생할 수 있습니다.

Android 7.0(API 수준 24) 이상을 타겟팅하는 앱에서는 멀티 윈도우 표시를 처리하는 방법을 구성할 수 있습니다. 예를 들어, 활동의 최소 허용 치수를 지정할 수 있습니다. 또한 앱에 멀티 윈도우 표시를 사용하지 않도록 끌 수도 있으며, 이 경우 시스템은 앱을 전체 화면 모드로만 표시합니다.

개요

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

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

그림 1. 화면 분할 모드로 나란히 실행되는 두 개의 앱.

사용자는 다음과 같이 멀티 윈도우 모드로 전환할 수 있습니다.

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

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

멀티 윈도우 수명 주기

멀티 윈도우 모드는 활동 수명 주기를 변경하지 않습니다.

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

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

사용자가 앱을 멀티 윈도우 모드에 놓으면 시스템은 구성 변경 처리에 지정된 대로 구성 변경을 활동에 알려줍니다. 이 동작은 사용자가 앱의 크기를 조정하거나 앱을 전체 화면 모드로 다시 전환할 때도 발생합니다. 기본적으로 이 같은 변경의 활동 수명 주기 영향은 기기 방향이 세로 모드에서 가로 모드로 전환되었음을 시스템이 앱에 알려줄 때와 동일합니다. 단, 기기 방향이 전환된 것이 아니라 기기 치수가 변경된 경우는 제외됩니다. 구성 변경 처리에서 설명한 대로, 활동은 스스로 구성 변경을 처리하거나, 활동을 소멸시키고 새 치수로 다시 활동을 생성하도록 시스템에 허용할 수 있습니다.

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

앱이 멀티 윈도우 모드에 있을 때 재개되는 상태는 기기의 Android 버전에 따라 달라집니다.

  • Android 9(API 수준 28) 이하에서는 포커스가 있는 활동만 RESUMED 상태에 있고 나머지는 모두 PAUSED입니다. 단일 앱 프로세스 내에 여러 활동이 있는 경우 Z 순서가 가장 높은 활동이 RESUMED이고 나머지는 PAUSED입니다.
  • Android 10(API 수준 29) 이상에서 상단에 포커스를 맞출 수 있는 모든 표시된 활동이 RESUMED입니다.

자세한 내용은 다중 재개 문서를 참고하세요.

앱을 멀티 윈도우 모드로 구성

앱이 API 수준 24 이상을 타겟팅하는 경우, 앱의 활동이 멀티 윈도우 표시를 지원하는지와 지원 방법을 설정할 수 있습니다. 매니페스트에서 속성을 설정하여 크기와 레이아웃을 모두 제어할 수 있습니다. 루트 활동의 속성 설정은 작업 스택 내의 모든 활동에 적용됩니다. 예를 들어, 루트 활동의 android:resizeableActivity가 true로 설정된 경우, 작업 스택에 있는 모든 활동의 크기를 조정할 수 있습니다.

참고: API 수준 23 이하를 타겟팅하는 다중 방향 앱을 빌드했을 때 사용자가 멀티 윈도우 모드에서 앱을 사용하는 경우 시스템은 앱의 크기를 강제로 조정합니다. 시스템은 앱에 예기치 않은 동작이 발생할 수 있음을 사용자에게 경고하는 대화상자를 표시합니다. 시스템은 고정 방향 앱의 크기는 조정하지 않습니다. 사용자가 멀티 윈도우 모드에서 고정 방향 앱을 열려고 시도하면, 앱이 전체 화면으로 표시됩니다.

Chromebook과 같은 일부 큰 기기에서는 android:resizeableActivity=”false”를 지정하더라도 앱이 크기 조절 가능한 창에서 실행될 수 있습니다. 이렇게 되면 앱이 중단되게 되는 경우, 필터를 사용하여 이러한 기기에 앱의 사용 가능 여부를 제한할 수 있습니다.

android:resizeableActivity

매니페스트의 <activity> 또는 <application> 요소에서 이 속성을 설정하여 멀티 윈도우 표시를 켜거나 끌 수 있습니다.

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

이 속성을 true로 설정하면, 활동을 화면 분할 모드와 자유 형식 모드로 시작할 수 있습니다. 이 속성을 false로 설정하면, 활동이 멀티 윈도우 모드를 지원하지 않습니다. 이 값이 false일 때 사용자가 멀티 윈도우 모드로 활동을 시작하려고 하면 활동은 전체 화면으로 열립니다.

앱이 API 수준 24를 타겟팅하지만 이 속성 값을 지정하지 않은 경우 이 속성의 기본값은 true가 됩니다.

android:supportsPictureInPicture

이 속성을 매니페스트의 <activity> 노드에 설정하여 활동이 PIP 모드 표시를 지원하는지 여부를 나타낼 수 있습니다. android:resizeableActivity가 false인 경우 이 속성이 무시됩니다.

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

레이아웃 속성

Android 7.0에서 <layout> 매니페스트 요소는 멀티 윈도우 모드에서 활동이 동작하는 방식에 영향을 미치는 여러 속성을 지원합니다.

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

예를 들어 다음 코드에는 활동이 자유 형식 모드로 표시될 때 이 활동의 기본 크기와 위치 및 최소 크기를 지정하는 방법이 나와 있습니다.

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

올바르게 구성 변경 처리

사용자가 창 크기를 조절할 때 발생하는 동작 등 개발자가 멀티 윈도우 구성 변경을 직접 처리하는 경우 최소한 다음 값과 함께 매니페스트에 android:configChanges 속성을 추가합니다.

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize|smallestScreenSize
      |screenLayout|orientation"
/>

android:configChanges을 추가하면 활동 및 프래그먼트는 소멸되어 다시 생성되는 대신에 onConfigurationChanged()의 콜백을 수신합니다. 그러면 필요에 따라 뷰를 수동으로 업데이트하고 리소스를 새로고침하고 기타 작업을 수행할 수 있습니다.

앱을 멀티 윈도우 모드에서 실행

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 이전에는 사용자가 단일 활동 내에서만 데이터를 드래그 앤 드롭할 수 있었습니다. 편집 가능한 TextView 위젯에 드롭된 콘텐츠를 빠르게 수용하도록 지원하려면 Jetpack의 OnReceiveContentListener를 참고하세요. 포괄적인 드래그 앤 드롭 지원(예: 앱에서 콘텐츠 드래그 사용 설정)은 드래그 앤 드롭 주제를 참고하세요.

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의 권한을 요청합니다.
DragAndDropPermissions.release()
ClipData에 지정된 콘텐츠 URI의 데이터에 액세스하는 데 필요한 권한을 해제합니다. 이 메서드를 호출하지 않으면 포함하는 활동이 소멸될 때 권한이 자동으로 해제됩니다.

멀티 인스턴스

각 루트 활동에는 별도의 프로세스에서 실행되며 자체 창에 표시되는 자체 작업이 있습니다. 별도의 창에서 앱의 새 인스턴스를 시작하려면 FLAG_ACTIVITY_NEW_TASK 플래그를 사용하여 새 활동을 시작하면 됩니다. 이를 멀티 윈도우 속성과 결합하여 새 창의 특정 위치를 요청할 수 있습니다. 예를 들어, 쇼핑 앱은 여러 개의 창을 표시하여 제품을 비교할 수 있습니다.

멀티 인스턴스를 SlidingPaneLayout을 사용하는 목록/세부정보 레이아웃과 같은 멀티 패널 레이아웃과 혼동하지 마세요. 멀티 패널 레이아웃은 단일 창 내에서 실행됩니다.

폴더블 기기에서 여러 인스턴스가 별도의 창에서 실행 중인 경우 포즈가 변경되면 하나 이상의 인스턴스가 백그라운드로 전송될 수 있습니다. 예를 들어, 기기가 펼쳐져 있고 폴드의 양쪽에서 각각 창 하나당 앱 인스턴스 하나가 실행 중이라면 이 기기를 접을 경우 두 인스턴스의 창을 작은 화면에 맞추려고 시도하는 대신 인스턴스 중 하나가 종료될 수 있습니다.

앱의 멀티 윈도우 지원 테스트

앱이 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가지 팁멀티 윈도우 플레이그라운드 샘플 앱을 참고하세요.