AudioFocus是Android用来管理对Audio资源的竞争,举个例子:当QQ音乐、网易云音乐、酷我音乐等多个音乐播放器在播放音乐时,只有一个会播放音乐,其它的音乐播放器会自动停止,这就是因为这几家音乐播放器平台都使用了AudioFocus来管理,如果不适用这个机制的话就会出现多家播放器同时播放音乐的现象。
网上讲解AudioFocus的例子很多,但是很多都是使用的废弃的方法,如下所示:
public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
这里就不说这个废弃的方法了,改为介绍现在推荐的的新的获取,如下所示:
public int requestAudioFocus(@NonNull AudioFocusRequest focusRequest)
可以看到旧的获取焦点的方法传入的参数是AudioFocousChangeListener、streamType和durationHint,而新的是传入AudioFocusRequest对象,百度了一下发现没什么人讲解这个AudioFocusRequest对象,所以只好看官方文档了,官方文档链接如下:https://developer.android.google.cn/reference/android/media/AudioFocusRequest
网页上讲解的很详细,这里粗略的翻译一下。
首先,讲了一下什么是AudioFocus:It is used to convey the fact that a user can only focus on a single audio stream at a time(它用来确保同一时间用户只能将焦点放到单一音频流上),这里最需要关注的句子是:Note: applications should not play anything until granted focus(应用在获取焦点前不应该播放任何音频)。当然啦,你不遵从也不影响你的应用使用,只不过会影响体验。
接着,讲了一下Foces的不同的类型
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS:
//长时间丢失焦点,当其他应用申请的焦点为AUDIOFOCUS_GAIN时,
//会触发此回调事件,例如播放QQ音乐,网易云音乐等
//通常需要暂停音乐播放,若没有暂停播放就会出现和其他音乐同时输出声音
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
//短暂性丢失焦点,当其他应用申请AUDIOFOCUS_GAIN_TRANSIENT或AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE时,
//会触发此回调事件,例如播放短视频,拨打电话等。
//通常需要暂停音乐播放
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
//短暂性丢失焦点并作降音处理
break;
case AudioManager.AUDIOFOCUS_GAIN:
//当其他应用申请焦点之后又释放焦点会触发此回调
//可重新播放音乐
break;
}
然后就是如何确定你的AudioFocusRequest,这里其实没什么好说的,直接看官方给出的例子就好了,我这里做了删减,毕竟没有全部用到,如果需要的话请自行研究:
// 初始化音频属性和焦点
mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
mPlaybackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.build();
mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(mPlaybackAttributes)
.build();
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
final Object mFocusLock = new Object();
boolean mPlaybackDelayed = false;
// 请求音频焦点,成功后播放音乐,失败后不播放
int res = mAudioManager.requestAudioFocus(mFocusRequest);
synchronized (mFocusLock) {
if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
mPlaybackDelayed = false;
} else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mPlaybackDelayed = false;
playbackNow();
}
}
// OnAudioFocusChangeListener的实现,也就是监听到的音频焦点变化
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mPlaybackDelayed || mResumeOnFocusGain) {
synchronized (mFocusLock) {
mPlaybackDelayed = false;
mResumeOnFocusGain = false;
}
playbackNow();
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
synchronized (mFocusLock) {
// this is not a transient loss, we shouldn't automatically resume for now
mResumeOnFocusGain = false;
mPlaybackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// we handle all transient losses the same way because we never duck audio books
synchronized (mFocusLock) {
// we should only resume if playback was interrupted
mResumeOnFocusGain = mMediaPlayer.isPlaying();
mPlaybackDelayed = false;
}
pausePlayback();
break;
}
}
暂时就到这里吧,以后使用中有问题再补充到这里