Android 14 (poziom 34 interfejsu API) wprowadza kilka ulepszeń interfejsów API obrazu w obrazie, które umożliwiają korzystanie z trybu wielozadaniowego. Obsługa obrazu w obrazie została wprowadzona w Androidzie 8.0 (poziom 26 interfejsu API), ale nie była powszechnie obsługiwana na Androidzie TV, a przed Androidem 13 nie była obsługiwana w Google TV. Tryb wielozadaniowy na telewizorze korzysta z trybu obrazu w obrazie, aby umożliwić współistnienie na ekranie 2 oddzielnych aplikacji: jednej działającej na pełnym ekranie i drugiej działającej w trybie obrazu w obrazie. Aplikacje działające w jednym z tych trybów muszą spełniać różne wymagania.
Domyślnie aplikacja obrazu w obrazie nakłada się na aplikację pełnoekranową. Jest to podobne do standardowego zachowania obrazu w obrazie w Androidzie.
Pamiętaj, że podczas integrowania trybu wielozadaniowego aplikacja musi deklarować swoje typy użycia zgodnie ze wskazówkami dotyczącymi jakości aplikacji TV.
Uruchamianie aplikacji w trybie obrazu w obrazie
Na urządzeniach z Androidem TV z Androidem 14 (poziom 34 interfejsu API) lub nowszym uruchom aplikację w trybie obrazu w obrazie, wywołując metodę enterPictureInPictureMode(). Urządzenia z Androidem TV 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 wywołane, współczynnik proporcji trybu obrazu w obrazie zostanie ustawiony tak, aby pasował do współczynnika proporcji odtwarzanego filmu.
Dodaj tytuł i podtytuł, aby poinformować użytkownika do czego zwykle służy ten obraz w obrazie.
Współistnienie z aplikacjami działającymi w trybie obrazu w obrazie
Gdy aplikacja działa w trybie pełnoekranowym, może być konieczne dostosowanie jej do innych aplikacji działających w trybie obrazu w obrazie.
Interfejsy API keep-clear
W niektórych przypadkach aplikacja obrazu w obrazie może nakładać się na ważne komponenty interfejsu w aplikacji pełnoekranowej. Aby temu zapobiec, dostępne są interfejsy API keep-clear, których aplikacje mogą używać do identyfikowania krytycznych komponentów interfejsu, które nie powinny być nakładane. System próbuje uwzględnić prośby o unikanie 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 preferKeepClear w układzie
XML, 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ą metody 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 trzeba utrzymywać całego View w czystości, ale
tylko jego części. Metody setPreferKeepClearRects() można użyć do
określenia obszarów View, które nie powinny być nakładane. Interfejsy, które nie używają natywnie Views, takie jak Flutter, Jetpack Compose i WebView, mogą mieć podsekcje, które wymagają utrzymania czystości. W takich przypadkach można użyć tego interfejsu API.
Rodzaje wykorzystania
Aplikacja musi zadeklarować atrybut wartości metadanych odpowiadający głównemu typowi lub
com.google.android.tv.pip.categorytypom użycia trybu obrazu w obrazie. Każda <activity>, która ma ustawiony
android:supportsPictureInPicture="true", powinna zadeklarować ten atrybut z
odpowiednią wartością z tabeli poniżej.
Typy użycia, które nie pasują do żadnej z tych kategorii, w szczególności odtwarzanie treści multimedialnych, są niedozwolone w trybie obrazu w obrazie na telewizorze.
| Wartość | Opis |
|---|---|
„communication” |
Przypadki użycia związane z komunikacją, np. połączenia wideo lub głosowe. |
„smartHome” |
Integracje z inteligentnym domem, np. połączone dzwonki do drzwi lub nianie elektroniczne. |
„health” |
Przypadki użycia związane ze zdrowiem, np. śledzenie aktywności fizycznej lub monitorowanie stanu zdrowia. |
„ticker” |
Przypadki użycia związane z tickerem, np. wyniki sportowe na żywo lub ticker wiadomości i akcji. |
Wiele wartości jest oddzielonych pionową kreską (|). Przykład:
<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />