Wielozadaniowość na telewizorze

Android 14 (poziom API 34) wprowadza pewne ulepszenia interfejsów API obrazu w oknie (PiP), aby umożliwić wielozadaniowość. Chociaż obsługa PiP została wprowadzona w Androidzie 8.0 (poziom interfejsu API 26), nie była szeroko obsługiwana na Androidzie TV, a przed Androidem 13 w ogóle nie była obsługiwana na Google TV. Wielozadaniowość na telewizorze wykorzystuje tryb obrazu w obrazie, aby umożliwić wyświetlanie na ekranie 2 oddzielnych aplikacji: jednej na pełnym ekranie, a drugiej w trybie obrazu 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 obrazu w obrazie

W przypadku urządzeń telewizyjnych 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 umożliwiającego przejście do trybu 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 zostanie dodane 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, aby dodać tytuł i podtytuł, aby poinformować użytkownika, do czego służy ten element PIP.

współistnienie z aplikacjami działającymi w trybie obrazu w obrazie;

Gdy aplikacja działa na pełnym ekranie, może być konieczne dostosowanie jej do innych aplikacji działających w trybie obrazu w obrazie.

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 stara się uwzględnić te prośby, aby uniknąć zasłania tych komponentów przez przeniesienie okna PiP.

Keep-Clear

Aby określić, że widok nie powinien być nakładany, użyj w swoim wygenerowanym kodzie XML wartości 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ą 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 użytkownika, które nie używają natywnych View, takich jak Flutter, Jetpack Compose czy WebView, mogą zawierać podsekcje, w których należy zachować puste regiony. 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 urządzeniami inteligentnego domu, np. połączonymi dzwonkami lub monitorami do noszenia dla dzieci;
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 pionowym (|). Na przykład:

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