我在这里遵循指示,我已经把这个测试项目放在一起来处理音频播放的中断.具体来说,我正在使用默认iphone时钟应用程序中的警报作为中断.似乎中断处理程序被调用但没有越过该let = interruptionType
行,因为" 错误类型 "出现两次.
import UIKit import AVFoundation class ViewController: UIViewController { var player = AVAudioPlayer() let audioPath = NSBundle.mainBundle().pathForResource("rachmaninov-romance-sixhands-alianello", ofType: "mp3")! func handleInterruption(notification: NSNotification) { guard let interruptionType = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? AVAudioSessionInterruptionType else { print("wrong type"); return } switch interruptionType { case .Began: print("began") // player is paused and session is inactive. need to update UI) player.pause() print("audio paused") default: print("ended") /**/ if let option = notification.userInfo?[AVAudioSessionInterruptionOptionKey] as? AVAudioSessionInterruptionOptions where option == .ShouldResume { // ok to resume playing, re activate session and resume playing // need to update UI player.play() print("audio resumed") } /**/ } } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. do { try player = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioPath)) player.numberOfLoops = -1 // play indefinitely player.prepareToPlay() //player.delegate = player } catch { // process error here } // enable play in background /sf/ask/17360801/ but this audio still gets interrupted by alerts do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) print("AVAudioSession Category Playback OK") do { try AVAudioSession.sharedInstance().setActive(true) print("AVAudioSession is Active") } catch let error as NSError { print(error.localizedDescription) } } catch let error as NSError { print(error.localizedDescription) } // add observer to handle audio interruptions // using 'object: nil' does not have a noticeable effect let theSession = AVAudioSession.sharedInstance() NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.handleInterruption(_:)), name: AVAudioSessionInterruptionNotification, object: theSession) // start playing audio player.play() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
此外,按照这里的想法,我已经修改了处理程序
func handleInterruption(notification: NSNotification) { //guard let interruptionType = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? AVAudioSessionInterruptionType else { print("wrong type"); return } if notification.name != AVAudioSessionInterruptionNotification || notification.userInfo == nil{ return } var info = notification.userInfo! var intValue: UInt = 0 (info[AVAudioSessionInterruptionTypeKey] as! NSValue).getValue(&intValue) if let interruptionType = AVAudioSessionInterruptionType(rawValue: intValue) { switch interruptionType { case .Began: print("began") // player is paused and session is inactive. need to update UI) player.pause() print("audio paused") default: print("ended") /** / if let option = notification.userInfo?[AVAudioSessionInterruptionOptionKey] as? AVAudioSessionInterruptionOptions where option == .ShouldResume { // ok to resume playing, re activate session and resume playing // need to update UI player.play() print("audio resumed") } / **/ player.play() print("audio resumed") } } }
结果是所有"开始","音频暂停","结束"和"音频恢复"都显示在控制台中,但音频播放实际上并未恢复.
注意:我移动了player.play()
注释掉的where option == .ShouldResume
if语句的外部,因为if
在.Ended
发生中断时该条件不正确.
(代表OP发布).
找到解决方案 在这里讨论后,将其插入viewDidLoad()
do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.MixWithOthers) } catch { }
在警报中断点击"确定"后,音频播放继续.与之前提到的不同,该解决方案不需要中断处理程序(@Leo Dabus已删除).
但是,如果您正在使用中断处理程序,则.play()
不得在其中调用,handleInterruption()
因为这样做并不能保证播放恢复并且似乎阻止audioPlayerEndInterruption()
调用(请参阅文档).相反,.play()
必须在audioPlayerEndInterruption()
(3个版本中的任何一个版本)中调用以保证恢复.
此外,如果您希望应用程序在应用程序处于后台时中断后继续播放,则AVAudioSession
必须在.MixWithOthers
@Simon Newstead注明选项.似乎如果用户希望应用程序在进入后台时继续播放,则假设用户还希望应用程序在应用程序处于后台时中断后继续播放是合乎逻辑的.实际上,这就是Apple Music应用程序所展示的行为.
@rockhammers的建议对我有用。这里
课前
let theSession = AVAudioSession.sharedInstance()
在viewDidLoad中
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.handleInterruption(notification:)), name: NSNotification.Name.AVAudioSessionInterruption, object: theSession)
然后功能
func handleInterruption(notification: NSNotification) { print("handleInterruption") guard let value = (notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? NSNumber)?.uintValue, let interruptionType = AVAudioSessionInterruptionType(rawValue: value) else { print("notification.userInfo?[AVAudioSessionInterruptionTypeKey]", notification.userInfo?[AVAudioSessionInterruptionTypeKey]) return } switch interruptionType { case .began: print("began") vox.pause() music.pause() print("audioPlayer.playing", vox.isPlaying) /**/ do { try theSession.setActive(false) print("AVAudioSession is inactive") } catch let error as NSError { print(error.localizedDescription) } pause() default : print("ended") if let optionValue = (notification.userInfo?[AVAudioSessionInterruptionOptionKey] as? NSNumber)?.uintValue, AVAudioSessionInterruptionOptions(rawValue: optionValue) == .shouldResume { print("should resume") // ok to resume playing, re activate session and resume playing /**/ do { try theSession.setActive(true) print("AVAudioSession is Active again") vox.play() music.play() } catch let error as NSError { print(error.localizedDescription) } play() } } }