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

问题描述 投票:0回答:1

摘要:

如果您只使用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发布更新,直到应用程序终止并重新启动。

  • 我尝试在VC A中对播放器进行全面清理并重新初始化。
  • 我试着不要在VC B上调用.play()。在这种情况下,一切都可以正常使用VC A.
  • VC B的播放器未注册锁屏更新,因为它只是在应用中播放视频以供预览。

只要AVPlayer的另一个实例被引入并用于在另一个View Controller中播放,Apple的AVPlayer就会破坏VC A的AVPlayer的锁屏更新功能。

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

我该如何解决这个问题?我不想从superview中删除VC A的播放器,并将其传递给VC B,并重新配置它,然后如果用户回来则在VC A中重新配置它。 (非常费力且容易出错)。在用户第一次进行VC B的播放(这是我快乐路径的一部分)之后,它目前还会永久更新锁定屏幕。

先谢谢你,Alex

swift avfoundation avplayer lockscreen
1个回答
0
投票

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

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

所以似乎AVPlayerViewController导致了锁定屏幕的问题并打破了它。切换到使用仍然使用AVPlayer但不使用AVPlayerViewController的“播放器”后,问题就消失了,我现在总是在锁定屏幕上看到我的播放控件。

© www.soinside.com 2019 - 2024. All rights reserved.