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

Android 8.1(API27)音乐播放器报MediaPlayer error: attachnewplayer called in state 64

解决Android MediaPlayer错误:attachnewplayer called in state 64

这个错误我之前帮不少开发者排查过,本质是MediaPlayer状态机违规操作导致的——State 64对应的是MediaPlayer的PREPARED状态(常量值为MediaPlayer.PREPARED),在这个状态下直接执行setDataSource或尝试重新关联播放器,就会触发这个错误,因为MediaPlayer的状态流转是严格受控的,不允许跳过重置步骤直接切换数据源。

结合你使用的Android 8.1(API 27)和提供的代码,给你几个针对性的解决方案:

1. 切换歌曲前正确重置MediaPlayer状态

在调用setDataSource之前,必须先将MediaPlayer重置到Idle状态,再重新初始化数据源并准备播放。修改你的playSong()方法如下:

public void playSong() {
    // 先处理MediaPlayer的状态重置
    if (player != null) {
        // 如果播放器已存在,先重置到Idle状态
        player.reset();
    } else {
        // 如果播放器未初始化,创建新实例并设置必要监听
        player = new MediaPlayer();
        // 设置准备完成监听,准备好后自动播放
        player.setOnPreparedListener(mediaPlayer -> mediaPlayer.start());
        // 设置错误监听,捕获播放过程中的异常
        player.setOnErrorListener((mediaPlayer, what, extra) -> {
            Log.e("MediaPlayerError", "Error code: " + what + ", extra: " + extra);
            return false; // 返回false让系统处理默认错误逻辑
        });
    }

    Song playSong = songs.get(songPosn);
    songTitle = playSong.getTitle();
    long currSong = playSong.getID();
    Uri trackUri = ContentUris.withAppendedId(
            android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 
            currSong
    );
    
    try {
        player.setDataSource(getApplicationContext(), trackUri);
        // 推荐用prepareAsync()避免阻塞主线程(尤其是UI线程)
        player.prepareAsync();
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(getApplicationContext(), "无法加载音频文件", Toast.LENGTH_SHORT).show();
    }
}

2. 同步MediaController的上下首按钮逻辑

确保MediaController的skipToPrevious()和skipToNext()方法调用的是上述修改后的playSong(),而不是直接操作MediaPlayer而不重置状态。比如你的MediaPlayerControl实现类中:

@Override
public void skipToNext() {
    songPosn = (songPosn + 1) % songs.size();
    playSong();
}

@Override
public void skipToPrevious() {
    songPosn = (songPosn - 1 + songs.size()) % songs.size();
    playSong();
}

3. 适配Android 8.1的额外注意事项

  • 后台播放权限:Android 8.0及以上对后台播放有严格限制,建议将音乐播放逻辑放在**前台服务(Foreground Service)**中,避免被系统回收,同时保证MediaController能正常交互。
  • 存储权限:确保你已经申请了READ_EXTERNAL_STORAGE权限(API 27可直接在Manifest中声明),否则无法获取媒体文件的URI。

错误原因再梳理

当你从列表选歌或点击MediaController的上下首时,之前的MediaPlayer可能已经处于PREPARED甚至STARTED状态,此时直接调用setDataSource会违反MediaPlayer的状态机规则——MediaPlayer必须从Idle状态开始,依次经过Initialized→Prepared才能进入播放状态,切换歌曲时必须先通过reset()回到Idle,再重新初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:48:37