Android 如何用同一按钮控制MediaPlayer播放停止及解决运行报错
报错原因
你当前代码的核心问题是点击事件中同时执行了start()和stop()两个互斥的MediaPlayer操作,完全不符合状态流转要求。报错信息中的state 64对应Stopped状态,error -38为状态不匹配错误:在停止状态调用播放、在无效状态调用停止都会触发该类报错。
正确实现代码
import android.media.MediaPlayer; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { // 全局声明MediaPlayer和播放状态标记 private MediaPlayer musicMP; private boolean isPlaying = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化MediaPlayer,加载raw目录下的音频 musicMP = MediaPlayer.create(this, R.raw.lofi); Button playMusic = findViewById(R.id.bell_peppers_and_beef); // 音频播放完成回调,重置状态标记 musicMP.setOnCompletionListener(mp -> isPlaying = false); playMusic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (isPlaying) { // 当前正在播放,执行停止逻辑 musicMP.stop(); isPlaying = false; // 停止后需要提前准备,下次点击可直接播放 musicMP.prepareAsync(); } else { // 当前未播放,执行播放逻辑 musicMP.start(); isPlaying = true; } } }); } @Override protected void onDestroy() { super.onDestroy(); // 页面销毁时释放MediaPlayer资源,避免内存泄漏 if (musicMP != null) { if (isPlaying) { musicMP.stop(); } musicMP.release(); musicMP = null; } } }
核心逻辑说明
- 用布尔变量
isPlaying维护当前播放状态,点击时根据状态判断执行播放/停止操作,避免同时调用互斥方法 - 调用
stop()后MediaPlayer会进入Stopped状态,必须调用prepare()或prepareAsync()完成准备才能再次播放,这里用异步准备避免阻塞主线程 - 监听播放完成事件,自动重置状态标记,避免播放结束后点击按钮无响应
- 页面销毁时主动释放MediaPlayer资源,防止后台占用内存
如果你需要的是暂停续播效果而非完全停止(下次播放从头开始),可以把停止逻辑中的
musicMP.stop()替换为musicMP.pause(),不需要额外调用prepareAsync()即可实现从暂停位置继续播放。
必要配置说明
- 确保res目录下新建了
raw子目录,你的lofi音频文件存放在该目录下,文件名只能使用小写字母、数字、下划线,不能包含中文、空格、特殊符号 - 若你后续需要读取外部存储的音频,在Android 13及以上系统需要在
AndroidManifest.xml中添加READ_MEDIA_AUDIO权限,当前使用内置raw目录音频无需额外权限 - 布局文件
activity_main.xml中必须存在id为bell_peppers_and_beef的Button控件
内容的提问来源于stack exchange,提问作者九つ喜助
相关产品推荐
相关产品推荐

