Multitasking auf dem Fernseher

Android 14 (API-Level 34) führt einige Verbesserungen an den Bild-im-Bild-APIs (PiP) ein, um Multitasking zu ermöglichen. BiB wurde zwar in Android 8.0 (API-Level 26) eingeführt, wurde aber vor Android 13 weder von Android TV noch von Google TV unterstützt. Beim Multitasking auf dem Fernseher wird der Bild-im-Bild-Modus verwendet, damit zwei separate Apps gleichzeitig auf dem Bildschirm angezeigt werden können: eine im Vollbildmodus und eine im Bild-im-Bild-Modus. Für Anwendungen, die in einem dieser Modi ausgeführt werden, gelten andere Anforderungen.

Standardmäßig wird die App im Bild-im-Bild-Modus über die App im Vollbildmodus gelegt. Das entspricht dem Standardverhalten der Android-Funktion „Bild im Bild“.

Bei der Integration von Multitasking muss deine App die Nutzungsarten gemäß den Qualitätsrichtlinien für TV-Apps deklarieren.

App im BiB-Modus ausführen

Auf Fernsehern mit Android 14 (API-Level 34) oder höher kannst du deine App im BiB-Modus ausführen, indem du enterPictureInPictureMode() aufrufst. Fernseher mit älteren Android-Versionen unterstützen den PiP-Modus nicht.

Hier ist ein Beispiel für die Implementierung der Logik einer Schaltfläche, mit der der PiP-Modus aktiviert wird:

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);
    }
}

Die Aktion wird nur hinzugefügt, wenn das Gerät die Systemfunktion FEATURE_PICTURE_IN_PICTURE hat. Wenn die Aktion ausgelöst wird, wird außerdem das Seitenverhältnis des BiB-Modus so eingestellt, dass es dem Seitenverhältnis des wiedergegebenen Videos entspricht.

Fügen Sie einen Titel und einen Untertitel hinzu, um den Nutzern zu vermitteln, wozu dieser PIP im Allgemeinen verwendet wird.

Neben Apps laufen, die im PiP-Modus ausgeführt werden

Wenn Ihre App im Vollbildmodus ausgeführt wird, muss sie sich möglicherweise an andere Apps anpassen, die im PiP-Modus ausgeführt werden.

Klare APIs

In einigen Fällen kann die PiP-App wichtige UI-Komponenten in der Vollbild-App überlagern. Um dies zu vermeiden, gibt es APIs, mit denen Apps kritische UI-Komponenten identifizieren können, die nicht überlagert werden sollten. Das System versucht, die Anfragen zu erfüllen, um diese Komponenten nicht zu verdecken, indem es das PiP-Fenster neu positioniert.

Keep-Clear

Wenn Sie angeben möchten, dass eine Ansicht nicht überlagert werden soll, verwenden Sie preferKeepClear in Ihrem XML-Layout wie im folgenden Beispiel:

<TextView
    android:id="@+id/important_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:preferKeepClear="true"
    android:text="@string/app_name"/>

Du kannst das auch programmatisch mit setPreferKeepClear() tun:

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);
}

Manchmal müssen Sie nicht den gesamten View freihalten, sondern nur einen Teil davon. Mit setPreferKeepClearRects() können Sie Bereiche des View angeben, die nicht überlagert werden sollen. UIs, die View nicht nativ verwenden, z. B. Flutter, Jetpack Compose und WebView, können Unterabschnitte haben, in denen Bereiche frei bleiben müssen. Diese API kann für diese Fälle verwendet werden.

Nutzungstypen

Ihre App muss ein Metadatenwertattribut von com.google.android.tv.pip.category deklarieren, das dem primären oder den primären Verwendungstypen für den Bild-in-Bild-Modus entspricht. Für alle <activity>, für die android:supportsPictureInPicture="true" festgelegt ist, muss dieses Attribut mit einem relevanten Wert aus der folgenden Tabelle deklariert werden.

Nutzungstypen, die in keine dieser Kategorien fallen, insbesondere die Wiedergabe von Medieninhalten, sind im Bild-im-Bild-Modus auf Fernsehern nicht erlaubt.

Wert Beschreibung
communication Kommunikationsanwendungsfälle wie Video- oder Sprachanrufe
smartHome Smart-Home-Integrationen wie verbundene Türklingeln oder Babyfone
health Gesundheitsbezogene Anwendungsfälle wie Fitness-Tracking oder Gesundheitsüberwachung
ticker Ticker-Anwendungsfälle wie Live-Sportergebnisse oder Nachrichten und Börsenticker.

Mehrere Werte werden durch einen vertikalen Strich (|) getrennt. Beispiel:

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