2016-08-06 3 views
4

지침 here을 따르고 있습니다. 오디오 재생 중단을 처리하기 위해이 테스트 프로젝트를 구성했습니다. 특히, 기본 iphone 시계 앱의 알람을 중단으로 사용하고 있습니다. 인터럽트 처리기가 호출되었지만 "wrong type"이 두 번 나타 났으므로 let = interruptionType 행을 지났습니다.Swift에서 중단 후 오디오를 다시 시작하는 방법은 무엇입니까?

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 https://stackoverflow.com/a/30280699/1827488 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. 
    } 
} 

또한, 아이디어 here 다음, 나는

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") 
      } 
     } 
    } 

결과에 핸들러입니다 수정 한 것을, "종료"와 "오디오 재개" "오디오가 일시 중지", "시작"공연의 모든 오디오 재생은 실제로 재개되지 않습니다.

참고 : 그 if 조건이 참이 아니기 때문에 문이 .Ended 중단이 발생 where option == .ShouldResume 주석 때 경우의 player.play() 외부 이동했다.

+1

사과는 내가 수정 된 왜곡 표시를했다. 인터럽트 처리기가 호출 중입니다. – rockhammer

+0

괜찮아요. 몇 분만에 나를 데려 갈 수 있기 때문에 처음으로 아무 것도 쓰지 않을 것입니다. ... 계속 지켜봐 주시기 바랍니다. – rockhammer

+0

CW 대답을 편집 해 주셔서 감사합니다!전체 답변을 직접 다시 게시 하시려면 CW 버전을 삭제하고 귀하의 업 포스팅을 해드립니다. – halfer

답변

8

(OP 대신 게시 됨).

해결책을 찾았습니다! 토론 here에 따라, 알람 중단에 "OK"를 클릭 한 후

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

viewDidLoad()이 삽입, 오디오 재생은 계속했다. 앞서 언급 한 것과 달리이 솔루션에는 중단 처리기가 필요하지 않습니다 (@Leo Dabus가 제거한 이후). 당신이 인터럽트 핸들러를 사용하는 경우

그러나, .play()는 &이 (docs 참조) audioPlayerEndInterruption()가 호출 될 방지하기 위해 보인다 재개 재생을 보장하지 않습니다 그렇게으로 handleInterruption() 내에서 호출 할 수 없습니다. 대신 .play()은 재개를 보장하기 위해 audioPlayerEndInterruption() (3 가지 버전 중 하나) 내에서 호출되어야합니다.

또한 AVAudioSession은 @Simon Newstead가 지정한 옵션 .MixWithOthers이 있어야 앱이 배경에있을 때 앱이 중단 된 후에 다시 재생되기를 원할 것입니다. 사용자가 백그라운드로 들어갈 때 앱이 계속 재생되기를 원한다면 앱이 배경에있는 동안 중단 후 앱이 다시 재생되기를 원하는 것으로 가정하는 것이 합리적입니다. 사실 그것은 Apple Music 앱이 전시 한 행동입니다.

2

@rockhammers 제안이 저에게 효과적이었습니다. Here

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

있는 viewDidLoad

의 클래스

let theSession = AVAudioSession.sharedInstance() 

전에

그리고 기능

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() 
     } 
    } 
} 
관련 문제