摘要:
如果您只使用AVPlayer仅在您的应用程序中播放流式音频,那么锁定屏幕更新将正常工作(许多流 - 一个接一个)。但是,如果您使用AVPlayer同时播放流媒体音频和本地视频文件(即使在使用单独的AVPlayer实例和不同的视图控制器时),那么当您尝试再次播放流媒体音频时 - 锁定屏幕上不会显示任何内容更多。与清理无关 - 因为连续播放多个音频文件工作正常并且每次都出现在锁定屏幕上,但是只要你播放1个视频文件(或者甚至将其初始化为任何AVPlayer而不调用.play()它),音频锁定屏幕更新永久停止工作,您需要重新启动应用程序才能再次工作。这对我来说听起来像AVFoundation的bug ...
详细分类:
我有一个视图控制器A和B的应用程序。视图控制器A是视图控制器B的演示者(使用导航控制器推送它)。 A和B都有一个单独的AVPlayer(A播放音频.B播放视频。音频流式传输。视频是docs目录中的本地文件)。
VC A配置其AVPlayer以使用图稿图像,进度状态,向前15s,向后15s按钮更新锁定屏幕。如果仅使用视图控制器A的播放器来播放音频,那么一切都很有效 - 无论我多少次回到它前进(I.E. VC B的播放器从未用于播放())。 (整个控制器正确无效)锁定屏幕始终有效,并始终更新所有必需的播放信息。
VC A(AVPlayer1) - > PUSH - > VC B(AVPlayer2)
这是注册锁屏更新(包括按钮和进度回调)的代码:
func setupNowPlaying() {
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = title
nowPlayingInfo[MPMediaItemPropertyArtist] = artist
let artwork = MPMediaItemArtwork.init(boundsSize: self.artImage.size, requestHandler: { (size) -> UIImage in
return self.artImage
})
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
guard let player = self.player else { return }
guard let currentItem = self.player?.currentItem else { return }
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = currentItem.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentItem.currentTime().seconds
let rcc = MPRemoteCommandCenter.shared()
let skipBackwardCommand = rcc.skipBackwardCommand
skipBackwardCommand.isEnabled = true
skipBackwardCommand.addTarget(handler: skipBackward)
skipBackwardCommand.preferredIntervals = [15]
let skipForwardCommand = rcc.skipForwardCommand
skipForwardCommand.isEnabled = true
skipForwardCommand.addTarget(handler: skipForward)
skipForwardCommand.preferredIntervals = [15]
UIApplication.shared.beginReceivingRemoteControlEvents()
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
此外,以下内容连接在AppDelegate(applicationWillResignActive)中,以启用后台播放(标准内容):
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay, .allowBluetooth, .allowBluetoothA2DP ])
print("Playback OK")
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
print(error)
}
当VC B出现并使用自己独立的AVPlayer播放视频时,锁定屏幕上不显示任何内容的问题开始出现。 VC A的AVPlayer首先暂停。如果我在VC B的播放器上调用.play(),那么当我回到VC A(通过单击导航栏中的Back <)时,锁定屏幕的进度更新将永远不再显示(整个播放UI不会显示),但背景播放仍然有效。
因此,只要我在另一个视图控制器上使用另一个AVPlayer,我的原始播放器将永远无法再次向锁屏UI发布更新,直到应用程序终止并重新启动。
只要AVPlayer的另一个实例被引入并用于在另一个View Controller中播放,Apple的AVPlayer就会破坏VC A的AVPlayer的锁屏更新功能。
我知道问题与单独控制器上的第二个AVPlayer有关,因为只是不在VC B的播放器上调用.play(),修复了VC A播放器上的屏幕锁定更新消失问题。
我该如何解决这个问题?我不想从superview中删除VC A的播放器,并将其传递给VC B,并重新配置它,然后如果用户回来则在VC A中重新配置它。 (非常费力且容易出错)。在用户第一次进行VC B的播放(这是我快乐路径的一部分)之后,它目前还会永久更新锁定屏幕。
先谢谢你,Alex
通过消除对VC-B中AVPlayerViewController的依赖,我能够避免这个问题。现在我使用名为“Player”(Cocoapods:“Player”)的第三方组件,它使用AVPlayerLayer,但不使用AVPlayerViewController。 https://cocoapods.org/pods/Player
不幸的是我丢失了我的播放UI控件(进度条,播放按钮,全屏按钮 - AVPlayerViewController免费提供给我)。所以我将不得不构建一些自定义播放控件。
所以似乎AVPlayerViewController导致了锁定屏幕的问题并打破了它。切换到使用仍然使用AVPlayer但不使用AVPlayerViewController的“播放器”后,问题就消失了,我现在总是在锁定屏幕上看到我的播放控件。