멀티 윈도우 모드를 통해 여러 앱이 같은 화면을 동시에 공유할 수 있습니다. 앱을 나란히 또는 상하로 표시하거나 (화면 분할 모드), 다른 앱에 오버레이된 작은 창에 한 앱을 표시하거나 (PIP 모드), 이동과 크기 조절이 가능한 별도의 창에 개별 앱을 표시할 수 있습니다 (데스크톱 창 모드).
휴대전화에서 화면 분할 모드에 액세스하는 방법에 관한 사용자 안내는 Pixel 휴대전화에서 앱 2개 동시에 보기를 참고하세요.
버전별 멀티 윈도우 기능
멀티 윈도우 사용자 환경은 Android 버전과 기기 유형에 따라 다릅니다.
Android 7.0 (API 수준 24)에서는 소형 화면 기기에서 화면 분할 모드를, 일부 기기에서 PIP 모드를 도입했습니다.
화면 분할 모드는 화면을 두 개의 앱으로 채우고, 이 앱을 나란히 또는 상하로 표시합니다. 사용자는 두 앱을 구분하는 구분선을 드래그하여 한 앱을 다른 앱보다 더 크게 또는 더 작게 만들 수 있습니다.
PIP 모드를 사용하면 사용자가 다른 앱과 상호작용하는 동안 동영상 재생을 계속할 수 있습니다 (PIP 모드 지원 참고).
대형 화면 기기 제조업체는 사용자가 각 활동의 크기를 자유롭게 조정할 수 있는 데스크톱 창 모드를 사용 설정할 수 있습니다.
활동의 최소 허용 치수를 지정하여 앱이 멀티 윈도우 모드를 처리하는 방식을 구성할 수 있습니다.
resizeableActivity="false"
를 설정하여 앱의 멀티 윈도우 모드를 사용 중지할 수도 있으며, 이 경우 시스템은 항상 앱을 전체 화면으로 표시합니다.
Android 8.0 (API 수준 26)은 PIP 모드를 소형 화면 기기로 확장합니다.
Android 12 (API 수준 31)는 멀티 윈도우 모드를 표준 동작으로 설정합니다.
큰 화면 (중형 또는 확장 창 크기 클래스)에서 플랫폼은 앱 구성과 관계없이 멀티 윈도우 모드의 모든 앱을 지원합니다.
resizeableActivity="false"
인 경우 디스플레이 크기를 수용하기 위해 필요한 경우 앱이 호환성 모드로 전환됩니다.작은 화면 (소형 창 크기 클래스)에서 시스템은 활동의
minWidth
및minHeight
를 확인하여 활동이 멀티 윈도우 모드에서 실행될 수 있는지 판단합니다.resizeableActivity="false"
인 경우 앱은 최소 너비 및 높이와 상관없이 멀티 윈도우 모드에서 실행되지 않습니다.
화면 분할 모드
사용자는 다음을 수행하여 화면 분할 모드를 활성화할 수 있습니다.
- 최근 화면을 엽니다.
- 앱을 스와이프하여 뷰로 가져옵니다.
- 앱 제목 표시줄에서 앱 아이콘을 누릅니다.
- 화면 분할 메뉴 옵션을 선택합니다.
- 최근 화면에서 다른 앱을 선택하거나 최근 화면을 닫고 다른 앱을 실행합니다.
사용자는 창 구분선을 화면 가장자리(예: 위 또는 아래, 왼쪽 또는 오른쪽)로 드래그하여 화면 분할 모드를 종료합니다.
인접 항목 실행
앱이 인텐트를 통해 콘텐츠에 액세스해야 하는 경우 FLAG_ACTIVITY_LAUNCH_ADJACENT
를 사용하여 인접한 스크린 분할 창에서 콘텐츠를 열 수 있습니다.
FLAG_ACTIVITY_LAUNCH_ADJACENT
는 스크린 분할 모드에서 실행되는 앱이 인접한 창에서 활동을 실행할 수 있도록 Android 7.0 (API 수준 24)에서 도입되었습니다.
Android 12L (API 수준 32) 및 이후 버전에서는 전체 화면으로 실행되는 앱이 분할 화면 모드를 활성화한 다음 인접한 창에서 활동을 실행할 수 있도록 플래그 정의가 확장되었습니다.
인접한 활동을 실행하려면 FLAG_ACTIVITY_LAUNCH_ADJACENT
를 FLAG_ACTIVITY_NEW_TASK
와 함께 사용합니다. 예를 들면 다음과 같습니다.
Kotlin
fun openUrlInAdjacentWindow(url: String) { Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or Intent.FLAG_ACTIVITY_NEW_TASK) }.also { intent -> startActivity(intent) } }
자바
public void openUrlInAdjacentWindow(String url) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }
멀티 윈도우 모드의 활동 수명 주기
멀티 윈도우 모드는 활동 수명 주기를 변경하지 않습니다. 그러나 멀티 윈도우에서 재개되는 앱의 상태는 Android 버전에 따라 다릅니다.
다중 재개
Android 10 (API 수준 29) 이상 버전은 다중 재개를 지원합니다. 기기가 멀티 윈도우 모드에 있을 때 모든 활동은 RESUMED
상태로 유지됩니다. 투명한 활동이 활동 위에 있거나 활동에 포커스를 맞출 수 없는 경우(예: 활동이 PIP 모드에 있는 경우) 활동이 일시중지될 수 있습니다. 알림 창이 열려 있는 경우와 같이 특정 시점에 포커스가 맞춰진 활동이 없을 수도 있습니다. onStop()
메서드는 평소와 같이 작동합니다. 이 메서드는 활동이 화면에서 사라질 때마다 호출됩니다.
Android 9 (API 수준 28)을 실행하는 일부 기기에서도 다중 재개를 사용할 수 있습니다. Android 9 기기에서 다중 재개를 사용 설정하려면 다음 매니페스트 메타데이터를 추가합니다.
<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />
지정된 기기가 이 매니페스트 메타데이터를 지원하는지 확인하려면 기기 사양을 참고하세요.
Android 9
Android 9(API 수준 28) 이하의 멀티 윈도우 모드에서는 사용자가 최근에 상호작용했던 활동만 지정된 시간에 활성 상태가 됩니다. 이 활동이 최상위로 간주되고 RESUMED
상태의 유일한 활동이 됩니다. 그 외에 표시되는 모든 활동은 STARTED
이지만 RESUMED
는 아닙니다.
그러나 시스템은 화면에 표시되지만 아직 다시 시작되지 않은 이러한 활동에 표시되지 않은 활동보다 더 높은 우선순위를 부여합니다. 사용자가 표시된 활동 중 하나와 상호작용하면, 해당 활동이 다시 시작되고 이전의 최상위 활동이 STARTED
상태에 들어갑니다.
단일 활성 앱 프로세스 내에 여러 활동이 있는 경우 z 순서가 가장 높은 활동이 재개되고 나머지는 일시중지됩니다.
구성 변경
사용자가 앱을 멀티 윈도우 모드에 놓으면 시스템은 구성 변경 처리에 지정된 대로 구성 변경을 활동에 알려줍니다. 이 동작은 사용자가 앱의 크기를 조정하거나 앱을 전체 화면 모드로 다시 전환할 때도 발생합니다.
기본적으로 이 같은 변경의 활동 수명 주기 영향은 기기 방향이 세로에서 가로로 전환되었음을 시스템이 앱에 알려줄 때와 동일합니다. 단, 앱 방향이 전환된 것이 아니라 앱 치수가 변경되었다는 것이 다릅니다. 활동은 구성 변경을 직접 처리하거나 앱이 시스템이 활동을 소멸시키고 새 크기로 활동을 다시 생성하도록 허용할 수 있습니다.
사용자가 창의 크기를 조정하여 한쪽 치수를 더 크게 만드는 경우, 시스템은 사용자 작업에 맞게 활동의 크기를 조정하고 필요한 경우 구성 변경을 수행합니다. 앱이 새로 노출되는 영역에 그리기를 수행할 때 지연이 발생하는 경우, 시스템은 windowBackground
속성 또는 기본 windowBackgroundFallback
스타일 속성에 지정된 색으로 이 영역을 임시로 채웁니다.
독점적 리소스 액세스
멀티 재개 기능을 지원하려면 onTopResumedActivityChanged()
수명 주기 콜백을 사용하세요.
콜백은 활동이 최상위 재개 활동 지위를 얻거나 상실할 때 호출되며, 이는 활동이 마이크 또는 카메라와 같은 공유 싱글톤 리소스를 사용하는 경우에 중요합니다.
Kotlin
override fun onTopResumedActivityChanged(topResumed: Boolean) { if (topResumed) { // Top resumed activity. // Can be a signal to re-acquire exclusive resources. } else { // No longer the top resumed activity. } }
자바
@Override public void onTopResumedActivityChanged(boolean topResumed) { if (topResumed) { // Top resumed activity. // Can be a signal to re-acquire exclusive resources. } else { // No longer the top resumed activity. } }
공유 하드웨어 제거와 같은 여러 다른 이유로 앱에서 리소스가 손실될 수 있습니다.
어떤 경우이든 앱은 사용 가능한 리소스에 영향을 주는 이벤트 및 상태 변경을 적절하게 처리해야 합니다.
카메라를 사용하는 앱의 경우 CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged()
는 카메라에 액세스해 볼 수 있는 적절한 때를 알려주는 힌트를 제공합니다.
이 메서드는 Android 10(API 수준 29)부터 사용할 수 있습니다.
카메라를 사용하는 다른 앱을 다른 디스플레이에서 열 수 있으므로 resizeableActivity=false
가 독점적 카메라 액세스 권한을 보장하지는 않습니다.
앱에서 포커스가 해제될 때 카메라를 해제할 필요는 없습니다. 예를 들어 사용자가 새로 포커스를 맞춘 최상위 재개 앱과 상호작용하는 동안 카메라 미리보기가 계속되는 것이 좋습니다. 최상위 재개 앱이 아니라면 앱에서 카메라를 계속 실행해도 괜찮지만 연결 해제 사례를 적절하게 처리해야 합니다. 최상위 재개 앱이 카메라를 사용하려는 경우 카메라를 열면 됩니다. 다른 앱에서는 액세스가 손실됩니다. 앱에서 다시 포커스를 가져오면 앱이 카메라를 다시 열 수 있습니다.
앱이 CameraDevice.StateCallback#onDisconnected()
콜백을 수신하면 카메라 기기의 후속 호출에서 CameraAccessException
이 발생합니다.
다중 디스플레이
Android 10(API 수준 29)은 보조 디스플레이에서의 활동을 지원합니다. 다중 디스플레이를 사용하는 기기에서 활동을 실행하는 경우 사용자는 하나의 디스플레이에서 다른 디스플레이로 활동을 이동할 수 있습니다. 다중 재개는 멀티스크린 시나리오에도 적용됩니다. 여러 활동이 동시에 사용자 입력을 수신할 수 있습니다.
앱은 실행될 때 또는 다른 활동을 만들 때 실행할 디스플레이를 지정할 수 있습니다. 이 동작은 매니페스트 파일에 정의된 활동 시작 모드와 활동을 실행하는 항목에 설정된 인텐트 플래그 및 옵션에 따라 달라집니다. 자세한 내용은 ActivityOptions
클래스를 참고하세요.
활동이 보조 디스플레이로 이동하는 경우 컨텍스트 업데이트, 창 크기 조절, 구성 및 리소스 변경을 실행할 수 있습니다. 활동이 구성 변경을 처리하면 onConfigurationChanged()
로 알림을 받습니다. 그렇지 않으면 활동이 다시 실행됩니다.
구성 변경이 처리된 경우 활동은 onCreate()
및 onConfigurationChanged()
에서 현재 디스플레이를 확인해야 합니다. 디스플레이가 변경되면 리소스 및 레이아웃도 업데이트되어야 합니다.
활동에 선택된 시작 모드에서 다중 인스턴스가 허용되는 경우 보조 화면에서 활동을 실행하면 새 활동 인스턴스가 만들어질 수 있습니다. 두 활동이 동시에 재개됩니다.
Android 8.0에서 도입된 다중 디스플레이 API도 검토해볼 수 있습니다.
활동 및 애플리케이션 컨텍스트 비교
다중 디스플레이에서는 올바른 컨텍스트를 사용하는 것이 매우 중요합니다. 리소스에 액세스하는 경우 활동 컨텍스트(표시됨)와 애플리케이션 컨텍스트(표시되지 않음)가 서로 다릅니다.
활동 컨텍스트는 디스플레이 정보를 포함하며 활동이 표시되는 디스플레이 영역에 맞게 항상 조정됩니다. 이를 통해 앱의 디스플레이 밀도 또는 창 측정항목에 관한 올바른 정보를 얻을 수 있습니다. 현재 창 또는 디스플레이에 관한 정보를 얻으려면 항상 활동 컨텍스트 (또는 다른 UI 기반 컨텍스트)를 사용해야 합니다. 활동 컨텍스트는 컨텍스트의 정보를 사용하는 일부 시스템 API (예: 토스트 메시지 개요 참고)에도 영향을 줍니다.
활동 창 구성 및 상위 디스플레이는 리소스 및 컨텍스트를 정의합니다. 다음과 같이 현재 디스플레이를 가져옵니다.
Kotlin
val activityDisplay = activity.getDisplay()
자바
Display activityDisplay = activity.getDisplay();
현재 활동 창 측정항목을 가져옵니다.
Kotlin
val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()
자바
WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
현재 시스템 구성의 최대 창 측정항목을 가져옵니다.
Kotlin
val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()
자바
WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();
최대 창 측정항목은 계산하거나 레이아웃을 선택하거나 미리 가져올 리소스의 크기를 결정하는 데 사용됩니다. onCreate()
에서 이 측정항목을 사용할 수 있으면 첫 번째 레이아웃 전달 전에 그러한 결정을 내릴 수 있습니다. 이 측정항목은 특정 뷰 요소를 배치하는 데 사용해서는 안 됩니다. 대신 Configuration
객체의 정보를 사용해야 합니다.
디스플레이 컷아웃
폴더블 기기가 접혔을 때와 펼쳐졌을 때 컷아웃 도형이 다를 수 있습니다. 컷아웃 문제를 방지하려면 디스플레이 컷아웃 지원을 참고하세요.
보조 디스플레이
DisplayManager
시스템 서비스에서 사용 가능한 디스플레이를 가져올 수 있습니다.
Kotlin
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager val displays = displayManager.getDisplays()
자바
DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); Display[] displays = displayManager.getDisplays();
Display
클래스를 사용하면 디스플레이 크기나 디스플레이가 안전한지 나타내는 플래그와 같은 특정 디스플레이 정보를 가져올 수 있습니다.
하지만 디스플레이 크기가 애플리케이션에 할당된 디스플레이 영역과 동일할 것이라고 가정해서는 안 됩니다. 멀티 윈도우 모드에서는 애플리케이션이 디스플레이의 일부를 차지하게 된다는 점을 기억하세요.
디스플레이에서 활동을 실행할 수 있는지 확인합니다.
Kotlin
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)
자바
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);
그런 다음 디스플레이에서 활동을 시작합니다.
Kotlin
val options = ActivityOptions.makeBasic() options.setLaunchDisplayId(targetDisplay.displayId) startActivity(intent, options.toBundle())
자바
ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(targetDisplay.displayId); startActivity(intent, options.toBundle());
다중 디스플레이 지원
Android는 소프트웨어 키보드, 배경화면 및 런처에 다중 디스플레이 지원을 제공합니다.
소프트웨어 키보드
디스플레이가 시스템 데코레이션을 지원하도록 구성된 경우 키보드를 보조 화면에 표시할 수 있습니다. 디스플레이에서 텍스트 입력란이 입력을 요청하는 경우 자동으로 입력 방식 편집기(IME)가 표시됩니다.
배경화면
Android 10(API 수준 29)에서 보조 화면에 배경화면이 포함될 수 있습니다. 프레임워크는 각 디스플레이에 별도의 WallpaperService.Engine
인스턴스를 만듭니다. 각 엔진의 표면이 독립적으로 그려지도록 해야 합니다. 개발자는 WallpaperService.Engine#getDisplayContext()
에서 디스플레이 컨텍스트를 사용하여 에셋을 로드할 수 있습니다. 또한 WallpaperInfo.xml
파일이 android:supportsMultipleDisplays="true"
로 설정되도록 해야 합니다.
런처
새로운 인텐트 필터 카테고리인 SECONDARY_HOME
은 보조 화면에 전용 활동을 제공합니다. 활동의 인스턴스는 디스플레이마다 하나씩 시스템 데코레이션을 지원하는 모든 디스플레이에서 사용됩니다.
<activity>
...
<intent-filter>
<category android:name="android.intent.category.SECONDARY_HOME" />
...
</intent-filter>
</activity>
활동에는 다중 인스턴스를 방지하지 않고 다양한 화면 크기에 맞게 조정할 수 있는 시작 모드가 있어야 합니다. 시작 모드는 singleInstance
또는 singleTask
가 될 수 없습니다.
예를 들어 Launcher3
의 AOSP 구현은 SECONDARY_HOME
활동을 지원합니다.
창 측정항목
Android 11 (API 수준 30)에는 멀티 윈도우 모드에서 실행되는 앱의 경계를 제공하기 위해 다음 WindowManager
메서드가 도입되었습니다.
getCurrentWindowMetrics()
: 시스템의 현재 윈도잉 상태에 관해WindowMetrics
객체를 반환합니다.getMaximumWindowMetrics()
: 시스템의 가장 큰 잠재적인 윈도잉 상태에 관해WindowMetrics
를 반환합니다.
Jetpack WindowManager 라이브러리 메서드 computeCurrentWindowMetrics()
및 computeMaximumWindowMetrics()
는 각각 유사한 기능을 제공하며 이전 버전인 API 수준 14와 호환됩니다.
현재 디스플레이 외의 디스플레이에 관한 측정항목을 얻으려면 다음을 실행합니다(코드 스니펫 참고).
- 디스플레이 컨텍스트를 만듭니다.
- 디스플레이의 창 컨텍스트를 만듭니다.
- 창 컨텍스트의
WindowManager
를 가져옵니다. - 앱에서 사용할 수 있는 최대 디스플레이 영역의
WindowMetrics
를 가져옵니다.
Kotlin
val windowMetrics = context.createDisplayContext(display) .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null) .getSystemService(WindowManager::class.java) .maximumWindowMetrics
자바
WindowMetrics windowMetrics = context.createDisplayContext(display) .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null) .getSystemService(WindowManager.class) .getMaximumWindowMetrics();
지원 중단된 메서드
Display
메서드 getSize()
및 getMetrics()
가 API 수준 30에서 지원 중단되었으며 새로운 WindowManager
메서드로 대체되었습니다.
Android 12 (API 수준 31)에서는 Display
메서드 getRealSize()
및 getRealMetrics()
를 지원 중단하고 이들의 동작을 업데이트하여 getMaximumWindowMetrics()
의 동작과 더 근접하게 일치시킵니다.
멀티 윈도우 모드 구성
앱이 Android 7.0 (API 수준 24) 이상을 타겟팅하는 경우 앱 활동이 멀티 윈도우 모드를 지원하는지 여부와 지원 방법을 설정할 수 있습니다. 매니페스트에서 속성을 설정하여 크기와 레이아웃을 모두 제어할 수 있습니다. 루트 활동의 속성 설정은 작업 스택 내의 모든 활동에 적용됩니다. 예를 들어, 루트 활동이 android:resizeableActivity="true"
로 설정된 경우, 작업 스택에 있는 모든 활동의 크기를 조정할 수 있습니다. Chromebook과 같은 일부 큰 기기에서는 android:resizeableActivity="false"
를 지정하더라도 앱이 크기 조절 가능한 창에서 실행될 수 있습니다. 이렇게 되면 앱이 중단되게 되는 경우, Google Play의 필터를 사용하여 이러한 기기에 앱의 사용 가능 여부를 제한할 수 있습니다.
Android 12 (API 수준 31)는 기본적으로 멀티 윈도우 모드로 설정되어 있습니다. 큰 화면(중형 또는 확장 창 크기 클래스)에서는 모든 앱이 앱 구성과 관계없이 멀티 윈도우 모드로 실행됩니다. 작은 화면에서 시스템은 활동의 minWidth
, minHeight
, resizeableActivity
설정을 통해 활동을 멀티 윈도우 모드에서 실행할 수 있는지 확인합니다.
resizeableActivity
매니페스트의 <activity>
또는 <application>
요소에서 이 속성을 설정하여 API 수준 30 이하에서 멀티 윈도우 모드를 사용 설정하거나 사용 중지할 수 있습니다.
<application
android:name=".MyActivity"
android:resizeableActivity=["true" | "false"] />;
이 속성을 true
로 설정하면 활동을 화면 분할 모드와 데스크톱 창 모드로 시작할 수 있습니다. 이 속성을 false
로 설정하면 활동이 멀티 윈도우 모드를 지원하지 않습니다. 값이 false이고 사용자가 멀티 윈도우 모드에서 활동을 시작하려고 하면 활동은 전체 화면으로 열립니다.
앱이 API 수준 24 이상을 타겟팅하지만 이 속성 값을 지정하지 않은 경우 이 속성의 기본값은 true가 됩니다.
앱이 API 수준 31 이상을 타겟팅하는 경우 이 속성은 작은 화면 및 큰 화면에서 다르게 작동합니다.
- 대형 화면 (중형 또는 확장 창 크기 클래스): 모든 앱이 멀티 윈도우 모드를 지원합니다. 이 속성은 활동의 크기를 조절할 수 있는지 여부를 나타냅니다.
resizeableActivity="false"
인 경우 디스플레이 크기를 준수하기 위해 필요한 경우 앱이 호환성 모드로 전환됩니다. - 작은 화면 (소형 창 크기 클래스):
resizeableActivity="true"
및 활동 최소 너비와 최소 높이가 멀티 윈도우 요구사항 내에 있는 경우 활동은 멀티 윈도우 모드를 지원합니다.resizeableActivity="false"
인 경우 활동은 최소 너비 및 높이와 관계없이 멀티 윈도우 모드를 지원하지 않습니다.
supportsPictureInPicture
이 속성을 매니페스트의 <activity>
노드에 설정하여 활동이 PIP 모드를 지원하는지 여부를 나타낼 수 있습니다.
<activity
android:name=".MyActivity"
android:supportsPictureInPicture=["true" | "false"] />
configChanges
멀티 윈도우 구성 변경사항을 직접 처리하려면(예: 사용자가 창 크기를 조절하는 경우) android:configChanges
속성을 앱 매니페스트 <activity>
노드에 추가하되 이 때 다음 값 이상을 사용합니다.
<activity
android:name=".MyActivity"
android:configChanges="screenSize | smallestScreenSize
| screenLayout | orientation" />
android:configChanges
을 추가하면 활동 및 프래그먼트는 소멸되어 다시 생성되는 대신에 onConfigurationChanged()
의 콜백을 수신합니다. 그런 다음 필요에 따라 뷰를 수동으로 업데이트하고 리소스를 새로고침하고 기타 작업을 수행할 수 있습니다.
<layout>
Android 7.0 (API 수준 24) 이상에서 <layout>
매니페스트 요소는 멀티 윈도우 모드에서 활동이 동작하는 방식에 영향을 미치는 여러 속성을 지원합니다.
android:defaultHeight
,android:defaultWidth
: 데스크톱 창 모드에서 실행될 때 활동의 기본 높이 및 너비입니다.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부터 시스템에서는 멀티 윈도우 모드로 실행할 수 있는 앱을 지원하는 기능을 제공합니다.
멀티 윈도우 모드에서 중지되는 기능
멀티 윈도우 모드에서 Android는 기기 화면을 다른 활동이나 앱과 공유하는 활동에 적용되지 않는 기능을 사용 중지하거나 무시할 수 있습니다.
또한 일부 시스템 UI 맞춤설정 옵션이 사용 중지됩니다. 예를 들어 앱이 멀티 윈도우 모드에서 실행되는 경우 상태 표시줄을 숨길 수 없습니다 (시스템 UI 공개 상태 제어 참고).
시스템에서 android:screenOrientation
속성 변경을 무시합니다.
멀티 윈도우 모드 쿼리 및 콜백
Activity
클래스는 멀티 윈도우 모드를 지원하는 다음 메서드를 제공합니다.
isInMultiWindowMode()
: 활동이 멀티 윈도우 모드에 있는지 나타냅니다.isInPictureInPictureMode()
: 활동이 PIP 모드에 있는지 나타냅니다.onMultiWindowModeChanged()
: 시스템은 액티비티가 멀티 윈도우 모드로 들어가거나 이 모드에서 나올 때마다 이 메서드를 호출합니다. 시스템은 활동이 멀티 윈도우 모드로 들어갈 때는 true 값을 메서드에 전달하고, 활동이 멀티 윈도우 모드에서 나올 때는 false 값을 전달합니다.onPictureInPictureModeChanged()
: 시스템은 활동이 PIP 모드로 들어가거나 이 모드에서 나올 때마다 이 메서드를 호출합니다. 시스템은 활동이 PIP 모드로 들어갈 때는 true 값을 메서드에 전달하고, 활동이 PIP에서 나올 때는 false 값을 전달합니다.
Fragment
클래스는 위와 같은 여러 메서드의 버전을 노출합니다(예: Fragment.onMultiWindowModeChanged()
).
PIP 모드
활동을 PIP 모드에 두려면 enterPictureInPictureMode()
를 호출합니다. 기기가 PIP 모드를 지원하지 않으면 이 메서드는 효과가 없습니다. 자세한 내용은 PIP 모드를 사용하여 동영상 추가를 참고하세요.
멀티 윈도우 모드에서 새 활동
새 활동을 실행할 때 가능하면 새 활동이 현재 활동 옆에 표시되어야 한다는 점을 나타낼 수 있습니다. 인텐트 플래그 FLAG_ACTIVITY_LAUNCH_ADJACENT
는 인접한 창에 새 활동을 만들도록 시스템에 지시하기 때문에 두 활동이 화면을 공유하게 됩니다. 시스템에서는 가급적 이렇게 만들려고 하지만 반드시 보장되지는 않습니다.
기기가 데스크톱 창 모드에 있고 새 활동을 실행 중인 경우 ActivityOptions.setLaunchBounds()
를 호출하여 새 활동의 치수와 화면 위치를 지정할 수 있습니다. 기기가 멀티 윈도우 모드에 있지 않으면 이 메서드는 영향을 미치지 않습니다.
API 수준 30 이하에서 작업 스택 내에 활동을 실행하면 활동이 화면의 활동을 대체하여 모든 멀티 윈도우 속성을 상속합니다. 새 활동을 멀티 윈도우 모드에서 별도 창으로 시작하려면, 새 작업 스택에서 활동을 실행해야 합니다.
Android 12(API 수준 31)에서는 앱이 여러 활동 간에 애플리케이션의 작업 창을 분할할 수 있습니다. XML 구성 파일을 만들거나 Jetpack WindowManager API를 호출하여 앱이 활동을 표시하는 방식(전체 화면, 나란히 표시 또는 스택)을 결정합니다.
드래그 앤 드롭
사용자는 두 활동이 화면을 공유하는 동안 한 활동에서 다른 활동으로 데이터를 드래그 앤 드롭할 수 있습니다. (Android 7.0 이전에는 사용자가 단일 활동 내에서만 데이터를 드래그 앤 드롭할 수 있었습니다.) 드롭된 콘텐츠 허용을 빠르게 지원하려면 DropHelper
API를 참고하세요. 포괄적인 드래그 앤 드롭 안내는 드래그 앤 드롭 사용 설정을 참고하세요.
멀티 인스턴스
각 루트 활동에는 별도의 프로세스에서 실행되며 자체 창에 표시되는 자체 작업이 있습니다. 별도의 창에서 앱의 새 인스턴스를 시작하려면 FLAG_ACTIVITY_NEW_TASK
플래그를 사용하여 새 활동을 시작하면 됩니다. 이를 멀티 윈도우 속성과 결합하여 새 창의 특정 위치를 요청할 수 있습니다. 예를 들어, 쇼핑 앱은 여러 개의 창을 표시하여 제품을 비교할 수 있습니다.
Android 12 (API 수준 31)를 사용하면 동일한 작업 창에서 활동의 두 인스턴스를 나란히 실행할 수 있습니다.
사용자가 애플리케이션 런처 또는 작업 표시줄에서 애플리케이션의 다른 인스턴스를 시작하도록 허용하려면 런처 활동이 android:resizeableActivity="true"
를 설정하고 여러 인스턴스를 방지하는 실행 모드를 사용하지 않아야 합니다. 예를 들어 singleInstancePerTask
활동은 FLAG_ACTIVITY_MULTIPLE_TASK
또는 FLAG_ACTIVITY_NEW_DOCUMENT
가 설정된 경우 다른 작업에서 여러 번 인스턴스화될 수 있습니다.
멀티 인스턴스를 SlidingPaneLayout
을 사용하여 하나의 창 내에서 실행되는 목록-세부정보 프레젠테이션과 같은 멀티 패널 레이아웃과 혼동하지 마세요.
폴더블 기기에서 여러 인스턴스가 별도의 창에서 실행 중인 경우 상태가 변경되면 하나 이상의 인스턴스가 백그라운드로 전송될 수 있습니다. 예를 들어, 기기가 펼쳐져 있고 폴드의 양쪽에서 각각 창 하나당 앱 인스턴스 하나가 실행 중이라면 이 기기를 접을 경우 두 인스턴스의 창을 작은 화면에 맞추려고 시도하는 대신 인스턴스 중 하나가 종료될 수 있습니다.
멀티 윈도우 모드 확인
앱이 API 수준 24 이상을 타겟팅하는지에 관계없이, Android 7.0 이상을 실행 중인 기기에서 사용자가 앱을 멀티 윈도우 모드로 시작하려고 하면 앱이 멀티 윈도우 모드에서 어떻게 동작하는지 확인해야 합니다.
테스트 기기
Android 7.0(API 수준 24) 이상을 실행하는 기기는 멀티 윈도우 모드를 지원합니다.
API 수준 23 이하
사용자가 앱을 멀티 윈도우 모드에서 사용하려고 시도하는 경우, 이 앱이 고정 방향을 선언하지 않으면 시스템이 앱의 크기를 강제로 조정합니다.
앱이 고정 방향을 선언하지 않는 경우 Android 7.0 이상을 실행 중인 기기에서 앱을 시작해야 하며, 앱을 화면 분할 모드에 두도록 시도해야 합니다. 앱의 크기를 강제로 조정하는 경우 사용자 환경이 적절한지 확인하세요.
앱이 고정 방향을 선언하는 경우, 앱을 멀티 윈도우 모드에 두도록 해야 합니다. 이때 앱이 전체 화면 모드 상태에 있는지 확인하세요.
API 수준 24~30
앱이 API 수준 24~30을 타겟팅하고 멀티 윈도우 지원을 중지하지 않는 경우, 화면 분할 모드와 데스크톱 창 모드에서 모두 다음 동작을 확인하세요.
앱을 전체 화면 모드에서 시작한 다음, 최근 버튼을 길게 눌러서 멀티 윈도우 모드로 전환합니다. 앱이 적절히 전환되는지 확인합니다.
앱을 멀티 윈도우 모드에서 직접 실행하고, 이 앱이 적절히 실행되는지 확인합니다. 멀티 윈도우 모드에서 앱을 실행하려면, 최근 버튼을 누르고 앱의 제목 표시줄을 길게 누른 다음 화면의 강조표시된 영역 중 하나로 제목 표시줄을 끌어서 놓습니다.
화면 분할선을 드래그하여 화면 분할 모드에서 앱의 크기를 조정합니다. 작동 중단 없이 앱 크기가 조정되는지 확인하고, 필요한 UI 요소가 표시되는지 확인합니다.
앱에 최소 치수를 지정한 경우, 창 크기가 이 치수보다 작도록 앱 크기를 조정해 봅니다. 지정된 최소 치수보다 더 작게 앱 크기를 조정할 수 없는지 확인합니다.
모든 테스트를 통해 앱의 성능이 적절한지 확인합니다. 예를 들어, 앱 크기를 조정한 후 UI를 업데이트하기에 지연이 너무 길지 않은지 확인합니다.
API 수준 31 이상
앱이 API 수준 31 이상을 타겟팅하고 기본 활동의 최소 너비와 최소 높이가 사용 가능한 디스플레이 영역의 각 크기보다 작거나 같다면 API 수준 24~30에 나열된 모든 동작을 확인하세요.
테스트 체크리스트
멀티 윈도우 모드에서 앱의 성능을 확인하려면, 다음 작업을 시도해 보세요. 별다른 설명이 없다면 화면 분할 및 데스크톱 창 모드에서 모두 이 작업을 시도해야 합니다.
다중 창 모드에 들어갔다 나옵니다.
앱에서 다른 앱으로 전환하고, 앱이 표시는 되지만 활성 상태가 아닐 때 적절히 동작하는지 확인합니다. 예를 들어 앱이 동영상을 재생 중인 경우, 사용자가 다른 앱과 상호작용하는 동안에 이 동영상이 계속 재생되는지 확인합니다.
화면 분할 모드에서 화면 분할선을 이동하여 앱을 크고 작게 바꾸어 봅니다. 앱을 나란히 또는 상하로 놓은 구성에서 이 작업을 시도해 봅니다. 앱이 비정상적으로 종료되지 않는지, 필수 기능이 표시되는지, 그리고 크기 조정 작업이 너무 오래 걸리지 않는지 확인합니다.
빠르게 연속해서 여러 가지 크기 조정 작업을 수행합니다. 앱이 비정상적으로 종료되지 않거나 메모리가 누수되지 않는지 확인합니다. Android 스튜디오의 메모리 프로파일러는 앱의 메모리 사용량에 관한 정보를 제공합니다 (메모리 프로파일러를 사용하여 앱의 메모리 사용량 검사 참고).
여러 가지 다른 창 구성에서 앱을 평소처럼 사용하며 이 앱이 제대로 작동하는지 확인합니다. 텍스트를 읽을 수 있는지 확인하고, 해당 UI 요소가 상호작용하기에 너무 작지 않은지 확인합니다.
멀티 윈도우 지원 사용 중지됨
API 수준 24~30에서 android:resizeableActivity="false"
를 설정하여 멀티 윈도우 지원을 사용 중지한 경우 Android 7.0~11을 실행하는 기기에서 앱을 실행하고 앱을 화면 분할 및 데스크톱 창 모드로 전환해야 합니다. 이때 앱이 전체 화면 모드에 남아있는지 확인하세요.
추가 리소스
Android의 멀티 윈도우 지원에 관한 자세한 내용은 다음을 참고하세요.
- Android MultiWindowPlayground 샘플
권장되는 항목 * 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다. * 기기 호환성 모드 * 대형 화면 크기 조절 지원 * 구성 변경 처리