仅在另一个AVPlayer实例播放视频内容之后,AVPlayer音频锁定屏幕更新才会停止工作

时间:2019-03-14 18:54:17

标签: swift avfoundation avplayer lockscreen

摘要:

如果仅使用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,直到应用程序终止并重新启动为止。

  • 我尝试在VC A中的播放器上进行完全清理并重新初始化。
  • 我试图不对VC B调用.play()(在这种情况下,对VC A一切正常)。
  • VC B的播放器未注册锁定屏幕更新,因为它仅在应用程序中播放视频以进行预览。

一旦引入另一个AVPlayer实例并用于另一个View Controller中,Apple AVPlayer的幕后工作就会破坏VC A的AVPlayer的锁屏更新功能。

我知道问题与单独控制器上的第二个AVPlayer有关,因为仅在VC B的播放器上不调用.play()即可解决VC A的播放器上的屏幕锁定更新消失的问题。

我该如何解决?我不想从超级视图中删除VC A的播放器,然后将其传递给VC B,然后重新配置它,然后在用户返回时再次在VC A中重新配置它。 (非常费力且容易出错)。当前,它还使锁定屏幕永久更新,这是在用户第一次执行VC B的播放后(这是我满意的途径的一部分)

预先感谢, 亚历克斯

1 个答案:

答案 0 :(得分:0)

通过消除对VC-B中AVPlayerViewController的依赖,我能够避免此问题。现在,我使用一个名为“ Player”(Cocoapods:“ Player”)的第三方组件,该组件使用AVPlayerLayer,但不使用AVPlayerViewController。 https://cocoapods.org/pods/Player

不幸的是,我丢失了回放UI控件(进度条,播放按钮,全屏按钮-AVPlayerViewController免费提供给我)。因此,我将必须构建一些自定义播放控件。

因此,看来AVPlayerViewController导致了锁屏问题并将其损坏。切换到仍然使用AVPlayer而不使用AVPlayerViewController的“ Player”后,问题消失了,现在我总是在锁定屏幕上看到我的播放控件。