解决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加载一个音频文件至内存中并返回这个音频在SoundPool内的ID
  • 通过SoundPool.play()传入音频的ID进行播放;

如上就是使用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();
            }
        }
    }
}

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

Code-Porter CSDN认证博客专家 代码界的扛把子
我从事多年Android软件开发及物联网方面开发,熟悉Java,Android,前端、数据库开发;对技术要求苛刻、热爱分享、热爱新技术
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页
实付 5.20元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值