一、前言
Android是多任务系统,Audio系统是竞争资源。在Android系统中允许多个应用同时播放音频,例如,我们在播放音乐的时候,点开了一个视频,如果音乐和视频声音混合在一起,这样就会让人不爽;如果,我们在听音乐的时候,收到信息,我们又希望能听到信息的提示音,可以让音乐的声音先降低,在结束音结束后再恢复音量。为了管理音频焦点,Android引入音频焦点(audio focus)这一特性。
这种机制是需要各个程序合作完成的,需要所有使用Audio资源的程序都按照这种机制来做,而如果有程序在它失去Audio Focus的时候仍然在使用Audio,Audio Focus拿它也没办法。而这一点对于开放系统的Android来说很致命的:用户可能安装没遵守这种机制的程序,或者版本太老还没引入这种机制的程序,这最终会导致很差的用户体验。
二、设计原则
如果,我们的APP没有遵循Audio Focus的机制来管理Audio资源的竞争,就会出现上述的音乐和视频声音混合在一起的情况,用户体验极差。那么对于音频焦点的处理流程,大致可以归纳为一下几点:
- 在使用音频前(例如播放音乐),需要先获取焦点,如果成功获取到焦点,才应该正式开始工作。
- 当其他app请求了焦点,而此时我们的app失去焦点,我们需要做相应的处理。例如,如果是短暂型失去焦点,我们可以暂停工作,如果是永久性失去焦点,我们就停止工作。
- 当完成工作后,我们需要手动释放音频焦点。
三、Audio Focus的申请与释放
3.1 Android 8.0(API 级别 26) 之前
3.1.1 Audio Focus的申请
获取Audio Focus用requestAudioFocus()方法,我们看一下的方法参数
public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
第一个参数:OnAudioFocusChangeListener
申请成功之后监听Audio Focus使用情况的Listener,后续如果有别的程序要竞争Audio Focus,都是通过这个Listener的onAudioFocusChange()方法来通知这个Audio Focus的使用者的。
AudioManager.OnAudioFocusChangeListener afChangeListener =
new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
//长时间丢失焦点,当其他应用申请的焦点为AUDIOFOCUS_GAIN时,会触发此回调事件
//例如播放QQ音乐,网易云音乐等
//此时应当暂停音频并释放音频相关的资源。
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
//短暂性丢失焦点,当其他应用申请AUDIOFOCUS_GAIN_TRANSIENT或AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE时,会触发此回调事件
//例如播放短视频,拨打电话等。
//通常需要暂停音乐播放
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
//短暂性丢失焦点并作降音处理,当其他应用申请AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK时,会触发此回调事件
//通常需要降低音量
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
}
//当其他应用申请焦点之后又释放焦点会触发此回调
//可重新播放音乐
}
};
第二个参数:streamType
这个参数和And