向 PiP 添加远程操作
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
如果您想向 PiP 窗口添加控件(播放、暂停等),请为要添加的每个控件创建一个 RemoteAction
。
- 为广播控件添加常量:
// Constant for broadcast receiver
const val ACTION_BROADCAST_CONTROL = "broadcast_control"
// Intent extras for broadcast controls from Picture-in-Picture mode.
const val EXTRA_CONTROL_TYPE = "control_type"
const val EXTRA_CONTROL_PLAY = 1
const val EXTRA_CONTROL_PAUSE = 2
- 为 PiP 窗口中的控件创建
RemoteActions
列表。
- 接下来,添加一个
BroadcastReceiver
并替换 onReceive()
,以设置每个按钮的操作。使用 DisposableEffect
注册接收器和远程操作。在播放器被处置时,取消注册接收器。
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun PlayerBroadcastReceiver(player: Player?) {
val isInPipMode = rememberIsInPipMode()
if (!isInPipMode || player == null) {
// Broadcast receiver is only used if app is in PiP mode and player is non null
return
}
val context = LocalContext.current
DisposableEffect(player) {
val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if ((intent == null) || (intent.action != ACTION_BROADCAST_CONTROL)) {
return
}
when (intent.getIntExtra(EXTRA_CONTROL_TYPE, 0)) {
EXTRA_CONTROL_PAUSE -> player.pause()
EXTRA_CONTROL_PLAY -> player.play()
}
}
}
ContextCompat.registerReceiver(
context,
broadcastReceiver,
IntentFilter(ACTION_BROADCAST_CONTROL),
ContextCompat.RECEIVER_NOT_EXPORTED
)
onDispose {
context.unregisterReceiver(broadcastReceiver)
}
}
}
- 将远程操作列表传入
PictureInPictureParams.Builder
:
val context = LocalContext.current
val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
val builder = PictureInPictureParams.Builder()
builder.setActions(
listOfRemoteActions()
)
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(modifier = pipModifier)
后续步骤
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-08-24。
[null,null,["最后更新时间 (UTC):2025-08-24。"],[],[],null,["# Add remote actions to PiP\n\nIf you want to add controls (play, pause, etc.) to your PiP window, create a\n[`RemoteAction`](/reference/android/app/RemoteAction) for each control you want to add.\n| **Note:** If you are using a [`MediaSession`](/guide/topics/media/media3), there will be default actions added to the window that you don't need to implement yourself.\n\n1. Add constants for your broadcast controls: \n\n ```kotlin\n // Constant for broadcast receiver\n const val ACTION_BROADCAST_CONTROL = \"broadcast_control\"\n\n // Intent extras for broadcast controls from Picture-in-Picture mode.\n const val EXTRA_CONTROL_TYPE = \"control_type\"\n const val EXTRA_CONTROL_PLAY = 1\n const val EXTRA_CONTROL_PAUSE = 2https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L58-L64\n ```\n2. Create a list of [`RemoteActions`](/reference/android/app/RemoteAction) for the controls in your PiP window.\n3. Next, add a [`BroadcastReceiver`](/reference/android/content/BroadcastReceiver) and override `onReceive()` to set the actions of each button. Use a [`DisposableEffect`](/develop/ui/compose/side-effects#disposableeffect) to register the receiver and the remote actions. When the player is disposed, unregister the receiver. \n\n ```kotlin\n @RequiresApi(Build.VERSION_CODES.O)\n @Composable\n fun PlayerBroadcastReceiver(player: Player?) {\n val isInPipMode = rememberIsInPipMode()\n if (!isInPipMode || player == null) {\n // Broadcast receiver is only used if app is in PiP mode and player is non null\n return\n }\n val context = LocalContext.current\n\n DisposableEffect(player) {\n val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {\n override fun onReceive(context: Context?, intent: Intent?) {\n if ((intent == null) || (intent.action != ACTION_BROADCAST_CONTROL)) {\n return\n }\n\n when (intent.getIntExtra(EXTRA_CONTROL_TYPE, 0)) {\n EXTRA_CONTROL_PAUSE -\u003e player.pause()\n EXTRA_CONTROL_PLAY -\u003e player.play()\n }\n }\n }\n ContextCompat.registerReceiver(\n context,\n broadcastReceiver,\n IntentFilter(ACTION_BROADCAST_CONTROL),\n ContextCompat.RECEIVER_NOT_EXPORTED\n )\n onDispose {\n context.unregisterReceiver(broadcastReceiver)\n }\n }\n }https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L274-L307\n ```\n4. Pass in a list of your remote actions to the [`PictureInPictureParams.Builder`](/reference/android/app/PictureInPictureParams.Builder): \n\n ```kotlin\n val context = LocalContext.current\n\n val pipModifier = modifier.onGloballyPositioned { layoutCoordinates -\u003e\n val builder = PictureInPictureParams.Builder()\n builder.setActions(\n listOfRemoteActions()\n )\n\n if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) {\n val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()\n builder.setSourceRectHint(sourceRect)\n builder.setAspectRatio(\n Rational(player.videoSize.width, player.videoSize.height)\n )\n }\n\n if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.S) {\n builder.setAutoEnterEnabled(shouldEnterPipMode)\n }\n context.findActivity().setPictureInPictureParams(builder.build())\n }\n VideoPlayer(modifier = pipModifier)https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/pictureinpicture/PictureInPictureSnippets.kt#L323-L344\n ```\n\nNext steps\n----------\n\n- See the [Socialite](https://github.com/android/socialite) app to see the best practices of Compose PiP in action.\n- See the [PiP design guidance](/design/ui/mobile/guides/home-screen/picture-in-picture) for more information."]]