멀티 윈도우 지원

멀티 윈도우 모드를 사용하면 여러 앱이 같은 화면을 동시에 공유할 수 있습니다. 앱은 나란히 또는 상하로 배치 (화면 분할 모드), 다른 앱에 오버레이되는 작은 창에 있는 앱 (PIP 모드), 이동 및 크기 조절이 가능한 별도의 창에 있는 개별 앱 (자유 형식 모드)일 수 있습니다.

그림 1. 화면 분할 모드에서 두 개의 앱을 나란히 표시합니다.

사용자 환경은 Android 버전과 기기 유형에 따라 다릅니다.

  • Android 7.0 (API 수준 24)에서는 작은 화면 기기에 화면 분할 모드를, 일부 기기에 PIP 모드를 도입했습니다.

    • 화면 분할 모드는 화면을 두 개의 앱으로 채우고, 이 앱을 나란히 또는 상하로 표시합니다. 사용자는 두 앱을 구분하는 구분선을 드래그하여 한 앱을 다른 앱보다 더 크게 만들 수 있습니다.

    • PIP 모드를 사용하면 사용자가 다른 앱과 상호작용하는 동안에도 동영상을 계속 재생할 수 있습니다 (PIP 모드 지원 참고).

    • 사용자가 각 활동의 크기를 자유롭게 조정할 수 있는 자유 형식 모드는 대형 화면 기기 제조업체에서 사용 설정할 수 있습니다.

    활동의 최소 허용 크기를 지정하여 앱이 멀티 윈도우 모드를 처리하는 방식을 구성할 수 있습니다. 또한 시스템에서 항상 앱을 전체 화면으로 표시하도록 resizeabableActivity="false"를 설정하여 앱의 멀티 윈도우 모드를 중지할 수도 있습니다.

  • Android 8.0 (API 수준 26)은 PIP 모드를 소형 화면 기기로 확장합니다.

  • Android 12 (API 수준 31)는 멀티 윈도우 모드를 표준 동작으로 지정합니다.

    • 대형 화면 (최소 너비 >= 600dp)에서 플랫폼은 앱 구성과 관계없이 멀티 윈도우 모드의 모든 앱을 지원합니다. resizeableActivity="false"인 경우 디스플레이 크기를 수용하기 위해 필요한 경우 앱이 호환성 모드로 전환됩니다.

    • 작은 화면 (최소 너비 < 600dp)에서 시스템은 활동의 minWidthminHeight를 확인하여 활동이 멀티 윈도우 모드에서 실행될 수 있는지 판단합니다. resizeableActivity="false"이면 앱은 최소 너비 및 높이와 상관없이 멀티 윈도우 모드에서 실행되지 않습니다.

화면 분할 모드

사용자는 다음을 수행하여 화면 분할 모드를 활성화할 수 있습니다.

  1. 최근 화면을 엽니다.
  2. 앱을 스와이프하여 뷰로 가져옵니다.
  3. 앱 제목 표시줄에서 앱 아이콘을 누릅니다.
  4. 화면 분할 메뉴 옵션을 선택합니다.
  5. 최근 화면에서 다른 앱을 선택하거나 최근 화면을 닫고 다른 앱을 실행합니다.

사용자는 창 구분선을 화면 가장자리(예: 위 또는 아래, 왼쪽 또는 오른쪽)로 드래그하여 화면 분할 모드를 종료할 수 있습니다.

인접 항목 실행

앱에서 인텐트를 통해 콘텐츠에 액세스해야 한다면 FLAG_ACTIVITY_LAUNCH_ADJACENT를 사용하여 인접한 화면 분할 창에서 콘텐츠를 열면 됩니다.

FLAG_ACTIVITY_LAUNCH_ADJACENT는 화면 분할 모드에서 실행되는 앱이 인접한 창에서 활동을 시작할 수 있도록 하기 위해 Android 7.0 (API 수준 24)에서 도입되었습니다.

Android 12L (API 수준 32) 이상에서는 전체 화면을 실행하는 앱이 화면 분할 모드를 활성화한 다음 인접한 창에서 활동을 시작할 수 있도록 플래그 정의를 확장했습니다.

인접 활동을 실행하려면 FLAG_ACTIVITY_LAUNCH_ADJACENTFLAG_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)
    }
}

Java

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
    }
}

Java

@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이 독점적인 카메라 액세스를 보장하지는 않습니다. 카메라를 사용하는 다른 앱이 다른 디스플레이에서 열릴 수 있기 때문입니다.

그림 2. 멀티 윈도우 모드의 카메라

앱이 포커스를 잃을 때 카메라를 해제할 필요는 없습니다. 예를 들어 사용자가 새로 포커스를 맞춘 최상위 재개 앱과 상호작용하는 동안 카메라 미리보기를 계속하고자 할 수 있습니다. 최상위 재개 앱이 아닌 경우에도 앱에서 카메라를 계속 실행해도 괜찮지만 연결 해제 사례를 적절하게 처리해야 합니다. 최상위 재개 앱이 카메라를 사용하려는 경우 카메라를 열 수 있으며 앱은 액세스 권한을 잃게 됩니다. 앱이 포커스를 다시 가져왔을 때 카메라를 다시 열 수 있습니다.

앱이 CameraDevice.StateCallback#onDisconnected() 콜백을 수신하면 카메라 기기에서 후속 호출이 CameraAccessException을 발생시킵니다.

다중 디스플레이

Android 10(API 수준 29)은 보조 디스플레이에서의 활동을 지원합니다. 다중 디스플레이를 사용하는 기기에서 활동을 실행하는 경우 사용자는 하나의 디스플레이에서 다른 디스플레이로 활동을 이동할 수 있습니다. 다중 재개는 멀티스크린 시나리오에도 적용됩니다. 여러 활동이 동시에 사용자 입력을 수신할 수 있습니다.

앱은 실행될 때 또는 다른 활동을 만들 때 실행할 디스플레이를 지정할 수 있습니다. 이 동작은 매니페스트 파일에 정의된 활동 시작 모드와 활동을 실행하는 항목에 설정된 인텐트 플래그 및 옵션에 따라 달라집니다. 자세한 내용은 ActivityOptions 클래스를 참고하세요.

활동이 보조 디스플레이로 이동하는 경우 컨텍스트 업데이트, 창 크기 조절, 구성 및 리소스 변경을 실행할 수 있습니다. 활동이 구성 변경을 처리하면 활동은 onConfigurationChanged()를 통해 알림을 받습니다. 그러지 않으면 활동이 다시 실행됩니다.

활동은 구성 변경을 처리하는 경우 onCreate()onConfigurationChanged()에서 현재 디스플레이를 확인해야 합니다. 디스플레이가 변경되면 리소스 및 레이아웃도 업데이트되어야 합니다.

활동에 선택된 시작 모드에서 다중 인스턴스가 허용되는 경우 보조 화면에서 활동을 실행하면 새 활동 인스턴스가 생성될 수 있습니다. 두 활동 모두 동시에 재개됩니다.

그림 3.여러 디스플레이에서 활동의 다중 인스턴스

Android 8.0에 도입된 다중 디스플레이 API도 읽어보는 것이 좋습니다.

활동 및 애플리케이션 컨텍스트 비교

다중 디스플레이에서는 올바른 컨텍스트를 사용하는 것이 매우 중요합니다. 리소스에 액세스하는 경우 활동 컨텍스트(표시됨)와 애플리케이션 컨텍스트(표시되지 않음)가 서로 다릅니다.

활동 컨텍스트는 디스플레이 정보를 포함하며 활동이 표시되는 디스플레이 영역에 맞게 항상 조정됩니다. 이렇게 하면 앱의 화면 밀도나 창 측정항목에 관한 올바른 정보를 가져올 수 있습니다. 현재 창 또는 디스플레이에 관한 정보를 가져오려면 항상 활동 컨텍스트 (또는 다른 UI 기반 컨텍스트)를 사용해야 합니다. 이는 컨텍스트의 정보를 사용하는 일부 시스템 API에도 영향을 미칩니다 (예: 토스트 메시지 개요 참고).

활동 창 구성 및 상위 디스플레이는 리소스 및 컨텍스트를 정의합니다. 다음과 같이 현재 디스플레이를 가져옵니다.

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

현재 활동 창 측정항목을 가져옵니다.

Kotlin

val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()

Java

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

현재 시스템 구성의 최대 창 측정항목을 가져옵니다.

Kotlin

val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()

Java

WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();

최대 창 측정항목은 계산하거나 레이아웃을 선택하거나 미리 가져올 리소스의 크기를 결정하는 데 사용됩니다. onCreate()에서 이 측정항목을 사용할 수 있으면 첫 번째 레이아웃 전달 전에 그러한 결정을 내릴 수 있습니다. 이러한 측정항목은 특정 뷰 요소를 배치하는 데 사용해서는 안 됩니다. 대신 Configuration 객체의 정보를 사용하세요.

디스플레이 컷아웃

폴더블 기기가 접혔을 때와 펼쳐졌을 때 컷아웃 도형이 다를 수 있습니다. 컷아웃 문제를 방지하려면 디스플레이 컷아웃 지원을 참고하세요.

보조 디스플레이

DisplayManager 시스템 서비스에서 사용 가능한 디스플레이를 가져올 수 있습니다.

Kotlin

val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()

Java

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)

Java

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())

Java

ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(targetDisplay.displayId);
startActivity(intent, options.toBundle());

다중 디스플레이 지원

Android는 소프트웨어 키보드, 배경화면 및 런처에 다중 디스플레이 지원을 제공합니다.

소프트웨어 키보드

디스플레이가 시스템 데코레이션을 지원하도록 구성된 경우 키보드를 보조 화면에 표시할 수 있습니다. 디스플레이에서 텍스트 입력란이 입력을 요청하는 경우 자동으로 입력 방식 편집기(IME)가 표시됩니다.

그림 4. 보조 디스플레이의 키보드

배경화면

Android 10(API 수준 29)에서 보조 화면에 배경화면이 포함될 수 있습니다. 프레임워크는 각 디스플레이에 별도의 WallpaperService.Engine 인스턴스를 만듭니다. 각 엔진의 표면이 독립적으로 그려지도록 해야 합니다. 개발자는 WallpaperService.Engine#getDisplayContext()에서 디스플레이 컨텍스트를 사용하여 애셋을 로드할 수 있습니다. 또한 WallpaperInfo.xml 파일이 android:supportsMultipleDisplays="true"로 설정해야 합니다.

그림 5. 스마트폰 및 보조 디스플레이의 배경화면

런처

새로운 인텐트 필터 카테고리인 SECONDARY_HOME은 보조 화면에 전용 활동을 제공합니다. 활동의 인스턴스는 디스플레이마다 하나씩 시스템 데코레이션을 지원하는 모든 디스플레이에서 사용됩니다.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

활동에는 다중 인스턴스를 방지하지 않고 다양한 화면 크기에 맞게 조정할 수 있는 시작 모드가 있어야 합니다. 시작 모드는 singleInstance 또는 singleTask가 될 수 없습니다.

예를 들어 Launcher3의 AOSP 구현은 SECONDARY_HOME 활동을 지원합니다.

그림 6. 스마트폰의 머티리얼 디자인 런처
그림 7. 보조 디스플레이의 머티리얼 디자인 런처

창 측정항목

Android 11 (API 수준 30)에서는 멀티 윈도우 모드에서 실행되는 앱의 경계를 제공하기 위해 다음 WindowManager 메서드가 도입되었습니다.

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

Java

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)는 기본적으로 멀티 윈도우 모드로 설정되어 있습니다. 대형 화면 (sw >= 600dp)에서는 모든 앱이 앱 구성과 관계없이 멀티 윈도우 모드로 실행됩니다. 작은 화면에서 시스템은 활동의 minWidth, minHeight, resizeableActivity 설정을 확인하여 활동이 멀티 윈도우 모드에서 실행될 수 있는지 판단합니다.

resizeableActivity

매니페스트의 <activity> 또는 <application> 요소에서 이 속성을 설정하여 API 수준 30 이하에서 멀티 윈도우 모드를 사용 설정 또는 사용 중지합니다.

<application
  android:name=".MyActivity"
  android:resizeableActivity=["true" | "false"] />;

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

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

앱이 API 수준 31 이상을 타겟팅하는 경우 이 속성은 작은 화면 및 큰 화면에서 다르게 작동합니다.

  • 큰 화면 (sw >= 600dp): 모든 앱이 멀티 윈도우 모드를 지원합니다. 이 속성은 활동의 크기를 조절할 수 있는지 여부를 나타냅니다. resizeableActivity="false"인 경우 디스플레이 크기를 준수하기 위해 필요한 경우 앱이 호환성 모드로 전환됩니다.
  • 작은 화면 (sw < 600dp): 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"를 설정하고 여러 인스턴스를 차단하는 시작 모드를 사용하지 않아야 합니다. 예를 들어 FLAG_ACTIVITY_MULTIPLE_TASK 또는 FLAG_ACTIVITY_NEW_DOCUMENT가 설정된 경우 singleInstancePerTask 활동은 여러 작업에서 여러 번 인스턴스화될 수 있습니다.

멀티 인스턴스를 단일 창 내에서 실행되는 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의 멀티 윈도우 지원에 관한 자세한 내용은 다음을 참고하세요.

##

맞춤 추천

* 참고: JavaScript가 사용 중지되어 있을 때 링크 텍스트가 표시됩니다. * 기기 호환성 모드 * 대형 화면 크기 조절 가능 여부 지원 * 구성 변경 처리