Audio Focus:概念本质、模式及Android中的管理

作者: IT Sectr 发布日期: 2026-05-23 阅读时间: 8 分钟

Audio Focus — Android机制,用于调节多个应用同时使用音频输出。它防止声音重叠:当一个应用开始播放时,系统自动静音或暂停另一个应用。根据Android Developer Guide, 2026Audio Focus是所有播放音频的应用的必备功能 — 没有它Google Play可能拒绝更新。

要点

  • Audio Focus — Android系统机制,用于协调应用之间的音频播放而不产生声音重叠。
  • 焦点请求通过AudioManager.requestAudioFocus()执行,并指定播放类型和持续时间。
  • 系统通过AudioManager.OnAudioFocusChangeListener通知焦点变化,使用AUDIOFOCUS_GAIN、LOSS和DUCK代码。
  • 自动恢复 — 收到AUDIOFOCUS_LOSS时应用应暂停播放,并在AUDIOFOCUS_GAIN时恢复。
  • Android 12+要求必须使用AndroidX中的AudioFocusRequestCompat来创建焦点请求。

什么是Audio Focus?

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与媒体播放

重要的是要理解Audio Focus并不自动管理播放。它只通知应用焦点事件。应用自己决定:暂停播放器、降低音量或继续播放。系统不强制 — 这是一个架构决策,留给开发者决定。

例外情况是导航应用(Google Maps、Yandex.Maps)。它们可以请求AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK类型的焦点,此时现有播放器被调低音量,语音提示在上方播放。提示结束后,播放器自动恢复音量。

Audio Focus在Android中如何工作

系统维护一个活动的音频焦点所有者。当新应用请求焦点时,系统确定优先级并向当前所有者发送事件。如果当前所有者忽略事件并继续大声播放,系统不施加惩罚 — 责任完全在播放器上。

焦点请求包含durationHint参数,告知系统预计持续时间:AUDIOFOCUS_GAIN(长时间播放 — 音乐、播客),AUDIOFOCUS_GAIN_TRANSIENT(短时间 — 通知声音、导航),AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK(短时间,允许调低现有播放器音量)。

焦点丢失时,应用收到三个代码之一:AUDIOFOCUS_LOSS(长期丢失 — 其他应用启动了音乐),AUDIOFOCUS_LOSS_TRANSIENT(临时丢失 — 通话、通知),AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK(临时丢失,可调低音量)。每个代码需要各自的反应。

Audio Focus事件链

用户在应用A中听音乐。来电 — 应用B(电话)请求AUDIOFOCUS_GAIN_TRANSIENT。系统向应用A发送AUDIOFOCUS_LOSS_TRANSIENT。播放器暂停。通话结束后,应用B释放焦点,系统通过AUDIOFOCUS_GAIN通知应用A — 播放器恢复播放。整个链耗时不到50毫秒。

Audio Focus请求的类型和模式

正确选择durationHint — 实现Audio Focus时的关键决定。类型选择错误会导致声音重叠、播放器无故停止或用户烦躁。

请求类型场景所有者反应
AUDIOFOCUS_GAIN启动音乐、播客AUDIOFOCUS_LOSS — 播放器应停止
AUDIOFOCUS_GAIN_TRANSIENT通话、语音通知AUDIOFOCUS_LOSS_TRANSIENT — 暂停
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCKGPS提示、短信号AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK — 降低音量
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE语音搜索、录音AUDIOFOCUS_LOSS — 完全停止

AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK的特性

Duck — 在次要声音播放期间将主播放器音量临时降低到20–30%。Android通过AudioManager.adjustSuggestedStreamVolume提供手动duck的API,但大多数播放器用自己的方法实现调低音量。根据Android Documentation (2026),duck处理不应超过3秒,之后音量恢复。

在代码中实现Audio Focus

要正确实现Audio Focus,需要按顺序执行三个步骤:创建请求,在播放前请求焦点,在回调中处理事件。使用AndroidX media中的AudioFocusRequestCompat可确保与所有Android版本兼容。

创建和执行Audio Focus请求

kotlin
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 — 向用户显示消息或延迟播放直到获得焦点。

焦点变化处理回调

kotlin
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_LOSSAUDIOFOCUS_LOSS_TRANSIENT很重要。在第一种情况下,播放器不应自动恢复 — 用户明确启动了其他音频。在第二种情况下 — 可以在收到AUDIOFOCUS_GAIN时自动恢复。wasPlayingBeforeLoss标志帮助记住是否需要恢复播放。

释放Audio Focus

kotlin
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的行为不同。让我们看下典型情况及正确的反应。

  • 音乐 + 通话 — 播放器暂停(AUDIOFOCUS_LOSS_TRANSIENT)。通话后自动恢复,如果用户未在播放器中执行操作。
  • 音乐 + 导航 — 播放器在语音提示期间被调低音量(DUCK)。音量在提示语结束后恢复。
  • 用户启动了其他应用 — 播放器收到AUDIOFOCUS_LOSS并停止。只能通过Play按钮恢复。
  • 视频 + 后台音乐 — 视频播放器请求AUDIOFOCUS_GAIN。音乐播放器收到LOSS并停止。
  • 语音搜索(Google Assistant) — 应用收到AUDIOFOCUS_LOSS_TRANSIENT,暂停并在助手回答后自动恢复。

焦点丢失后自动恢复

实现一个标志来记住音乐在焦点丢失前是否正在播放很重要。如果用户自己按了暂停然后来了电话 — 不需要恢复。标志在用户明确暂停时重置,在播放开始时设置。

根据Google的UX研究(2024),通话后自动恢复将用户满意度提高22%。但如果播放器在用户已经开始观看视频后恢复 — 这会引起烦躁。wasPlayingBeforeLoss标志防止错误的恢复。

常见问题

Audio Focus对所有音频应用都是强制性的吗?

是的,从Android 12开始,Google Play建议所有播放音频的应用实现Audio Focus。Music & Audio类别的应用必须实现才能发布。忽视可能导致更新被拒绝。

如何检查Audio Focus是否正常工作?

启动播放器,然后打开另一个音频应用(例如YouTube Music)。您的播放器应暂停。然后关闭YouTube Music — 播放器应自动恢复。对于duck测试,使用带有语音提示的Google Maps。

AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK在实践中是什么?

系统通知:“另一个应用需要播放一个短声音 — 调低您的播放器”。这对于语音提示和短通知是最佳的。外部音频结束后,音量无需手动干预即可恢复。

可以拒绝Audio Focus丢失请求吗?

形式上可以 — 系统不强制。但在实践中这意味着声音重叠。用户将同时听到音乐和通话,导致负面体验。Google建议始终通过停止播放器来处理AUDIOFOCUS_LOSS。

Audio Focus在除Android之外的其他平台上工作吗?

在iOS上,由AVAudioSession管理的Audio Session扮演类似角色。机制相似:类别和选项决定了声音重叠时的行为。然而API和规则有根本性的不同 — 每个框架实现方式不同。

总结

  • Audio Focus — Android中的系统音频仲裁器,防止来自不同应用的声音重叠。
  • 焦点请求通过AudioFocusRequestCompat执行,指定durationHint:GAIN、TRANSIENT或TRANSIENT_MAY_DUCK。
  • OnAudioFocusChangeListener回调处理四个事件:GAIN、LOSS、LOSS_TRANSIENT和LOSS_TRANSIENT_CAN_DUCK。
  • AUDIOFOCUS_LOSS时播放器停止,TRANSIENT时 — 暂停并自动恢复,DUCK时 — 调低音量。
  • 记住wasPlayingBeforeLoss标志很重要,以防止在用户明确暂停后恢复播放。
  • 通过abandonAudioFocusRequest释放焦点在暂停和停止播放器时是必需的。
  • 在iOS上,Audio Focus的等效物是Audio Session(AVAudioSession),拥有自己的类别和模式。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读