仅为学习记录,感谢所有技术分享

Android10.0AudioFocus之如何使用(一)

Android AudioFocus音频焦点机制学习和理解

Android10.0AudioFocus之AudioFocusRequest

音频焦点AudioFocus

目录

1.AudioManager中焦点durationHint定义说明

2.MediaFocusControl.java中的requestAudioFocus方法过程

 3.FocusRequester处理FocusRequester对象

4.AudioFocus流程


 

音频焦点是规则,是个弱管理。也就是说如果你想播放,不管拿不拿得到音频焦点,都是可以播放的。影响的只是体验效果,不是播放问题

1.AudioManager中焦点durationHint定义说明

  1. AUDIOFOCUS_GAIN:长时间获取焦点,一般用于音视频。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS (长时间丢失焦点,这个时候需要停止播放,并释放资源。根据不同的逻辑,有时候还会释放焦点)
  2. AUDIOFOCUS_GAIN_TRANSIENT:短暂获得,一般用于电话,语音助理等。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS_TRANSIENT (短暂失去焦点,这时可以暂停播放,但是不必要释放资源,因为很快又会获取到焦点)
  3. AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:短暂性获得焦点并降音,可混音播放,一般用于导航。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK (短暂失去焦点,但是可以跟新的焦点拥有者同时播放,并做降噪处理)
  4. AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:(android后加的)与AUDIOFOCUS_GAIN_TRANSIENT类似,表示一个短暂的获取焦点,一般用于录音或者语音识别。此参数会触发其他监听器的AudioManager.AUDIOFOCUS_LOSS_TRANSIENT 

2.MediaFocusControl.java中的requestAudioFocus方法过程

  1. 判断mFocusStack值的size不能超过100
  2. 检查当前栈顶的元素是否是应用占用状态,若处于占用状态,那么focusGrantDelayed = true
  3. 压栈之前,需要检查当前栈中是否已经有这个应用的记录,如含有则删除。
    若mFocusStrack不为null(!mFocusStack.empty()),且栈顶的clientId与需要申请焦点的clientId相同(mFocusStack.peek().hasSameClient(clientId)),得到栈顶元素即FocusRequester对象。若申请的时长(focusChangeHint)及flag相同,则表示申请重复,直接返回AUDIOFOCUS_REQUEST_GRANTED;若二者有一个不同则表示需要重新申请,同时此时focusGrantDelayed为false需要将栈顶元素出栈并将其释放
  4. removeFocusStackEntry-- 移除可能在栈中(栈顶或栈中)其他位置存在着相同的clientId的元素
  • 栈顶:释放后通知栈顶应用,使其获得audioFocus
  • 非栈顶:只是移除该记录,无需更改当前audioFocus的占有情况
  1. 创建FocusRequester实例将其请求包含的各种信息传入
  2. 如果focusGrantDelayed = true会延迟申请,进入pushBelowLockedFocusOwners方法,在方法中把此次请求FocusRequester实例入栈,而非被压在栈顶,放在lastLockedFocusOwnerIndex位置,即电话记录之后,则电话的焦点释放后则该请求开始申请; 如果focusGrantDelayed = false则无需延迟获取焦点,同样创建FocusRequester实例,但需先通知栈中其他记录失去焦点,然后入栈,最后通知自己获得焦点
  3. 继续会进入propagateFocusLossFromGain_syncAf方法,遍历mFocusStack,调用FocusRequester对象的handleExternalFocusGain方法,通知栈中其他元素丢失焦点流程。通过while(stackIterator.hasNext())得到FocusRequester对象,进入handleExternalFocusGain方法
  4. notifyExtPolicyFocusGrant_syncAf做相应的通知

FocusRequester处理FocusRequester对象

根据MediaFocusControl.java中propagateFocusLossFromGain_syncAf传递来的nfr.getGainRequest()值做焦点的获取/丢失处理

变量:

  1. gainRequest: 根据传入值做对应的返回值
  • 若传进来的参数是 AudioManager.AUDIOFOCUS_GAIN,return AudioManager.AUDIOFOCUS_LOSS
  • 若传进来的参数是 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
  1. mFocusLossReceived: 方法handleFocusLoss中赋值,默认为AudioManager.AUDIOFOCUS_NONE

4.AudioFocus流程

Android通过adb获取音频焦点 android audio focus_java