App für BiB einrichten

Führen Sie im Aktivitäts-Tag der Datei AndroidManifest.xml folgende Schritte aus:

  1. Fügen Sie supportsPictureInPicture hinzu und legen Sie den Wert auf true fest, um anzugeben, dass Sie in Ihrer App „Bild im Bild“ (BiB) verwenden.
  2. Fügen Sie configChanges hinzu und legen Sie den Wert auf orientation|screenLayout|screenSize|smallestScreenSize fest, um anzugeben, dass Ihre Aktivität Änderungen an der Layoutkonfiguration verarbeitet. So wird Ihre Aktivität nicht neu gestartet, wenn sich das Layout während des Übergangs in den PiP-Modus ändert.
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

Gehen Sie in Ihrem Compose-Code so vor:

  1. Fügen Sie diese Erweiterung auf Context hinzu. Sie werden diese Erweiterung im Laufe des Leitfadens mehrmals verwenden, um auf die Aktivität zuzugreifen.
    internal fun Context.findActivity(): ComponentActivity {
        var context = this
        while (context is ContextWrapper) {
            if (context is ComponentActivity) return context
            context = context.baseContext
        }
        throw IllegalStateException("Picture in picture should be called in the context of an Activity")
    }

BiB beim Verlassen der App für Android-Versionen vor Android 12 hinzufügen

Wenn Sie BiB für Android-Versionen vor Android 12 hinzufügen möchten, verwenden Sie addOnUserLeaveHintProvider. So fügen Sie PiP für Android-Versionen vor Android 12 hinzu:

  1. Füge ein Versions-Gate hinzu, damit dieser Code nur in den Versionen O bis R aufgerufen wird.
  2. Verwenden Sie eine DisposableEffect mit Context als Schlüssel.
  3. Definieren Sie in DisposableEffect das Verhalten, wenn onUserLeaveHintProvider mit einer Lambda-Funktion ausgelöst wird. Rufen Sie im Lambda enterPictureInPictureMode() für findActivity() auf und übergeben Sie PictureInPictureParams.Builder().build().
  4. Fügen Sie addOnUserLeaveHintListener mit findActivity() hinzu und übergeben Sie den Lambda-Ausdruck.
  5. Fügen Sie in onDispose mit findActivity() removeOnUserLeaveHintListener hinzu und übergeben Sie den Lambda-Ausdruck.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
    Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
    val context = LocalContext.current
    DisposableEffect(context) {
        val onUserLeaveBehavior = Runnable {
            context.findActivity()
                .enterPictureInPictureMode(PictureInPictureParams.Builder().build())
        }
        context.findActivity().addOnUserLeaveHintListener(
            onUserLeaveBehavior
        )
        onDispose {
            context.findActivity().removeOnUserLeaveHintListener(
                onUserLeaveBehavior
            )
        }
    }
} else {
    Log.i("PiP info", "API does not support PiP")
}

BiB beim Verlassen der App für Android 12 und höher hinzufügen

Ab Android 12 wird die PictureInPictureParams.Builder über einen Modifikator hinzugefügt, der an den Videoplayer der App übergeben wird.

  1. Erstellen Sie einen modifier und rufen Sie onGloballyPositioned dafür auf. Die Layoutkoordinaten werden in einem späteren Schritt verwendet.
  2. Erstellen Sie eine Variable für den PictureInPictureParams.Builder().
  3. Fügen Sie eine if-Anweisung hinzu, um zu prüfen, ob das SDK S oder höher ist. Füge in diesem Fall setAutoEnterEnabled zum Builder hinzu und setze den Wert auf true, um beim Wischen in den PiP-Modus zu wechseln. Dadurch wird eine flüssigere Animation als bei enterPictureInPictureMode erzielt.
  4. Verwende findActivity(), um setPictureInPictureParams() anzurufen. Rufen Sie build() für builder auf und übergeben Sie das Ergebnis.

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(true)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}
VideoPlayer(pipModifier)

Mit setAspectRatio das Seitenverhältnis des PiP-Fensters festlegen

Wenn du das Seitenverhältnis des PiP-Fensters festlegen möchtest, kannst du entweder ein bestimmtes Seitenverhältnis auswählen oder die Breite und Höhe der Videogröße des Players verwenden. Wenn du einen Media3-Player verwendest, prüfe, ob der Player nicht null ist und die Videogröße des Players nicht VideoSize.UNKNOWN entspricht, bevor du das Seitenverhältnis festlegst.

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
        builder.setAspectRatio(
            Rational(player.videoSize.width, player.videoSize.height)
        )
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

Wenn Sie einen benutzerdefinierten Player verwenden, legen Sie das Seitenverhältnis für die Höhe und Breite des Players mit der für Ihren Player spezifischen Syntax fest. Wenn die Größe des Players während der Initialisierung geändert wird und die gültigen Grenzen des Seitenverhältnisses überschritten werden, stürzt die App ab. Möglicherweise müssen Sie Prüfungen hinzufügen, um festzustellen, wann das Seitenverhältnis berechnet werden kann, ähnlich wie bei einem Media3-Player.