健身APP遇远程推送通知打断后,如何重置duckOthers音频会话?
嘿,这个场景我太熟悉了——很多健身类APP都会遇到音频会话被通知打断后duck失效的问题。别担心,核心思路就是监听音频会话的中断事件,在中断结束后重新激活duckOthers设置,下面是具体的实现细节(以iOS的AVFoundation为例):
具体解决方案步骤
1. 先注册音频会话中断通知
首先你需要在APP初始化或者音频模块启动时,注册AVAudioSessionInterruptionNotification,这样当音频会话被外部事件(比如带音效的推送通知)中断时,你的代码能及时收到回调:
// 示例:在ViewController的viewDidLoad或者音频管理单例的init方法中注册 NotificationCenter.default.addObserver( self, selector: #selector(handleAudioSessionInterruption(_:)), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance() )
2. 处理中断结束的回调逻辑
在回调方法里,我们需要判断中断的类型是“结束”,然后触发重置操作。这里要注意区分中断结束时的shouldResume选项,确保不会重复操作:
@objc private func handleAudioSessionInterruption(_ notification: Notification) { guard let userInfo = notification.userInfo, let typeRawValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt, let interruptionType = AVAudioSession.InterruptionType(rawValue: typeRawValue) else { return } // 当中断事件结束时,触发重置 if interruptionType == .ended { let interruptionOptions = userInfo[AVAudioSessionInterruptionOptionKey] .flatMap { $0 as? UInt } .map(AVAudioSession.InterruptionOptions.init(rawValue:)) // 如果系统提示需要恢复会话,或者没有明确选项,都执行重置 if interruptionOptions?.contains(.shouldResume) ?? true { resetDuckOthersAudioSession() } } }
3. 核心:重置duckOthers音频会话
这个方法是关键,我们需要重新配置音频会话的类别和选项,确保duckOthers被正确设置,然后重新激活会话:
private func resetDuckOthersAudioSession() { let audioSession = AVAudioSession.sharedInstance() do { // 这里用你原本设置的会话类别,比如.playback(因为要主动播放短音频) try audioSession.setCategory( .playback, mode: .default, options: [.duckOthers] ) // 重新激活会话 try audioSession.setActive(true) } catch { print("重置音频会话失败: \(error.localizedDescription)") // 这里可以根据业务需求添加错误处理,比如提示用户 } }
额外要注意的细节
- 确保你最初的音频会话类别是
.playback,而不是.ambient——.ambient类别不会触发duckOthers效果,因为它是和其他音频共存的低优先级类别。 - 如果你的短音频是用
AVPlayer播放的,重置会话后,可能需要检查播放器的状态,必要时重新播放当前片段(不过大部分情况下,会话激活后AVPlayer会自动恢复播放)。 - 尽量把重置操作做得轻量,避免频繁触发影响用户体验——毕竟通知音效一般都是短暂的,用户几乎察觉不到重置的过程。
内容的提问来源于stack exchange,提问作者SentryDevCo
相关产品推荐
相关产品推荐

