2013-05-14 24 views
10

Piszę niestandardowy odtwarzacz z AVPlayera do odtwarzania wideo. Zgodnie z docs firmy Apple ustawić warstwę wideo:Przywróć odtwarzanie wideo AVPlayer po uruchomieniu aplikacji

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

Gdzie self.playerView zwykle klasa z tych dokumentów:

@implementation PlayerView 

+ (Class) layerClass { 
    return [AVPlayerLayer class]; 
} 

- (AVPlayer *)player { 
    return [(AVPlayerLayer *)[self layer] player]; 
} 

- (void)setPlayer:(AVPlayer *) player { 
    [(AVPlayerLayer *) [self layer] setPlayer:player]; 
} 

Problemem jest: Kiedy blisko aplikacji (przycisk Start) lub ekran blok , odtwarzanie wideo zostanie zatrzymane, a gdy wznowione zostanie TYLKO odtwarzanie audio, obraz na ekranie jest nadal wyświetlany przed ekranem blokowym - jest w pełni statyczny i zmienia ramkę.

Jak wznowić odtwarzanie VIDEO po zablokowaniu ekranu?

Wydaje muszę zarejestrować powiadomień, a po aplikacji staje się warstwą aktywną resume 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]; 
} 

Odpowiedz

15

I jedno rozwiązanie, które łączy wszystkie te informacje razem.

Może status odtwarzacza powinien być obsługiwany inaczej, ale podoba mi się sposób rekursywny.

Uwaga: Jeśli nie potrzebujesz dokładnego czasu przeszukiwania, możesz użyć numeru [_player seekToTime:<#(CMTime)#> completionHandler:<#^(BOOL finished)completionHandler#>] Jest to szybsze, ale dotyczy najbliższej klatki kluczowej.

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

Skorzystaj z UIApplicationWillEnterForegroundNotification również. W ten sposób wiesz, aplikacja będzie aktywne i widoczne dla użytkownika:

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

Przepraszam, ale moje pytanie nie dotyczyło tego. – HotJard

1

Po kilku badań odkryłem, że ta sama torba jest w odtwarzaczu iOS (WebBrowser, MPMoviePlayerController). Być może dlatego, że typem dystrybucji jest pobieranie progresywne.

rozwiązaniem jest więc:

  • Zastosowanie poniżej powiadomień i zapisać aktualny czas.
  • Po wznowieniu aplikacji odtwórz AVPlayer i rozpocznij odtwarzanie od zapisanego czasu .

We wszystkich innych przypadkach zdjęcie jest zablokowane lub widok staje się czarny.

+0

To powinna być zaakceptowana odpowiedź. Również, jeśli zaimplementujesz zachowanie w powiadomieniach, pamiętaj, że NIE MOŻESZ przekazać obiektu odtwarzacza do powiadomień UIApplication, jeśli twoje powiadomienie nigdy nie zostanie wywołane, to jest winowajcą. –

1

Sztuką jest, aby odłączyć wszystkie warstwy wideo ze swoich zawodników, gdy aplikacja zrobił wprowadzić tło i doczepić je, gdy aplikacja zrobił stać się ponownie aktywne.

Więc w swojej -applicationDidEnterBackground: masz do uruchomienia mechanizmu, który powoduje

avPlayerLayer.player = nil; 

iw swoim -applicationDidBecomeActive: Państwo ponownie podłączyć odtwarzacz jak

avPlayerLayer.player = self.avPlayer; 

też spojrzeć na ten uwagą techniczną (QA1668) od Apple.

+0

Nie musisz tego robić, może to jest naprawione? –

4

Działa to dla mnie na Swift 3

Dodaj gdzieś podczas konfigurowania widok:

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

Grab odtwarzacz i zmusić go do gry:

func appWillEnterForegroundNotification() { 
    myPlayer.play() 
} 

Nie zapomnij usunąć obserwatorów, gdy ich nie potrzebujesz:

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

Hmm .. Jestem całkiem pewien, że spowoduje to zachowanie +1 dla klasy, która go zawiera. Tak więc "deinit" nigdy nie zostanie wywołany. Musiałbyś usunąć obserwatora z innego miejsca, aby obiekt został zwolniony:] –

+1

Tak "viewDidDisappear" byłoby dobrym miejscem do usunięcia obserwatora. – Harish

+0

Zaktualizowałem odpowiedź. Dziękuję @AndresCanella and Harish <3 – budidino

Powiązane problemy