在设备锁定时,我无法在后台模式下播放播放列表。它在锁定时播放当前音频,但我无法在后台模式下转到下一个音频文件。
我正在使用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 {
}
}
}
}
}
}