2016-08-06 11 views
4

私は指示hereに従っています。このテストプロジェクトをまとめて、オーディオ再生の中断を処理しました。特に、私は割り込みとしてデフォルトのiPhoneクロックアプリからのアラームを使用しています。中断ハンドラが呼び出されているが、 "間違ったタイプ"が2回現れたので、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") 
      } 
     } 
    } 

結果にハンドラをしている変更したこと、「終了」と「オーディオを再開」「音声が一時停止」「始め」のショーのすべてコンソールでは起動しますが、オーディオ再生は実際には再開されません。

注:.Ended中断が発生したときにそのif条件が真ではないので、私はif文をコメントアウトwhere option == .ShouldResumeplayer.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()がそうするようhandleInterruption()以内に起動してはいけません。

は&を再開する演劇を保証するものではありません(docsを参照)と呼ばれるようにaudioPlayerEndInterruption()を防ぐように思われます。代わりに.play()は、再開を保証するためにaudioPlayerEndInterruption()(その3つのバージョンのいずれか)内で呼び出さなければなりません。

さらに、AVAudioSessionは、@Simon Newsteadが指摘したオプション.MixWithOthersを指定する必要があります。アプリがバックグラウンドのときに中断してから再生を再開するにはユーザーがバックグラウンドに入ったときにアプリを続けて再生したい場合、アプリがバックグラウンドにある間に中断後にアプリが再生を再開したいと思うことは論理的です。実際、それはアップルミュージックアプリによって出現した動作です。

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() 
     } 
    } 
} 
関連する問題