Skip to main content

Chapter 111: Audio Focus, Interruption, Background Audio, Permission

手机上的声音资源同时承载音乐、视频、通话、闹钟、导航、游戏、录音和系统提示。读完本章后,读者应能追踪一次声音播放或录音请求如何经过 App、Framework、系统服务、权限策略、路由策略和硬件设备,并能判断某个声音现象属于焦点竞争、中断、后台资格、麦克风权限还是蓝牙/通话路由切换。

本章贯穿一个具体场景:用户正在听播客,导航 App 播报转向提示,随后电话呼入,用户接听电话并切换到蓝牙耳机,通话结束后播客尝试恢复播放。这个场景覆盖播放、spoken audio、ducking、interruption、后台播放、麦克风权限、蓝牙 profile 和 call / VoIP / media 路由竞争,足以把音频策略的系统责任链串起来。

移动 OS 处理音频的核心结论是:App 只能声明自己的音频意图,最终决策由系统根据用户可见状态、音频用途、通话状态、权限、后台资格、路由可用性和平台策略完成。Android 公开提供 Audio Focus、AudioAttributes、MediaSession、Foreground Service、runtime permission 等入口;Apple 公开提供 AVAudioSession category、mode、option、interruption notification、route change notification、Info.plist 用途说明和后台音频模式等入口。公开文档能确认 API 语义和 App 可依赖行为,Apple daemon、私有仲裁器和内部数据库细节属于实现层,本章只在公开行为边界内推断责任链。

版本边界需要先固定。Android 8.0 到 Android 11 引入 AudioFocusRequest 和系统 ducking 行为,Android 12 以后系统会更强地管理焦点丢失后的淡出和来电静音,Android 15 目标版本还要求请求音频焦点的 App 处于 top app 或 foreground service 状态;这些规则见 Android 官方的 Manage audio focus。Android 12 以后麦克风和相机增加全局开关与状态栏指示器;Android 14 以后前台服务与 while-in-use 权限之间的限制更明确。Apple 侧以公开 AVAudioSession API 和 Apple Audio Session Programming Guide 的 Responding to InterruptionsAudio Session Categories and Modes 为边界。

111.1 Audio Focus 与多 App 音频资源管理

Audio Focus 是 Android 用来管理多 App 播放关系的公开控制面。它的工作定义是:App 在播放前向系统声明自己需要怎样的音频占用,系统根据当前持有焦点的 App、请求类型、AudioAttributes、通话状态和系统版本返回授予、延迟或失败,并在焦点变化时要求旧 App 暂停、duck、保持混音或停止。Audio Focus 管理的是播放关系,不直接等同于底层设备所有权;真正的输出设备路由、音量组、蓝牙 profile 和硬件配置仍由更底层的 audio policy 与 HAL / driver 路径处理。

在贯穿场景中,播客 App 播放 spoken audio,导航 App 播报转向提示。播客 App 通常以媒体或语音内容方式请求焦点,导航 App 以短暂提示方式请求焦点。系统需要决定播客是否继续播放、降低音量、暂停,或者在提示结束后恢复。Android 公开要求 App 在播放前调用 requestAudioFocus(),在停止播放后释放焦点,并使用 AudioAttributes 描述音频用途和内容类型。系统依据这些信息处理 AUDIOFOCUS_GAINAUDIOFOCUS_GAIN_TRANSIENTAUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCKAUDIOFOCUS_LOSSAUDIOFOCUS_LOSS_TRANSIENT 等状态。

Audio Focus 的责任链可以写成 App 意图 → Framework 请求 → AudioService / AudioPolicy → 当前焦点状态 → 回调或系统强制处理 → 播放器状态变化。App 的责任是声明用途、请求焦点、响应回调、在永久丢失焦点后等待用户动作。系统服务的责任是保存当前焦点栈、比较新旧请求、触发 duck / pause / mute / delayed gain,并把焦点变化通知给相关 App。内核和驱动层只看到音频流、设备、buffer 和硬件状态,通常不理解“播客”和“导航提示”这类产品语义。

Android 12 以后,系统在某些条件下会强制淡出正在播放的媒体或游戏音频;来电时也可以静音符合条件的媒体或游戏音频。这个变化说明 Audio Focus 从“合作式约定”逐步增强为“系统可执行策略”。Android 15 目标版本进一步把请求焦点与 top app / foreground service 状态绑定,使后台 App 的音频请求先接受生命周期和用户可见性检查。

Apple 平台没有向 App 暴露 Android 式 Audio Focus 栈,而是通过 AVAudioSession 表达同一类系统问题。App 设置 category、mode 和 option,系统根据这些声明决定该 App 是否可与其他音频混音、是否打断其他非混音音频、是否受静音开关和锁屏影响、是否允许录音和播放。AVAudioSessionCategoryPlayback 表达长期播放意图,AVAudioSessionCategoryPlayAndRecord 表达同时录放意图,mixWithOthersduckOthersinterruptSpokenAudioAndMixWithOthers 这类 option 表达混音或降低其他声音的意图。

判断一个多 App 播放问题时,应先看 App 声明的音频用途,再看系统当前状态。对 Android,先检查 AudioAttributes、focus gain 类型、是否收到 onAudioFocusChange()、目标 API level、是否处于 foreground service 或 top app。对 Apple,先检查 AVAudioSession category / mode / option、session 是否 active、是否收到 interruption 或 route change notification、后台模式是否声明。这个顺序能把“App 自己暂停”“系统要求暂停”“系统自动 duck”“通话导致中断”分开。

111.2 Interruption:电话、闹钟、系统提示与其他 App

Interruption 是系统把正在进行的音频会话临时停下或改变状态的事件。它的工作定义是:一个更高优先级或不可混音的音频行为到来后,系统改变当前 App 的音频会话或焦点状态,使当前播放或录音停止、暂停、降低音量或失去路由,并在条件满足时给出恢复信号。电话、闹钟、系统警报、Siri / 语音助手、VoIP、导航提示和其他 App 的独占音频都可能触发 interruption。

贯穿场景中,电话呼入后,播客的播放路径受到通话路径抢占。Android 侧表现为 focus loss、系统来电静音、AudioManager 回调、MediaSession 状态变化或播放器暂停;Apple 侧表现为 AVAudioSessionInterruptionNotificationuserInfo 中的 interruption type 指明 began 或 ended,结束阶段的 option 可能给出 shouldResume 提示。Apple 公开文档明确说明中断开始后 App 应保存状态并更新 UI,中断结束后按需恢复状态、更新 UI、重新激活 session,并根据 shouldResume 决定是否自动播放。

Interruption 的关键在于状态保存和恢复是否服从用户动作,单纯观察“声音被停了”只能说明现象。用户接听电话时,播客 App 可能被挂起,通话结束时也可能已经不在前台;用户通过耳机或锁屏控制暂停过播客时,App 收到结束通知后直接恢复会违反用户意图。稳定做法是把播放状态拆成三个变量:中断前是否正在播放、系统是否给出恢复提示、用户在中断期间是否改变了播放意图。只有这三个变量共同支持恢复时,App 才应恢复播放。

下面的序列图描述一次 interruption 的责任边界。图中只表达公开可观察路径,不绑定 Apple 或 Android 的私有服务实现。

这个路径把系统和 App 的职责分开。系统负责检测竞争音频、改变 session / focus、切换硬件路由、发送通知。App 负责保存播放点、停止实时处理、释放或保持必要资源、更新界面、决定恢复策略。硬件层负责切换 codec、蓝牙、扬声器、听筒或麦克风路径;硬件不保存业务播放意图。

排查 interruption 问题时,应先确认中断源。电话和闹钟通常优先级高,系统能强制改变音频状态;其他 App 的媒体播放更多依赖 focus / session 策略;系统提示和导航提示可能触发 duck 而非 pause。然后确认恢复条件:Android 看 AUDIOFOCUS_GAIN 是否到达、焦点丢失是 transient 还是 permanent;Apple 看 interruption ended 与 shouldResume,同时检查用户是否通过远程控制改过状态。最后检查 App 是否把播放器状态、UI 状态和 session active 状态绑定在一起,很多“自动恢复失败”来自这三个状态分离后缺少同步。

111.3 Ducking、Pausing、Mixing 与音频策略

Ducking、pausing、mixing 和 exclusive 是系统面对多个声音同时出现时的四类策略。Ducking 是降低一个声音的音量,让另一个短声音清晰出现;pausing 是暂停旧声音,等待新声音结束或用户恢复;mixing 是允许多个声音同时播放;exclusive 是让一个声音独占会话或路由,使其他声音停止或失去输出资格。这些策略对应产品语义,不应按音量大小机械选择。

播客加导航提示适合用 spoken audio 语义分析。播客也是语音内容,导航提示也是语音内容。两个语音叠加会降低可懂度,所以系统或 App 往往选择暂停播客,或者在很短提示中降低播客音量。音乐加导航提示更适合 duck,因为音乐连续性强,短提示结束后恢复音量即可。游戏背景音乐加队友语音可以 mix,同时语音可占用更高优先级。闹钟、来电、紧急提示更接近 exclusive 或强制 interruption,因为用户需要可靠听到。

Android 的自动 ducking 在 Android 8.0 以后由系统支持:当第二个 App 以 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 请求焦点,并且第一个 App 满足条件时,系统可以降低第一个 App 的活动播放器音量,第二个 App 释放焦点后再恢复。官方文档还说明 speech content 不适合自动 duck,因为用户可能错过语音内容。这个边界直接影响播客、导航、听书和语音学习类 App 的策略:它们应使用 AudioAttributes.CONTENT_TYPE_SPEECH,并在需要暂停时通过 setWillPauseWhenDucked(true) 让系统回调 App。

Apple 的 category / option 表达的是同类选择。mixWithOthers 表达可与其他音频混音,duckOthers 表达让其他音频降低音量,interruptSpokenAudioAndMixWithOthers 面向 spoken audio 场景。category 决定默认是否会打断非混音音频,mode 补充语音通话、视频录制、电影播放、spoken audio 等使用场景,option 微调混音、duck、蓝牙和扬声器行为。系统根据这些声明与当前设备状态完成最终裁决。

可以把四类策略压缩成一个判断表:

策略适合场景App 应声明的意图用户可见结果失败表现
Ducking音乐播放中插入短导航提示、系统短提示短暂焦点、允许降低其他音频背景声音变小,提示清晰,随后恢复语音内容被降低后听不清
Pausing播客、听书、课程中插入电话、长语音提示speech content、需要回调处理当前内容暂停,提示结束后按条件恢复恢复点丢失或自动播放违背用户意图
Mixing游戏音效、环境声、协作语音、伴奏可混音 category / option 或适当 usage多路声音同时存在音量层级混乱或提示被遮盖
Exclusive电话、录音、闹钟、低延迟独占会话通话/录音/警报相关 category、mode 或 focus gain其他声音停止或不可闻旧声音继续播放干扰核心任务

这个表的迁移价值在于把“谁的声音更大”转换成“用户当前任务是什么”。用户听播客时,核心任务是理解语义;用户听音乐时,核心任务是持续氛围;用户接电话时,核心任务是实时双向通话;用户录音时,核心任务是麦克风输入完整性。音频策略应服务这个任务,而音频 Framework 的 category、mode、focus gain、usage 和 content type 是把任务提交给系统的字段。

111.4 Background Audio 与系统批准的长期播放

Background Audio 是系统允许 App 在离开前台后继续播放、录音或维持音频会话的资格集合。它的工作定义是:App 通过声明用途、维持媒体会话、展示用户可见控制面、接受后台执行限制和响应系统回收,获得长期播放或通信的系统通道。后台音频把长期执行任务放进用户可见性、通知控制、锁屏控制、功耗、焦点和媒体路由的共同约束中。

贯穿场景中,用户把播客 App 切到后台继续播放。Android 上,现代媒体播放通常使用 Media3 MediaSessionService 或等价服务结构,配合 MediaSession、媒体通知和 mediaPlayback foreground service type。Android 官方 Background playback with a MediaSessionService 说明媒体后台播放需要前台服务权限和媒体播放前台服务权限,通知会随 PlayerMediaSession 状态更新。Android 官方 Foreground service typesmediaPlayback 定义为从后台继续音频或视频播放的前台服务类型。

Android 的后台播放链路可写成 用户开始播放 → App 建立 Player → MediaSession 暴露控制面 → Service 进入 foreground service → 系统展示媒体通知 → 音频焦点和路由继续受系统治理。这个链路中,foreground service 的意义是让用户看见并可控制长期播放,同时让系统把该 App 视为有正在进行的用户可见任务。MediaSession 的意义是让系统、耳机、车机、锁屏、通知和其他控制器都能通过统一控制面读写播放状态。

Apple 上,后台音频需要合适的 AVAudioSession category,例如 playback,并在 App 的 Info.plist 中声明后台音频模式。Apple Audio Session Programming Guide 在 category 表中说明,若 App 需要在静音开关或锁屏下继续播放,应添加 UIBackgroundModesaudio key,并使用正确 category。iOS 还会把锁屏控制、控制中心、耳机控制、Now Playing 信息和 session 状态联系起来。公开 API 侧,App 依赖 AVAudioSession、后台模式声明、远程控制事件和 Now Playing metadata 形成用户可见播放路径。

后台音频的系统批准并不意味着无限运行。Android 后台前台服务受启动限制、类型声明、通知、权限和系统回收影响;暂停或停止超过一定条件后,服务可能退出 foreground 状态并被系统销毁。Apple 后台音频也需要持续符合音频用途,播放结束、session 失活、用户停止、系统资源压力和策略变化都会改变运行资格。稳定设计应把后台音频当成“有用户可见控制面的长期任务”,并将播放状态、通知状态、MediaSession / Now Playing 状态、焦点状态和服务生命周期保持同步。

排查后台音频问题时,可以按五步定位。第一,确认 App 是否真的处于用户发起的播放或通信任务。第二,确认 Android MediaSession、foreground service type 和通知是否有效,或 Apple AVAudioSession category 与 UIBackgroundModes 是否匹配。第三,确认是否在后台非法启动服务,Android 12 以后后台启动 foreground service 有明确限制。第四,确认音频焦点或 session 是否被通话、闹钟、其他 App 或系统策略打断。第五,确认用户可见控制面是否反映真实状态,通知或锁屏显示播放中而播放器已经停止,会导致系统和用户都得到错误信号。

111.5 Microphone Permission 与录音隐私边界

麦克风权限是系统把音频输入能力从硬件能力包装成可授权、可撤销、可提示、可审计资源的边界。它的工作定义是:App 访问麦克风前必须声明用途、获得用户授权,并在运行期状态、后台资格和系统隐私开关允许时,才能让录音 source 进入 audio input path。麦克风输入同时受到权限、前台状态、后台服务类型、录音 source、隐私指示器、路由和通话状态约束。

Android 侧,RECORD_AUDIO 属于 dangerous runtime permission。Android 官方 Request runtime permissions 说明,Android 6.0 以后危险权限需要在运行时请求,用户拒绝或撤销后 App 应降级功能。Android 12 以后,支持设备提供麦克风和相机全局开关,App 使用麦克风或相机时状态栏出现指示器。Android 14 以后,启动需要 while-in-use 权限的 foreground service 时,系统会在创建服务时检查当前权限;后台状态下创建 microphone foreground service 会因 while-in-use 权限不可用而抛出 SecurityException,官方 Restrictions on starting a foreground service from the background 对此有明确说明。

Apple 侧,App 访问麦克风需要在 Info.plist 中提供麦克风用途说明,并通过系统权限提示获得用户授权。录音相关路径通常使用 AVAudioSessionCategoryRecordAVAudioSessionCategoryPlayAndRecord,再配合 recorder、audio unit、WebRTC 或其他音频输入链路。用户授权、session category、当前 route、通话状态、后台模式和系统隐私指示共同决定是否能采集声音。具体授权数据库和守护进程属于 App 不应依赖的实现层;App 可依赖的是公开权限 API、用途说明、session 配置和系统提示行为。

麦克风权限链路可写成下面的流程图。

这个图说明麦克风检查由多层共同完成。Manifest 或 Info.plist 只说明 App 可能需要能力;runtime permission 或系统授权只说明用户同意;前台状态或合规后台任务说明此刻有资格访问;Audio Session / AudioRecord 配置说明 App 选择了输入路径;系统隐私指示器和开关让用户看到真实使用。任何一层不成立,录音都会失败、静音、抛异常或无法进入预期路由。

录音隐私边界还要区分“录音”和“播放”。一个 App 可以拥有后台播放资格,却没有后台录音资格;可以播放媒体,却无法打开麦克风;可以在前台录音,却无法在后台启动麦克风 foreground service;可以拥有 RECORD_AUDIO 授权,却因全局麦克风开关、通话占用、蓝牙 profile 或 session category 不匹配而拿不到有效输入。排查时应按 权限声明 → 用户授权 → 当前可见状态 → foreground service / background mode → audio session / route → input source → 系统指示器 的顺序定位。

111.6 Bluetooth、Call、VoIP、Media Playback 的路由竞争

音频路由竞争是系统在多个输入输出设备和多个音频任务之间选择真实硬件路径的问题。它的工作定义是:当蓝牙耳机、扬声器、听筒、USB、车机、通话基带、VoIP session 和媒体播放同时存在时,系统根据设备连接状态、profile 能力、通话优先级、session / focus 意图、用户选择和功耗策略决定输入输出走哪条路径。路由竞争解决的是“声音从哪里出、麦克风从哪里进、采样率和延迟按谁的约束配置”。

贯穿场景中,用户在电话呼入后切换到蓝牙耳机。媒体播放常用蓝牙 A2DP 路径,提供较高音质和较高延迟;通话和 VoIP 常用 HFP / HSP 或平台等价语音链路,提供双向语音、麦克风输入、通话控制和较低带宽语音编码。切换到通话路径后,媒体播放可能暂停或静音,麦克风 route 变成蓝牙耳机,输出也从扬声器或 A2DP 变成通话 profile。通话结束后,系统需要恢复媒体路由,App 还要决定是否恢复播放。

Android 侧,Audio Policy 负责把 usage、content type、device role、volume group、通信状态和可用设备映射到输出输入设备。App 能通过 AudioAttributes、Audio Focus、MediaSession、AudioDeviceInfo、CommunicationDevice 等公开 API 表达意图或观察设备变化,但最终路由由系统策略决定。VoIP App 若使用 telecom 相关能力、MODE_IN_COMMUNICATION、通信设备选择和前台服务,需要与媒体播放、电话、蓝牙和系统音量策略共同工作。

Apple 侧,AVAudioSession category、mode 和 option 对路由有直接影响。playAndRecordvoiceChatvideoChat、允许蓝牙、默认扬声器、AirPlay 等配置会改变系统可选路由集合。系统通过 route change notification 告诉 App 设备插拔、蓝牙切换、采样率变化或可用输入输出变化;App 需要重建音频图、更新 UI、重新配置 buffer duration 或采样率,并在必要时重新激活 session。

路由竞争常见失败可以分成四类。第一类是 profile 失败:App 期待蓝牙高音质播放,但进入通话后系统切到双向语音 profile,音质降低属于策略结果。第二类是输入源失败:App 以为正在用手机麦克风,实际 route 已切到蓝牙麦克风,录音质量和延迟随之改变。第三类是焦点和路由混淆:App 只处理 focus gain,却没有处理 route change,恢复播放后声音走错设备。第四类是格式变化失败:蓝牙、USB 或内置设备切换导致采样率、声道数或 buffer duration 变化,音频图未重建会产生无声、杂音或延迟异常。

因此,蓝牙、通话、VoIP 和媒体播放的排查顺序应与系统层级一致。先确认用户选择的设备和系统当前 route,再确认通话状态和 VoIP session 状态,然后检查 App 的 category / mode / AudioAttributes / focus gain,接着检查是否收到 route change / interruption / focus callback,最后才分析 HAL、driver 或硬件兼容性。这个顺序能防止把系统策略结果误判为播放器 bug。

111.7 Audio Focus / Audio Session 对用户体验的系统治理

Audio Focus 和 Audio Session 的共同目标,是把多个 App 的声音行为治理成符合用户当前任务的体验。系统治理的对象包括播放连续性、语音可懂度、通话可靠性、录音隐私、后台可控性、设备路由一致性和功耗边界。App 的设计目标应从“尽量保持自己的声音”转向“把自己的声音意图准确提交给系统,并对系统策略变化做可恢复响应”。

设计音乐 App 时,默认路径应是媒体播放、可后台、可锁屏控制、响应 duck、永久 focus loss 后等待用户重新播放。设计播客和听书 App 时,应强调 speech content,遇到导航、来电或语音助手时保存播放点,系统给出恢复信号且用户未改变意图时再恢复。设计导航 App 时,应使用短暂焦点或适合 spoken audio 的策略,让提示清晰出现并在结束后释放焦点。设计游戏 App 时,应区分背景音乐、音效和语音聊天,背景音乐可 duck,实时语音需要更强的通信 session 和路由处理。设计录音 App 时,应把麦克风权限、前台状态、录音指示器、route 和中断恢复放在同一条路径中。

跨平台设计可以使用同一组责任链,但入口字段不同。Android 的核心字段是 AudioAttributes、AudioFocusRequest、MediaSession、foreground service type、runtime permission 和 AudioDevice / route 观察。Apple 的核心字段是 AVAudioSession category、mode、option、active 状态、interruption notification、route change notification、Info.plist 用途说明和后台模式。共同的判断维度是:入口 API 是否表达真实用途,系统服务是否有足够策略信息,权限是否覆盖当前行为,后台资格是否用户可见,路由变化是否同步到播放器,失败时 UI 是否呈现真实状态。

下面把贯穿场景复盘成可迁移判断顺序。

阶段系统问题Android 检查点Apple 检查点用户可见结果
播客开始播放是否可获得播放焦点requestAudioFocus()、AudioAttributes、MediaSessionplayback category、session active、Now Playing声音开始,锁屏/通知可控制
切后台继续播放是否有长期播放资格MediaSessionService、mediaPlayback foreground service、通知UIBackgroundModes audio、playback category离开前台后继续播放
导航提示到来是否 duck、pause 或 mixtransient focus、may duck、speech contentduck / mix option、spoken audio mode背景音降低或暂停,提示清晰
电话呼入是否发生强中断focus loss、incoming call mute、MediaSession 状态interruption began、session deactivated播客停止或静音,电话优先
切蓝牙耳机路由是否改变device route、通信状态、profileroute change notification、category / option声音和麦克风切到耳机
通话结束是否恢复播放AUDIOFOCUS_GAIN、用户动作、播放状态interruption ended、shouldResume、用户动作按条件恢复或保持暂停

这个表的核心价值是把用户体验问题落到系统检查点。播客没有恢复,可能是永久焦点丢失、用户在中断中暂停、session 未重新激活、route change 后播放器未重建、后台服务已退出或系统策略拒绝。声音从错误设备输出,可能是 route change 未处理、蓝牙 profile 改变、通话 mode 未退出或用户选择的设备被系统覆盖。录音没有声音,可能是权限撤销、全局麦克风开关关闭、后台 microphone service 受限、输入 route 变更或通话占用。

最终设计原则可以压缩成一句话:音频 App 应以用户当前任务为中心声明系统可理解的音频意图,并把焦点变化、中断、后台资格、麦克风权限和路由变化全部纳入状态机。这样做的结果是,系统策略变化不再表现为随机暂停、突然变小、后台被杀、录音失败或蓝牙错路由,而是表现为可解释、可恢复、可由用户控制的音频体验。

最小自检任务

用户正在使用一个播客 App 听一段 40 分钟节目。App 已进入后台,锁屏界面显示正在播放。此时导航 App 播报转向提示,随后电话呼入。用户接听电话并切换到蓝牙耳机,通话结束后播客没有自动恢复。请按系统路径分析:哪些检查点能判断这是正常策略结果,哪些检查点能定位 App 的处理缺陷,哪些用户可见结果能帮助你区分 Audio Focus、Interruption、Background Audio、Microphone Permission 和 Route Change。

答案要点

应先把路径拆成播放、后台、导航提示、电话中断、蓝牙路由、通话结束六个阶段。播放阶段检查 Android 的 AudioAttributes、AudioFocusRequest、MediaSession,或 Apple 的 playback category、session active 和 Now Playing 状态。后台阶段检查 Android 是否使用 MediaSessionService、mediaPlayback foreground service 和媒体通知,或 Apple 是否声明 UIBackgroundModes audio 并使用合适 category。导航提示阶段检查播客是否标记为 speech content,导航是否请求 transient / may duck,Apple 侧是否使用 duck / mix / spoken audio 相关 option;播客被短暂停顿或降低音量通常属于策略结果。

电话呼入阶段应检查 focus loss 或 interruption began。Android 上来电可能触发焦点丢失、媒体静音或播放器暂停;Apple 上 session 会收到 interruption began 并失活。App 缺陷通常出现在状态保存:没有记录中断前播放位置、没有记录用户是否在中断期间按过暂停、没有在 interruption ended 或 focus gain 后重新同步播放器和 UI。通话结束后不自动恢复也可能是正常结果,例如系统没有给出恢复提示、用户中途暂停、焦点丢失属于 permanent,或 App 已退出后台播放资格。

蓝牙阶段应检查 route change。若通话切到蓝牙 HFP / HSP 或等价语音链路,媒体音质和路由改变属于系统策略;通话结束后没有回到预期输出设备,通常要检查 route change notification、通信 mode 是否退出、音频图是否按新采样率和设备重建。麦克风权限只在录音或 VoIP 输入路径中成为主检查点;单纯播客播放失败通常先看焦点、中断、后台和路由。用户可见证据包括锁屏播放状态、媒体通知、系统通话界面、蓝牙设备选择、麦克风指示器、权限弹窗、播放按钮状态和声音实际输出设备。

本章知识点总结

  • 焦点治理:Audio Focus 管理多 App 播放关系,App 声明用途,系统根据当前状态决定授予、duck、暂停、静音或失败。
  • Session 语义:Apple 通过 AVAudioSession category、mode 和 option 表达播放、录音、混音、duck 和通话类意图。
  • 版本边界:Android 8.0 引入更完整的 AudioFocusRequest 和自动 ducking,Android 12 以后系统对焦点丢失和来电静音有更强执行能力。
  • 中断恢复:Interruption 需要保存播放点、UI 状态和用户意图,恢复播放必须同时满足系统信号和用户意图。
  • Ducking 策略:Ducking 适合音乐中插入短提示,spoken audio 更适合暂停或显式处理回调。
  • 混音边界:Mixing 适合环境声、游戏音效和协作语音,exclusive 适合电话、闹钟、录音和强优先级任务。
  • 后台播放:Background Audio 需要用户可见控制面、媒体会话、合适服务或后台模式,并持续服从系统生命周期。
  • 媒体会话:MediaSession 或 Now Playing 把后台播放暴露给通知、锁屏、耳机、车机和系统控制器。
  • 麦克风权限:麦克风访问同时受到声明、用户授权、当前可见状态、后台资格、全局开关、录音 source 和系统指示器约束。
  • 前台服务:Android 的 mediaPlayback 和 microphone foreground service type 把长期播放或录音纳入用户可见执行模型。
  • 路由竞争:蓝牙、通话、VoIP 和媒体播放竞争真实输入输出设备,系统按 profile、通话状态、用户选择和 session 意图决策。
  • 蓝牙切换:A2DP 更偏媒体播放,HFP / HSP 更偏双向语音,通话切换会改变音质、延迟、麦克风和输出路径。
  • 排查顺序:音频问题应按用途声明、焦点或 session、权限、后台资格、路由变化、播放器状态和硬件路径逐层定位。
  • 用户体验:稳定音频体验来自系统可理解的意图声明,以及对焦点、中断、后台、权限和路由变化的完整状态机处理。