Entrar no PiP nos horários corretos

O app não pode entrar no modo PiP nas seguintes situações:

  • Se o vídeo for interrompido ou pausado.
  • Se você estiver em uma página diferente do app 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 no vídeo em reprodução

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

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

Alternar o estado com base no lançamento do jogador

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

fun releasePlayer() {
    shouldEnterPipMode = false
}

Use o estado para definir se o modo PiP foi inserido (antes do Android 12)

  1. Como a adição do PiP pré-12 usa um DisposableEffect, é necessário criar uma nova variável com rememberUpdatedState com newValue definido como 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: () -> 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")
    }

Use o estado para definir se o modo picture-in-picture foi aberto (após o Android 12)

Transmita a variável de estado para setAutoEnterEnabled para que o app entre no modo PiP 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)

Use setSourceRectHint para implementar 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, ele também cria uma animação mais suave para sair do modo picture-in-picture. Adicione essa API ao criador de PiP para indicar a área da atividade que fica visível após a transição para o PiP.

  1. Adicione setSourceRectHint() ao builder somente se o estado definir que o app precisa entrar no modo PiP. Isso evita o cálculo de sourceRect quando o app não precisa entrar no PiP.
  2. Para definir o valor sourceRect, use os layoutCoordinates fornecidos 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)