App für BiB einrichten

Führen Sie im Aktivitätstag Ihrer Datei AndroidManifest.xml folgende Schritte aus:

  1. Fügen Sie supportsPictureInPicture hinzu und legen Sie es auf true fest, um anzugeben, dass Sie die Bild-im-Bild-Funktion (BiB) in Ihrer App verwenden.
  2. Fügen Sie configChanges hinzu und legen Sie es 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 während der Übergänge in den BiB-Modus Layoutänderungen auftreten.
<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")
    }

PiP-Funktion für Apps, die im Hintergrund ausgeführt werden, für Versionen vor Android 12 hinzufügen

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

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

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

PiP-Funktion in der Leave-App für Android 12 und höher hinzufügen

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

  1. Erstellen Sie ein modifier und rufen Sie onGloballyPositioned dafür auf. Die Layoutkoordinaten werden in einem späteren Schritt verwendet.
  2. Erstellen Sie eine Variable für die PictureInPictureParams.Builder().
  3. Fügen Sie eine if-Anweisung hinzu, um zu prüfen, ob das SDK S oder höher ist. Fügen Sie in diesem Fall setAutoEnterEnabled zum Builder hinzu und legen Sie den Wert auf true fest, um beim Wischen in den BiB-Modus zu wechseln. So wird die Animation flüssiger als bei der Verwendung von enterPictureInPictureMode.
  4. Verwenden Sie findActivity(), um setPictureInPictureParams() anzurufen. Rufen Sie build() im builder auf und übergeben Sie es.

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 BiB-Fensters festlegen

Sie können das Seitenverhältnis des BiB-Fensters entweder festlegen oder die Breite und Höhe der Videogröße des Players verwenden. Wenn Sie einen Media3-Player verwenden, prüfen Sie, ob der Player nicht null ist und die Videogröße des Players nicht gleich VideoSize.UNKNOWN ist, bevor Sie das Seitenverhältnis festlegen.

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 er die gültigen Grenzen des Seitenverhältnisses überschreitet, stürzt Ihre 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.