Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Nếu bạn muốn thêm các nút điều khiển (phát, tạm dừng, v.v.) vào cửa sổ PiP, hãy tạo một RemoteAction cho mỗi nút điều khiển mà bạn muốn thêm.
Thêm hằng số cho các chế độ điều khiển thông báo truyền tin:
// Constant for broadcast receiverconstvalACTION_BROADCAST_CONTROL="broadcast_control"// Intent extras for broadcast controls from Picture-in-Picture mode.constvalEXTRA_CONTROL_TYPE="control_type"constvalEXTRA_CONTROL_PLAY=1constvalEXTRA_CONTROL_PAUSE=2
Tạo danh sách RemoteActions cho các nút điều khiển trong cửa sổ PiP.
Tiếp theo, hãy thêm BroadcastReceiver và ghi đè onReceive() để đặt các thao tác của từng nút. Sử dụng DisposableEffect để đăng ký trình thu và các thao tác từ xa. Khi trình phát bị loại bỏ, hãy huỷ đăng ký trình thu.
@RequiresApi(Build.VERSION_CODES.O)@ComposablefunPlayerBroadcastReceiver(player:Player?){valisInPipMode=rememberIsInPipMode()if(!isInPipMode||player==null){// Broadcast receiver is only used if app is in PiP mode and player is non nullreturn}valcontext=LocalContext.currentDisposableEffect(player){valbroadcastReceiver:BroadcastReceiver=object:BroadcastReceiver(){overridefunonReceive(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)}}}
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-08-27 UTC.
[null,null,["Cập nhật lần gần đây nhất: 2025-08-27 UTC."],[],[],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."]]