如何检测Media3媒体项切换来自下一曲还是上一曲的Seek操作?
如何区分Media3中seekToNext/seekToPrevious触发的媒体项切换方向
你可以通过以下几种方式判断媒体项切换是来自下一曲还是上一曲的操作:
1. 对比切换前后的媒体项索引
在MediaSession.Callback中维护当前播放的媒体项索引,通过索引变化判断方向:
- 首先在服务端定义变量记录当前索引:
private var currentMediaIndex = 0 - 当
onMediaItemTransition触发时,获取新媒体项在播放列表中的索引并对比:override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { super.onMediaItemTransition(mediaItem, reason) mediaItem ?: return val playlist = player.currentMediaItems ?: return val newIndex = playlist.indexOf(mediaItem) if (newIndex != -1) { val isNext = when { // 处理循环场景:最后一曲切下一曲回到第一首 currentMediaIndex == playlist.size - 1 && newIndex == 0 -> true // 正常下一曲 newIndex > currentMediaIndex -> true // 处理循环场景:第一首切上一曲回到最后一首 currentMediaIndex == 0 && newIndex == playlist.size - 1 -> false // 正常上一曲 else -> newIndex < currentMediaIndex } // 根据isNext值执行对应逻辑 currentMediaIndex = newIndex } } - 注意:如果播放列表有动态修改,要同步更新
currentMediaIndex以保证准确性。
2. 使用自定义命令替代原生seek方法
不直接调用controller.seekToNext()/controller.seekToPrevious(),而是发送自定义命令,在服务端处理时记录切换方向:
- UI端发送自定义命令:
// 下一曲按钮点击事件 nextBtn.setOnClickListener { controller.sendCustomCommand("CUSTOM_NEXT", Bundle.EMPTY) } // 上一曲按钮点击事件 prevBtn.setOnClickListener { controller.sendCustomCommand("CUSTOM_PREV", Bundle.EMPTY) } - 服务端
MediaSession.Callback中处理自定义命令并标记方向:private var lastTransitionDirection: String? = null override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, command: String, extras: Bundle? ): ListenableFuture<Bundle> { when (command) { "CUSTOM_NEXT" -> { lastTransitionDirection = "NEXT" player.seekToNext() } "CUSTOM_PREV" -> { lastTransitionDirection = "PREV" player.seekToPrevious() } } return Futures.immediateFuture(Bundle.EMPTY) } override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { super.onMediaItemTransition(mediaItem, reason) if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_SEEK) { // 通过lastTransitionDirection判断切换方向 when(lastTransitionDirection) { "NEXT" -> { /* 处理下一曲逻辑 */ } "PREV" -> { /* 处理上一曲逻辑 */ } } // 重置标记,避免后续误判 lastTransitionDirection = null } }
3. 监听Player的PositionDiscontinuity事件
通过Player的addListener监听位置中断事件,利用PositionDiscontinuityReason区分方向:
player.addListener(object : Player.Listener { override fun onPositionDiscontinuity( oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, reason: Int ) { super.onPositionDiscontinuity(oldPosition, newPosition, reason) if (reason == Player.POSITION_DISCONTINUITY_REASON_SEEK_FORWARD) { // 下一曲触发的跳转 } else if (reason == Player.POSITION_DISCONTINUITY_REASON_SEEK_BACKWARD) { // 上一曲触发的跳转 } } })
注意:该方法需要确认你的Media3版本支持对应枚举值,部分场景下建议结合索引判断保证准确性。
内容的提问来源于stack exchange,提问作者Debayan Ghosh Dastider
相关产品推荐
相关产品推荐

