Android官方开发文档Training系列课程中文版:管理音频播放之管理音频焦点

简介: 原文地址:http://android.xsoftlab.net/training/managing-audio/audio-focus.html因为可能会存在多个APP播放音频,所以考虑它们之间的交互方式是一件很重要的事情。

原文地址:http://android.xsoftlab.net/training/managing-audio/audio-focus.html

因为可能会存在多个APP播放音频,所以考虑它们之间的交互方式是一件很重要的事情。为了避免多个音乐播放器APP在同一时间播放音乐,Android使用了音频焦点的方式来管理音频的播放,只有获取了音频焦点的APP才可以播放音频。

在APP开始播放音频之前,APP需要请求以及接收音频的焦点。同样的,APP还应该知道如何监听音频焦点的丢失事件,以及当事件发生的时候,如何恰当的作出响应。

请求音频焦点

在APP播放音频之前,APP应该对使用的音频流持有音频焦点。可以使用 requestAudioFocus() 方法来获取焦点,如果请求成功的话,它会返回 AUDIOFOCUS_REQUEST_GRANTED

你必须指定你所使用的音频流,并且还需要请求短暂的音频焦点,或者永久的音频焦点。当你想要播放一个短暂的音频时可以请求短暂的音频焦点(举例:当播放导航声音时)。当需要播放一个长时间的音频时,就需要请求永久的音频焦点(举例,播放音乐)。

下面的代码展示了对音乐音频流上请求了永久的音频焦点。你应该在开始播放之前立即请求音频焦点,比如当用户按下了播放按钮或者游戏中下节背景音乐开始之前。

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                                 // Use the music stream.
                                 AudioManager.STREAM_MUSIC,
                                 // Request permanent focus.
                                 AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    am.registerMediaButtonEventReceiver(RemoteControlReceiver);
    // Start playback.
}

一旦APP结束了播放,应该确保调用了abandonAudioFocus()方法。这会通知到系统你不再需要请求焦点,以及它会解注与之关联的AudioManager.OnAudioFocusChangeListener回调接口。在丢弃短暂焦点的例子中,它允许任何被中止的APP可以继续播放音频。

// Abandon audio focus when playback complete    
am.abandonAudioFocus(afChangeListener);

当请求短暂的音频焦点时,有一些附加选项:无论你是否想要正常开启”ducking”选项,当一个友好的APP失去音频焦点的时候,它会立即停止播放。通过请求一个瞬态音频焦点时,它允许闪避,当你告诉其它音频APP它可以接收它们的持续播放,只要它们会降低音量直到音频焦点返回给它。

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                             // Use the music stream.
                             AudioManager.STREAM_MUSIC,
                             // Request permanent focus.
                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback.
}

闪避对间歇性的音频流APP来说特别适合,比如导航方向的播报信息。

当其它APP如上面描述的那样请求音频焦点时,它可以在永久的音频焦点或者短暂的音频焦点之间选择,这两个焦点会由请求焦点时注册的监听回调方法回调回来。

处理音频焦点的丢失

如果APP可以请求到音频焦点,那么接下来在其它APP请求焦点的时候,它就可能会失去那个焦点。APP如何响应焦点的丢失,取决于丢失的方式。

音频焦点改变接口的回调方法onAudioFocusChange()会接收一个参数,这个参数用于描述焦点改变事件。特别的,焦点的丢失事件可能与原先部分请求的焦点类型相对应–永久丢失,短暂丢失以及短暂的限制性闪避。

通常来说,音频焦点的短暂丢失应该致使APP的音频流静音。否则就应该保持相同的状态。你应该继续监视音频焦点的改变,以便当APP恢复焦点的时候从暂停的地方恢复播放。

如果音频焦点的丢失是永久性的,假设现在有其他APP被用来监听音频焦点,这时,APP应该有效的自动终止。在实际情况中,这意味着停止播放,移除媒体按钮监听器–这运行一个新的音频播放器来专门处理这些事件,以及丢弃持有的音频焦点。在那时,在APP重新播放之前,你会期待有用户来触发那个请求。

在下面的代码中,如果音频丢失是短暂的,我们会暂停播放或者暂停我们的媒体播放器对象,并会在重新获得焦点时恢复它们。如果丢失是永久性的,它会解注我们的媒体按钮事件接收器以及停止对音频焦点改变的监听。

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!

Ducking 是降低音频流输出音量的过程,这可以使得其他APP的短暂音频听起来更轻快更和谐,而不会总是打断APP的播放过程。

下面的代码,当我们临时的失去焦点时,会降低媒体播放器对象的音量,当再一次获得焦点时,会将音量等级恢复至原来的值。

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
        }
    }
};

音频焦点的丢失是由大多数重要的广播影响的,但是不单单只是有它引起的。系统会广播一系列的意图来使你留意用户的听觉体验。下节课会演示如何监视音频焦点来增进用户的整体体验。

目录
相关文章
|
1月前
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
73 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
|
4月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
755 76
|
5月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
312 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
5月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
140 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
5月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
113 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
6月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
299 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
5月前
|
安全 Android开发 iOS开发
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
257 1
|
6月前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
133 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
7月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
125 19
|
7月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
206 14