Wielozadaniowość na telewizorze

Android 14 (poziom API 34) wprowadza pewne ulepszenia interfejsów API obrazu w oknie (PiP), aby umożliwić wielozadaniowość. Obsługa PiP została wprowadzona w Androidzie 8.0 (poziom interfejsu API 26), ale 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 pionie, aby umożliwić 2 z nich oddzielne aplikacje na ekranie: jedna działająca w całości a druga w trybie Obraz w obrazie. Znaleziono różne wymagania dla aplikacji działających w jednym z tych trybów.

Domyślnie aplikacja PIP nakłada się na aplikację pełnoekranową. To jest działa tak samo jak w przypadku funkcji obraz w obrazie na Androidzie.

Pamiętaj, że przy integrowaniu funkcji wielozadaniowych aplikacja musi zadeklarować typów wykorzystania w zgodnie ze wskazówkami dotyczącymi jakości aplikacji na telewizory.

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(). Wcześniejsze urządzenia telewizyjne Androida nie obsługują trybu obraz w obrazie.

Oto przykład implementacji funkcji logicznej przycisku Enter 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 zostanie dodane tylko wtedy, gdy urządzenie ma funkcję systemową FEATURE_PICTURE_IN_PICTURE. Gdy działanie zostanie uruchomione, 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ł, które informują użytkownika o tym, do czego służy ten 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 pieszych

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ć prośby, aby nie uwzględnić tych komponentów przez gdy zmienisz położenie okna.

Keep-Clear

Aby wskazać, że widok nie powinien być nakładany, użyj preferKeepClear w Układ 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. Za pomocą parametru setPreferKeepClearRects() możesz określić regiony View, które nie powinny być nakładane. Interfejsy, które nie używają Środowisko View, takie jak Flutter, Jetpack Compose i WebView, może mieć podsekcje, które wymagają zachowania przejrzystości regionów. Tego interfejsu API można używać w takich przypadkach.

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. Wszystkie <activity>, które ustawiono android:supportsPictureInPicture="true" powinien zadeklarować ten atrybut przy użyciu tagu odpowiednią wartość 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, na przykład do śledzenia aktywności fizycznej lub zdrowia.
ticker Przypadki użycia znacznika, np. wyniki sportowe na żywo, wiadomości i akcje giełdowe.

Kilka wartości jest rozdzielonych pionową kreską (|). Na przykład:

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