我们手机中安装着各种类型的应用,音乐类、视频类、直播类等,再加上手机本身闹铃、信息通知以及电话等铃声,都需要播放音频。如果多个应用同时播放音频,会发生什么?
为了避免多个应用同时发声,系统引入了音频焦点的概念,以满足最佳音频播放效果。比如听音乐的同时又打开了一个视频,这时候需要音乐暂停来播放视频。
那么,实际使用过程中,国内应用在音频焦点释放申请表现如何?本次评测选取了视频类、音乐里等100款应用,验证他们的表现。
音频焦点简介
什么是音频焦点
音频焦点(AudioFocus),是系统引入的用来解决多应用抢占音频通道的机制,避免多个应用同时播放音、视频,造成混合音。
应用程序在播放音频文件前,应该请求获得音频焦点,并且同时注册**音频焦点,如果音频焦点被系统或其他应用程序抢占时,当前应用可以做出合适的响应,如暂停或音量降低等,以便用户更轻松地听到新的音频源。
音频焦点是合作的,需要所有使用音频资源的程序都按照这种机制来执行,但系统不会强制应用执行,需要应用自觉遵守音频焦点机制,建立良好的生态环境。
不同类型的音频焦点
AUDIOFOCUS_GAIN:用于指示音频焦点的增益或未知持续时间的音频焦点请求;
AUDIOFOCUS_GAIN_TRANSIENT:用于指示临时增益或音频焦点请求,预计持续时间短;
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:用于指示音频焦点的临时请求,预计持续时间较短时间量,以及其他音频应用程序可以继续播放的位置降低产出水平后(也称为“回避”);
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:用于指示音频焦点的临时请求,预计持续时间较短,没有其他应用程序或系统组件应该播放的时间量、任何东西。独占和瞬态音频焦点请求的例子是语音、备忘记录和语音识别,在此期间系统不应该播放任何内容通知,媒体播放应暂停;
AUDIOFOCUS_LOSS:用于指示未知持续时间的音频焦点丢失;
AUDIOFOCUS_LOSS_TRANSIENT:用于指示音频焦点的瞬时丢失;
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:用于指示音频焦点的失败者可能发生的音频焦点的瞬时丢失,如果它想继续播放(也称为“躲避”),则降低其输出音量,新的焦点所有者不需要其他人保持沉默。
100款应用音频焦点评测
应用分析
一、测试环境
硬件环境:Mate 20X 6+128G
软件版本:EMUI9.0.0
二、测试范围
本次测试选取了100款应用,包含视频类、短视频类、直播类、学习类、阅读类、新闻类、音乐类 包含音视频播放的应用。
三、预置条件
后台开启音乐播放器播放音乐,Log查看音乐播放器申请音频焦点。
四、操作步骤
1、打开测试应用,打开应用中任意视频进行播放;
2、通过adb shell logcat 获取测试过程中信息。
五、测试结果
通过测试发现80%的应用表现良好,但20%的应用播放过程中会造成前台应用声音小且多个声音交错混乱。其中直播类应用在音频焦点申请方面表现较差,未申请率达39%,其中也不乏我们常见的直播类应用,需进行适配改进。

图一
选取两个直播应用(腾讯NOW直播、酷狗直播),对比其申请音频焦点和未申请音频焦点的Log信息,发现未申请音频焦点会导致开启多个音频通道,导致音频内容混合,影响用户感受。
通常两个应用的播放流程如图二所示,Your APP在播放前要申请音频焦点,在播放过程中要进行音频焦点的**,当发现Another APP在申请音频焦点时,Your APP会**到该申请动作,此时Your APP应该停止播放,并释放该音频焦点供Another APP使用,保证Another APP正常播放。

图二
可以查看腾讯NOW直播Log信息来看两个应用正常播放时的显示信息,如图三所示:

图三
我们再来看下音频混淆的现象,如图四所示,Another App没有申请音频焦点直接播放造成了音频混淆。

图四
对比查看酷狗直播的Log信息,因为酷狗直播没有进行音频焦点的申请,后台音乐没有释放焦点而导致音频混淆。酷狗直播Log信息,如图五所示:

图五
适配建议
通过使用AudioManager中的方法及时申请音频焦点,注册音频焦点的**,对失去和再次获取音频焦点进行逻辑处理。
申请音频焦点的方法:
private void requestAudioFocus(){
AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
if (am != null) {
//请求焦点的参数说明:
//AUDIOFOCUS_GAIN:想要长期占有焦点,失去焦点者stop播放和释放
//AUDIOFOCUS_GAIN_TRANSIENT:想要短暂占有焦点,失去焦点者pause播放
//AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:想要短暂占有焦点,失去焦点者可以继续播放但是音量需要调低
//AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:想要短暂占有焦点,但希望失去焦点者不要有声音播放
am.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}
释放的方法:
private void abandonAudioFocus(){
AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
if (am != null) {
am.abandonAudioFocus(mAudioFocusListener);
}
监听方法:
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
// Pause playback
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
}
}
};
如果丢失的短暂音频焦点允许DUCK状态,在这种情况下,应用程序降低音量继续播放,不需要暂停。
Duck!
DUCK:降低您应用程序的音量,从而不会打扰其他应用程序音频的播放。
在下面的代码片段中,当我们失去焦点的时候,降低了媒体播放的音量,重新获得焦点的时候,将音量恢复到原来的状态。
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
// Lower the volume
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Raise it back to normal
}
}
};
转自安卓绿色联盟





































苏公安网备 32011402010933号