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

Kotlin中MediaPlayer无法循环播放Raw目录MP3资源求助

MediaPlayer音频无法循环播放问题解决

问题核心分析

你的代码存在两个关键问题,导致音频无法循环、监听器不触发:

  1. 监听器绑定时机错误:初始化时mediaPlayer为null,使用?.安全调用的监听器设置代码会被直接跳过。后续创建MediaPlayer实例后,未为其绑定监听器,所以播放完成或出错时不会触发回调。
  2. 局部变量生命周期问题:mediaPlayer是onCreate内的局部变量,onCreate执行完成后可能被垃圾回收,导致播放中断或状态异常。

修正后的代码

class MainActivity : AppCompatActivity() {

    private var mediaPlayer: MediaPlayer? = null // 提升为成员变量,避免过早被GC回收

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化视图组件
        val textView = findViewById<TextView>(R.id.txtSceneDescription).apply {
            movementMethod = ScrollingMovementMethod()
            text = "Run 29"
        }
        val txtPlayerCmd = findViewById<TextView>(R.id.textInputEditText)

        // 获取音频资源ID
        val soundId = resources.getIdentifier("ocean_waves", "raw", packageName)

        // 初始化MediaPlayer并配置播放逻辑
        if (mediaPlayer == null) {
            Toast.makeText(this, "Media player is null, creating new instance", Toast.LENGTH_SHORT).show()
            mediaPlayer = MediaPlayer.create(this, soundId).apply {
                isLooping = true // 启用内置循环播放

                // 绑定播放完成监听器
                setOnCompletionListener { player ->
                    Toast.makeText(this@MainActivity, "Playback Completed", Toast.LENGTH_SHORT).show()
                    // 内置循环失效时,手动重置播放
                    if (!player.isLooping) {
                        player.seekTo(0)
                        player.start()
                    }
                }

                // 绑定错误监听器
                setOnErrorListener { _, errorCode, extraInfo ->
                    Toast.makeText(this@MainActivity, "Playback Error: $errorCode, $extraInfo", Toast.LENGTH_SHORT).show()
                    true // 标记错误已处理
                }

                start() // 启动播放
            }
        } else {
            Toast.makeText(this, "Media Player exists, starting playback", Toast.LENGTH_SHORT).show()
            mediaPlayer?.start()
        }
    }

    // Activity销毁时释放MediaPlayer资源,避免内存泄漏
    override fun onDestroy() {
        super.onDestroy()
        mediaPlayer?.apply {
            stop()
            release()
        }
        mediaPlayer = null
    }
}

关键修改说明

  • 成员变量声明:把mediaPlayer从局部变量改为Activity成员变量,避免被提前回收,保证播放状态稳定。
  • 监听器正确绑定:创建MediaPlayer实例后,直接通过apply函数为实例设置监听器,确保回调逻辑绑定到实际播放对象。
  • 资源释放:添加onDestroy方法释放MediaPlayer资源,这是Android媒体播放的标准最佳实践,防止内存泄漏。
  • 双重保障循环:既启用了MediaPlayer内置的isLooping,又在完成监听器中增加手动重启逻辑,避免内置循环失效的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:22:04