Entrar no PiP nos horários corretos

O app não deve entrar no modo picture-in-picture nas seguintes situações:

  • Se o vídeo estiver parado ou pausado.
  • Se você estiver em uma página do app diferente do player de vídeo.

Para controlar quando o app entra no modo picture-in-picture, adicione uma variável que rastreia o estado do player de vídeo usando um mutableStateOf.

Alternar o estado com base na reprodução do vídeo

Para alternar o estado com base na reprodução do player de vídeo, adicione um listener ao player. Alterne o estado da variável de estado com base na reprodução do player:

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

Alternar o estado com base na liberação do player

Quando o player for liberado, defina a variável de estado como false:

fun releasePlayer() {
    shouldEnterPipMode = false
}

Usar o estado para definir se o modo picture-in-picture será ativado (antes do Android 12)

  1. Como a adição do picture-in-picture antes do Android 12 usa um DisposableEffect, é necessário criar uma nova variável por rememberUpdatedState com newValue definido como a sua variável de estado. Isso garante que a versão atualizada seja usada no DisposableEffect.
  2. Na lambda que define o comportamento quando o OnUserLeaveHintListener é acionado, adicione uma instrução if com a variável de estado em torno da chamada para 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 = Runnable {
                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")
    }

Usar o estado para definir se o modo picture-in-picture será ativado (depois do Android 12)

Transmita a variável de estado para setAutoEnterEnabled para que o app só entre no modo picture-in-picture no momento certo:

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)

Usar setSourceRectHint para uma animação suave

A API setSourceRectHint cria uma animação mais suave para entrar no modo picture-in-picture. No Android 12 e versões mais recentes, ela também cria uma animação mais suave para sair do modo picture-in-picture. Adicione essa API ao builder do picture-in-picture para indicar a área da atividade que fica visível após a transição para o modo picture-in-picture.

  1. Só adicione setSourceRectHint() ao builder se o estado definir que o app precisa entrar no modo picture-in-picture. Isso evita o cálculo de sourceRect quando o app não precisa entrar no modo picture-in-picture.
  2. Para definir o valor sourceRect, use as layoutCoordinates fornecidas pela função onGloballyPositioned no modificador.
  3. Chame setSourceRectHint() no builder e transmita a variável 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)