在 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 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-08-24 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間: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."]]