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 기기의 경우 enterPictureInPictureMode()
를 호출하여 PiP 모드에서 앱을 실행합니다. 이전 버전의 Android를 실행하는 TV 기기는 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 구성요소를 식별하는 데 사용할 수 있는 keep-clear API가 있습니다. 시스템은 PiP 창의 위치를 변경하여 이러한 구성요소가 가려지지 않도록 요청을 처리하려고 시도합니다.
뷰가 오버레이되어서는 안 된다고 지정하려면 다음 예와 같이 XML 레이아웃에서 preferKeepClear
를 사용하세요.
<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
의 겹쳐져서는 안 되는 영역을 지정하는 데 사용할 수 있습니다. Flutter, Jetpack Compose, WebView와 같이 기본적으로 View
를 사용하지 않는 UI에는 리전을 깨끗하게 유지해야 하는 하위 섹션이 있을 수 있습니다. 이러한 경우에 이 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" />