PIP 用にアプリを設定する

AndroidManifest.xml ファイルのアクティビティ タグで、次の操作を行います。

  1. supportsPictureInPicture を追加して true に設定し、アプリでピクチャー イン ピクチャー(PiP)を使用することを宣言します。
  2. configChanges を追加して orientation|screenLayout|screenSize|smallestScreenSize に設定し、アクティビティがレイアウト構成の変更を処理することを指定します。これにより、PIP モードへの遷移中にレイアウト変更が発生した場合でもアクティビティが再起動されなくなります。
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

Compose コードで、次の操作を行います。

  1. この拡張機能を Context に追加します。このガイドでは、この拡張機能をアクティビティにアクセスするために何度も使用します。
    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")
    }

Android 12 より前の休暇アプリに PIP を追加

Android 12 より前のバージョンで PIP を追加するには、addOnUserLeaveHintProvider を使用します。Android 12 より前のバージョンで PiP を追加する手順は次のとおりです。

  1. このコードが O から R までのバージョンでのみアクセスされるように、バージョンゲートを追加します。
  2. キーとして Context を使用して DisposableEffect を使用します。
  3. DisposableEffect 内で、ラムダを使用して onUserLeaveHintProvider がトリガーされたときの動作を定義します。ラムダで、findActivity() に対して enterPictureInPictureMode() を呼び出し、PictureInPictureParams.Builder().build() を渡します。
  4. findActivity() を使用して addOnUserLeaveHintListener を追加し、ラムダを渡します。
  5. onDispose で、findActivity() を使用して removeOnUserLeaveHintListener を追加し、ラムダを渡します。

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

Android 12 以降の休暇アプリに PiP を追加

Android 12 以降では、PictureInPictureParams.Builder は、アプリの動画プレーヤーに渡される修飾子を通じて追加されます。

  1. modifier を作成し、その onGloballyPositioned を呼び出します。レイアウト座標は後の手順で使用します。
  2. PictureInPictureParams.Builder() の変数を作成します。
  3. SDK が S 以降かどうかを確認する if ステートメントを追加します。その場合は、setAutoEnterEnabled をビルダーに追加し、true に設定して、スワイプ時に PiP モードに移行します。これにより、enterPictureInPictureMode を経由するよりもスムーズなアニメーションが実現します。
  4. findActivity() を使用して setPictureInPictureParams() を呼び出します。builderbuild() を呼び出し、渡します。

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)

setAspectRatio を使用して PIP ウィンドウのアスペクト比を設定する

PiP ウィンドウのアスペクト比を設定するには、特定のアスペクト比を選択するか、プレーヤーの動画サイズの幅と高さを使用します。Media3 プレーヤーを使用している場合は、アスペクト比を設定する前に、プレーヤーが null ではなく、プレーヤーの動画サイズが VideoSize.UNKNOWN と等しくないことを確認します。

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)

カスタム プレーヤーを使用している場合は、プレーヤー固有の構文を使用して、プレーヤーの高さと幅のアスペクト比を設定します。初期化中にプレーヤーのサイズが変更され、アスペクト比の有効な範囲外になった場合、アプリがクラッシュすることに注意してください。media3 プレーヤーの場合と同様に、アスペクト比を計算できるタイミングに関するチェックを追加する必要がある場合があります。