当前位置: 首页 > news >正文

音频焦点学习之AudioFocusRequest.Builder类剖析

背景:

什么是音频焦点
两个或两个以上的 Android 应用可同时向同一输出流播放音频,并且系统会将所有音频混合在一起。虽然这是一项出色的技术,但却会给用户带来很大的困扰。为了避免所有音乐应用同时播放,Android 引入了“音频焦点”的概念。一次只能有一个应用获得音频焦点。

当您的应用需要输出音频时,它需要请求获得音频焦点,获得焦点后,就可以播放声音了。不过,在您获得音频焦点后,您可能无法将其一直持有到播放完成。其他应用可以请求焦点,从而占有您持有的音频焦点。如果发生这种情况,您的应用应暂停播放或降低音量,以便于用户听到新的音频源。

正常申请音频焦点步骤及代码

一般普通App要实现音频需要如下几个步骤
1、创建AudioAttributes相关属性,传递给 focus request.

Creating AudioAttributes to be used for the playback and the focus request.

2、确定AudioFocus的Request类型,使用AudioFocusRequest.Builder创建对应的AudioFocusRequest

Configuring and creating the AudioFocusRequest instance that defines the intended focus behaviors.

3、创建了AudioFocusRequest后,调用AudioManager.requestAudioFocus进行焦点申请,而且判断返回值
Requesting audio focus and checking the return code to see if playback can happen right away, or is delayed.

4、实现好对应的OnAudioFocusChangeListener焦点监听类,响应焦点的丢失和获取进行相关处理

Implementing a focus change listener to respond to focus gains and losses.

源码如下

 // initialization of the audio attributes and focus requestmAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);mPlaybackAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build();mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).setAudioAttributes(mPlaybackAttributes).setAcceptsDelayedFocusGain(true).setWillPauseWhenDucked(true).setOnAudioFocusChangeListener(this, mMyHandler).build();mMediaPlayer = new MediaPlayer();mMediaPlayer.setAudioAttributes(mPlaybackAttributes);final Object mFocusLock = new Object();boolean mPlaybackDelayed = false;// requesting audio focusint res = mAudioManager.requestAudioFocus(mFocusRequest);synchronized (mFocusLock) {if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {mPlaybackDelayed = false;} else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {mPlaybackDelayed = false;playbackNow();} else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {mPlaybackDelayed = true;}}// implementation of the OnAudioFocusChangeListener@Overridepublic void onAudioFocusChange(int focusChange) {switch (focusChange) {case AudioManager.AUDIOFOCUS_GAIN:if (mPlaybackDelayed || mResumeOnFocusGain) {synchronized (mFocusLock) {mPlaybackDelayed = false;mResumeOnFocusGain = false;}playbackNow();}break;case AudioManager.AUDIOFOCUS_LOSS:synchronized (mFocusLock) {// this is not a transient loss, we shouldn't automatically resume for nowmResumeOnFocusGain = false;mPlaybackDelayed = false;}pausePlayback();break;case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:// we handle all transient losses the same way because we never duck audio bookssynchronized (mFocusLock) {// we should only resume if playback was interruptedmResumeOnFocusGain = mMediaPlayer.isPlaying();mPlaybackDelayed = false;}pausePlayback();break;}}// Important:// Also set "mResumeOnFocusGain" to false when the user pauses or stops playback: this way your// application doesn't automatically restart when it gains focus, even though the user had// stopped it.

音频焦点请求的不同类型

The different types of focus requests
一共4个大类型原文解释如下:

AudioManager.AUDIOFOCUS_GAIN

expresses the fact that your application is now the sole source of audio that the user is listening to. The duration of the audio playback is unknown, and is possibly very long: after the user finishes interacting with your application, (s)he doesn’t expect another audio stream to resume. Examples of uses of this focus gain are for music playback, for a game or a video player.

AudioManager.AUDIOFOCUS_GAIN_TRANSIENT

is for a situation when you know your application is temporarily grabbing focus from the current owner, but the user expects playback to go back to where it was once your application no longer requires audio focus. An example is for playing an alarm, or during a VoIP call. The playback is known to be finite: the alarm will time-out or be dismissed, the VoIP call has a beginning and an end. When any of those events ends, and if the user was listening to music when it started, the user expects music to resume, but didn’t wish to listen to both at the same time.

AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK

this focus request type is similar to AUDIOFOCUS_GAIN_TRANSIENT for the temporary aspect of the focus request, but it also expresses the fact during the time you own focus, you allow another application to keep playing at a reduced volume, “ducked”. Examples are when playing driving directions or notifications, it’s ok for music to keep playing, but not loud enough that it would prevent the directions to be hard to understand. A typical attenuation by the “ducked” application is a factor of 0.2f (or -14dB), that can for instance be applied with MediaPlayer.setVolume(0.2f) when using this class for playback.

AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE

is also for a temporary request, but also expresses that your application expects the device to not play anything else. This is typically used if you are doing audio recording or speech recognition, and don’t want for examples notifications to be played by the system during that time.

中文解释如下
在这里插入图片描述

AudioFocusRequest.Builder公共方法

常见的的公共方法解释如下:
在这里插入图片描述
在这里插入图片描述

这里重点强调解释几个常见的:

setAcceptsDelayedFocusGain
public AudioFocusRequest.Builder setAcceptsDelayedFocusGain (boolean acceptsDelayedFocusGain)

主要是标记focus request请求是可以可以接受延时获取焦点的,为什么会有延时焦点这么一说呢?
可以看一下如下解释:

Audio focus can be “locked” by the system for a number of reasons: during a phone call, when the car to which the device is connected plays an emergency message… To support these situations, the application can request to be notified when its request is fulfilled, by flagging its request as accepting delayed focus, with Builder.setAcceptsDelayedFocusGain(boolean).
If focus is requested while being locked by the system, AudioManager.requestAudioFocus(AudioFocusRequest) will return AudioManager.AUDIOFOCUS_REQUEST_DELAYED. When focus isn’t locked anymore, the focus listener set with Builder.setOnAudioFocusChangeListener(OnAudioFocusChangeListener) or with Builder.setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler) will be called to notify the application it now owns audio focus.

简单说就是可能申请焦点时候,焦点可能是被锁定的,比如打电话等场景,如果不进行setAcceptsDelayedFocusGain(true),那么默认就直接返回audio focus请求失败,一旦设置成了可以接受焦点延时,那么就会返回AUDIOFOCUS_REQUEST_DELAYED,而不是直接返回失败,一旦返回AUDIOFOCUS_REQUEST_DELAYED,那么就一定要设置setOnAudioFocusChangeListener设置对应的监听audio focus什么时候进行了GAIN,方便进行焦点获取后的操作。

setWillPauseWhenDucked

public AudioFocusRequest.Builder setWillPauseWhenDucked (boolean pauseOnDuck)

主要用了声明app是如何对待Audio ducking的情况,因为app申请的类型是AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK时候,它成为了新焦点,但影响原来的焦点,这个时候就有2中处理方式
1、一种系统默认处理直接让原来音频焦点app不接受丢失焦点的回调,而是系统层面直接吧原来音频焦点app的声音进行音量减低,主要听到肯定是新焦点app的声音,

2、系统直接发送相关的AUDIOFOCUS_LOSS_TRANSIENT_MAY_DUCK回调通知给老焦点app,让老焦点app自己进行pasue处理,系统不会直接减低老焦点app的音量

When an application requested audio focus with AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, the system will duck the current focus owner.

Note: this behavior is new for Android O, whereas applications targeting SDK level up to API 25 had to implement the ducking themselves when they received a focus loss of AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK.

But ducking is not always the behavior expected by the user. A typical example is when the device plays driving directions while the user is listening to an audio book or podcast, and expects the audio playback to pause, instead of duck, as it is hard to understand a navigation prompt and spoken content at the same time. Therefore the system will not automatically duck when it detects it would be ducking spoken content: such content is detected when the AudioAttributes of the player are qualified by AudioAttributes.CONTENT_TYPE_SPEECH. Refer for instance to AudioAttributes.Builder.setContentType(int) and MediaPlayer.setAudioAttributes(AudioAttributes) if you are writing a media playback application for audio book, podcasts… Since the system will not automatically duck applications that play speech, it calls their focus listener instead to notify them of AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK, so they can pause instead. Note that this behavior is independent of the use of AudioFocusRequest, but tied to the use of AudioAttributes.

If your application requires pausing instead of ducking for any other reason than playing speech, you can also declare so with Builder.setWillPauseWhenDucked(boolean), which will cause the system to call your focus listener instead of automatically ducking.

原文地址:
https://mp.weixin.qq.com/s/Hh4Udbf8rDNPIm7A5EwTEA
更多framework和audio相关实战开发干货,请关注下面“千里马学框架”

http://www.dtcms.com/a/449404.html

相关文章:

  • 国产某能谱仪产品分析
  • 《Vuejs设计与实现》第 5 章(非原始值响应式方案)下 代理数组
  • 网站服务器速度查询北京网站设计公司兴田德润放心
  • 版本控制器git(1)--- git 初识与安装
  • 网站如何收录网络营销策划方案ppt
  • Three.js NodeMaterial 节点材质系统文档
  • 2025 中小企业 AI 转型:核心岗技能 “怎么证、怎么用”?
  • ML4T - 第8章第1节 蒙特卡洛估计夏普率 Monte Carlo Estimation of Sharpe Ratio
  • 滨州企业网站建设WordPress的数据库在哪
  • K230基础-颜色识别
  • git 中常用的命令
  • 网络屏蔽工具,强制软件断网
  • 面试经典150题[049]:合并区间(LeetCode 56)
  • 取名字网站如何做wordpress程序员主题
  • 第7章 n步时序差分 n步时序差分预测
  • 【代码随想录算法训练营——Day28】贪心算法——134.加油站、135.分发糖果、860.柠檬水找零、406.根据身高重建队列
  • 网上服务平台官网入口潍坊百度搜索优化
  • 直播网站怎么做啊如何做php分页网站
  • 【IDE】Linux下使用openocd烧录bin文件
  • 【剑斩OFFER】算法的暴力美学——将 x 减到零的最小操作数
  • Docker(四)—— 使用 Docker 搭建 Nginx 并实现 HTTPS 访问
  • 浏览器中的隐藏IDE: Elements (元素) 面板
  • 【JVM】实战篇(一)
  • 住房城市建设部门户网站一件代发48个货源网站
  • 宣武深圳网站建设公司下关网站建设
  • 电商的网站有几个如何做高校的网站版面设计
  • 蚁群算法解决TSP问题
  • 数据库丢失但没备份过?救星:二进制日志
  • 【C++实战(74)】深入C++安全编程:密码学实战之旅
  • inbound 概念及题目