Configurare l'app per PIP

Nel tag dell'attività del file AndroidManifest.xml, procedi nel seguente modo:

  1. Aggiungi supportsPictureInPicture e impostalo su true per dichiarare che utilizzerai la modalità Picture in picture (PIP) nella tua app.
  2. Aggiungi configChanges e impostalo su orientation|screenLayout|screenSize|smallestScreenSize per specificare che la tua attività gestisce le modifiche alla configurazione del layout. In questo modo, l'attività non viene riavviata quando si verificano modifiche al layout durante le transizioni della modalità PiP.
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

Nel codice di Compose, segui questi passaggi:

  1. Aggiungi questa estensione su Context. Utilizzerai questa estensione più volte nel corso della guida per accedere all'attività.
    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")
    }

Aggiungi PIP all'uscita dall'app per versioni precedenti ad Android 12

Per aggiungere il PIP per le versioni precedenti ad Android 12, utilizza addOnUserLeaveHintProvider. Segui questi passaggi per aggiungere la funzionalità PiP per le versioni precedenti ad Android 12:

  1. Aggiungi un controllo della versione in modo che questo codice sia accessibile solo nelle versioni da O a R.
  2. Utilizza un DisposableEffect con Context come chiave.
  3. All'interno di DisposableEffect, definisci il comportamento per quando onUserLeaveHintProvider viene attivato utilizzando una funzione lambda. Nella funzione lambda, chiama enterPictureInPictureMode() su findActivity() e trasmetti PictureInPictureParams.Builder().build().
  4. Aggiungi addOnUserLeaveHintListener utilizzando findActivity() e passa l'espressione lambda.
  5. In onDispose, aggiungi removeOnUserLeaveHintListener utilizzando findActivity() e passa la funzione lambda.

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

Aggiungi PIP all'uscita dall'app per Android 12 e versioni successive

A partire da Android 12, l'PictureInPictureParams.Builder viene aggiunto tramite un modificatore che viene passato al video player dell'app.

  1. Crea un modifier e chiama onGloballyPositioned. Le coordinate del layout verranno utilizzate in un passaggio successivo.
  2. Crea una variabile per PictureInPictureParams.Builder().
  3. Aggiungi un'istruzione if per verificare se l'SDK è S o versioni successive. In questo caso, aggiungi setAutoEnterEnabled al builder e impostalo su true per attivare la modalità PiP con uno scorrimento. In questo modo, l'animazione è più fluida rispetto a quella che si ottiene con enterPictureInPictureMode.
  4. Usa il numero findActivity() per chiamare setPictureInPictureParams(). Chiama build() su builder e trasmettilo.

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)

Utilizza setAspectRatio per impostare le proporzioni della finestra PiP

Per impostare le proporzioni della finestra PiP, puoi scegliere proporzioni specifiche o utilizzare la larghezza e l'altezza delle dimensioni del video del player. Se utilizzi un player media3, verifica che il player non sia nullo e che le dimensioni del video del player non siano uguali a VideoSize.UNKNOWN prima di impostare le proporzioni.

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)

Se utilizzi un player personalizzato, imposta le proporzioni in base all'altezza e alla larghezza del player utilizzando la sintassi specifica per il tuo player. Tieni presente che se il player viene ridimensionato durante l'inizializzazione e non rientra nei limiti validi delle proporzioni, l'app si arresterà in modo anomalo. Potresti dover aggiungere controlli per stabilire quando è possibile calcolare le proporzioni, in modo simile a come avviene per un player Media3.