1,背景
在推送到达时,会播放一些简单声音,这个声音比较短,大概十几个字,遇到了一个问题,就是同时收到多个推送,同时播放同一个声音,会出现部分声音播放不完全,只播放一半的问题
2,调研
我们播放音乐的方法
MediaPlayer mediaPlayer = MediaPlayer.create(context,R.raw.test_mp3);
mediaPlayer.setVolume(1F, 1F);
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(mp -> mediaPlayer.release());
通过这种方式播放,一次播放没有问题,但是多次调用,就会出现本地音乐只播放一半的问题, 查询问题出现的原因,发现是因为MediaPlayer播放短音乐的时候,会偶尔出现Mediaplayer被GC回收的情况,这个查了很多的博客文档,没找到解决的方案
同时查询文档,发现播放这种短音乐,铃声等比较适合的是SoundPool,接下来,尝试使用SoundPool播放本地短音乐
public void play(){
SoundPool soundPool;
if (Build.VERSION.SDK_INT >= 21) {
SoundPool.Builder builder = new SoundPool.Builder();
builder.setMaxStreams(1);
AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
builder.setAudioAttributes(attrBuilder.build());
soundPool = builder.build();
} else {
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
}
final int voiceId = soundPool.load(context, R.raw.sound, 1);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
soundPool.play(voiceId, 1, 1, 1, 0, 1);
}
}
});
}
直接调用Play方法,发现还是会出现多次播放播放一半的问题,想一下,MediaPlayer是因为多次播放,都在创建MediaPlayer,导致被GC回收,那么SoundPool应该也是这个问题,修改成单例方式,果然可以
3,最终方案
/**
* 播放音乐控制类
* 支持播放较短的音乐
*/
public class VoicePlayManager {
private static volatile VoicePlayManager mInstance = null;
private Context mContext;
private VoicePlayManager(Context context) {
this.mContext = context;
}
public static VoicePlayManager getInstance(Context context) {
if (mInstance == null) {
synchronized (PushManager.class) {
if (mInstance == null) {
mInstance = new VoicePlayManager(context);
}
}
}
return mInstance;
}
private SoundPool soundPool = null;
public void createSoundPool() {
if (soundPool == null) {
//实例化SoundPool
//sdk版本21是SoundPool 的一个分水岭
if (Build.VERSION.SDK_INT >= 21) {
SoundPool.Builder builder = new SoundPool.Builder();
builder.setMaxStreams(1);
AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
//加载一个AudioAttributes
builder.setAudioAttributes(attrBuilder.build());
soundPool = builder.build();
} else {
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
}
}
}
public void playSoundPool(int resId) {
createSoundPool();
final int voiceId = soundPool.load(mContext, resId, 1);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
soundPool.play(voiceId, 1, 1, 1, 0, 1);
}
}
});
}
}
最终调用
VoicePlayManager.getInstance(context).playSoundPool(R.raw.test_mp3);
多次调用,问题没有在出现,解决了问题