仅为学习记录,感谢所有技术分享
Android10.0AudioFocus之如何使用(一)
Android AudioFocus音频焦点机制学习和理解
Android10.0AudioFocus之AudioFocusRequest
音频焦点AudioFocus
目录
1.AudioManager中焦点durationHint定义说明
2.MediaFocusControl.java中的requestAudioFocus方法过程
3.FocusRequester处理FocusRequester对象
4.AudioFocus流程
音频焦点是规则,是个弱管理。也就是说如果你想播放,不管拿不拿得到音频焦点,都是可以播放的。影响的只是体验效果,不是播放问题
1.AudioManager中焦点durationHint定义说明
- AUDIOFOCUS_GAIN:长时间获取焦点,一般用于音视频。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS (长时间丢失焦点,这个时候需要停止播放,并释放资源。根据不同的逻辑,有时候还会释放焦点)
- AUDIOFOCUS_GAIN_TRANSIENT:短暂获得,一般用于电话,语音助理等。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS_TRANSIENT (短暂失去焦点,这时可以暂停播放,但是不必要释放资源,因为很快又会获取到焦点)
- AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:短暂性获得焦点并降音,可混音播放,一般用于导航。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK (短暂失去焦点,但是可以跟新的焦点拥有者同时播放,并做降噪处理)
- AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:(android后加的)与AUDIOFOCUS_GAIN_TRANSIENT类似,表示一个短暂的获取焦点,一般用于录音或者语音识别。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
2.MediaFocusControl.java中的requestAudioFocus方法过程
- 判断mFocusStack值的size不能超过100
- 检查当前栈顶的元素是否是应用占用状态,若处于占用状态,那么focusGrantDelayed = true
- 压栈之前,需要检查当前栈中是否已经有这个应用的记录,如含有则删除。
若mFocusStrack不为null(!mFocusStack.empty()),且栈顶的clientId与需要申请焦点的clientId相同(mFocusStack.peek().hasSameClient(clientId)),得到栈顶元素即FocusRequester对象。若申请的时长(focusChangeHint)及flag相同,则表示申请重复,直接返回AUDIOFOCUS_REQUEST_GRANTED;若二者有一个不同则表示需要重新申请,同时此时focusGrantDelayed为false需要将栈顶元素出栈并将其释放- removeFocusStackEntry-- 移除可能在栈中(栈顶或栈中)其他位置存在着相同的clientId的元素
- 栈顶:释放后通知栈顶应用,使其获得audioFocus
- 非栈顶:只是移除该记录,无需更改当前audioFocus的占有情况
- 创建FocusRequester实例将其请求包含的各种信息传入
- 如果focusGrantDelayed = true会延迟申请,进入pushBelowLockedFocusOwners方法,在方法中把此次请求FocusRequester实例入栈,而非被压在栈顶,放在lastLockedFocusOwnerIndex位置,即电话记录之后,则电话的焦点释放后则该请求开始申请; 如果focusGrantDelayed = false则无需延迟获取焦点,同样创建FocusRequester实例,但需先通知栈中其他记录失去焦点,然后入栈,最后通知自己获得焦点
- 继续会进入propagateFocusLossFromGain_syncAf方法,遍历mFocusStack,调用FocusRequester对象的handleExternalFocusGain方法,通知栈中其他元素丢失焦点流程。通过while(stackIterator.hasNext())得到FocusRequester对象,进入handleExternalFocusGain方法
- notifyExtPolicyFocusGrant_syncAf做相应的通知
FocusRequester处理FocusRequester对象
根据MediaFocusControl.java中propagateFocusLossFromGain_syncAf传递来的nfr.getGainRequest()值做焦点的获取/丢失处理
变量:
- gainRequest: 根据传入值做对应的返回值
- 若传进来的参数是 AudioManager.AUDIOFOCUS_GAIN,return AudioManager.AUDIOFOCUS_LOSS
- 若传进来的参数是 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
- mFocusLossReceived: 方法handleFocusLoss中赋值,默认为AudioManager.AUDIOFOCUS_NONE