Problem with MPMoviePlayerPlaybackDidFinishNotification - iphone

I am having a strange problem. I need to stop the player when playback finishes. I am using
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stopAudio)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
Though the player stops but for the first time stopAudio mehod is called twice, 2nd time it is called 4 times, 3rd time it is called 6 times and so on. I don't know how to tackle this problem. My stopAudio method is
- (void)stopAudio {
[player pause];
[player stop];
}
I do have a custom button via which also the stopAudio method can be called.
Any suggestions Plz...

You seem to add yourself as the observer each time you start playing. Since the observation request is not cleared when the player stops, the number of observation requests grows and you get more and more notifications. Either make sure you register only once or unregister using removeObserver: or removeObserver:name:object: when the player stops playing.

Solved the problem...as Zoul suggested I removed the observer inside the stopAudio method. I also replaced the nil object by the player in the NSNotificationCenter. It is working fine now... Thanx Zoul
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stopAudio)
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
my stopAudio method is :
- (void)stopAudio {
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player pause];
[player stop];
}

Related

UIWebView and MPMoviePlayerController

I hvae addd one webview having youtube link. When user play viedo it defaults open iOS movie player. I want to track notification of that movie player when it exits full screen or playing stopped. I have tried all notification generated by MPMoviewPlayerController . None of them are being fired. It fiers only when we instatinate MPMoviewPlayerViewCotntroller object and present MPMoviewPlayer from that.
That's becuase Youtube videos inside UIWebView are not MPMoviewPlayerViewCotntroller.
On iOS7:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerWillEnterFullscreen:)
name:#"UIMoviePlayerControllerDidEnterFullscreenNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerWillExitFullscreen:)
name:#"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];
On iOS8 it's a bit of a problem because these events are gone, and you need to add observer like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ios8EnterFullscreen:)
name:UIWindowDidBecomeVisibleNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ios8ExitFullscreen:)
name:UIWindowDidBecomeHiddenNotification object:nil];
And check that when it fires it is indeed a movie player (because it fires also on UIAlertView and stuff):
- (void)ios8EnterFullscreen:(NSNotification *)notification
{
if ([notification.object isMemberOfClass:[UIWindow class]])
{
//do your thing...
}
}

iOS application is unresponsive after performing [moviePlayer.view removeFromSuperview]

I'm building a very simple iOS iPad app that consists of a view and 4 buttons.
So basically you have in the Storyboard:
->ViewController
->View (this is added just for alignment and position sake, nothing else)
->View
->Button1
->Button2
->Button3
->Button4
When you press a button a movie will play in fullscreen mode, the same for all 4 buttons.
Once the movie is done, either because it finished or the user pressed "done",
[moviePlayer.view removeFromSuperview] is used to remove the movie, and everything returns to the initial state of the app, with the 4 buttons.
this is the code that plays the movie when a button is pressed
- (void) playMovie:(NSString *)fileName
ofType:(NSString *)fileType
{
NSString *filePath=[[NSBundle mainBundle] pathForResource:fileName ofType:fileType];
NSURL *fileUrl=[NSURL fileURLWithPath:filePath];
self.moviePlayer=[[MPMoviePlayerController alloc] initWithContentURL:fileUrl];
[self.view addSubview:self.moviePlayer.view];
self.moviePlayer.fullscreen = YES;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerWillExitFullscreenNotification
object:self.moviePlayer];
[self.moviePlayer prepareToPlay];
[self.moviePlayer play];
}
And this is the code I use to stop and remove the movie:
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerWillExitFullscreenNotification
object:player];
if ([player respondsToSelector:#selector(setFullscreen:animated:)])
{
[player stop];
[player setFullscreen:NO animated:YES];
[player.view removeFromSuperview];
}
}
The problem I encounter is this, after [player.view removeFromSuperview]; is performed, I return to the initial view, with no background image (it turns black) and no response from any of the buttons.
if I remove the view that contains the buttons, and add the buttons to the main view, it works as expected.
Sorry if this isn't too clear, I've been through books and lots of websites but don't seem to be able to get my head around this.
Cheers!
It looks like you are removing the "player" from the superview, but what you orginally added was a "movieplayer"...try removing that from the superview.
I changed the MPMoviePlayerController for a MPMoviePlayer*View*Controller and referenced the movie player within it, without using the setFullScreen and everything started working as expected.
So basically adding a view to the superview and the MPMoviePlayerController setFullScreen=YES are no good in this case.

My MoviePlayer doesn't respond to function

I am facing problem of memory leak and other MoviePlayer new initiation as my MoviePlayer doesn't respond to function, in which I am releasing that player on my done button.
(void) playMovieAtURL
{
MPMoviePlayerViewController *mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoURL]];
mpViewController.view.backgroundColor = [UIColor blackColor];
[self presentMoviePlayerViewControllerAnimated:mpViewController];
[mpViewController.view setCenter:self.view.center];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:mpViewController];
}
// When the movie is done,release the controller. (Doesn't come in it.)
-(void)myMovieFinishedCallback:(NSNotification*)aNotification
{
MPMoviePlayerController* theMovie=[aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:theMovie];
// Release the movie instance created in playMovieAtURL
[theMovie release];
}
Not sure it's your case, but this is what documentation says about MPMoviePlayerPlaybackDidFinishNotification:
This notification is not sent in cases
where the movie player is displaying
in fullscreen mode and the user taps
the Done button. In that instance, the
Done button causes movie playback to
pause while the player transitions out
of fullscreen mode. If you want to
detect this scenario in your code, you
should monitor other notifications
such as
MPMoviePlayerDidExitFullscreenNotification.
It seems that MPMoviePlayerPlaybackDidFinishNotification is called just when the movie stops by itself.
If you are using the Done button, you should use MPMoviePlayerDidExitFullscreenNotification instead.
I tried to solve it by passing nil and now it is returning me callbacks but still the movie won't releases, I will try ur suggestion also. Anyways my new code
-(void) playMovieAtURL
{
MPMoviePlayerViewController *mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoURL]];
mpViewController.view.backgroundColor = [UIColor blackColor];
[self presentMoviePlayerViewControllerAnimated:mpViewController];
[mpViewController.view setCenter:self.view.center];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
}
// When the movie is done,release the controller.
-(void)myMovieFinishedCallback:(NSNotification*)aNotification
{
MPMoviePlayerController* theMovie=[aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
// Release the movie instance created in playMovieAtURL
[theMovie release];
}

how to get done button event in MPMOviewplayercontroller in iphone?

I have used MPMoviePlayerController for playing video file.I want to get done button event but i dont know how to get can you help me for this questions
You can use MPMoviePlayerPlaybackDidFinishNotification.. Dont think there is a notification that only triggers when the done button is pressed and not when the movie finishes by itself thou...
Add this when creating the MPmovieplayerController:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish: ) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer] ;
And then this method:
-(void)moviePlayBackDidFinish: (NSNotification*)notification{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer] ;
[moviePlayer stop];
[moviePlayer release];
}

Properly displaying and dismissing fullscreen MPMoviePlayerController in iOS 3.2 (iPad)

I'm having lots of trouble displaying a fullscreen movie in my iPad app and then allowing the user to dismiss it with either the Done button or the "un-fullscreen" button on the player controls.
Initially I was using MPMoviePlayerViewController for the movie presentation, but I wasn't receiving the enter/exit fullscreen notifications from its MPMoviePlayerController object, so I switched to doing it myself.
I can make the movie appear fullscreen (although the transition is janky), but when either the "Done" or "un-fullscreen" buttons are pressed, no action is taken by the player. I've posted my code below:
- (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];
}
And here is the code for my didFinish callback
- (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];
}
So obviously I am doing something wrong but I've been up and down the documentation and I can't figure out how to make the movie just go away. I figured it would be more intuitive than this. What am I doing wrong?
Here are how the events -> notifications work:
User presses 'Done' button
MPMoviePlayerWillExitFullscreenNotification
MPMoviePlayerDidExitFullscreenNotification
User presses 'Leave fullscreen' button on transport
MPMoviePlayerWillExitFullscreenNotification
MPMoviePlayerDidExitFullscreenNotification
Note that playback does not stop
Movie reaches end
MPMoviePlayerPlaybackDidFinishNotification with the MPMoviePlayerPlaybackDidFinishReasonUserInfoKey set to MPMovieFinishReasonPlaybackEnded
If you call setFullscreen:NO animated:YES on your MoviePlayerController instance from this notification, you'll then get the WillExit and DidExit notifications.
Note that you don't get the PlaybackDidFinish notification when the user presses the Done or Leave Fullscreen buttons.
So, typically, if you want to get rid of the MoviePlayer's view, you need to put [self.moviePlayerController.view removeFromSuperview] in the DidExitFullscreen notification handler. WillExitFullscreen is too soon.
Here's my 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];
}
Yes. That's great. There are really notifications mentioned above...
However, there are no MPMoviePlayerPlaybackWillFinishNotification somewhy!!!
That's really a problem.
When you call the movie player as modal (no matter which of the following methods used presentViewController/presentModalViewController/presentVideoController), if you defined .fullScreen = YES, it's not expected to call MPMoviePlayerWillExitFullscreenNotification notification at all (obviously, because it's not cosidering we enter/exit from full screen, but only present/dismiss the controller).
But there are really no any notifications that the video is about to finish and close. That's needed (besides any other situations possible) to catch the moment when the transition of dismissing is started. (The transition, of course, starts before the MPMoviePlayerPlaybackDidFinishNotification called). And, at the same time, application:supportedInterfaceOrientationsForWindow: for previously shown controller is called before the notification, and there is no way to say the AppDelegate that our current controller must be shown already in another orientation.
So, since my video is fullscreen and also without any controls shown (this is kind of an intro, so I just until it finishes) my solution was just to have a timer which checks every short tick (0.1 seconds) what is the video current position... and it it's close to the end, then this is the moment for my own notification.