应用程序激活后恢复AVPlayervideo播放

我从AVPlayer编写自定义播放器进行video播放。 根据苹果公司的文档设置video层:

self.player = [IPLPlayer new]; self.player.playerLayer = (AVPlayerLayer *)self.playerView.layer; 

self.playerView是这些文档中的常见类:

  @implementation PlayerView + (Class) layerClass { return [AVPlayerLayer class]; } - (AVPlayer *)player { return [(AVPlayerLayer *)[self layer] player]; } - (void)setPlayer:(AVPlayer *) player { [(AVPlayerLayer *) [self layer] setPlayer:player]; } 

问题是:当closures应用程序(主页button)或阻止屏幕时,video播放停止,当继续播放audio播放时,屏幕上的图像仍然是阻止屏幕之前的图像 – 完全静态并且注意更改帧。

屏幕被屏蔽后如何恢复VIDEO播放?

似乎我必须注册通知,并在应用程序成为活动后恢复video层:

  -(void)registerNotification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterBackground) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterForeground) name:UIApplicationDidBecomeActiveNotification object:nil]; } -(void)unregisterNotification { [[NSNotificationCenter defaultCenter] removeObserver:self]; } -(void)willEnterBackground { NSLog(@"willEnterBackground"); [self.playerView willEnterBackground]; } -(void)didEnterForeground { NSLog(@"didEnterForeground"); [self.playerView didEnterForeground]; } 

而一个解决scheme将所有这些信息结合在一起。

也许玩家状态应该有不同的处理方式,但我喜欢recursion的方式。

注意:如果你不需要精确的查找时间,你可以使用[_player seekToTime:<#(CMTime)#> completionHandler:<#^(BOOL finished)completionHandler#>]它更快,但它寻求最近的关键帧。

 - (void)viewDidLoad { [super viewDidLoad]; .... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; } -(void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; } .... -(void) appEnteredForeground { AVPlayerLayer *player = (AVPlayerLayer *)[playerView layer]; [player setPlayer:NULL]; [player setPlayer:_player]; [self playAt:currentTime]; } -(void) appEnteredBackground { [_player pause]; currentTime = [_player currentTime]; } -(void)playAt: (CMTime)time { if(_player.status == AVPlayerStatusReadyToPlay && _player.currentItem.status == AVPlayerItemStatusReadyToPlay) { [_player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) { [_player play]; }]; } else { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self playAt:time]; }); } } 

也使用UIApplicationWillEnterForegroundNotification 。 这样你就知道你的应用程序对于用户来说是活跃和可见的:

 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appEnteredForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; 

这在Swift 3上适合我

在设置视图的同时添加一个地方:

 NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForegroundNotification), name: .UIApplicationWillEnterForeground, object: nil) 

抓住你的播放器,并强制播放:

 func appWillEnterForegroundNotification() { myPlayer.play() } 

不要忘记在不需要的时候移除观察者:

 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self) } 

经过一些研究,我发现,相同的包是在iOS播放器(WebBrowser,MPMoviePlayerController)。 可能是因为分配types的内容是渐进式下载。

所以解决办法是:

  • 使用下面的通知并保存当前时间。
  • 应用程序恢复后,重新创buildAVPlayer并从保存的时间开始播放。

在所有其他情况下,图像被阻挡,或者视图变黑。

诀窍是,当应用程序进入后台并从应用程序重新启动时重新连接到应用程序时,将所有video图层从其播放器中分离出来。

所以在你的-applicationDidEnterBackground:你必须触发一个结果的机制

 avPlayerLayer.player = nil; 

并在你的应用程序-applicationDidBecomeActive:你重新附加播放器

 avPlayerLayer.player = self.avPlayer; 

也看看这个苹果的技术说明( QA1668 )。