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: () -> Unit = {
            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 ステートメントを追加します。スワイプ操作で PiP モードに入るようにするには、ビルダーに setAutoEnterEnabled を追加して true に設定します。これにより、enterPictureInPictureMode を経由するよりもアニメーションがスムーズになります。
  4. findActivity() を使用して setPictureInPictureParams() を呼び出します。builder に対して build() を呼び出して渡します。

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][6] と等しくないことを確認します。

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 プレーヤーの場合と同様に、アスペクト比を計算できるタイミングのチェックを追加する必要があります。