解决Android SoundPool播放多个音效没有播放完成回调通知

/ Android / 没有评论 / 1773浏览

解决Android SoundPool播放多个音效没有播放完成回调通知

一、在我们需要播放一些短促的音乐或者音效的时候(播放mp3文件),通常会使用SoundPoolApi来播放因为可以对音频文件进行预加载至内存中从而能够迅速播放出来

二、SoundPool的简单使用

SoundPool soundPool = new SoundPool.Builder().build();
int soundId = soundPool.load(App.getApplication(), R.raw.mp3_0, 1);
soundPool.play(soundId, 1, 1, 0, 0, 1);

如上就是使用SoundPool的整个流程

三、当你需要按顺序进行多个音效播放的时候你会发现SoundPool并没有提供播放完成的回调通知那我们怎么才能实现呢?

四、音效初始化的时候通过MediaPlayer获取到音效的时长,然后将soundId和时长存入Map中

protected void init() {
    //保存音效ID和对应的音效时长
    Map<Integer, Integer> soundIdMap = new HashMap<>();
    SoundPool soundPool = new SoundPool.Builder().build();
    Integer[] mp30 = loadRaw(soundPool, App.getApplication(), R.raw.mp3_0);
    Integer[] mp31 = loadRaw(soundPool, App.getApplication(), R.raw.mp3_1);
    Integer[] mp32 = loadRaw(soundPool, App.getApplication(), R.raw.mp3_2);
    soundIdMap.put(mp30[0], mp30[1]);
    soundIdMap.put(mp31[0], mp32[1]);
    soundIdMap.put(mp32[0], mp32[1]);
}
/**
* 加载音频文件
*/
private Integer[] loadRaw(SoundPool soundPool, Context context, int raw) {
    int soundId = soundPool.load(context, raw, 1);
    int duration = getMp3Duration(context, raw);
    return new Integer[]{soundId, duration};
}
/**
* 获取音频文件的时长
*/
private int getMp3Duration(Context context, int rawId) {
    try {
        Uri uri = Uri.parse("android.resource://" + context.getPackageName() + "/" + rawId);
        MediaPlayer mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(context, uri);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.prepare();
        return mediaPlayer.getDuration();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return 0;
}

五、相信大家都听说过睡眠排序算法吧,没看错这里就是通过睡眠法将音频按顺序播放,如下:

/**
 * 音频播放线程
 */
private class PlayThread extends Thread {
    @Override
    public void run() {
        Set<Integer> soundIdSet = soundIdMap.keySet();
        for (Integer soundId : soundIdSet) {
            soundPool.play(soundId, 1, 1, 0, 0, 1);
            try {
                //获取当前音频的时长
                Thread.sleep(soundIdMap.get(soundId));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

每次开始播放音频后将线程休眠音频的时长,然后在继续播放下一个音频就可以了