14

我从 AVPlayer 编写自定义播放器用于视频播放。根据Apple docs设置视频层:

    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];
}

问题是:当关闭应用程序(主页按钮)或阻止屏幕时,视频播放停止,并且当仅恢复音频播放恢复时,屏幕上的图像仍然是阻止屏幕之前的图像 - 它是完全静态的并且注意更改帧。

屏幕被阻塞后如何恢复视频播放?

似乎我必须注册通知,并在应用程序变为活动状态后恢复视频层:

    -(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];
}
4

5 回答 5

18

一个将所有这些信息绑定在一起的解决方案。

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

注意:如果您不需要确切的查找时间,您可以使用[_player seekToTime:<#(CMTime)#> completionHandler:<#^(BOOL finished)completionHandler#>]It's faster 但它会查找最近的关键帧。

- (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];
        });
    }
}
于 2015-11-09T16:11:13.253 回答
7

这在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)
}
于 2017-04-21T09:02:06.093 回答
3

也可以使用UIApplicationWillEnterForegroundNotification。这样您就知道您的应用程序将处于活动状态并且对用户可见:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appEnteredForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
于 2013-05-14T23:44:16.373 回答
2

诀窍是在应用程序进入后台时从播放器中分离所有视频层,在应用程序再次激活时重新附加它们。

所以在你的-applicationDidEnterBackground:你必须触发一个机制,导致

avPlayerLayer.player = nil;

然后在你的-applicationDidBecomeActive:身上重新连接播放器

avPlayerLayer.player = self.avPlayer;

另请查看 Apple 的此技术说明 ( QA1668 )。

于 2014-04-02T17:50:32.363 回答
1

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

所以解决方案是:

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

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

于 2013-05-17T17:18:33.420 回答