TV에서 멀티태스킹

Android 14(API 수준 34)에서는 멀티태스킹을 지원하기 위해 PIP(Picture-in-Picture) API를 개선했습니다. PiP 지원은 Android 8.0(API 수준 26)에서 도입되었지만 Android TV에서는 널리 지원되지 않았으며 Android 13 이전에는 Google TV에서 전혀 지원되지 않았습니다. TV용 멀티태스킹은 PIP 모드를 사용하여 두 개의 앱이 화면에 공존하도록 허용합니다. 하나는 전체 화면으로 실행되고 다른 하나는 PIP 모드로 실행됩니다. 이러한 모드 중 하나에서 실행되는 앱에는 서로 다른 요구사항이 있습니다.

기본 동작은 PIP 앱이 전체 화면 앱을 오버레이하는 것입니다. 이는 표준 Android PIP 모드 동작과 거의 같습니다.

멀티태스킹을 통합할 때 애플리케이션은 사용 유형 TV 앱 품질 가이드라인을 준수해야 합니다.

PIP 모드로 앱 실행

Android 14 (API 수준 34) 이상을 실행하는 TV 기기의 경우 PIP로 앱을 실행합니다. enterPictureInPictureMode()를 호출하여 모드를 전환할 수 있습니다. 이전 실행 TV 기기 Android 버전은 PIP 모드를 지원하지 않습니다.

다음은 입력 버튼을 위한 로직을 구현하는 방법의 예입니다. PIP 모드:

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    pictureInPictureButton.visibility =
        if (requireActivity().packageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
            pictureInPictureButton.setOnClickListener {
                val aspectRatio = Rational(view.width, view.height)
                val params = PictureInPictureParams.Builder()
                    .setAspectRatio(aspectRatio)
                    .build()
                val result = requireActivity().enterPictureInPictureMode(params)
            }
            View.VISIBLE
        } else {
            View.GONE
        }
}

자바

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (requireActivity().getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
        pictureInPictureButton.setVisibility(View.VISIBLE);
        pictureInPictureButton.setOnClickListener(v -> {
            Rational aspectRatio = new Rational(view.getWidth(), view.getHeight());
            PictureInPictureParams params = new PictureInPictureParams.Builder()
                    .setAspectRatio(aspectRatio)
                    .setTitle("My Streaming App")
                    .setSubtitle("My On-Demand Content")
                    .build();
            Boolean result = requireActivity().enterPictureInPictureMode(params);
        });
    } else {
        pictureInPictureButton.setVisibility(View.GONE);
    }
}

이 작업은 기기에 시스템 기능 FEATURE_PICTURE_IN_PICTURE가 있는 경우에만 추가됩니다. 또한 작업이 트리거되면 재생 중인 동영상의 가로세로 비율과 일치하도록 PIP 모드의 가로세로 비율이 설정됩니다.

이 PIP가 일반적으로 어떤 용도로 사용되는지 사용자에게 알리기 위해 제목자막을 추가해야 합니다.

PIP 모드에서 실행되는 앱과 공존

앱이 전체 화면 앱으로 실행 중일 때 PIP 모드에서 실행 중인 다른 앱에 맞게 조정해야 할 수 있습니다.

Keep-clear API

경우에 따라 PIP 앱이 화면 내부의 중요한 UI 구성요소를 전체 화면 앱 이 문제를 완화하기 위해 앱에서 UI 구성요소를 식별할 수 있습니다. 시스템은 PiP 창의 위치를 변경하여 이러한 구성요소가 가려지지 않도록 요청을 처리하려고 시도합니다.

Keep-Clear

뷰를 오버레이하지 않도록 지정하려면 다음과 같이 preferKeepClear를 사용합니다. XML 레이아웃을 사용해야 합니다.

<TextView
    android:id="@+id/important_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:preferKeepClear="true"
    android:text="@string/app_name"/>

setPreferKeepClear()를 사용하여 프로그래매틱 방식으로 이 작업을 실행할 수도 있습니다.

Kotlin

private lateinit var binding: MyLayoutBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding = MyLayoutBinding.inflate(layoutInflater)
    setContentView(binding.root)
    binding.importantText.isPreferKeepClear = true
}

자바

private MyLayoutBinding binding;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = MyLayoutBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());
    binding.importantText.setPreferKeepClear(true);
}

전체 View를 깨끗하게 유지할 필요가 없고 일부만 유지하면 되는 경우도 있습니다. setPreferKeepClearRects()View의 겹쳐져서는 안 되는 영역을 지정하는 데 사용할 수 있습니다. 사용하지 않는 UI Flutter, Jetpack Compose, WebView와 같은 View는 기본적으로 영역을 명확히 해야 하는 하위 섹션이 있습니다. 이러한 경우에 이 API를 사용할 수 있습니다.

사용 유형

앱은 PIP 모드의 기본 사용 유형 또는 유형에 해당하는 com.google.android.tv.pip.category메타데이터 값 속성을 선언해야 합니다. android:supportsPictureInPicture="true"를 설정한 모든 <activity>는 아래 표의 관련 값으로 이 속성을 선언해야 합니다.

이러한 카테고리에 속하지 않는 사용 유형, 특히 TV의 PIP 모드에서 허용되지 않습니다.

설명
"communication" 영상 통화 또는 음성 통화와 같은 통신 사용 사례
"smartHome" 스마트 홈 통합(예: 연결된 초인종 또는 아기 모니터)
"health" 피트니스 추적 또는 건강 모니터링과 같은 건강 사용 사례
"ticker" 라이브 스포츠 점수, 뉴스, 주식 시세 표시 등 시세 표시 사용 사례

값이 여러 개인 경우 세로 막대 (|)로 구분합니다. 예를 들면 다음과 같습니다.

<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />