首页 文章

应用程序激活后恢复AVPlayer视频播放

提问于
浏览
10

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

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

How to resume VIDEO playing after screen is blocked?

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

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

5 回答

  • 3

    一种解决方案将所有这些信息绑定在一起 .

    也许播放器状态应该以不同的方式处理,但我喜欢递归方式 .

    注意:如果您不需要精确的搜索时间,则可以使用 [_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];
            });
        }
    }
    
  • 1

    这对我有用 Swift 3

    在设置视图时添加某处:

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

    grab 你的玩家并强制它玩:

    func appWillEnterForegroundNotification() {
      myPlayer.play()
    }
    

    不要忘记在不需要时删除观察者:

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

    也可以使用 UIApplicationWillEnterForegroundNotification . 这样,您就知道您的应用会对用户有效且可见:

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

    经过一些研究,我发现,同一个包在iOS播放器(WebBrowser,MPMoviePlayerController)中 . 可能是因为分发类型的内容是Progressive Download .

    所以解决方案是:

    • 使用以下通知并节省当前时间 .

    • 应用程序恢复后,重新创建AVPlayer并从保存的时间开始播放 .

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

  • 17

    诀窍是当app did 进入后台时将所有视频图层从其玩家分离,并在app did 再次变为活动状态时重新附加它们 .

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

    avPlayerLayer.player = nil;
    

    并在你的 -applicationDidBecomeActive: 中重新安装玩家

    avPlayerLayer.player = self.avPlayer;
    

    另请参阅Apple的技术说明(QA1668) .

相关问题