W Androidzie 14 (poziom 34 interfejsu API) wprowadzono ulepszenia interfejsów API obrazu w obrazie (PiP), które umożliwiają wielozadaniowość. Obsługa trybu obraz w obrazie została wprowadzona w Androidzie 8.0 (poziom interfejsu API 26), ale nie była powszechnie obsługiwana na Androidzie TV i w ogóle nie była obsługiwana na Google TV przed Androidem 13. Wielozadaniowość na telewizorze wykorzystuje tryb obrazu w obrazie, aby umożliwić jednoczesne korzystanie z 2 osobnych aplikacji na ekranie: jedna działa na pełnym ekranie, a druga w trybie obrazu w obrazie. Wymagania dotyczące aplikacji działających w tych trybach są różne.
Domyślnie aplikacja w trybie obraz w obrazie nakłada się na aplikację w trybie pełnoekranowym. Działa to podobnie jak standardowa funkcja obraz w obrazie na Androidzie.
Pamiętaj, że podczas integrowania wielozadaniowości aplikacja musi deklarować typy użycia zgodnie ze wskazówkami dotyczącymi jakości aplikacji na Androida TV.
Uruchamianie aplikacji w trybie obrazu w obrazie
Na urządzeniach TV z Androidem 14 (API na poziomie 34) lub nowszym uruchom aplikację w trybie obrazu w obrazie, wywołując funkcję enterPictureInPictureMode()
. Telewizory z wcześniejszymi wersjami Androida nie obsługują trybu obrazu w obrazie.
Oto przykład implementacji logiki przycisku, który umożliwia przejście do trybu obrazu w obrazie:
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 } }
Java
@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); } }
Działanie jest dodawane tylko wtedy, gdy urządzenie ma funkcję systemową FEATURE_PICTURE_IN_PICTURE
. Gdy działanie zostanie uruchomione, format obrazu w trybie obrazu w obrazie zostanie dopasowany do formatu obrazu odtwarzanego filmu.
Dodaj tytuł i podtytuł, aby poinformować użytkownika, do czego zwykle służy ten PIP.
Współdziałanie z aplikacjami działającymi w trybie obrazu w obrazie
Gdy aplikacja działa w trybie pełnoekranowym, może wymagać dostosowania do innych aplikacji działających w trybie obrazu w obrazie.
Interfejsy API Keep-clear
W niektórych przypadkach aplikacja w trybie obrazu w obrazie może nakładać się na ważne komponenty interfejsu w aplikacji działającej na pełnym ekranie. Aby temu zapobiec, dostępne są interfejsy API, które umożliwiają aplikacjom identyfikowanie krytycznych komponentów interfejsu, na które nie powinny się nakładać. System próbuje spełnić te prośby, aby uniknąć zasłaniania tych komponentów przez zmianę położenia okna obrazu w obrazie.
Aby określić, że widok nie powinien być nakładany, użyj w układzie XML elementu preferKeepClear
, jak w tym przykładzie:
<TextView
android:id="@+id/important_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:preferKeepClear="true"
android:text="@string/app_name"/>
Możesz to też zrobić programowo za pomocą 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 }
Java
private MyLayoutBinding binding; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = MyLayoutBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); binding.importantText.setPreferKeepClear(true); }
Czasami nie musisz utrzymywać w czystości całej View
, ale tylko jej część. Właściwość setPreferKeepClearRects()
może służyć do określania regionów View
, które nie powinny być nakładane. Interfejsy, które nie korzystają z View
natywnie, np. Flutter, Jetpack Compose i WebView, mogą mieć podsekcje, w których należy zachować wolną przestrzeń. W takich przypadkach można użyć tego interfejsu API.
Rodzaje wykorzystania
Aplikacja musi deklarować atrybut wartości metadanychcom.google.android.tv.pip.category
, który odpowiada głównemu typowi lub typom użycia trybu obrazu w obrazie. Każdy <activity>
, który ma ustawiony atrybut android:supportsPictureInPicture="true"
, powinien zadeklarować ten atrybut z odpowiednią wartością z tabeli poniżej.
Typy użycia, które nie należą do żadnej z tych kategorii, w szczególności odtwarzanie treści multimedialnych, nie są dozwolone w trybie obrazu w obrazie na telewizorze.
Wartość | Opis |
---|---|
„communication ” |
przykłady zastosowań komunikacyjnych, np. rozmowy wideo lub połączenia głosowe; |
„smartHome ” |
integracje z inteligentnym domem, np. połączone dzwonki do drzwi lub nianie elektroniczne; |
„health ” |
przypadki użycia związane ze zdrowiem, takie jak śledzenie aktywności fizycznej lub monitorowanie stanu zdrowia; |
„ticker ” |
Przykłady zastosowań paska informacyjnego, np. wyniki sportowe na żywo, wiadomości i notowania giełdowe. |
Wiele wartości jest rozdzielonych pionową kreską (|
). Przykład:
<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />