摘要:
如果仅使用AVPlayer仅在您的应用程序中播放流音频,则“锁屏更新”就可以正常工作(许多流-接一个)。但是,如果您同时使用AVPlayer播放流媒体音频和本地视频文件(即使使用AVPlayer的单独实例并在不同的视图控制器上),那么当您尝试再次播放流媒体音频时-锁定屏幕上将不会显示任何内容还有。与清理无关-因为连续播放多个音频文件可以正常工作,并且每次都在锁定屏幕上显示,但是只要您播放1个视频文件(甚至将其初始化为任何AVPlayer而不调用.play()它),音频锁定屏幕更新将永久停止工作,您需要重新启动该应用程序才能使其再次运行。对我来说,这听起来像是AVFoundation的错误...
详细细分:
我对View Controller A和View Controller A很着迷。View Controller A是View Controller B的演示者(使用导航控制器将其推送)。 A和B内部都有一个单独的 AVPlayer(A播放音频。B播放视频。音频流式传输。视频是docs目录中的本地文件)。
VC A将其AVPlayer配置为使用图稿图像,进度状态,前进15秒,前进15秒按钮更新锁定屏幕。 如果仅使用视图控制器A的播放器来播放音频,那么一切都很好,无论我来回播放了多少次(即VC B的播放器都从未使用过play())。 (整个控制器正确地初始化了)锁定屏幕始终有效,并且始终更新所有必需的播放信息。
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时(通过在导航栏中单击“返回<”),锁定屏幕的进度更新将永远不会再次显示(整个播放UI不会出现),但是后台播放仍然有效。
因此,一旦我在另一个View Controller上使用另一个AVPlayer,我的原始播放器将永远无法将更新发布到锁定屏幕UI,直到应用程序终止并重新启动为止。
一旦引入另一个AVPlayer实例并用于另一个View Controller中,Apple AVPlayer的幕后工作就会破坏VC A的AVPlayer的锁屏更新功能。
我知道问题与单独控制器上的第二个AVPlayer有关,因为仅在VC B的播放器上不调用.play()即可解决VC A的播放器上的屏幕锁定更新消失的问题。
我该如何解决?我不想从超级视图中删除VC A的播放器,然后将其传递给VC B,然后重新配置它,然后在用户返回时再次在VC A中重新配置它。 (非常费力且容易出错)。当前,它还使锁定屏幕永久更新,这是在用户第一次执行VC B的播放后(这是我满意的途径的一部分)
预先感谢, 亚历克斯
答案 0 :(得分:0)
通过消除对VC-B中AVPlayerViewController的依赖,我能够避免此问题。现在,我使用一个名为“ Player”(Cocoapods:“ Player”)的第三方组件,该组件使用AVPlayerLayer,但不使用AVPlayerViewController。 https://cocoapods.org/pods/Player
不幸的是,我丢失了回放UI控件(进度条,播放按钮,全屏按钮-AVPlayerViewController免费提供给我)。因此,我将必须构建一些自定义播放控件。
因此,看来AVPlayerViewController导致了锁屏问题并将其损坏。切换到仍然使用AVPlayer而不使用AVPlayerViewController的“ Player”后,问题消失了,现在我总是在锁定屏幕上看到我的播放控件。