一、AudioFocus常见的焦点请求
AUDIOFOCUS_GAIN:用于指示音频焦点的增益或未知持续时间的音频焦点请求。当其他应用申请焦点之后又释放焦点会触发此回调。
AUDIOFOCUS_GAIN_TRANSIENT:用于指示临时增益或音频焦点请求,预计持续时间短,比如notification sounds
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:用于指示音频焦点的临时请求,预计持续时间较短时间量,以及其他音频应用程序可以继续播放的位置降低产出水平后(也称为“回避”)。
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:用于指示音频焦点的临时请求,预计持续时间较短,没有其他应用程序或系统组件应该播放的时间量、任何东西。 独占和瞬态音频焦点请求的例子是语音、备忘记录和语音识别,在此期间系统不应该播放任何内容通知,媒体播放应暂停。
AUDIOFOCUS_LOSS:
长时间丢失焦点,当其他应用申请的焦点为AUDIOFOCUS_GAIN时,
会触发此回调事件,例如播放QQ音乐,网易云音乐等
AUDIOFOCUS_LOSS_TRANSIENT:
短暂性丢失焦点,当其他应用申请AUDIOFOCUS_GAIN_TRANSIENT或AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE时,
会触发此回调事件,例如播放短视频,拨打电话等。
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:用于指示音频焦点的失败者可能发生的音频焦点的瞬时丢失,如果它想继续播放(也称为“躲避”),则降低其输出音量,新的焦点所有者不需要其他人保持沉默。
二、例子
packages/apps/Car/LocalMediaPlayer/src/com/android/car/media/localmediaplayer/Player.java
申请音频焦点
private boolean requestAudioFocus(Runnable onSuccess) {
int result = mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
onSuccess.run();
return true;
}
Log.e(TAG, "Failed to acquire audio focus");
return false;
}
监听音频焦点的变化
private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focus) {
switch (focus) {
case AudioManager.AUDIOFOCUS_GAIN:
resumePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
pausePlayback();
break;
default:
Log.e(TAG, "Unhandled audio focus type: " + focus);
}
}
};
释放音频焦点
public void destroy() {
stopPlayback();
mNotificationManager.cancelAll();
mAudioManager.abandonAudioFocus(mAudioFocusListener);
mMediaPlayer.release();
}
三、思路
播放视频时被来电中断或短信提示音中断再回到播放界面,没有声音或没有继续播放
(1)如果打印abandonAudioFocus log,其他模块放弃了audio focus,但是视频APP没有来申请获取audio focus,需要找视频APP的厂商来确认代码逻辑,看有没有调用AudioManager.java的requestAudioFocus()函数来获取。
(2)如果视频APP重新获取audio focus,但是获取不到,需要检查Audio framework的逻辑。常见的是,正在打电话时,其他APP会无法获取到audio focus。
对应代码可以查看AudioService.java的requestAudioFocus()函数,该函数再调用到MediaFocusControl.java的requestAudioFocus()函数。
在MediaFocusControl.java的requestAudioFocus()函数里面添加调试log来确认是在哪个return语句返回。