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

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,提问作者九つ喜助

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:36:04