An MPMoviePlayerViewController which is presented modally through presentMoviePlayerViewControllerAnimated: automatically dismisses itself when it's content finishes playing.
I've tried to disable this, since I want to play other content afterwards. However, even if I register to the NSNotificationCenter with [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedCallback:) name:MPMoviePlayerPlaybackDidFinishNotification object:playerVC.moviePlayer]; and set some other content, it still dismisses.
How can I stop MPMoviePlayerViewController from automatically dismissing itself?
UPDATE:
As a clarification, this question is only about removing the automatic dismissal and not about dealing with the disabled 'done' button. The selected answer reflects. This is by design, since we assume the developer adds their own means of dismissing the MPMoviePlayerViewController. However, #bickster's answer deals with the 'done' button as well.
Thanks to this blog article I figured out that MPMoviePlayerViewController automatically registers itself to the NSNotificationCenter upon creation. You have to first remove this registration and it will stop dismissing itself automatically.
// Initialize the movie player view controller with a video URL string
MPMoviePlayerViewController *playerVC = [[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:aVideoUrl]] autorelease];
// Remove the movie player view controller from the "playback did finish" notification observers
[[NSNotificationCenter defaultCenter] removeObserver:playerVC name:MPMoviePlayerPlaybackDidFinishNotification object:playerVC.moviePlayer];
You can use this code to stop the viewcontroller from automatically dismissing and capture the event when the user clicks the "Done" button so you can dismiss the viewcontroller yourself.
Step 1. - alloc a MPMoviePlayerViewController
videoPlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:[[NSURL alloc ]initWithString:[aURL];
Step 2. - Remove the default MPMoviePlayerPlaybackDidFinishNotification observer and add your own
[[NSNotificationCenter defaultCenter] removeObserver:videoPlayer
name:MPMoviePlayerPlaybackDidFinishNotification object:videoPlayer.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:videoPlayer.moviePlayer];
Step 3. - Present viewcontroler
[self presentMoviePlayerViewControllerAnimated:videoPlayer];
Step 4. - Add videoFinish: method
-(void)videoFinished:(NSNotification*)aNotification{
int value = [[aNotification.userInfo valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (value == MPMovieFinishReasonUserExited) {
[self dismissMoviePlayerViewControllerAnimated];
}
}
You can try something like this.
when the mpmovieplayercontroller finishes playing a video and you recieve the notification in your method movieFinishedCallback: implemect
[playerVC.movieplayer setContentURL:// set the url of the file you want to play here];
[playerVC.moviePlayer play];
Hope this helps
Since "Done" button is not working anymore if I remove MPMoviePlayerPlaybackDidFinishNotification from NSNotificationCenter, I change repeat mode to MPMovieRepeatModeOne.
Then, everything's working fine except the video is repeated.
MPMoviePlayerViewController *playerVC = [[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:aVideoUrl]] autorelease];
[playerVC.moviePlayer setRepeatMode:MPMovieRepeatModeOne];
Related
I am using the MPMoviePlayerController to play some streaming videos of type .m3u from a url. They video player launches perfectly and the video starts playing perfectly as well, but as soon as I press the Seek Forward or Next or beginSeekingForward button the video complete stops/freezes. After that I can click Done to dismiss the player or scrub the progress bar and it will come back to play to video. But the I can't click on the play/pause or at least seems not to do anything.
I have spent quite sometime looking around online for answer or at least a hint so I can tackle this issue in the right direction but not luck. So, I really hope someone could help with this. Btw, this only happens on iOS 8+, currently I am testing it in iOS 8.1.
This is how I create the player and load the video to it.
NSURL *videoURL = [NSURL URLWithString:self.video.flvurl];
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL: videoURL];
self.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
self.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
self.moviePlayer.shouldAutoplay = NO;
self.moviePlayer.fullscreen = YES;
self.moviePlayer.repeatMode = YES;
self.moviePlayer.view.backgroundColor = [UIColor blackColor];
self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.moviePlayer.view.frame = self.containerView.frame;
[self.view addSubview:self.moviePlayer.view];
[self.moviePlayer prepareToPlay];
[self.moviePlayer play];
I have tried using multiple different notifications to see if I can catch this within one of them, but not luck at all. I have tested all of these notifications so far.. I have added this to the self.moviePlayer and also the self.moviePlayer.view not luck in either of them.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(willResignActive:)
name:UIApplicationWillResignActiveNotification
object:self.moviePlayer.view];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoPlaybackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer.view];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoStartedPlaying:)
name:MPMoviePlayerNowPlayingMovieDidChangeNotification
object:self.moviePlayer.view];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoLoadState:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.moviePlayer.view];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoPlaybackState:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.moviePlayer.view];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoPlaybackUserInfoKey:)
name:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey
object:self.moviePlayer.view];
Well, if you need more relevant code please let me know. I really need some help with this.. Thanks in advance.
This code worked for me, but just to get rid of freezing. Sign up for the MPMoviePlayerLoadStateDidChangeNotification, like you did above. In the callback method, I simply set the movie players contentURL to the original URL I had initialized it with at the start, and set the movie player to play again.
The functionality of this is when you tap the NEXT or BACK buttons in fullscreen, the video simply starts playing again from the start. That may not be ideal since the user might not expect this, but at least it will stop it from freezing. I'm currently trying to find a better workaround.
- (void) videoLoadState:(NSNotification *)notification
{
MPMovieLoadState loadState = moviePlayer.loadState;
if(loadState == MPMovieLoadStateUnknown)
{
NSLog(#"Movie Load state is unknown");
moviePlayer.contentURL = currentlyPlayingVideoURL;
[moviePlayer prepareToPlay];
}
}
If you check the value of MPMoviePlaybackState in this method, it will always be MPMoviePlaybackStateStopped when NEXT or BACK are pressed, so I'm not sure how to handle it...
I am facing an issue with MPMoviePlayerController in iOS 7. When i single tap on the forward seek button the video stops and not allow to do anything like to play again full screen and slider change.
Here is my code.
remove the Observer for the MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter] removeObserver:moviePlayerViewController name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerViewController.moviePlayer];
and add New Notification MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
Here is my custom method to handle the MPMoviePlayerPlaybackDidFinishNotification
-(void)videoFinished:(NSNotification*)aNotification{
MPMoviePlayerController *moviePlayer = [aNotification object];
NSLog(#"%f",moviePlayer.currentPlaybackTime);
int reason = [[[aNotification userInfo] valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (reason == MPMovieFinishReasonPlaybackEnded) {
}else if (reason == MPMovieFinishReasonUserExited) {
[self performSelector:#selector(dismiss:) withObject:aNotification afterDelay:0.5];
}else if (reason == MPMovieFinishReasonPlaybackError) {
}
}
I need to stop this strange behaviour on single click and continue to play.
Anyone know how to do this?
Thanks.
I think there are no any notifications or event are available on user
interaction with the standard player buttons, and i have to implement
own UI for the player controls. by this way we can then determine the
actions for a single touch, long touch, etc. Then, we can add whatever
functionality like increasing the play rate, or simply seeking to a
time.
I have a MPMoviePlayerViewController, I don't want to initialize it with a content url, I just want to have a empty movie player GUI out there. Whenever I want it to load a movie, it then starts loading. But I can't
self.playerViewController = [[MPMoviePlayerViewController alloc] init];
MPMoviePlayerController *player = [self.playerViewController moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerPlaybackStateChanged:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
player.shouldAutoplay = FALSE;
player.initialPlaybackTime = 0;
[player setFullscreen:FALSE];
[player.view setFrame:CGRectMake(0, -20, self.view.bounds.size.width, self.view.bounds.size.height/2)];
[self.view addSubview:player.view];
As you see, I init the MPMoviePlayerViewController with no content url, and I set the autoplay to false, but when I run the application. Even though there is no video url given, I can still see a label "Loading ..." near the "Done" button, why???? How can I remove the loading label?
Just use MPMoviePlayerController instead of MPMoviePlayerViewController. You'll need to build a view controller around it if you want to display it modally.
You could also maybe iterate through [MPMoviePlayerViewController view].subviews until you find the UILabel, but that approach might break in future versions of iOS.
I am using a MPMoviePlayer to stream a video URL.
The video starts in a view's frame after the user taps on it. That works ok. As the video is embedded, the default control places a Zoom in button.
When the user presses the zoom in, the video goes fullscreen ok, without interrupting playback.
However, when the user presses again the zoom out button, i have three problems:
The video zooms to a corner of the screen and then disappears,
instead of returning to the original position.
The video disappears after going to the corner, and playback ends,
instead of continue playing the video.
The MPMoviePlayerDidExitFullscreenNotification never gets called,
only the MPMoviePlayerWillExitFullscreenNotification is called. I have tried sending nil and the mediaPlayerController to the notification center.
Also when pressing the Done button the video goes to the corner of the screen and disappears.
My player is created by doing:
moviePlayer=[[MPMoviePlayerController alloc] init];
moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
moviePlayer.shouldAutoplay=YES;
moviePlayer.controlStyle=MPMovieControlStyleEmbedded;
moviePlayer.view.hidden = YES;
Then when the user taps on the view this happens:
- (void) playVideo {
NSURL *url=[NSURL URLWithString: _news.videoUrl];
moviePlayer.contentURL = url;
moviePlayer.view.hidden = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerWillExitFullScreen:) name:MPMoviePlayerWillExitFullscreenNotification object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidExitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:moviePlayer];
[moviePlayer play];
}
- (void) moviePlayerWillExitFullScreen:(NSNotification*)notification {
NSLog(#"WILL EXIT FULLSCREEN");
}
- (void) moviePlayerDidExitFullScreen:(NSNotification*)notification {
NSLog(#"EXITED FULLSCREEN"); //NOT CALLED
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
NSLog(#"FINISHED PLAYIIING");
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
moviePlayer.view.hidden = YES;
}
Well, on the meanwhile I will answer 3 of my 4 questions:
The video zooms to a corner of the screen and then disappears, instead of returning to the original position.
The video disappears after going to the corner, and playback ends, instead of continue playing the video.
Also when pressing the Done button the video goes to the corner of the screen and disappears.
The problem was that after exiting fullscreen mode the -viewWillAppearAnimated method is called. The layout was modified in that method and that's why the playback stopped and view was sent to corner.
I have a single view app with 5 buttons and when one of the buttons is pressed, the player slides up over the original view and begins playing the video in fullscreen (as it should).
All works great with the exception of when pressing the Fullscreen/Minimize icon (the two diagonal arrows pointing to each other next to the play back controls). When pressing this, the original view with the five buttons slides up over the video player. The problem is the video is still playing underneath the original view. I would really like to eliminate the Fullscreen/Minimize icon but from I can tell, that does not seem possible. So... I am thinking, I might be able to use an observer to listen to when the Fullscreen/Minimize icon is pressed and I can do what I need to. I just can not find anything solid on how to do this. Any help/direction would be greatly appreciated.
Here is my current code...
-(IBAction)playvideo {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Megamind" ofType:#"mov"]];
MPMoviePlayerViewController * playerController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[self presentMoviePlayerViewControllerAnimated:(MPMoviePlayerViewController *)playerController];
playerController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[playerController.moviePlayer play];
[playerController release];
playerController=nil;
}
- (void)moviePlayerWillExitFullscreen:(NSNotification *)theNotification {
MPMoviePlayerController *playerController = [theNotification object];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerWillExitFullscreen:)
name:MPMoviePlayerWillExitFullscreenNotification
object:nil];
[playerController stop];
[self dismissMoviePlayerViewControllerAnimated];
}
This line is causing you that behaviour.
[self presentMoviePlayerViewControllerAnimated:(MPMoviePlayerViewController *)playerController];
It is pretty much similar to your regular presentModalViewController method.
It presents the Movieplayer and its view controller Modally. So the default settings here are
movieplayer.controlStyle = MPMovieControlStyleFullScreen
which are set up by default.
So when you press those diagonal arrows, it exits that mode, and gives a notification for that. But you have to setup an observer first to listen to that notifcation as you did for movie finished.
You did
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedPlayback:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
This adds a notification to observe for movie completion notifications.
For exiting full screen mode add one more observer that is this..
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieExitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
And you should be good to go after adding the -(void) movieExitFullScreen:(NSNotification *) selector for the same. Hope it helps. :)
Put this line just after the init of your MPMoviePlayer :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerWillExitFullscreen:)
name:MPMoviePlayerWillExitFullscreenNotification
object:nil];
I think you're adding the observer in the method where you want to be REMOVING it.
You want this
MPMoviePlayerController *playerController = [theNotification object];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerWillExitFullscreen:)
name:MPMoviePlayerWillExitFullscreenNotification
object:nil];
in the playVideo()
and THIS
[[NSNotificationCenter defaultCenter] removeObserver:self
name:name:MPMoviePlayerWillExitFullscreenNotificationn
object:nil];
in the moviePlayerWillExitFullscreen method.
I did find a solution and my lack of knowledge put me in a situation where I do not fully understand why it works this way. My apologies for not having a thorough reasoning. In my original code... the MPMoviePlayerWillExitFullscreenNotification was not answering to taps. This is true for MPMoviePlayerDidExitFullscreenNotification as well. What was answering was MPMoviePlayerPlaybackDidFinishNotification. Here is teh working code in knowing that the MPMoviePlayerPlaybackDidFinishNotification was working and also applied to the Fullscreen/Embed presses.
-(IBAction)playvideo {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Megamind" ofType:#"mov"]];
MPMoviePlayerViewController * playerController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedPlayback:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self presentMoviePlayerViewControllerAnimated:(MPMoviePlayerViewController *)playerController];
playerController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[playerController.moviePlayer play];
[playerController release];
playerController=nil;
NSLog(#"playvideo");
}
- (void)movieFinishedPlayback:(NSNotification*)notification {
MPMoviePlayerController *playerController = [notification object];
[playerController pause];
[self dismissMoviePlayerViewControllerAnimated];
}