我使用AVAudioPlayer播放音频。我启用了后台音频,并且音频会话配置正确。
我实现了audioSessionGotInterrupted
方法,以便在音频会话中断时被通知。这是我目前的代码:
@objc private func audioSessionGotInterrupted(note: NSNotification) {
guard let userInfo = note.userInfo,
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSessionInterruptionType(rawValue: typeValue) else {
return
}
if type == .began {
print("interrupted")
// Interruption began, take appropriate actions
player.pause()
saveCurrentPlayerPosition()
}
else if type == .ended {
if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt {
let options = AVAudioSessionInterruptionOptions(rawValue: optionsValue)
if options == .shouldResume {
print("restored")
// Interruption Ended - playback should resume
setupPlayer()
player.play()
} else {
// Interruption Ended - playback should NOT resume
// just keep the player paused
}
}
}
}
现在我执行以下操作:
我的commandCenter play()
方法按预期调用。但是,使用audioSessionGotInterrupted
调用type == .began
方法。
怎么可能?我希望不会发现此类通知或至少.ended
我使用的是iOS 10 beta 8。
答案 0 :(得分:2)
虽然上面的答案是正确的,但它仍然在我的应用程序中造成了很多麻烦,并导致了很多用于检查多种情况的样板代码。
如果您阅读了AVAudioSessionInterruptionWasSuspendedKey
的说明,则说明如果未在将应用发送到后台(每次锁定屏幕时发生)之前停用音频会话,就会引发通知。
要解决此问题,您仅需在将应用发送到后台时没有声音播放时停用会话,然后在声音播放时将其激活。之后,您将不会收到AVAudioSessionInterruptionWasSuspendedKey
通知。
NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: .main) { sender in
guard self.player.isPlaying == false else { return }
self.setSession(active: false)
}
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { sender in
guard self.player.isPlaying else { return }
self.setSession(active: true)
}
func setSession(active: Bool) -> Bool {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(.playback, mode: .default)
try session.setActive(active)
return true
} catch let error {
print("*** Failed to activate audio session: \(error.localizedDescription)")
return false
}
}
注意:激活会话可能不是必需的,因为它由Apple的内部回放类(例如AVPlayer)处理,但是手动进行是一种很好的做法。
答案 1 :(得分:1)
检查
从iOS 10开始,系统将停用大多数应用程序的音频会话,以响应应用程序进程被暂停的情况。当应用再次开始运行时,它将收到一个中断通知,说明其音频会话已被系统停用。该通知必须延迟时间,因为只有在应用再次运行时才能传递该通知。如果您的应用程序的音频会话由于此原因而被暂停,则userInfo词典将包含值为true的AVAudioSessionInterruptionWasSuspendedKey键。
如果您的音频会话配置为不可混合(播放,playAndRecord,soloAmbient和multiRoute类别的默认行为),建议您在去时不积极使用音频的情况下停用音频会话进入后台。这样做可以避免您的音频会话被系统停用(并收到此令人困惑的通知)。
if let reason = AVAudioSessionInterruptionType(rawValue: reasonType as! UInt) {
switch reason {
case .began:
var shouldPause = true
if #available(iOS 10.3, *) {
if let _ = notification.userInfo?[AVAudioSessionInterruptionWasSuspendedKey] {
shouldPause = false
}
}
if shouldPause {
self.pause()
}
break
case .ended:
break
}
}