PIP 모드 지원

Android 8.0(API 수준 26)에서는 활동을 PIP 모드로 실행할 수 있습니다. PIP는 주로 동영상 재생에 사용되는 특수한 유형의 멀티 윈도우 모드입니다. 사용자가 기본 화면에서 앱 간에 이동하거나 콘텐츠를 탐색할 때 화면 모서리에 고정된 작은 창에서 동영상을 볼 수 있습니다.

PIP는 Android 7.0에서 사용할 수 있는 멀티 윈도우 API를 활용하여 고정 동영상 오버레이 창을 제공합니다. PIP를 앱에 추가하려면 PIP를 지원하는 활동을 등록하고 필요한 경우 활동을 PIP 모드로 전환하며 활동이 PIP 모드일 때 UI 요소를 숨기고 동영상 재생이 지속되게 해야 합니다.

PIP 창이 화면 맨 윗 부분에서 시스템이 선택한 모서리에 나타납니다. PIP 창을 다른 위치로 드래그할 수 있습니다. 창을 탭하면 두 개의 특수 제어가 표시됩니다. 전체 화면 전환(창 가운데)과 닫기 버튼(오른쪽 상단 모서리의 'X')입니다.

앱에서 현재 활동이 PIP 모드로 전환되는 시점을 제어합니다. 다음은 몇 가지 예입니다.

  • 사용자가 홈 또는 최근 버튼을 탭하여 다른 앱을 선택하면 활동이 PIP 모드로 전환될 수 있습니다(사용자가 다른 활동을 동시에 실행하는 동안 Google 지도에서 계속 경로를 표시하는 방법임).
  • 사용자가 동영상을 보다가 다른 콘텐츠를 탐색할 때 동영상을 PIP 모드로 전환할 수 있습니다.
  • 사용자가 콘텐츠 에피소드의 끝을 시청하는 동안 동영상을 PIP 모드로 전환할 수 있습니다. 기본 화면에는 시리즈의 다음 에피소드에 관한 홍보 또는 요약 정보가 표시됩니다.
  • 사용자가 동영상을 보는 동안 앱이 추가 콘텐츠를 대기열에 올리는 방법을 제공할 수 있습니다. 동영상이 PIP 모드로 계속 재생되는 동안 기본 화면에 콘텐츠 선택 활동이 표시됩니다.

PIP 모드 지원 선언

기본적으로 시스템에서는 앱의 PIP를 자동으로 지원하지 않습니다. 앱에서 PIP를 지원하려면 android:supportsPictureInPicturetrue로 설정하여 매니페스트에 동영상 활동을 등록하세요. 또한 PIP 모드 전환 중에 레이아웃이 변경될 때 활동이 다시 시작되지 않도록 활동이 레이아웃 구성 변경을 처리하도록 지정합니다.

<activity android:name="VideoActivity"
    android:supportsPictureInPicture="true"
    android:configChanges=
        "screenSize|smallestScreenSize|screenLayout|orientation"
    ...

PIP 모드로 활동 전환

PIP 모드로 전환하려면 활동에서 enterPictureInPictureMode()를 호출해야 합니다. 예를 들어, 다음 코드는 사용자가 앱 UI에서 전용 버튼을 클릭할 때 활동을 PIP 모드로 전환합니다.

Kotlin

override fun onActionClicked(action: Action) {
    if (action.id.toInt() == R.id.lb_control_picture_in_picture) {
        activity?.enterPictureInPictureMode()
        return
    }
}

자바

@Override
public void onActionClicked(Action action) {
    if (action.getId() == R.id.lb_control_picture_in_picture) {
        getActivity().enterPictureInPictureMode();
        return;
    }
    ...
}

백그라운드로 이동하지 않고 활동을 PIP 모드로 전환하는 로직을 포함할 수도 있습니다. 예를 들어 앱에서 탐색하는 동안 사용자가 홈 또는 최근 버튼을 누르면 Google 지도가 PIP 모드로 전환됩니다. onUserLeaveHint()를 재정의하여 이 케이스를 발견할 수 있습니다.

Kotlin

override fun onUserLeaveHint() {
    if (iWantToBeInPipModeNow()) {
        enterPictureInPictureMode()
    }
}

자바

@Override
public void onUserLeaveHint () {
    if (iWantToBeInPipModeNow()) {
        enterPictureInPictureMode();
    }
}

PIP 모드에서 UI 처리

활동이 PIP 모드로 전환되거나 PIP 모드에서 나가면 시스템에서 Activity.onPictureInPictureModeChanged() 또는 Fragment.onPictureInPictureModeChanged()를 호출합니다.

활동의 UI 요소를 다시 그리려면 이 콜백을 재정의해야 합니다. PIP 모드에서는 활동이 작은 창에 표시됩니다. PIP 모드에서는 사용자가 UI 요소와 상호작용할 수 없으며 작은 UI 요소의 세부정보는 잘 보이지 않을 수 있습니다. 최소한의 UI가 포함된 동영상 재생 활동에서 최고의 사용자 환경을 제공합니다. 활동에서는 동영상 재생 제어만 표시해야 합니다. 활동이 PIP 모드가 되기 전에 다른 UI 요소를 삭제하고, 활동이 전체 화면으로 다시 전환되면 UI 요소를 복원합니다.

Kotlin

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean,
                                           newConfig: Configuration) {
    if (isInPictureInPictureMode) {
        // Hide the full-screen UI (controls, etc.) while in picture-in-picture mode.
    } else {
        // Restore the full-screen UI.
    }
}

자바

@Override
public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) {
    if (isInPictureInPictureMode) {
        // Hide the full-screen UI (controls, etc.) while in picture-in-picture mode.
    } else {
        // Restore the full-screen UI.
        ...
    }
}

제어 추가

PIP 창에서는 사용자가 휴대기기의 창을 탭하거나 TV 리모컨에서 메뉴를 선택하여 창 메뉴를 열 때 제어를 표시할 수 있습니다.

앱에 활성 미디어 세션이 있으면 재생, 일시중지, 다음, 이전 제어가 표시됩니다.

또한 PIP 모드로 들어가기 전에 PictureInPictureParams.Builder.setActions()PictureInPictureParams를 빌드하여 명시적으로 맞춤 활동을 지정하고 enterPictureInPictureMode(android.app.PictureInPictureParams) 또는 setPictureInPictureParams(android.app.PictureInPictureParams)를 사용하여 PIP 모드로 들어갈 때 매개변수를 전달할 수 있습니다. 조심하세요. getMaxNumPictureInPictureActions()를 초과하여 추가하려고 하면 최대 수에 도달하게 됩니다.

PIP 모드에서 동영상을 계속 재생합니다.

활동이 PIP로 전환되면 시스템에서 활동을 일시중지 상태로 전환하고 활동의 onPause() 메서드를 호출합니다. PIP 모드에서 활동이 일시중지된 경우에도 동영상 재생은 일시중지하지 않고 계속 재생되어야 합니다.

Android 7.0 이상에서는 시스템에서 활동의 onStop()onStart()를 호출할 때 동영상 재생을 일시중지한 다음 재개해야 합니다. 그러면 onPause()에서 앱이 PIP 모드에 있는지 확인하고 명시적으로 재생을 계속할 필요가 없습니다.

onPause() 구현에서 재생을 일시중지해야 하면 isInPictureInPictureMode()를 호출하여 PIP 모드를 확인하고 다음과 같이 재생을 적절히 처리합니다.

Kotlin

override fun onPause() {
    super.onPause()
    // If called while in PIP mode, do not pause playback
    if (isInPictureInPictureMode) {
        // Continue playback
    } else {
        // Use existing playback logic for paused Activity behavior.
    }
}

자바

@Override
public void onPause() {
    // If called while in PIP mode, do not pause playback
    if (isInPictureInPictureMode()) {
        // Continue playback
        ...
    } else {
        // Use existing playback logic for paused Activity behavior.
        ...
    }
}

활동이 PIP 모드에서 다시 전체 화면 모드로 전환되면 시스템에서 활동을 다시 시작하고 onResume() 메서드를 호출합니다.

PIP 모드에서 단일 재생 활동 사용

앱에서 동영상 재생 활동이 PIP 모드인 동안 사용자가 기본 화면에서 콘텐츠를 탐색할 때 새 동영상을 선택하는 경우가 있습니다. 사용자를 혼란스럽게 할 수 있는 새로운 활동을 실행하는 대신 기존 재생 활동의 새 동영상을 전체 화면 모드로 재생합니다.

동영상 재생 요청에 단일 활동을 사용하고 필요에 따라 PIP 모드로 전환해 들어가거나 나오려면 매니페스트에서 활동의 android:launchModesingleTask로 설정하세요.

<activity android:name="VideoActivity"
    ...
    android:supportsPictureInPicture="true"
    android:launchMode="singleTask"
    ...

활동에서 onNewIntent()를 재정의하고 새 동영상을 처리하며 필요한 경우 기존 동영상 재생을 중지합니다.

권장사항

RAM이 부족한 기기에서는 PIP가 사용 중지될 수 있습니다. 앱에서 PIP를 사용하려면 hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)를 호출하여 PIP를 사용할 수 있는지 확인하세요.

PIP는 전체 화면 동영상을 재생하는 활동에 사용합니다. 활동을 PIP 모드로 전환할 때 동영상 콘텐츠 이외의 콘텐츠는 표시하지 않습니다. PIP 모드에서 UI 처리에 설명된 대로 활동이 PIP 모드로 들어가고 UI 요소를 숨기는 시점을 추적합니다.

PIP 창은 화면 모서리에 플로팅 창으로 표시되므로 PIP 창으로 가려질 수 있는 영역의 기본 화면에는 중요한 정보를 표시하지 않아야 합니다.

활동이 PIP 모드에 있으면 기본적으로 입력 포커스를 받지 않습니다. PIP 모드에서 입력 이벤트를 받으려면 MediaSession.setCallback()을 사용합니다. setCallback() 사용에 관한 자세한 내용은 Now Playing 카드 표시를 참고하세요.

앱이 PIP 모드에 있을 때 PIP 창에서 동영상을 재생하면 음악 플레이어 앱이나 음성 검색 앱과 같은 다른 앱에서 오디오 간섭이 발생할 수 있습니다. 이를 방지하려면 오디오 포커스 관리에 설명된 대로 동영상 재생을 시작할 때 오디오 포커스를 요청하고 오디오 포커스 변경 알림을 처리합니다. PIP 모드에서 오디오 포커스 손실 알림을 받으면 동영상 재생을 일시중지하거나 중지합니다.

앱이 PIP 모드로 전환되면 상단 활동만 PIP 모드로 전환됩니다. 멀티 윈도우 기기에서와 같은 일부 상황에서는 그 아래에 있는 활동이 PIP 활동과 함께 다시 표시될 수 있습니다. 이러한 케이스는 아래 활동에 onResume() 또는 onPause() 콜백을 가져오게 하는 등 그에 맞게 처리해야 합니다. 또한 사용자가 그 활동과 상호작용할 수도 있습니다. 예를 들어 동영상 목록 활동이 표시되어 있고 PIP 모드에서 재생되는 동영상 활동이 있는 경우 사용자는 목록에서 새 동영상을 선택할 수 있습니다. 그러면 PIP 활동이 그에 따라 업데이트되어야 합니다.

추가 샘플 코드

Android에서 작성된 샘플 앱을 다운로드하려면 PIP 모드 샘플을 참조하세요. Kotlin으로 작성된 샘플 앱을 다운로드하려면 Android PIP 모드 샘플(Kotlin)을 참조하세요.