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

MediaPlayer延迟重复播放时,切换按钮在等待阶段无法停止音频的问题求助

解决方案

问题根源有两个:一是stop()方法里只判断mediaPlayer.isPlaying(),但音频播放完进入5秒延迟阶段时,mediaPlayer已经处于停止状态,导致停止逻辑不执行;二是后台的延迟重启任务还在等待,到点会自动重新启动音频。

要实现“无论音频是否在延迟阶段,点击按钮都能彻底停止”的需求,你需要:

  • 保存延迟任务的引用,方便随时取消它
  • 修改stop()方法,移除播放状态判断,直接执行停止清理逻辑,同时取消延迟任务
  • 每次启动音频前,确保之前的延迟任务已经被取消

修改后的完整代码

public static MediaPlayer mediaPlayer = new MediaPlayer();
public View mView;
private Context mContext;
public boolean status;
// 新增:保存延迟任务的引用,用于后续取消
private Handler delayHandler;
private Runnable restartRunnable;

public boolean getStatus() {
    return status;
}
public void setStatus(boolean status) {
    this.status = status;
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void toggle(View view, Context context) {
    this.mView = view;
    this.mContext = context;

    // 用status判断状态比直接判断mediaPlayer更可靠
    if (getStatus()) {
        this.stop();
    } else {
        this.start();
    }
}

/**
 * 启动扫描音频
 */
@SuppressLint("UseCompatLoadingForColorStateLists")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void start() {
    // 先取消之前的延迟任务(如果存在)
    if (delayHandler != null && restartRunnable != null) {
        delayHandler.removeCallbacks(restartRunnable);
    }

    // 释放旧的mediaPlayer实例,避免内存泄漏
    if (mediaPlayer != null) {
        mediaPlayer.release();
    }
    
    mediaPlayer = MediaPlayer.create(mContext, scanner);
    mediaPlayer.setOnPreparedListener(mediaPlayerListener -> mediaPlayer.start());
    
    // 创建新的延迟重启任务
    delayHandler = new Handler(Looper.getMainLooper());
    restartRunnable = () -> mediaPlayer.start();
    mediaPlayer.setOnCompletionListener(listener -> delayHandler.postDelayed(restartRunnable, 5000));
    
    setStatus(true);
    // 可选:添加开启提示
    // Snackbar.make(mView, "Scanner is ON", Snackbar.LENGTH_SHORT).show();
}

/**
 * 停止扫描音频
 */
@SuppressLint("UseCompatLoadingForColorStateLists")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void stop() {
    // 取消延迟重启任务
    if (delayHandler != null && restartRunnable != null) {
        delayHandler.removeCallbacks(restartRunnable);
        delayHandler = null;
        restartRunnable = null;
    }

    // 彻底清理mediaPlayer资源,不管当前是否在播放
    try {
        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.release();
            mediaPlayer = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    mView.setBackgroundTintList(null);
    Snackbar.make(mView, "Scanner is OFF", Snackbar.LENGTH_LONG).setAction("Action", null).show();
    setStatus(false);
}

辅助方法保持不变

public static void setTimeout(Runnable runnable, int delay) {
    new Handler(Looper.getMainLooper()).postDelayed(runnable, delay);
}

这样修改后,无论音频处于播放中还是5秒延迟等待阶段,点击按钮都能彻底停止音频,不会再出现自动重启的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:09:47