如何在 Swift 2 / AVPlayer 中恢复背景音频?

问题描述 投票:0回答:5

我正在学习 Swift 作为我的第一门编程语言。

我花了好几个小时才在中断(例如通话)后恢复背景音频播放

应该发生什么:

    当应用程序进入后台时,音频继续播放(有效)
  1. 被电话打断时,收到打断开始通知 (有效)
  2. 通话结束时,收到中断通知 结束(有效)
  3. 继续播放音频(
  4. 不起作用 - 听不到任何声音
非常感谢任何帮助!谢谢

备注:

    该应用程序已注册背景音频,并且在中断之前可以正常播放
  1. 我尝试过有或没有时间延迟来恢复播放 - 都不起作用

代码:

import UIKit import AVFoundation var player: AVQueuePlayer! class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) try AVAudioSession.sharedInstance().setActive(true, withOptions: .NotifyOthersOnDeactivation) } catch { } let songNames = ["music"] let songs = songNames.map { AVPlayerItem(URL: NSBundle.mainBundle().URLForResource($0, withExtension: "mp3")!) } player = AVQueuePlayer(items: songs) let theSession = AVAudioSession.sharedInstance() NSNotificationCenter.defaultCenter().addObserver(self, selector:"playInterrupt:", name:AVAudioSessionInterruptionNotification, object: theSession) player.play() } func playInterrupt(notification: NSNotification) { if notification.name == AVAudioSessionInterruptionNotification && notification.userInfo != nil { var info = notification.userInfo! var intValue: UInt = 0 (info[AVAudioSessionInterruptionTypeKey] as! NSValue).getValue(&intValue) if let type = AVAudioSessionInterruptionType(rawValue: intValue) { switch type { case .Began: print("aaaaarrrrgggg you stole me") player.pause() case .Ended: let timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: "resumeNow:", userInfo: nil, repeats: false) } } } } func resumeNow(timer : NSTimer) { player.play() print("attempted restart") } }
    
ios swift audio avfoundation avplayer
5个回答
6
投票
终于收到了!

解决方案:通过将 setCategory 行更改为:

添加可混合选项

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: .mixWithOthers )
    

1
投票
我编写了这样的代码,并成功恢复了通话结束时的音频。我是在 Xcode 6.4 上构建的,并在我的 iPhone 4S 上运行该应用程序。

var player: AVQueuePlayer! = nil override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func viewDidAppear(animated: Bool) { super.viewDidAppear(true) var song = AVPlayerItem(URL: NSBundle.mainBundle().URLForResource("AlmostAYearAgo", withExtension: "mp3")!) player = AVQueuePlayer(items: [song]) let theSession = AVAudioSession.sharedInstance() NSNotificationCenter.defaultCenter().addObserver(self, selector: "playInterrupt:", name: AVAudioSessionInterruptionNotification, object: theSession) player.play() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func playInterrupt(notification: NSNotification) { if notification.name == AVAudioSessionInterruptionNotification && notification.userInfo != nil { var info = notification.userInfo! var intValue: UInt = 0 (info[AVAudioSessionInterruptionTypeKey] as! NSValue).getValue(&intValue) if let type = AVAudioSessionInterruptionType(rawValue: intValue) { switch type { case .Began: print("aaaaarrrrgggg you stole me") player.pause() case .Ended: let timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: "resumeNow:", userInfo: nil, repeats: false) } } } } func resumeNow(timer : NSTimer) { player.play() print("attempted restart") }
    

0
投票
对我来说,结束中断后重新加载播放器解决了问题:

func interruptionNotification(_ notification: Notification) { guard let type = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt, let interruption = AVAudioSessionInterruptionType(rawValue: type) else { return } if interruption == .ended && playerWasPlayingBeforeInterruption { player.replaceCurrentItem(with: AVPlayerItem(url: radioStation.url)) play() } }
    

0
投票
对我来说,增加延迟可以解决问题:

@objc func handleInterruption(_ notification: Notification) { // audio interuption - restart audio player for any type (began or ended) to make sure it keeps going guard let type = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt, let interruption = AVAudioSession.InterruptionType(rawValue: type) else { NSLog("*** Incorrect notification format") return } if interruption == .began { NSLog("audio interruption: began") } else if interruption == .ended { NSLog("audio interruption: ended") if isRunning { // Sadly this lengthy delay hack is necessary, otherwise sounds won't play :( DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) { self.start() // sets up the audio session, connects nodes, starts the engine, plays the player, and sets isRunning to true } } } }
延迟确实需要这么长。 2s 并没有达到目的。


-1
投票
西蒙,我绝对确认一下。我花了2天时间找它!如果您只使用:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)

 那么无论你做什么,如果你使用:
,你的播放器都不会恢复播放音频:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.MixWithOthers)

然后它就完美地工作了,并且在应用程序处于后台时接到电话后将恢复。

谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.