Audio Focus — Android机制,用于调节多个应用同时使用音频输出。它防止声音重叠:当一个应用开始播放时,系统自动静音或暂停另一个应用。根据Android Developer Guide, 2026,Audio Focus是所有播放音频的应用的必备功能 — 没有它Google Play可能拒绝更新。
要点
Audio Focus — Android中一个集中的音频仲裁系统。当一个应用请求焦点时,系统检查是否有活动的焦点“所有者”,并向其发送丢失通知。所有者可以根据焦点类型降低音量(duck)、暂停播放或忽略。
在Android 8.0之前,焦点通过AudioManager.requestAudioFocus(callback, stream, durationHint)管理。从Android 8.0开始,出现了AudioFocusRequest,增加了指定请求类型和自动恢复焦点的功能。在Android 12中,机制得到加强 — 所有媒体播放器必须正确处理焦点才能在Google Play上发布。
根据Google I/O 2024,约15%的用户在音频应用评论中的投诉与声音重叠有关。正确实现Audio Focus可以解决这个问题,并将用户体验在收听时间上提高30%。
重要的是要理解Audio Focus并不自动管理播放。它只通知应用焦点事件。应用自己决定:暂停播放器、降低音量或继续播放。系统不强制 — 这是一个架构决策,留给开发者决定。
例外情况是导航应用(Google Maps、Yandex.Maps)。它们可以请求AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK类型的焦点,此时现有播放器被调低音量,语音提示在上方播放。提示结束后,播放器自动恢复音量。
系统维护一个活动的音频焦点所有者。当新应用请求焦点时,系统确定优先级并向当前所有者发送事件。如果当前所有者忽略事件并继续大声播放,系统不施加惩罚 — 责任完全在播放器上。
焦点请求包含durationHint参数,告知系统预计持续时间:AUDIOFOCUS_GAIN(长时间播放 — 音乐、播客),AUDIOFOCUS_GAIN_TRANSIENT(短时间 — 通知声音、导航),AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK(短时间,允许调低现有播放器音量)。
焦点丢失时,应用收到三个代码之一:AUDIOFOCUS_LOSS(长期丢失 — 其他应用启动了音乐),AUDIOFOCUS_LOSS_TRANSIENT(临时丢失 — 通话、通知),AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK(临时丢失,可调低音量)。每个代码需要各自的反应。
用户在应用A中听音乐。来电 — 应用B(电话)请求AUDIOFOCUS_GAIN_TRANSIENT。系统向应用A发送AUDIOFOCUS_LOSS_TRANSIENT。播放器暂停。通话结束后,应用B释放焦点,系统通过AUDIOFOCUS_GAIN通知应用A — 播放器恢复播放。整个链耗时不到50毫秒。
正确选择durationHint — 实现Audio Focus时的关键决定。类型选择错误会导致声音重叠、播放器无故停止或用户烦躁。
| 请求类型 | 场景 | 所有者反应 |
|---|---|---|
| AUDIOFOCUS_GAIN | 启动音乐、播客 | AUDIOFOCUS_LOSS — 播放器应停止 |
| AUDIOFOCUS_GAIN_TRANSIENT | 通话、语音通知 | AUDIOFOCUS_LOSS_TRANSIENT — 暂停 |
| AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK | GPS提示、短信号 | AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK — 降低音量 |
| AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE | 语音搜索、录音 | AUDIOFOCUS_LOSS — 完全停止 |
Duck — 在次要声音播放期间将主播放器音量临时降低到20–30%。Android通过AudioManager.adjustSuggestedStreamVolume提供手动duck的API,但大多数播放器用自己的方法实现调低音量。根据Android Documentation (2026),duck处理不应超过3秒,之后音量恢复。
要正确实现Audio Focus,需要按顺序执行三个步骤:创建请求,在播放前请求焦点,在回调中处理事件。使用AndroidX media中的AudioFocusRequestCompat可确保与所有Android版本兼容。
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val focusRequest = AudioFocusRequestCompat.Builder()
.setFocusGain(AudioManagerCompat.AUDIOFOCUS_GAIN)
.setOnAudioFocusChangeListener(focusChangeListener)
.build()
val result = AudioManagerCompat.requestAudioFocus(audioManager, focusRequest)
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
startPlayback()
}
焦点请求应在每次用户按下Play时在开始播放之前执行。如果结果是AUDIOFOCUS_REQUEST_GRANTED — 开始播放。如果是DENIED — 向用户显示消息或延迟播放直到获得焦点。
private val focusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {
restoreVolume()
if (wasPlayingBeforeLoss) resumePlayback()
}
AudioManager.AUDIOFOCUS_LOSS -> {
pausePlayback()
wasPlayingBeforeLoss = false
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
pausePlayback()
wasPlayingBeforeLoss = true
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
duckVolume()
}
}
}
在回调中,区分AUDIOFOCUS_LOSS和AUDIOFOCUS_LOSS_TRANSIENT很重要。在第一种情况下,播放器不应自动恢复 — 用户明确启动了其他音频。在第二种情况下 — 可以在收到AUDIOFOCUS_GAIN时自动恢复。wasPlayingBeforeLoss标志帮助记住是否需要恢复播放。
private fun abandonAudioFocus() {
AudioManagerCompat.abandonAudioFocusRequest(audioManager, focusRequest)
}
调用abandonAudioFocusRequest通知系统应用不再需要焦点。这在暂停和停止播放器时调用很重要。如果不释放焦点,请求AUDIOFOCUS_GAIN的其他应用将不会收到LOSS,声音会重叠。
正确处理焦点丢失 — 通过Google Play审核的关键要求。处理不当会导致负面评价:用户抱怨音乐在通话期间或导航之上继续播放。
收到AUDIOFOCUS_LOSS时,播放器应停止并在明确按下Play之前不恢复。在AUDIOFOCUS_LOSS_TRANSIENT(通话、通知)时,播放器暂停并在焦点恢复时自动恢复。在AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK时,播放器在外部音频期间临时将音量降低到20–30%。
根据Android Developer Guide (2026),duck应通过将AudioTrack的当前音量乘以0.2–0.3的系数来实现。不要使用AudioManager.setStreamVolume — 这会改变系统音量并影响其他应用。Duck仅在自己的播放器端执行。
在来电时,系统通过电话应用自动请求AUDIOFOCUS_GAIN_TRANSIENT。播放器收到AUDIOFOCUS_LOSS_TRANSIENT并暂停。通话结束后或如果用户拒绝通话,焦点返回 — 播放器自动恢复播放,如果是音乐播放器的话。
对于导航应用(Google Maps),在语音提示时使用AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK。播放器被调低音量2–3秒,然后音量恢复。如果用户听的是播客而不是音乐,与其duck不如暂停 — 在播客中每一秒都很重要。
在实践中,开发者会遇到几个标准场景,其中Audio Focus的行为不同。让我们看下典型情况及正确的反应。
实现一个标志来记住音乐在焦点丢失前是否正在播放很重要。如果用户自己按了暂停然后来了电话 — 不需要恢复。标志在用户明确暂停时重置,在播放开始时设置。
根据Google的UX研究(2024),通话后自动恢复将用户满意度提高22%。但如果播放器在用户已经开始观看视频后恢复 — 这会引起烦躁。wasPlayingBeforeLoss标志防止错误的恢复。
常见问题
是的,从Android 12开始,Google Play建议所有播放音频的应用实现Audio Focus。Music & Audio类别的应用必须实现才能发布。忽视可能导致更新被拒绝。
启动播放器,然后打开另一个音频应用(例如YouTube Music)。您的播放器应暂停。然后关闭YouTube Music — 播放器应自动恢复。对于duck测试,使用带有语音提示的Google Maps。
系统通知:“另一个应用需要播放一个短声音 — 调低您的播放器”。这对于语音提示和短通知是最佳的。外部音频结束后,音量无需手动干预即可恢复。
形式上可以 — 系统不强制。但在实践中这意味着声音重叠。用户将同时听到音乐和通话,导致负面体验。Google建议始终通过停止播放器来处理AUDIOFOCUS_LOSS。
在iOS上,由AVAudioSession管理的Audio Session扮演类似角色。机制相似:类别和选项决定了声音重叠时的行为。然而API和规则有根本性的不同 — 每个框架实现方式不同。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。