Android 14 (poziom API 34) wprowadza pewne ulepszenia interfejsów API obrazu w oknie (PiP), aby umożliwić wielozadaniowość. Choć obsługa obrazu w obrazie została wprowadzona w Androidzie 8.0 (poziom interfejsu API 26), nie była ona powszechnie obsługiwana w Androidzie TV i w ogóle nie była obsługiwana w Google TV przed Androidem 13. Wielozadaniowość na telewizorze korzysta z trybu PIP, dzięki czemu na ekranie mogą współistnieć 2 oddzielne aplikacje: jedna działająca w trybie pełnoekranowym, a druga w trybie obraz w obrazie. W przypadku aplikacji działających w jednym z tych trybów obowiązują różne wymagania.
Domyślnie aplikacja PiP nakłada się na aplikację pełnoekranową. Jest to podobne do standardowego działania funkcji obraz w obrazie na Androidzie.
Pamiętaj, że podczas integracji wielozadaniowości aplikacja musi deklarować typy użycia zgodnie ze wskazówkami dotyczącymi jakości aplikacji na Androida TV.
Uruchamianie aplikacji w trybie PIP
W przypadku urządzeń TV z Androidem 14 (poziom interfejsu API 34) lub nowszym uruchom aplikację w trybie PiP, wywołując enterPictureInPictureMode()
. Urządzenia telewizyjne z wcześniejszymi wersjami Androida nie obsługują trybu obrazu w obrazie.
Oto przykład implementacji logiki przycisku, który uruchamia tryb 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 } }
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 zostanie uruchomione działanie, współczynnik kształtu obrazu w trybie PiP zostanie ustawiony tak, aby pasował do współczynnika kształtu obrazu odtwarzanego filmu.
Pamiętaj o dodaniu tytułu i podtytułu, aby poinformować użytkownika, do czego służy dany obraz PIP.
współistnienie z aplikacjami działającymi w trybie obrazu w obrazie;
Gdy aplikacja działa w trybie pełnego ekranu, może wymagać przystosowania do innych aplikacji działających w trybie PIP.
Interfejsy API dotyczące tworzenia przejść dla pojazdów uprzywilejowanych
W niektórych przypadkach aplikacja PiP może nakładać się na ważne elementy interfejsu w aplikacji pełnoekranowej. Aby temu zapobiec, aplikacje mogą używać interfejsów API keep-clear do identyfikowania kluczowych elementów interfejsu, które nie powinny być nakładane. System próbuje uwzględnić żądania, aby nie uwzględnić tych komponentów, zmieniając ustawienie okna PIP.
Aby wskazać, ż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 też wykonać tę czynność programowo za pomocą elementu 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 pozostawiać pustego obszaru wokół całego View
, tylko jego części. Właściwość setPreferKeepClearRects()
pozwala określić regiony View
, które nie powinny być nakładane. Interfejsy, które natywnie nie korzystają z interfejsów View
, takie jak Flutter, Jetpack Compose i komponent WebView, mogą zawierać podsekcje, w przypadku których regiony muszą pozostać puste. W takich przypadkach możesz użyć tego interfejsu API.
Typy wykorzystania
Aplikacja musi zadeklarować atrybut wartości metadanych com.google.android.tv.pip.category
, który odpowiada głównemu lub wielu typom użycia w trybie obrazu w obrazie. Każdy element <activity>
, który ma ustawiony atrybut android:supportsPictureInPicture="true"
, powinien zadeklarować ten atrybut z odpowiednią wartością z tabeli poniżej.
Typy użytkowania, które nie pasują 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 ” |
komunikacja, np. rozmowy wideo lub głosowe; |
„smartHome ” |
Integracje z inteligentnymi domami, takimi jak połączone dzwonki do drzwi czy elektroniczna niania. |
„health ” |
przypadki użycia związane ze zdrowiem, takie jak śledzenie aktywności fizycznej lub monitorowanie stanu zdrowia; |
„ticker ” |
zastosowania tickera, takie jak wyniki sportowe na żywo czy tickery wiadomości i akcji; |
Wiele wartości jest rozdzielanych znakiem kreski pionowej (|
). Na przykład:
<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />