音频输入通常来自内置麦克风、外部麦克风或 音频接口。音频输入也可以来自 电话对话。
有时,两个或多个应用可能都想“捕获”相同的音频输入。 它们可能在执行不同的任务。 例如,接收音频的某些应用可能是“录音”就像简单的录音机一样, 而其他应用可能在“监听”例如 Google 助理或无障碍服务 响应语音指令。
无论是哪种情况,这些应用都需要接收音频输入。 在本页中,我们使用“捕获”一词无论 或只听音频内容。
如果两个或多个应用想要同时捕获音频,则可能存在问题 将同一来源的音频信号传输到所有设备上。本页介绍了 Android 系统如何在多个捕获音频的应用之间共享音频输入。
Android 10 之前的行为
在 Android 10 之前,输入音频流只能由一个应用在
。如果某个应用已经在录制或收听音频,您的应用可能
创建 AudioRecord
对象,但如果调用此对象,系统会返回错误
AudioRecord.startRecording()
因此无法开始录制。
这条规则有一个例外情况,那就是特权应用(如 Google 助理或
无障碍服务)已获得相应的权限
android.permission.CAPTURE_AUDIO_HOTWORD
,并使用了以下类型的音频来源
HOTWORD
。在这种情况下,另一个应用可以开始录制。这时候
特权应用已终止,新应用捕获了输入。
Android 9 中还添加了一项更改:仅在前台运行的应用(或者 前台服务)可以捕获音频输入。如果某个应用没有 前台服务或前台界面组件开始捕获时,应用 继续运行,但收到静默消息,即使它是唯一一个捕获的应用 音频。
Android 10 行为
Android 10 之前的行为是“先到先得”。 应用开始捕获音频后,其他应用都无法访问 音频输入,直到正在捕获音频的应用停止运行。
Android 10 强制实施一个优先级方案,用于切换输入音频流 应用之间会发生哪些变化。在大多数情况下,如果新应用获取音频输入, 之前捕获的应用继续运行,但会收到静默。在某些 这样,系统就可以继续向这两个应用传送音频。各种 共享场景如下所述。
此架构类似于音频焦点处理多个应用的方式 音频输出的使用。不过,音频焦点由 通过编程请求获得和释放焦点,同时在输入源切换 此处所述的架构是基于应用的优先级政策, 。
为了捕获音频,Android 会区分两种类型的应用:
- “普通”由用户安装的应用。
- “特权”设备上预装的应用。其中包括 Google 助理以及所有无障碍服务。
此外,系统会通过不同方式
如果它使用“对隐私敏感”的音频来源:
CAMCORDER
或 VOICE_COMMUNICATION
。
使用和共享音频输入的优先级规则如下:
- 特权应用的优先级高于普通应用。
- 具有可见前台界面的应用比后台应用具有更高的优先级。
- 相较于从非隐私敏感源捕获音频的应用,从隐私敏感源捕获音频的应用有着更高的优先级。
- 两个普通应用永远无法同时捕获音频。
- 在某些情况下,特权应用可以与其他应用共享音频输入。
- 如果两个优先级相同的后台应用都在捕获音频,则后开始的那个优先级更高。
共享方案
当两个应用尝试捕获音频时, 它们都能接收输入信号 安静。
四种主要方案如下:
- Google 助理 + 普通应用
- 无障碍服务 + 普通应用
- 两个普通应用
- 语音通话 + 普通应用
Google 助理 + 普通应用
Google 助理是特权应用,因为它是预安装应用,并且拥有
角色 RoleManager.ROLE_ASSISTANT
。
拥有此角色的任何其他预安装应用都会受到类似处理。
Android 根据以下规则共享输入音频:
Google 助理可以接收音频(无论是在前台还是后台运行) 除非已有另一个使用隐私敏感音频源的应用正在捕获音频。
除非 Google 助理具有可见界面,否则应用会接收音频 组件。
请注意,仅当 Google 助理在后台运行时,这两个应用才会接收音频 而另一个应用没有从隐私敏感音频源进行捕获。
无障碍服务 + 普通应用
AccessibilityService
需要进行严格的声明。
Android 根据以下规则共享输入音频:
如果服务的界面位于顶部,则服务和应用都会收到 音频输入。此行为提供了控制语音通话或视频通话等功能 以及使用语音指令捕获音频
如果该服务不在顶部,则此情况的处理方式与下述两个普通应用的情况一样。
两个普通应用
当两个应用同时进行捕获时,只有一个应用接收音频,另一个应用会受到静默处理。
Android 根据以下规则共享输入音频:
- 如果两个应用都对隐私安全不敏感, 界面位于顶层的应用接收音频。 如果两个应用都没有界面,则较晚开始者接收音频。
- 如果其中一个应用属于隐私敏感型应用,则该应用会接收音频, 另一个应用即使顶部有界面或开始捕获音频,也会发出静音 。
- 如果这两个应用都对隐私敏感,则开始捕获数据最多的应用 最近接收音频,另一个则静音。
语音通话 + 普通应用
如果
AudioManager.getMode()
为
MODE_IN_CALL
或
MODE_IN_COMMUNICATION
。
Android 根据以下规则共享输入音频:
- 通话始终接收音频。
- 如果音频是 无障碍服务。
如果是特权通话,则应用可以捕获语音通话 具有权限的(预安装)应用
CAPTURE_AUDIO_OUTPUT
。要捕获语音通话的上行链路 (TX) 和/或下行链路 (RX),应用必须 指定音频来源
MediaRecorder.AudioSource.VOICE_UPLINK
或MediaRecorder.AudioSource.VOICE_DOWNLINK
、 和/或设备AudioDeviceInfo.TYPE_TELEPHONY
。
Android 11 行为
Android 11(API 级别 30)遵循 Android 10 优先级方案
。它还在 AudioRecord
、MediaRecorder
和
AAudioStream
,用于启用和停用并发捕获音频的功能;
无论所选用例如何
这些新方法包括:
AudioRecord.Builder.setPrivacySensitive()
AudioRecord.isPrivacySensitive()
MediaRecorder.setPrivacySensitive()
MediaRecorder.isPrivacySensitive()
AAudioStreamBuilder_setPrivacySensitive()
AAudioStream_isPrivacySensitive()
当 setPrivacySensitive()
为 true
时,拍摄用例是不公开的,甚至
特权助理无法同时捕获音频此设置会覆盖
取决于音频源的默认行为。例如,
VOICE_COMMUNICATION
默认为私有状态,但 UNPROCESSED
不是私有状态。
配置变更
当多个应用同时捕获音频时,只有一个或两个应用 “有效”(接收音频);其他参与者会被静音(接收静音)。当 活跃应用发生更改时,音频框架可能会重新配置音频路径 规则:
- 每个活跃应用的音频输入设备可能会发生变化(例如,从 将内置麦克风连接到连接的蓝牙耳机)。
- 启用与优先级最高的活动应用相关联的预处理。全部 其他预处理会被忽略。
由于在优先级较高的应用变为活动状态时,正在运行的应用可能会被静音,
您可以注册
AudioManager.AudioRecordingCallback
在AudioRecord
上
或MediaRecorder
对象在配置发生更改时收到通知。
可能的更改如下:
- 捕获受到静默处理或解除静默处理
- 设备更改
- 预处理更改
- 音频流属性更改(采样率、通道掩码、采样格式)
您必须调用
AudioRecord.registerAudioRecordingCallback()
。
仅当应用正在接收音频且发生更改时才执行回调。
onRecordingConfigChanged()
方法会返回包含当前音频捕获状态的 AudioRecordingConfiguration
。请使用以下
方法以了解更改:
isClientSilenced()
- 如果返回客户端的音频目前因捕获政策而处于静音状态,则返回 true。
getAudioDevice()
- 返回活动音频设备。
getEffects()
- 返回有效预处理效果。请注意,如果客户端不是优先级最高的活跃应用,则有效效果可能与
getClientEffects()
返回的效果不同。 getFormat()
- 返回数据流属性。请注意,客户端接收的实际音频数据始终遵循
getClientFormat()
返回的所需格式。框架会自动执行必要的重新采样、通道和格式转换,从硬件接口使用的格式转换为客户端指定的格式。 AudioRecord.getActiveRecordingConfiguration()
。- 返回有效的记录配置。
您可以拨打以下号码,大致了解设备上所有进行中的录音
AudioManager.getActiveRecordingConfigurations()
。