You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ExoPlayer进入STATE_ENDED状态后如何执行播放控制命令?

解决ExoPlayer STATE_ENDED状态下无法执行播放命令的问题

首先,你当前的实现存在几个核心逻辑问题,导致命令无法生效:

  1. seekToPreviousMediaItem()在播放列表仅含单个媒体项时无作用,因为不存在"上一个"项
  2. STATE_ENDED状态下无需调用prepare(),ExoPlayer播放结束后仍处于已就绪状态,重复调用反而会干扰状态流转
  3. 依赖"上一个项"的逻辑不符合你的需求场景(你需要重播当前项)

正确的概念验证实现

替换onPlaybackStateChanged中的逻辑,直接定位到当前媒体项的起始位置并启动播放:

private val listener = object : Player.Listener {
    override fun onPlaybackStateChanged(playbackState: Int) {
        super.onPlaybackStateChanged(playbackState)
        if (playbackState == Player.STATE_ENDED) {
            val player = playerHolder.getPlayer()
            // 定位到当前媒体项的0毫秒位置
            player.seekTo(player.currentMediaItemIndex, 0)
            // 直接启动播放,无需额外prepare
            player.play()
        }
    }
}

扩展到你的最终需求(追加歌曲到播放列表并播放)

如果要实现将当前歌曲追加到播放列表末尾并从新追加的歌曲开始播放,可以这样修改:

private val listener = object : Player.Listener {
    override fun onPlaybackStateChanged(playbackState: Int) {
        super.onPlaybackStateChanged(playbackState)
        if (playbackState == Player.STATE_ENDED) {
            val player = playerHolder.getPlayer()
            val currentItem = player.currentMediaItem ?: return
            
            // 把当前媒体项追加到播放列表末尾
            player.addMediaItem(currentItem)
            // 定位到刚追加的新项(列表最后一位)
            player.seekTo(player.mediaItemCount - 1, 0)
            player.play()
        }
    }
}

额外验证要点

  • 确保playerHolder.getPlayer()始终返回同一个ExoPlayer实例
  • 检查播放器repeatMode是否设置为Player.REPEAT_MODE_OFF,避免和内置循环功能冲突
  • 可在调用play()前打印播放器状态,确认处于Player.STATE_READY或Player.STATE_ENDED状态

内容的提问来源于stack exchange,提问作者John Glen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:27:08