电话通话后恢复AVPlayer

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

[SO上似乎有很多解决方案可以解决这个问题,但是这些解决方案都没有对我有用。我目前正在使用Swift5。我有一个AVPlayer在ViewController中播放动画(循环播放)。通过CallKit进行呼叫时,无论我应答还是拒绝呼叫,在处理完呼叫后AVPlayer播放的动画都不会恢复。中断处理程序似乎被称为before中断,但通常不会被称为after中断。

        override func viewDidLoad() {
            super.viewDidLoad()
            prepareBGVideo()
            ...
            NotificationCenter.default.addObserver(
                self,
                selector: #selector(applicationWillEnterForeground(notification:)),
                name: UIApplication.willEnterForegroundNotification,
                object: nil)
            ...
        }        

       func prepareBGVideo() {
            guard let path = Bundle.main.path(forResource: "animation", ofType:"mp4") else {
                print("video not found")
                return
            }

            let item = AVPlayerItem(url: URL(fileURLWithPath: path))
            avPlayer = AVPlayer(playerItem: item)

            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(loopVideoBG),
                                                   name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                                   object: item)
            NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption(notification:)), name: AVAudioSession.interruptionNotification, object: nil)
            avPlayerLayer = AVPlayerLayer(player: avPlayer)
            avPlayerLayer.backgroundColor = UIColor.black.cgColor
            avPlayer.volume = 0
            avPlayer.actionAtItemEnd = .none
            avPlayer.play()

            view.backgroundColor = .clear
            avPlayerLayer.frame = view.layer.bounds
            view.layer.insertSublayer(avPlayerLayer, at: 0)
            avPlayerLayer.videoGravity = isIPAD ? AVLayerVideoGravity.resize : AVLayerVideoGravity.resizeAspectFill // Changed from AVLayerVideoGravity.resizeAspect to AVLayerVideoGravity.resize so that video fits iPad screen

            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(willEnterForeground),
                                                   name: UIApplication.willEnterForegroundNotification,
                                                   object: nil)
        }

        @objc func handleInterruption(notification: Notification) {
            guard let info = notification.userInfo,
                let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
                let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
                    return
            }
            if type == .began {
                // Interruption began, take appropriate actions (save state, update user interface)
                self.avPlayer.pause()
            } else if type == .ended {
                guard let optionsValue =
                    info[AVAudioSessionInterruptionOptionKey] as? UInt else {
                        return
                }
                let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
                if options.contains(.shouldResume) {
                    // Interruption Ended - playback should resume
                    self.avPlayer.play()
                }
            }
        }

        /// Resume video while app wake up from background
        @objc func willEnterForeground() {
            avPlayer.seek(to: CMTime.zero)
            JPUtility.shared.performOperation(0.1) {
                self.avPlayer.play()
            }
        }

        @objc func loopVideoBG() {
            avPlayer.seek(to: CMTime.zero)
            avPlayer.play()
        }

这里是我尝试过的所有解决方案:

  1. Waiting two seconds before calling self.avPlayer.play() in if options.contains(.shouldResume){}
  2. self.avPlayer.play()。这种方法的问题在于if options.contains(.shouldResume){}块不会总是被调用,因此设置Setting AVAudioSession.sharedInstance().setActive to false when interruption begins and then setting it ot true when interruption ends无效。
  3. AVAudioSession.sharedInstance().setActive。我的动画仍然没有音频。

[我已经提到在if interruption == .ended {}中恢复播放,但有人建议不要这样做。这会被视为良好做法吗?

是否有办法确保执行setActive块?或者也许是一种比观察Setting AVAudioSession playback category to AVAudioSessionCategoryOptions.MixWithOthers更可靠的解决方法?

ios avfoundation avplayer swift5 avaudiosession
1个回答
0
投票

我解决了这个问题,但是创建了一个共享的AVAudioSession类,其中包含对所有具有动画的屏幕的引用。

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