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

Android MediaPlayer调用setDataSource时抛出IllegalStateException问题求助

解决MediaPlayer调用setDataSource时抛出的IllegalStateException异常

嘿,我来帮你搞定这个头疼的问题!你遇到的java.lang.IllegalStateException根源在于MediaPlayer的状态管理错误——当你调用stop()方法后,MediaPlayer会进入Stopped状态,这个状态下直接调用setDataSource()是完全不被允许的,必须先把MediaPlayer重置到Idle状态才行。

问题出在哪?

看你的stopPlay()方法:

private fun stopPlay() {
    mediaPlayer!!.pause()
    mediaPlayer!!.stop()
}

调用stop()之后,MediaPlayer就停留在了Stopped状态,这时候你在playSong()里直接调用setDataSource(),就触发了状态异常,因为Stopped状态下只能调用reset()或者release(),不能直接设置数据源。

修复方案

1. 修正stopPlay()方法,添加重置操作

我们需要在停止播放后,把MediaPlayer重置到Idle状态,这样后续才能重新设置数据源:

private fun stopPlay() {
    // 先判断是否在播放,再暂停
    if (mediaPlayer?.isPlaying == true) {
        mediaPlayer?.pause()
    }
    mediaPlayer?.stop()
    mediaPlayer?.reset() // 关键步骤:重置到Idle状态,允许后续设置数据源
}

2. 优化playSong()方法,简化逻辑并避免重复代码

把重复的监听器设置、状态判断逻辑抽离,同时做好空安全处理:

private fun playSong(songPath: String) {
    if (mediaPlayer == null) {
        mediaPlayer = MediaPlayer().apply {
            setOnPreparedListener(this@YourActivity) // 替换成你的类名
            setOnCompletionListener(this@YourActivity)
        }
    } else {
        // 如果MediaPlayer不在Idle状态,先处理状态
        when {
            mediaPlayer?.isPlaying == true -> stopPlay()
            mediaPlayer?.isPlaying == false -> mediaPlayer?.reset()
        }
    }
    // 此时MediaPlayer处于Idle状态,可以安全设置数据源
    mediaPlayer?.setDataSource(songPath)
    mediaPlayer?.prepareAsync()
}

补充说明

  • MediaPlayer有严格的状态机,每个方法都只能在特定状态下调用,一定要遵循状态流转规则。
  • 尽量用?.替代!!做空安全判断,避免潜在的空指针异常。
  • 当你不再需要MediaPlayer时,记得调用release()释放资源,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Muhammad Sajid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:32:34