Je ne parviens pas à afficher un film en plein écran dans mon application iPad, puis à permettre à l'utilisateur de le rejeter à l'aide du bouton Terminé ou du bouton "Plein écran" des commandes du lecteur.
Au départ, j'utilisais MPMoviePlayerViewController
pour la présentation du film, mais je ne recevais pas les notifications plein écran d'entrée/de sortie de son objet MPMoviePlayerController
, je suis donc passé à le faire moi-même.
Je peux faire en sorte que le film apparaisse en plein écran (bien que la transition soit janky), mais lorsque le bouton "Terminé" ou le bouton "plein écran" est enfoncé, aucune action n'est entreprise par le lecteur. J'ai posté mon code ci-dessous:
- (void)startPlayingMovieWithURLString:(NSString *)movieURLString {
// I get all of these callbacks **EXCEPT** the "willExitFullScreen:" callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterFullScreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullScreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishPlayback:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self.moviePlayerController setContentURL:someExistingURL];
// "self" is a UIViewController subclass, and is presented as a "fullscreen" modal view controller from its parent
// I'm setting the movie player's view's frame to take up the full rectangle of my view controller, but really I want the movie to be completely removed when the user presses "done" (that is, removed from the view hierarchy). Not sure when/where to do this.
self.moviePlayerController.view.frame = self.view.frame;
[self.view addSubview:self.moviePlayerController.view];
[self.moviePlayerController setFullscreen:YES animated:YES];
}
Et voici le code de mon rappel didFinish
- (void)didFinishPlayback:(NSNotification *)notification {
// This ends up recursively telling the player that playback ended, thus calling this method, thus…well you get the picture.
// What I'm trying to do here is just make the player go away and show my old UI again.
[self.moviePlayerController setFullscreen:NO animated:YES];
}
Alors évidemment, je fais quelque chose de mal, mais j'ai parcouru la documentation et je ne vois pas comment faire en sorte que le film disparaisse tout simplement. Je pensais que ce serait plus intuitif que cela. Qu'est-ce que je fais mal?
Voici comment les événements -> notifications fonctionnent:
L'utilisateur appuie sur le bouton 'Terminé'
MPMoviePlayerWillExitFullscreenNotification
MPMoviePlayerDidExitFullscreenNotification
L'utilisateur appuie sur le bouton 'Quitter le plein écran' lors du transport
MPMoviePlayerWillExitFullscreenNotification
MPMoviePlayerDidExitFullscreenNotification
Le film arrive à la fin
MPMoviePlayerPlaybackDidFinishNotification
avec la MPMoviePlayerPlaybackDidFinishReasonUserInfoKey
définie sur MPMovieFinishReasonPlaybackEnded
setFullscreen:NO animated:YES
sur votre instance MoviePlayerController à partir de cette notification, vous recevrez alors les notifications WillExit
et DidExit
.PlaybackDidFinish
lorsque l'utilisateur appuie sur les boutons Terminé ou Quitter le plein écran.En règle générale, si vous souhaitez vous débarrasser de la vue de MoviePlayer, vous devez insérer [self.moviePlayerController.view removeFromSuperview]
dans le gestionnaire de notifications DidExitFullscreen
. WillExitFullscreen
est trop tôt.
Voici mon code:
- (void)willEnterFullscreen:(NSNotification*)notification {
NSLog(@"willEnterFullscreen");
}
- (void)enteredFullscreen:(NSNotification*)notification {
NSLog(@"enteredFullscreen");
}
- (void)willExitFullscreen:(NSNotification*)notification {
NSLog(@"willExitFullscreen");
}
- (void)exitedFullscreen:(NSNotification*)notification {
NSLog(@"exitedFullscreen");
[self.movieController.view removeFromSuperview];
self.movieController = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)playbackFinished:(NSNotification*)notification {
NSNumber* reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
switch ([reason intValue]) {
case MPMovieFinishReasonPlaybackEnded:
NSLog(@"playbackFinished. Reason: Playback Ended");
break;
case MPMovieFinishReasonPlaybackError:
NSLog(@"playbackFinished. Reason: Playback Error");
break;
case MPMovieFinishReasonUserExited:
NSLog(@"playbackFinished. Reason: User Exited");
break;
default:
break;
}
[self.movieController setFullscreen:NO animated:YES];
}
- (void)showMovie {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterFullscreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enteredFullscreen:) name:MPMoviePlayerDidEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitedFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
NSURL* movieURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tron" ofType:@"mov"]];
self.movieController = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
self.movieController.view.frame = self.view.frame;
[self.view addSubview:movieController.view];
[self.movieController setFullscreen:YES animated:YES];
[self.movieController play];
}
Oui. C'est génial. Il y a vraiment des notifications mentionnées ci-dessus ...
Cependant, il n'y a pas de MPMoviePlayerPlaybackWillFinishNotification somewhy !!! C'est vraiment un problème.
Lorsque vous appelez le lecteur de film comme modal (quelle que soit la méthode utilisée, presentViewController/presentModalViewController/presentVideoController), si vous avez défini .fullScreen = YES, l'appel de MPMoviePlayerWillExitFullscreenNotification notification n'est pas attendu. (évidemment, parce que c’est pas parce que c’est pas parce que nous entrons/sortons du plein écran, mais seulement de présenter/renvoyer le contrôleur).
Mais il n'y a vraiment aucune notification que la vidéo est sur le point de se terminer et se fermer. Cela est nécessaire (en plus de toutes les autres situations possibles) pour saisir le moment où la transition de licenciement commence. (La transition commence, bien sûr, avant le MPMoviePlayerPlaybackDidFinishNotification appelé). Et, en même temps, application: supportedInterfaceOrientationsForWindow: le contrôleur précédemment affiché est appelé avant la notification, et il n'y a aucun moyen de dire à AppDelegate que notre contrôleur actuel doit être affiché déjà dans une autre orientation.
Donc, puisque ma vidéo est en plein écran et sans aucun contrôle affiché (ceci est une sorte d’intro, donc jusqu’à ce qu’elle se termine) ma solution consistait simplement à avoir une minuterie qui vérifie chaque tick court (0,1 seconde) ce qui est la position actuelle de la vidéo ... et si elle est proche de la fin, le moment est venu pour ma propre notification.