AVPlayerLayer blank after entering background while being in a hidden controller and entering foreground and being shown
Asked Answered
O

4

13

I have an App in which I use AVPlayerLayer (used within a subclass of UIView just like Apples AV Foundation Programming Guide). Ihave a couple of view controllers witch are held in the View Controller that is resonsible for the menu (JASidePanels are used). The problem is as follows:

Everything works ok until the view controller with the AVPlayers does'nt get hidden (some other view is presented) and the the app enters background, gets back again and returns to the view. This Causes the AVPlayerLayer to display blank/transparent. The item is loaded as well as i can try playing it and indeed it is played but no video is seen.

What is the solution to this behaviour (and what is the cause of it)? Thx in advance.

Obrien answered 12/2, 2014 at 18:52 Comment(4)
Did you ever resolve this? PS. Relevant xkcd: xkcd.com/979Mychal
I had a similar issue, but the video didn't resume instead of going transparent. Try pausing the video when the app will enter background, and then play the video when the app enters foreground.Unstoppable
Paste the code here. This will help us understand your problem.Rockett
Finally I just went with reloading the video file in in the player and "accept" this error ;).Obrien
C
4

player?.seek(to: .zero) triggers AVPlayerLayer to render preview.
To smoothly update and pause the video on closing/opening the app in my case I've added the following:

private func setupObservers() {
    NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}

@objc
private func willResignActive() {
    player?.pause()
}

@objc
private func didBecomeActive() {
    player?.seek(to: .zero)
}
Counterfeit answered 17/6, 2020 at 13:4 Comment(0)
G
1

I'm not sure what causes it but a solution that worked for me was to reset the player on the AVPlayerLayer

   avPlayerLayer = AVPlayerLayer(player: currentAvPlayer)
Geraldina answered 11/2, 2016 at 13:58 Comment(0)
J
0

SWIFT 3

I had the same problem. Each time my app went into the background and then back into the foreground, my AVPlayer would disappear. Below is a simpler version of the code that works for me ... I needed to reset the player on UIApplicationWillEnterForeground. I can add more code if you need it, just let me know. It seems to be working for now. Cheers!

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var avPlayer: AVPlayer!
    var avPlayerLayer: AVPlayerLayer!
    var paused: Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()

        // Be sure to add your file to your app (not in the assets folder) and add it to your target
        let theURL = Bundle.main.url(forResource:"yourVideoFile", withExtension: "mp4")

        avPlayer = AVPlayer(url: theURL!)
        avPlayerLayer = AVPlayerLayer(player: avPlayer)

        avPlayerLayer.frame = view.layer.bounds
        avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill

        // .none is for looping videos if you uncomment "p: AVPlayerItem" below. 
        // .pause is to pause at the end of the video and hold the last frame
        avPlayer.actionAtItemEnd = .pause
        view.layer.insertSublayer(avPlayerLayer, at: 0)

        NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(notification:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,object: avPlayer.currentItem)

        NotificationCenter.default.addObserver(self, selector: #selector(appMovingToForeground), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        avPlayer.play()
        paused = false
    }

    func playerItemDidReachEnd(notification: Notification) {
        print("THE END")

        // uncomment the following line for a looping video
        // let p: AVPlayerItem = notification.object as! AVPlayerItem
        // p.seek(to: kCMTimeZero)

    }

    func appMovingToForeground() {
        print("App moved to foreground!")
        avPlayerLayer = AVPlayerLayer(player: avPlayer)
        view.layer.insertSublayer(avPlayerLayer, at: 0)

        // If you want your video or video loop to continue playing when app moves to foreground add:
        // avPlayer.play()
        // paused = false

    }

}
Johannesburg answered 15/3, 2017 at 23:6 Comment(0)
O
0

Finally I just went with reloading the video file in the player.

Obrien answered 15/9, 2020 at 9:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.