首页 文章

为什么AVPlayer在后台不能继续播放下一首歌?

提问于
浏览
1

我一直在使用AVPlayer从远程源播放音乐 . 我获取URL,使用一个来创建一个AVPlayerItem,然后我将其与我的AVPlayer实例关联 . 我将一个观察者添加到我与玩家关联的项目中,以观察项目何时完成播放( AVPlayerItemDidPlayToEndTimeNotification ) . 当观察者在项目结束时通知我时,我然后创建一个新的AVPlayerItem并重新执行它 . 这在iOS 9.2的前台和后台运行良好 .

Problem: 由于我已更新到iOS 9.3,因此无法在后台运行 . 这是相关代码:

var portionToBurffer = Double()
var player = AVPlayer()


func prepareAudioPlayer(songNSURL: NSURL, portionOfSongToBuffer: Double){

   self.portionToBuffer = portionOfSongToBuffer

   //create AVPlayerItem
   let createdItem = AVPlayerItem(URL: songNSURL)

   //Associate createdItem with AVPlayer
   player = AVPlayer(playerItem: createdItem)

   //Add item end observer
   NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerItemDidReachEnd:", name: AVPlayerItemDidPlayToEndTimeNotification, object: player.currentItem)

   //Use KVO to see how much is loaded
   player.currentItem?.addObserver(self, forKeyPath: "loadedTimeRanges", options: .New, context: nil)

}


override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "loadedTimeRanges" {
    if let loadedRangeAsNSValueArray = player.currentItem?.loadedTimeRanges {
        let loadedRangeAsCMTimeRange = loadedRangeAsNSValueArray[0].CMTimeRangeValue
        let endPointLoaded = CMTimeRangeGetEnd(loadedRangeAsCMTimeRange)
        let secondsLoaded = CMTimeGetSeconds(endPointLoaded)
        print("the endPointLoaded is \(secondsLoaded) and the duration is \(CMTimeGetSeconds((player.currentItem?.duration)!))")


        if secondsLoaded >= portionToBuffer  {
            player.currentItem?.removeObserver(self, forKeyPath: "loadedTimeRanges")
            player.play()
        }
    }
}
}



 func playerItemDidReachEnd(notification: NSNotification){
     recievedItemEndNotification()
 }





func recievedItemEndNotification() {
   //register background task
   bgTasker.registerBackgroundTask()

   if session.playlistSongIndex == session.playlistSongTitles.count-1 {
       session.playlistSongIndex = 0
   } else {
       session.playlistSongIndex += 1
   }

     prepareAudioPlayer(songURL: session.songURLs[session.playlistSongIndex], portionOfSongToBuffer: 30.00)

  }

我设置了断点,以便在后台调用 player.play() . 当我打印 player.rate 时,它读取 0.0 . 我检查了AVPlayerItem的属性 playbackLikelyToKeepUp ,它是 true . 我还确认,当应用程序在后台时,新URL已成功用于创建新的AVPlayerItem并与AVPlayer关联 . 我已经开启了音频和播放背景功能,我甚至打开了一个有限长度的后台任务(在上面的代码中为 bgTasker.registerBackgroundTask ) . 不知道发生了什么 .

我找到了THIS但我不确定它有帮助 . 任何建议都会很棒,谢谢

2 回答

  • 0

    当观察者在项目结束时通知我时,我然后创建一个新的AVPlayerItem并重新执行

    但问题是同时游戏停止,规则是只有当你在前台玩并继续在后台玩游戏时才允许进行背景游戏 .

    我建议使用AVQueuePlayer而不是AVPlayer . 这将允许您在当前项目仍在播放时将下一个项目排入队列 - 因此,我们可能希望,这将被视为继续播放 .

  • 0

    我遇到了类似的问题,我在谷歌搜索了很多网站,但没有找到答案 .

    现象

    我的应用程序的问题是,当我开始播放音频,并将应用程序转换为背景时,它将完成当前音频的播放,并且当播放第二个音频时,它将加载一些数据,但之后它会停止,如果我将应用程序转到前台,它将播放音频 .

    解决方案

    我的解决方案是添加以下调用 .

    UIApplication.shared.beginReceivingRemoteControlEvents()

    因此启用后台音频功能是不够的,我们需要开始接收远程控制器事件 .

相关问题