播放列表不会在后台模式下继续播放

时间:2017-08-11 11:57:23

标签: swift avfoundation avplayer

在设备锁定时,我无法在后台模式下播放播放列表。它在锁定时播放当前音频,但我无法在后台模式下转到下一个音频文件。

我正在使用collectionView和自定义单元格,我允许用户点击并播放该单元格中的音频。我让它自动播放,所以当音频完成后,它会自动滚动到下一个单元格并播放该单元格,依此类推。所有这一切都有效,它只是在设备被锁定时,在后台模式下,下一个音频单元的播放停止并且不会继续。我在下一个音频文件的加载之间有3秒的调度延迟。

非常感谢任何帮助或见解。

查看控制器

import UIKit
import AVFoundation

class MainVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, CustomCellDelegate {

var streams: [[String:Any]] = []

@IBOutlet weak var cv: UICollectionView!

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if let cell = cv.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CollectionViewCell {
        cell.delegate = self
        cell.nameLbl.text = streams[indexPath.item]["shortname"] as? String
        return cell
    } else {
        return CollectionViewCell()
    }
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    if thereIsCellTapped != true {

        let item = cv.cellForItem(at: indexPath) as! CollectionViewCell
        self.loadingCell()

        let when = DispatchTime.now() + 3 // change 2 to desired number of seconds
                DispatchQueue.main.asyncAfter(deadline: when) {
        DispatchQueue.main.async {
            UIView.animate(
                withDuration: 0.5,
                delay: 0,
                usingSpringWithDamping: 1,
                initialSpringVelocity: 1,
                options: [],
                animations: {

                    item.superview?.bringSubview(toFront: item)
                    self.view.layoutIfNeeded()

                },
                }), completion: { (finished: Bool) in
            let theStream = self.streams[indexPath.item]["audioUrl"] as? String
            item.audioStreamSelected(audioUrl: audioUrl!)

            })
            )
           }
        }
    }
}


func closeView(_ cell: CollectionViewCell) {

    let visibleItems: NSArray = indexPath as NSArray
    let currentItem: IndexPath = visibleItems.object(at: 0) as! IndexPath
    let nextItem: IndexPath = IndexPath(item: currentItem.item + 1, section: 0)

    if nextItem.row == streams.count{
        self.cv?.scrollToItem(
            at: IndexPath(row: 0, section: 0),
            at: .right,
            animated: true
        )
    } else {

        self.cv.scrollToItem(at: nextItem, at: .left, animated: true)
        let when = DispatchTime.now() + 3 
        DispatchQueue.main.asyncAfter(deadline: when) {
            self.collectionView(self.cv, didSelectItemAt: nextItem as IndexPath)
        }
    }
 }
}

自定义单元格

import UIKit
import AVFoundation
import MediaPlayer


protocol CustomCellDelegate {
   func closeView(_ cell:CollectionViewCell)
}

class CollectionViewCell: UICollectionViewCell {
    var player = AVPlayer()
    var playerItem:AVPlayerItem?
let mpic = MPRemoteCommandCenter.shared()
var delegate: CustomCellDelegate?
var _timeObserver:Any?

@IBOutlet weak var nameLbl: UILabel!

@IBAction func closeBtn(_ sender: Any) {

    if let delegate = self.delegate {
        delegate.closeView(self)
    }
}


override func awakeFromNib() {
    super.awakeFromNib()

    NotificationCenter.default.addObserver(self,selector: #selector(playerItemDidReachEnd(_:)),name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                           object: player.currentItem)

    UIApplication.shared.beginReceivingRemoteControlEvents()

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

}



func setupNowPlayingInfoCenter() {
    UIApplication.shared.beginReceivingRemoteControlEvents()
    mpic.skipBackwardCommand.isEnabled = false
    mpic.seekBackwardCommand.isEnabled = false

    mpic.playCommand.addTarget {event in
        self.player.play()
        self.setupNowPlayingInfoCenter()
        return .success
    }
    mpic.pauseCommand.addTarget {event in
        self.player.pause()
        return .success
    }
    mpic.nextTrackCommand.addTarget {event in
        return .success
    }
    mpic.previousTrackCommand.addTarget {event in
        return .success
    }

}



func playerItemDidReachEnd(_ notification: Notification) {
    if let _: AVPlayerItem = notification.object as? AVPlayerItem {
        player.replaceCurrentItem(with: nil)
        if let delegate = self.delegate {
            delegate.closeView(self)
        }
        player.pause()
        player.seek(to: kCMTimeZero)

        if (_timeObserver != nil) {
            player.removeTimeObserver(_timeObserver!)
            _timeObserver = nil
        }

    }
}


 func audioStreamSelected(audioUrl: String){
   if let streamer = URL(string: audioUrl){

    let playerItem:AVPlayerItem = AVPlayerItem(url: streamer)
        self.player = AVPlayer(playerItem: playerItem)
        player.replaceCurrentItem(with: playerItem)
        player.actionAtItemEnd = .pause




 if (_timeObserver == nil) {
        _timeObserver = player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) {
            [weak self] time in

             if self?.player.currentItem?.status == AVPlayerItemStatus.readyToPlay {

                }
           }
        }
     }

  }

}

0 个答案:

没有答案