Videos mit Bild im Bild (BiB) hinzufügen

Compose ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Hier erfahren Sie, wie Sie den Bild-im-Bild-Modus in der Funktion „Schreiben“ unterstützen.

Ab Android 8.0 (API-Ebene 26) können Aktivitäten in Android im Bild-im-Bild-Modus (PiP) gestartet werden. BiB ist ein spezieller Mehrfenstermodus, der hauptsächlich für die Videowiedergabe verwendet wird. Nutzer können sich ein Video in einem kleinen Fenster ansehen, das an einer Ecke des Bildschirms angepinnt ist, während sie zwischen Apps wechseln oder Inhalte auf dem Hauptbildschirm durchsuchen.

Für die Funktion „Bild-im-Bild“ werden die Mehrfenster-APIs genutzt, die in Android 7.0 verfügbar gemacht wurden, um das angepinnte Video-Overlay-Fenster bereitzustellen. Wenn Sie Ihrer App PiP hinzufügen möchten, müssen Sie die Aktivitäten registrieren, die PiP unterstützen, die Aktivität bei Bedarf in den PiP-Modus umschalten und dafür sorgen, dass die UI-Elemente ausgeblendet sind und die Videowiedergabe fortgesetzt wird, wenn die Aktivität im PiP-Modus ist.

Das PiP-Fenster wird in der obersten Ebene des Bildschirms in einer vom System ausgewählten Ecke angezeigt.

PiP wird auch auf kompatiblen Android TV-Geräten mit Android 14 (API-Level 34) oder höher unterstützt. Es gibt zwar viele Ähnlichkeiten, aber bei der Verwendung von PiP auf dem Fernseher gibt es zusätzliche Aspekte zu beachten.

Interaktionsmöglichkeiten der Nutzer mit dem PiP-Fenster

Nutzer können das PiP-Fenster an eine andere Stelle ziehen. Ab Android 12 haben Nutzer außerdem folgende Möglichkeiten:

  • Tippen Sie einmal auf das Fenster, um eine Vollbildschaltfläche, eine Schaltfläche zum Schließen, eine Schaltfläche für die Einstellungen und benutzerdefinierte Aktionen Ihrer App (z. B. Wiedergabesteuerungen) aufzurufen.

  • Doppeltippen Sie auf das Fenster, um zwischen der aktuellen BiB-Größe und der maximalen oder minimalen BiB-Größe zu wechseln. Wenn Sie beispielsweise auf ein maximiertes Fenster doppeltippen, wird es minimiert. Das Gegenteil ist auch der Fall.

  • Ziehen Sie das Fenster zum linken oder rechten Rand, um es auszublenden. Um die Verriegelung des Fensters aufzuheben, tippen Sie entweder auf den sichtbaren Teil des verschobenen Fensters oder ziehen Sie ihn heraus.

  • Ändern Sie die Größe des BiB-Fensters durch Zusammen- oder Auseinanderziehen.

Ihre App steuert, wann die aktuelle Aktivität in den PiP-Modus wechselt. Hier einige Beispiele:

  • Eine Aktivität kann in den PiP-Modus wechseln, wenn der Nutzer auf die Schaltfläche „Startseite“ tippt oder zum Startbildschirm wischt. So wird in Google Maps weiterhin eine Wegbeschreibung angezeigt, während der Nutzer gleichzeitig eine andere Aktivität ausführt.

  • Ihre App kann ein Video in den Bild-im-Bild-Modus versetzen, wenn der Nutzer vom Video zurückgeht, um andere Inhalte zu suchen.

  • Deine App kann ein Video in den BiB-Modus versetzen, während sich ein Nutzer das Ende einer Episode ansieht. Auf dem Hauptbildschirm werden Werbe- oder Zusammenfassungsinformationen zur nächsten Folge der Serie angezeigt.

  • Ihre App kann Nutzern die Möglichkeit bieten, während der Wiedergabe eines Videos zusätzliche Inhalte der Wiedergabeliste hinzuzufügen. Das Video wird im PiP-Modus fortgesetzt, während auf dem Hauptbildschirm eine Aktivität zur Inhaltsauswahl angezeigt wird.

Unterstützung von PiP deklarieren

Standardmäßig unterstützt das System PiP für Apps nicht automatisch. Wenn Sie PiP in Ihrer App unterstützen möchten, registrieren Sie Ihre Videoaktivität in Ihrem Manifest, indem Sie android:supportsPictureInPicture auf true festlegen. Geben Sie außerdem an, dass Ihre Aktivität Änderungen an der Layoutkonfiguration verarbeitet, damit sie nicht neu gestartet wird, wenn beim Wechsel in den PiP-Modus Layoutänderungen auftreten.

<activity android:name="VideoActivity"
    android:supportsPictureInPicture="true"
    android:configChanges=
        "screenSize|smallestScreenSize|screenLayout|orientation"
    ...

Aktivitäten auf BiB umstellen

Ab Android 12 kannst du deine Aktivitäten in den BiB-Modus versetzen, indem du das Flag setAutoEnterEnabled auf true setzt. Bei dieser Einstellung wechselt eine Aktivität bei Bedarf automatisch in den PiP-Modus, ohne dass onUserLeaveHint enterPictureInPictureMode() explizit aufgerufen werden muss. Das hat den zusätzlichen Vorteil, dass die Übergänge viel reibungsloser sind. Weitere Informationen finden Sie unter Übergangsanimationen zum PiP-Modus über die Touchbedienung optimieren.

Wenn Ihre App auf Android 11 oder niedriger ausgerichtet ist, muss eine Aktivität enterPictureInPictureMode() aufrufen, um in den PiP-Modus zu wechseln. Im folgenden Code wird beispielsweise eine Aktivität in den PiP-Modus geschaltet, wenn der Nutzer auf eine spezielle Schaltfläche in der App-Benutzeroberfläche klickt:

Kotlin

override fun onActionClicked(action: Action) {
    if (action.id.toInt() == R.id.lb_control_picture_in_picture) {
        activity?.enterPictureInPictureMode()
        return
    }
}

Java

@Override
public void onActionClicked(Action action) {
    if (action.getId() == R.id.lb_control_picture_in_picture) {
        getActivity().enterPictureInPictureMode();
        return;
    }
    ...
}

Möglicherweise möchten Sie eine Logik einbinden, die eine Aktivität in den BiB-Modus verwandelt, anstatt in den Hintergrund zu gehen. Google Maps wechselt beispielsweise in den BiB-Modus, wenn der Nutzer während der Navigation in der App die Startbildschirmtaste oder die Schaltfläche „Letzte“ drückt. Sie können diesen Fall abfangen, indem Sie onUserLeaveHint() überschreiben:

Kotlin

override fun onUserLeaveHint() {
    if (iWantToBeInPipModeNow()) {
        enterPictureInPictureMode()
    }
}

Java

@Override
public void onUserLeaveHint () {
    if (iWantToBeInPipModeNow()) {
        enterPictureInPictureMode();
    }
}

Empfohlen: Für eine reibungslose PiP-Übergangsfunktion sorgen

Bei Android 12 wurden die animierten Übergänge zwischen Vollbild- und BiB-Fenstern deutlich verbessert. Wir empfehlen Ihnen dringend, alle erforderlichen Änderungen vorzunehmen. Anschließend werden diese Änderungen automatisch auf große Bildschirme wie faltbare Smartphones und Tablets skaliert, ohne dass Sie weitere Maßnahmen ergreifen müssen.

Wenn Ihre App keine entsprechenden Updates enthält, funktionieren PiP-Übergänge zwar weiterhin, die Animationen sind jedoch weniger ausgefeilt. Ein Wechsel vom Vollbildmodus in den BiB-Modus kann beispielsweise dazu führen, dass das BiB-Fenster während des Übergangs ausgeblendet wird, bevor es nach Abschluss des Übergangs wieder angezeigt wird.

Diese Änderungen umfassen Folgendes:

  • Reibungsloserer Wechsel in den BiB-Modus von der Bedienung über Gesten
  • Richtige sourceRectHint für den Wechsel in den PiP-Modus und den Ausstieg aus dem PiP-Modus festlegen
  • Automatische Größenanpassung für Inhalte ohne Video deaktivieren

Im Android-Kotlin-Beispiel für Picture-in-Picture finden Sie eine Referenz für eine reibungslose Umstellung.

Einfacher Wechsel zum BiB-Modus von der Bedienung über Gesten

Ab Android 12 sorgt das Flag setAutoEnterEnabled für eine viel flüssigere Animation beim Wechsel zu Videoinhalten im PiP-Modus über die Gestennavigation, z. B. wenn Sie vom Vollbildmodus zum Startbildschirm wischen.

Führen Sie die folgenden Schritte aus, um diese Änderung vorzunehmen. Sehen Sie sich als Referenz dieses Beispiel an:

  1. Verwenden Sie setAutoEnterEnabled, um PictureInPictureParams.Builder zu erstellen:

    Kotlin

    setPictureInPictureParams(PictureInPictureParams.Builder()
        .setAspectRatio(aspectRatio)
        .setSourceRectHint(sourceRectHint)
        .setAutoEnterEnabled(true)
        .build())

    Java

    setPictureInPictureParams(new PictureInPictureParams.Builder()
        .setAspectRatio(aspectRatio)
        .setSourceRectHint(sourceRectHint)
        .setAutoEnterEnabled(true)
        .build());
  2. Rufen Sie setPictureInPictureParams mit dem aktuellen PictureInPictureParams an. Die App wartet nicht auf den onUserLeaveHint-Callback (wie es unter Android 11 der Fall gewesen wäre).

    Du kannst setPictureInPictureParams beispielsweise bei der allerersten Wiedergabe und bei jeder weiteren Wiedergabe aufrufen, wenn sich das Seitenverhältnis ändert.

  3. Rufen Sie setAutoEnterEnabled(false) auf, aber nur bei Bedarf. So möchtest du beispielsweise wahrscheinlich nicht in den Bild-im-Bild-Modus wechseln, wenn die aktuelle Wiedergabe pausiert ist.

Richtige sourceRectHint zum Aufrufen und Beenden des BiB-Modus festlegen

Seit der Einführung von BiB in Android 8.0 gibt setSourceRectHint an, welcher Bereich der Aktivität nach dem Wechsel in den Bild-im-Bild-Modus sichtbar ist, z. B. die Videowiedergabegrenzen in einem Videoplayer.

Unter Android 12 verwendet das System sourceRectHint, um sowohl beim Aktivieren als auch beim Deaktivieren des PiP-Modus eine viel flüssigere Animation zu implementieren.

So richtest du sourceRectHint richtig ein, um den BiB-Modus zu starten und zu beenden:

  1. Erstellen Sie PictureInPictureParams mit den richtigen Grenzen als sourceRectHint. Wir empfehlen außerdem, dem Videoplayer einen Listener für Layoutänderungen hinzuzufügen:

    Kotlin

    val mOnLayoutChangeListener =
    OnLayoutChangeListener { v: View?, oldLeft: Int,
            oldTop: Int, oldRight: Int, oldBottom: Int, newLeft: Int, newTop:
            Int, newRight: Int, newBottom: Int ->
        val sourceRectHint = Rect()
        mYourVideoView.getGlobalVisibleRect(sourceRectHint)
        val builder = PictureInPictureParams.Builder()
            .setSourceRectHint(sourceRectHint)
        setPictureInPictureParams(builder.build())
    }
    
    mYourVideoView.addOnLayoutChangeListener(mOnLayoutChangeListener)

    Java

    private final View.OnLayoutChangeListener mOnLayoutChangeListener =
            (v, oldLeft, oldTop, oldRight, oldBottom, newLeft, newTop, newRight,
            newBottom) -> {
        final Rect sourceRectHint = new Rect();
        mYourVideoView.getGlobalVisibleRect(sourceRectHint);
        final PictureInPictureParams.Builder builder =
            new PictureInPictureParams.Builder()
                .setSourceRectHint(sourceRectHint);
        setPictureInPictureParams(builder.build());
    };
    
    mYourVideoView.addOnLayoutChangeListener(mOnLayoutChangeListener);
  2. Aktualisieren Sie bei Bedarf die sourceRectHint, bevor das System den Ausstiegsübergang startet. Wenn das System den PiP-Modus beenden wird, wird die Ansichtshierarchie der Aktivität in der Zielkonfiguration (z. B. Vollbild) angeordnet. Die App kann einen Listener für Layoutänderungen an die Stamm- oder Zielansicht (z. B. die Videoplayeransicht) anhängen, um das Ereignis zu erkennen und sourceRectHint vor Beginn der Animation zu aktualisieren.

    Kotlin

    // Listener is called immediately after the user exits PiP but before animating.
    playerView.addOnLayoutChangeListener { _, left, top, right, bottom,
                        oldLeft, oldTop, oldRight, oldBottom ->
        if (left != oldLeft
            || right != oldRight
            || top != oldTop
            || bottom != oldBottom) {
            // The playerView's bounds changed, update the source hint rect to
            // reflect its new bounds.
            val sourceRectHint = Rect()
            playerView.getGlobalVisibleRect(sourceRectHint)
            setPictureInPictureParams(
                PictureInPictureParams.Builder()
                    .setSourceRectHint(sourceRectHint)
                    .build()
            )
        }
    }

    Java

    // Listener is called right after the user exits PiP but before animating.
    playerView.addOnLayoutChangeListener((v, left, top, right, bottom,
                        oldLeft, oldTop, oldRight, oldBottom) -> {
        if (left != oldLeft
            || right != oldRight
            || top != oldTop
            || bottom != oldBottom) {
            // The playerView's bounds changed, update the source hint rect to
            // reflect its new bounds.
            final Rect sourceRectHint = new Rect();
            playerView.getGlobalVisibleRect(sourceRectHint);
            setPictureInPictureParams(
                new PictureInPictureParams.Builder()
                    .setSourceRectHint(sourceRectHint)
                    .build());
        }
    });

Nahtlose Größenanpassung für Inhalte, die keine Videos sind, deaktivieren

In Android 12 wird das Flag setSeamlessResizeEnabled hinzugefügt, das eine viel flüssigere Cross-Fading-Animation beim Ändern der Größe von nicht videobasierten Inhalten im PiP-Fenster ermöglicht. Bisher konnten durch die Größenanpassung von Inhalten ohne Videos in einem BiB-Fenster zu verwirrenden visuellen Artefakten geführt werden.

So deaktivierst du die automatische Größenanpassung für Inhalte, die keine Videos sind:

Kotlin

setPictureInPictureParams(PictureInPictureParams.Builder()
    .setSeamlessResizeEnabled(false)
    .build())

Java

setPictureInPictureParams(new PictureInPictureParams.Builder()
    .setSeamlessResizeEnabled(false)
    .build());

Benutzeroberfläche während der Wiedergabe im Bild-im-Bild-Modus

Wenn die Aktivität in den Bild-im-Bild-Modus wechselt oder ihn verlässt, ruft das System Activity.onPictureInPictureModeChanged() oder Fragment.onPictureInPictureModeChanged() auf.

Android 15 führt Änderungen ein, die für einen noch reibungsloseren Übergang in den PiP-Modus sorgen. Das ist für Apps mit UI-Elementen vor der Haupt-UI von Vorteil, die in PiP angezeigt werden.

Entwickler verwenden den onPictureInPictureModeChanged()-Callback, um Logik zu definieren, die die Sichtbarkeit der eingeblendeten UI-Elemente ein-/ausschaltet. Dieser Callback wird ausgelöst, wenn die Animation für den Beginn oder das Ende des PiP-Videos abgeschlossen ist. Ab Android 15 enthält die Klasse PictureInPictureUiState einen neuen Status.

Bei diesem neuen UI-Status wird in Apps, die auf Android 15 ausgerichtet sind, der Rückruf Activity#onPictureInPictureUiStateChanged() mit isTransitioningToPip() aufgerufen, sobald die PiP-Animation beginnt. Es gibt viele UI-Elemente, die für die App im PiP-Modus nicht relevant sind, z. B. Ansichten oder Layouts mit Informationen wie Vorschlägen, anstehenden Videos, Bewertungen und Titeln. Wenn die App in den PiP-Modus wechselt, verwende den onPictureInPictureUiStateChanged()-Callback, um diese UI-Elemente auszublenden. Wenn die App vom PiP-Fenster in den Vollbildmodus wechselt, kannst du diese Elemente mit dem onPictureInPictureModeChanged()-Callback wieder einblenden, wie in den folgenden Beispielen gezeigt:

Kotlin

override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) {
        if (pipState.isTransitioningToPip()) {
          // Hide UI elements.
        }
    }

Java

@Override
public void onPictureInPictureUiStateChanged(PictureInPictureUiState pipState) {
        if (pipState.isTransitioningToPip()) {
          // Hide UI elements.
        }
    }

Kotlin

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
        if (isInPictureInPictureMode) {
          // Unhide UI elements.
        }
    }

Java

@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
        if (isInPictureInPictureMode) {
          // Unhide UI elements.
        }
    }

Durch die schnelle Sichtbarkeitsschaltung irrelevanter UI-Elemente (für ein PiP-Fenster) wird eine flüssigere und flackerfreie PiP-Einblendungsanimation ermöglicht.

Überschreiben Sie diese Callbacks, um die UI-Elemente der Aktivität neu zu zeichnen. Beachten Sie, dass Ihre Aktivitäten im PiP-Modus in einem kleinen Fenster angezeigt werden. Nutzer können nicht mit den UI-Elementen Ihrer App interagieren, wenn die App im PiP-Modus ist. Außerdem sind die Details kleiner UI-Elemente möglicherweise schwer zu erkennen. Videowiedergaben mit minimaler Benutzeroberfläche bieten die beste Nutzererfahrung.

Wenn Ihre App benutzerdefinierte Aktionen für PiP bereitstellen muss, lesen Sie den Abschnitt Steuerelemente hinzufügen auf dieser Seite. Entfernen Sie andere UI-Elemente, bevor die Aktivität in den PiP-Modus wechselt, und stellen Sie sie wieder her, wenn die Aktivität wieder im Vollbildmodus angezeigt wird.

Steuerelemente hinzufügen

Im PiP-Fenster können Steuerelemente angezeigt werden, wenn der Nutzer das Menü des Fensters öffnet, indem er auf dem Mobilgerät auf das Fenster tippt oder das Menü über die TV-Fernbedienung auswählt.

Wenn für eine App eine aktive Mediensitzung vorliegt, werden die Steuerelemente „Wiedergabe“, „Pause“, „Weiter“ und „Zurück“ angezeigt.

Sie können auch benutzerdefinierte Aktionen explizit angeben, indem Sie PictureInPictureParams mit PictureInPictureParams.Builder.setActions() erstellen, bevor Sie den PiP-Modus aktivieren, und die Parameter übergeben, wenn Sie den PiP-Modus mit enterPictureInPictureMode(android.app.PictureInPictureParams) oder setPictureInPictureParams(android.app.PictureInPictureParams) aktivieren. Sei vorsichtig. Wenn Sie mehr als getMaxNumPictureInPictureActions() hinzufügen, erhalten Sie nur die maximale Anzahl.

Videowiedergabe in der Bild-im-Bild-Funktion fortsetzen

Wenn die Aktivität in den PiP-Modus wechselt, setzt das System die Aktivität in den Pausierstatus und ruft die Methode onPause() der Aktivität auf. Die Videowiedergabe sollte nicht pausiert und stattdessen fortgesetzt werden, wenn die Aktivität beim Wechsel in den BiB-Modus pausiert wird.

Unter Android 7.0 und höher sollten Sie die Videowiedergabe pausieren und fortsetzen, wenn das System onStop() und onStart() für Ihre Aktivität aufruft. So müssen Sie nicht prüfen, ob sich Ihre App in onPause() im PiP-Modus befindet, und die Wiedergabe nicht manuell fortsetzen.

Wenn du das Flag setAutoEnterEnabled nicht auf true gesetzt hast und die Wiedergabe in deiner onPause()-Implementierung pausieren möchtest, prüfe mit einem Aufruf von isInPictureInPictureMode(), ob der PiP-Modus aktiv ist, und handel entsprechend. Beispiel:

Kotlin

override fun onPause() {
    super.onPause()
    // If called while in PiP mode, do not pause playback.
    if (isInPictureInPictureMode) {
        // Continue playback.
    } else {
        // Use existing playback logic for paused activity behavior.
    }
}

Java

@Override
public void onPause() {
    // If called while in PiP mode, do not pause playback.
    if (isInPictureInPictureMode()) {
        // Continue playback.
        ...
    } else {
        // Use existing playback logic for paused activity behavior.
        ...
    }
}

Wenn die Aktivität aus dem PiP-Modus in den Vollbildmodus wechselt, setzt das System die Aktivität fort und ruft die Methode onResume() auf.

Eine einzelne Wiedergabeaktivität für PiP verwenden

In Ihrer App kann ein Nutzer ein neues Video auswählen, wenn er auf dem Hauptbildschirm nach Inhalten sucht, während sich eine Videowiedergabe im BiB-Modus befindet. Spielen Sie das neue Video in der vorhandenen Wiedergabeaktivität im Vollbildmodus ab, anstatt eine neue Aktivität zu starten, die den Nutzer verwirren könnte.

Damit eine einzelne Aktivität für Videowiedergabeanfragen verwendet und bei Bedarf in den BiB-Modus gewechselt bzw. deaktiviert wird, setze den android:launchMode der Aktivität in deinem Manifest auf singleTask:

<activity android:name="VideoActivity"
    ...
    android:supportsPictureInPicture="true"
    android:launchMode="singleTask"
    ...

Überschreiben Sie in Ihrer Aktivität onNewIntent() und verarbeiten Sie das neue Video. Beenden Sie bei Bedarf die Wiedergabe des vorhandenen Videos.

Best Practices

Auf Geräten mit wenig RAM ist PiP möglicherweise deaktiviert. Bevor deine Anwendung BiB verwendet, prüfe durch Aufrufen von hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE), ob sie verfügbar ist.

Der Bild-im-Bild-Modus ist für Aktivitäten gedacht, bei denen Videos im Vollbildmodus abgespielt werden. Wenn Sie die Aktivität in den PiP-Modus umschalten, sollten Sie nur Videoinhalte anzeigen. Nachverfolgen, wann deine Aktivität in den BiB-Modus wechselt, und UI-Elemente ausblenden, wie unter Handhabung der Benutzeroberfläche während BiB beschrieben.

Wenn eine Aktivität im PiP-Modus ist, erhält sie standardmäßig nicht den Eingabefokus. Wenn du Eingabeereignisse im PiP-Modus erhalten möchtest, verwende MediaSession.setCallback(). Weitere Informationen zur Verwendung von setCallback() findest du unter Now Playing-Karte anzeigen.

Wenn sich Ihre App im Bild-im-Bild-Modus befindet, kann die Videowiedergabe im Bild-im-Bild-Fenster zu Audiostörungen bei einer anderen App führen, z. B. bei einer Musik-Player-App oder einer Sprachsuch-App. Um dies zu vermeiden, fordern Sie den Audiofokus an, wenn Sie die Videowiedergabe starten, und verarbeiten Sie Benachrichtigungen zur Änderung des Audiofokus wie unter Audiofokus verwalten beschrieben. Wenn Sie im PiP-Modus eine Benachrichtigung zum Verlust des Audiofokus erhalten, pausieren oder beenden Sie die Videowiedergabe.

Wenn Ihre App demnächst in den Bild-im-Bild-Modus wechselt, wird nur die oberste Aktivität in diesem Modus angezeigt. In einigen Fällen, z. B. auf Geräten mit mehreren Fenstern, wird die Aktivität darunter jetzt angezeigt und ist neben der PiP-Aktivität wieder sichtbar. Sie sollten diesen Fall entsprechend behandeln, einschließlich der folgenden Aktivität, um einen onResume()- oder onPause()-Callback zu erhalten. Es ist auch möglich, dass der Nutzer mit der Aktivität interagiert. Wenn du beispielsweise eine Videolistenaktivität und die Videowiedergabe im BiB-Modus siehst, kann der Nutzer ein neues Video aus der Liste auswählen und die BiB-Aktivität wird entsprechend aktualisiert.

Zusätzlicher Beispielcode

Eine in Kotlin geschriebene Beispiel-App finden Sie unter Android PictureInPicture Sample (Kotlin).