How to resume audio after interruption in Swift?

前端 未结 2 860
误落风尘
误落风尘 2020-12-30 11:12

I am following instructions here, I\'ve put together this test project to handle interruptions to audio play. Specifically, I\'m using the alarm from the default iphone cloc

相关标签:
2条回答
  • 2020-12-30 11:52

    (Posted on behalf of the question author, after it was posted in the question).

    Solution found! Following discussion here, inserted this in viewDidLoad()

    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.MixWithOthers)
    } catch {        
    }
    

    After clicking "ok" on the alarm interruption, the audio play continued. Unlike previously noted, the solution does NOT require an interruption handler (which @Leo Dabus has since removed).

    However if you are using an interruption handler, .play() must NOT be invoked within handleInterruption() as doing so does NOT guarantee play to resume & seems to prevent audioPlayerEndInterruption() to be called (see docs). Instead .play() must be invoked within audioPlayerEndInterruption() (any of its 3 versions) to guarantee resumption.

    Furthermore, AVAudioSession must be give option .MixWithOthers noted by @Simon Newstead if you want your app to resume play after interruption when your app is in the background. It seems that if a user wants the app to continue playing when it goes into the background, it is logical to assume the user also wants the app to resume playing after an interruption while the app is in the background. Indeed that is the behaviour exhibited by the Apple Music app.

    0 讨论(0)
  • 2020-12-30 12:03

    @rockhammers suggestion worked for me. Here

    before class

    let theSession = AVAudioSession.sharedInstance()
    

    in viewDidLoad

        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.handleInterruption(notification:)), name: NSNotification.Name.AVAudioSessionInterruption, object: theSession)
    

    And then the Function

    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()
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题