Возобновление воспроизведения видео AVPlayer после активации приложения
Я пишу пользовательский плеер из AVPlayer для воспроизведения видео. Согласно документам Apple, установите уровень видео:
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];
}
Проблема заключается в следующем: когда закрывается приложение (кнопка "Главная") или экран блока, воспроизведение видео прекращается, и когда возобновляется ТОЛЬКО возобновление воспроизведения звука, изображение на экране по-прежнему остается на экране блока - оно полностью статично и заменяет кадры изменения.
Как возобновить воспроизведение 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];
}
Ответы
Ответ 1
И одно решение, которое связывает всю эту информацию вместе.
Возможно, статус игрока должен обрабатываться по-разному, но мне нравится рекурсивный путь.
Примечание. Если вам не требуется точное время поиска, вы можете использовать [_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];
});
}
}
Ответ 2
Это работает для меня на 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)
}
Ответ 3
Используйте также UIApplicationWillEnterForegroundNotification
. Таким образом, вы знаете, что ваше приложение будет активным и видимым для пользователя:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appEnteredForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
Ответ 4
После некоторых исследований, которые я нашел, этот же пакет находится в iOS-плеере (WebBrowser, MPMoviePlayerController). Может быть, потому, что тип распространения контента - прогрессивная загрузка.
Таким образом, решение:
- Используйте ниже уведомления и сохраните текущее время.
- После того, как приложение возобновлено, заново создайте AVPlayer и начните воспроизведение с сохраненного времени.
Во всех остальных случаях изображение блокируется или изображение становится черным.
Ответ 5
Хитрость заключается в том, чтобы отделить все видеослои от своих игроков, когда приложение было ввести фон и реплантации их, когда приложение было снова стать активным.
Итак, в вашем -applicationDidEnterBackground:
вам нужно вызвать механизм, который приводит к
avPlayerLayer.player = nil;
и в вашем -applicationDidBecomeActive:
вы снова -applicationDidBecomeActive:
плеер, как
avPlayerLayer.player = self.avPlayer;
Также взгляните на эту техническую ноту (QA1668) от Apple.