一、在我們需要播放一些短促的音樂或者音效的時候(播放mp3文件),通常會使用SoundPool
Api來播放因爲可以對音頻文件進行預加載至內存中從而能夠迅速播放出來
二、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();
}
}
}
}
每次開始播放音頻後將線程休眠音頻的時長,然後在繼續播放下一個音頻就可以了