前言:
之前公司项目里要求加入一个音乐播放的功能,大体功能是获取音乐列表在线播放音乐,在手机锁屏时有锁屏音乐界面,由于之前没有写过此类功能,因此踩了许多坑,今天我记录下来,供小伙伴们参考。
安卓自带的MediaPlayer就支持在线音乐播放功能,所以我就没有引用其他框架,全凭自己摸索实现
1.MediaPlayer初始化
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
});
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
}
});
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
});
setOnCompletionListener:音乐播放完毕触发回调
setOnPreparedListener:音频资源加载成功触发回调
setOnErrorListener:因网络或者音频资源问题导致的错误回调
2.音频播放
//设置音频文件到MediaPlayer对象中
mMediaPlayer.setDataSource(audio.audio_url);
//让MediaPlayer对象准备,用这个方法防止加载时耗时导致anr
mMediaPlayer.prepareAsync();
MediaPlayer有两个方法mMediaPlayer.prepare()和mMediaPlayer.prepareAsync(),因为音频资源是在线加载因此需要异步操作避免anr。
3.指定播放位置
public void seekToPosition(int position) {
try {
if(isPrepared) {
mMediaPlayer.seekTo(position);
}
} catch (Exception e) {
}
}
在执行seekTo的前提下要保证MediaPlayer已经加载资源完毕,因此用到了setOnPreparedListener来监听是否加载完毕,不然在资源没有加载完毕前使用seekTo会出现不可描述的问题(当时测试提bug了,貌似会报错)。
4.切换歌曲
mMediaPlayer.stop();
mMediaPlayer.reset();
切换歌曲reset()很重要,否则会抛异常IllegalStateException,reset之后再加载新的音频资源
5.焦点问题
试想一下假如本APP在播放音乐,然后你打开了其他应用也播放音乐,那么焦点就会失去,此时就应该暂停音乐。
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
//获取到音频焦点
case AudioManager.AUDIOFOCUS_GAIN:
break;
//可能在很长时间里失去音频焦点
case AudioManager.AUDIOFOCUS_LOSS:
if(isPrepared) {
mBinder.pauseMusic();
}
break;
// 音频焦点瞬时失去
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if(isPrepared) {
mBinder.pauseMusic();
}
break;
//音频焦点瞬时失去带闪避
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
break;
}
}
因涉及代码安全就不贴出全部代码了,只要主要这几点功能基本就能实现。