什么是 AudioFocus?为什么在播放音乐时需要申请它?

解读

国内面试官问这道题,并不是想听你背定义,而是考察“对 Android 音频并发体系的完整理解”。
一句话:AudioFocus 是 Android 5.0 之后官方强推的“音频礼貌”机制,用来解决“多个 App 同时出声”这一中国式乱象。
答不到“系统级仲裁 + 应用级回调 + 用户感知”这三层,基本会被认为“没做过音乐/车载/长语音业务”。

知识点

  1. 音频焦点三要素
    申请类型:AUDIOFOCUS_GAIN / _GAIN_TRANSIENT / _GAIN_TRANSIENT_MAY_DUCK / _GAIN_TRANSIENT_EXCLUSIVE
    失去原因:AUDIOFOCUS_LOSS / _LOSS_TRANSIENT / _LOSS_TRANSIENT_CAN_DUCK
    回调通道:AudioManager.OnAudioFocusChangeListener(主线程回调,必须同步处理)

  2. 系统仲裁规则(国内 ROM 共性)
    电话 > 语音助手 > 导航 > 多媒体 > 游戏 > 通知
    同一优先级按“申请时间戳”先到先得;厂商白名单(微信、抖音、高德)可插队。

  3. 焦点与播放器生命周期绑定
    获得焦点 → start/play
    失去永久焦点 → pause+释放资源
    失去临时焦点 → pause/duck(降低音量到 20% 以下,不可静音)
    重新获得 → 恢复播放/音量

  4. 8.0 之后 AudioFocusRequest 必填
    必须显式指定 AudioAttributes(USAGE_MEDIA / USAGE_ASSISTANCE_NAVIGATION 等),否则系统直接拒掉;
    接受延迟焦点(setAcceptsDelayedFocusGain)与暂停键(setWillPauseWhenDucked)两个开关决定 duck 策略。

  5. 国内合规与体验红线
    工信部 164 号文:后台播放必须响应电话、导航、语音助手,否则按“恶意常驻”下架;
    应用商店自动化测试会注入 AudioFocus 事件,30 s 内不暂停直接打回。

  6. 常见翻车点
    在 Service 里申请焦点,但 Service 被 kill 没释放 → 系统锁死音频通道,用户手机“失声”投诉;
    忘记处理 LOSS_TRANSIENT_CAN_DUCK,直接把音量设 0 → 用户切回 App 没声音,一星差评;
    直播场景用 GAIN_TRANSIENT 抢焦点,导致用户后台音乐被永久停掉 → 被商店归类为“恶意打断”。

答案

AudioFocus 是 Android 提供的系统级音频仲裁机制,用于在多 App 并发场景下统一调度播放权。
申请流程:

  1. 构造 AudioFocusRequest,声明 AudioAttributes、焦点类型、是否接受 duck;
  2. 调用 AudioManager.requestAudioFocus(),返回 AUDIOFOCUS_REQUEST_GRANTED 才允许 start();
  3. 实现 OnAudioFocusChangeListener,在 LOSS 时 pause/release,在 LOSS_TRANSIENT_CAN_DUCK 时把音量降到 20% 以下;
  4. 播放结束或界面退出,必须 abandonAudioFocus(),否则系统拒绝后续申请。

不申请的后果:

  • 用户一边听歌一边进你的 App,两边同时外放,体验极差;
  • 国内 ROM 的白名单机制会直接把你静音,甚至杀进程;
  • 应用商店合规检测不通过,版本被驳回或下架。

因此,播放音乐前必须先拿到 AudioFocus,并在整个播放生命周期内正确响应焦点回调,这是国内上线音频类 App 的硬性门槛。

拓展思考

  1. 折叠屏/车载双声道场景:系统可能同时输出两路音频(导航左声道、音乐右声道),此时焦点策略由车载服务(CarAudioService)重新映射,App 需通过 CarAudioManager 申请 CarAudioFocus,否则被强制静音。
  2. 多实例播放器:抖音极速版与主版共存,使用同一 UID,系统把二者视为同一“音频任务”,需在内部再用 UUID 区分焦点,避免 A 实例失去焦点导致 B 实例被误杀。
  3. 低延迟场景(耳返/K 歌):AAudio + EXCLUSIVE 模式会绕过 AudioFlinger 混音,焦点系统仍生效,但回调延迟从 50 ms 降到 5 ms,要求焦点监听线程与渲染线程同一线程模型,否则出现爆音。
  4. 未来隐私沙盒:Android 14 限制后台启动前台服务,音频焦点申请将绑定 TOP_APP 状态,后台播放必须迁移到 MediaSession + MediaBrowserService,焦点请求由系统代理,App 无法直接调用 requestAudioFocus,需提前适配。