Android MediaPlayer播放结束后暂停图标无法切回播放图标问题
实现方案
核心逻辑是给MediaPlayer绑定播放完成回调,音频播放结束后会自动触发这个回调,在回调内把图标切回播放样式即可,顺便修复你原有代码里的几个隐患问题。
具体修改点
- 新增
setOnCompletionListener监听,播放完成触发时将图标切回播放样式,同时释放MediaPlayer资源避免内存泄漏 - 把MediaPlayer改为页面成员变量,不要每次点击都新建局部实例,避免重复点击时多个音频重叠播放、内存泄漏
- 把同步的
prepare()替换为prepareAsync(),网络音频加载用同步方法会阻塞主线程导致ANR,你之前写的setOnPreparedListener本身就是配合异步准备使用的,之前搭配同步prepare属于错误写法 - 补充异常、页面销毁场景的资源释放和图标重置逻辑,避免异常情况下图标一直停留在暂停状态
修改后的完整代码
// 提为成员变量,不要放在点击方法里当局部变量 private MediaPlayer mediaPlayer; // 如果你已经在别的地方初始化过playiIcon就不用重复声明 private ImageView playiIcon; public void song444 (View v) { // 重复点击时先释放之前的播放实例,避免音频重叠 if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; playiIcon.setImageResource(R.drawable.ic_play); } mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource("https://test.test.mp3"); // 音频准备完成后自动播放,切换暂停图标 mediaPlayer.setOnPreparedListener(mp -> { mp.start(); playiIcon.setImageResource(R.drawable.ic_pause); }); // 核心:播放完成回调 mediaPlayer.setOnCompletionListener(mp -> { // 切回播放图标 playiIcon.setImageResource(R.drawable.ic_play); // 释放资源 mp.release(); mediaPlayer = null; }); // 异步准备网络音频,避免阻塞主线程 mediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); // 加载出错时重置图标和资源 playiIcon.setImageResource(R.drawable.ic_play); if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } } } // 页面销毁时必须释放MediaPlayer,防止内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } }
注意把代码里的
R.drawable.ic_play替换成你自己项目里的播放图标资源id即可。
内容的提问来源于stack exchange,提问作者Chad Davis
相关产品推荐
相关产品推荐

