Android Kotlin应用音频文件随机顺序播放问题求助
Android随机音频连续播放问题解决
我用Kotlin开发Android应用,需求是随机播放音频文件,播放完成一个后自动播放下一个。但当前代码会出现多个音频同时播放的问题,没等前一个播完就启动下一个。试过用CountDownTimer实现等待,结果启动后只播一个音频就停了(可能崩溃),原代码如下:
class MainActivity : AppCompatActivity() { fun playSound(running:Int) { var completition=1 while (running==1 && completition==1) { completition=0 var rnds = Random.nextInt(0..1) if (rnds==1 ) { val mMediaPlayer = MediaPlayer.create(this, R.raw.right) mMediaPlayer!!.isLooping = false mMediaPlayer!!.start() mMediaPlayer!!.setOnCompletionListener { completition=1 } } if (rnds==0 ) {val mMediaPlayer = MediaPlayer.create(this, R.raw.left) mMediaPlayer!!.isLooping = false mMediaPlayer!!.start() mMediaPlayer!!.setOnCompletionListener { completition=1 } } } } fun music(){ var i=1 while(i==1) { i=0 val random=(0..1).random() if (random==1){ val refMediaPlayer=MediaPlayer.create(this,R.raw.right) refMediaPlayer!!.isLooping = false refMediaPlayer!!.start() //object :CountDownTimer(1000,100) { //override fun onTick(p0: Long) { // TODO("Not yet implemented") // } //override fun onFinish() { //i=1 //} // }.start(); } if (random==0){ val refMediaPlayer=MediaPlayer.create(this,R.raw.left) refMediaPlayer!!.isLooping = false refMediaPlayer!!.start() // object :CountDownTimer(1000,100) { //override fun onTick(p0: Long) { // TODO("Not yet implemented") // } // override fun onFinish() { // i=1 // } //}.start(); } } } // 4. Destroys the MediaPlayer instance when the app is closed // override fun onStop() { // super.onStop() // if (mMediaPlayer != null) { // mMediaPlayer!!.release() // mMediaPlayer = null // } //} override fun onCreate(savedInstanceState: Bundle?) { val running=1 super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) music() } }
问题分析
- 原代码用主线程的while循环控制播放,会阻塞UI线程,而且MediaPlayer的
OnCompletionListener是异步回调,while循环不会等待回调触发就持续执行,导致多个MediaPlayer实例被同时创建并播放,出现音频重叠问题。 - CountDownTimer的固定时长和音频实际播放时长不匹配,要么音频还没播完timer就触发,要么播完了timer还没到,且未处理MediaPlayer资源释放,容易引发内存泄漏甚至崩溃。
修复方案
利用MediaPlayer的播放完成回调实现连续随机播放,同时严格管理MediaPlayer资源:
class MainActivity : AppCompatActivity() { private var currentMediaPlayer: MediaPlayer? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 启动第一个随机音频 playRandomSound() } private fun playRandomSound() { // 释放上一个MediaPlayer资源,避免内存泄漏 currentMediaPlayer?.release() // 随机选择要播放的音频 val soundRes = if ((0..1).random() == 1) R.raw.right else R.raw.left // 创建并播放新的音频 currentMediaPlayer = MediaPlayer.create(this, soundRes).apply { isLooping = false start() // 播放完成后自动触发下一个随机音频播放 setOnCompletionListener { playRandomSound() } } } // 页面停止时释放MediaPlayer资源,符合Android生命周期规范 override fun onStop() { super.onStop() currentMediaPlayer?.release() currentMediaPlayer = null } }
代码说明
- 用
currentMediaPlayer变量跟踪当前播放的MediaPlayer实例,每次播放新音频前先释放旧实例,避免资源浪费和内存泄漏。 - 完全依赖
OnCompletionListener回调触发下一次播放,确保前一个音频播放完成后才启动下一个,不会出现音频重叠。 - 在
onStop()方法中释放资源,防止应用退到后台后继续占用系统资源,避免被系统回收或引发异常。
内容的提问来源于stack exchange,提问作者Sashkoto
相关产品推荐
相关产品推荐

