Ingresa PiP en los momentos correctos

Tu app no debe ingresar al modo PiP en las siguientes situaciones:

  • Si el video está detenido o pausado
  • Si estás en una página de la app diferente del reproductor de video.

Para controlar cuándo tu app ingresa en el modo de PIP, agrega una variable que haga un seguimiento del estado del reproductor de video con un mutableStateOf.

Activa o desactiva el estado según si se está reproduciendo el video

Para activar o desactivar el estado según si el reproductor de video está reproduciendo contenido, agrega un objeto de escucha al reproductor. Activa o desactiva el estado de tu variable de estado según si el jugador está jugando o no:

player.addListener(object : Player.Listener {
    override fun onIsPlayingChanged(isPlaying: Boolean) {
        shouldEnterPipMode = isPlaying
    }
})

Activa o desactiva el estado según si se libera el reproductor

Cuando se lance el reproductor, establece la variable de estado en false:

fun releasePlayer() {
    shouldEnterPipMode = false
}

Usa el estado para definir si se ingresó al modo PiP (anterior a Android 12)

  1. Dado que agregar PiP anterior a la versión 12 usa un DisposableEffect, debes crear una variable nueva con rememberUpdatedState con newValue establecida como tu variable de estado. Esto garantizará que se use la versión actualizada en DisposableEffect.
  2. En la lambda que define el comportamiento cuando se activa OnUserLeaveHintListener, agrega una sentencia if con la variable de estado alrededor de la llamada a enterPictureInPictureMode():

    val currentShouldEnterPipMode by rememberUpdatedState(newValue = shouldEnterPipMode)
    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: () -> Unit = {
                if (currentShouldEnterPipMode) {
                    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")
    }

Usa el estado para definir si se ingresó al modo PiP (después de Android 12)

Pasa tu variable de estado a setAutoEnterEnabled para que tu app solo entre en el modo PIP en el momento adecuado:

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

    // Add autoEnterEnabled for versions S and up
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

Usa setSourceRectHint para implementar una animación fluida

La API de setSourceRectHint crea una animación más fluida para ingresar al modo PiP. En Android 12 y versiones posteriores, también crea una animación más fluida para salir del modo de PiP. Agrega esta API al compilador de PiP para indicar el área de la actividad que es visible después de la transición a PiP.

  1. Agrega setSourceRectHint() solo a builder si el estado define que la app debe ingresar al modo PiP. Esto evita calcular sourceRect cuando la app no necesita ingresar a PiP.
  2. Para establecer el valor sourceRect, usa el layoutCoordinates que se proporciona desde la función onGloballyPositioned en el modificador.
  3. Llama a setSourceRectHint() en el builder y pasa la variable sourceRect.

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
    }

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

VideoPlayer(pipModifier)