29

On my iPhone i'm playing video/audio files in fullscreen mode. When the video/audio file reached its end then the following method is triggered:

- (void) movieFinishedCallback:(NSNotification*) aNotification {
    MPMoviePlayerController *player = [aNotification object];

    [player stop];

    [[NSNotificationCenter defaultCenter] 
        removeObserver:self
        name:MPMoviePlayerPlaybackDidFinishNotification
        object:player];

    [player autorelease];
    [moviePlayer.view removeFromSuperview];

    NSLog(@"stopped?");
}

That works fine! But the problem is when i press on the "Done" button when the video/audio file is still playing. Then this method doesn't get triggered...

Anyone any idea how to catch the event when the "Done" button is pressed? Because right now media player stays in the view. Its not disappearing.

Kampai
  • 22,848
  • 21
  • 95
  • 95
w00
  • 26,172
  • 30
  • 101
  • 147

7 Answers7

43

It worked for me on iPad when I listen to MPMoviePlayerWillExitFullscreenNotification.

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(doneButtonClick:) 
                                             name:MPMoviePlayerWillExitFullscreenNotification 
                                           object:nil];

And selector method:

-(void)doneButtonClick:(NSNotification*)aNotification{
    NSNumber *reason = [notification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];

    if ([reason intValue] == MPMovieFinishReasonUserExited) {
        // Your done button action here
    }
}
beryllium
  • 29,669
  • 15
  • 106
  • 125
  • 2
    My MPMovieplayer style is FullScreen. Now tapping on Done button - video just Pause and it doesn't notify for MPMoviePlayerWillExitFullscreenNotification. Any idea? – ruyamonis346 Jun 13 '14 at 11:23
  • It's worth noting I had to create a property in my viewController in order to get it working... `MPMoviePlayerController *moviePlayer =` didn't work. – Magoo May 12 '15 at 15:05
  • @Rajneesh071 use `MPMoviePlayerPlaybackDidFinishNotification` instead. @Magoo it works without property (tested on iOS 8.3) – derpoliuk Jun 07 '15 at 09:12
21

check for a enum inside notification userInfo dictionary

NSNumber *reason = [notification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];

if ([reason intValue] == MPMovieFinishReasonUserExited) {

   // done button clicked!

}

Selected answer has since integrated my response. Please refer above.

dklt
  • 1,703
  • 1
  • 12
  • 12
17

SUCCESSFULLY TESTED IN iOS7 AND iOS8

Check and remove earlier notification observer if any for MPMoviePlayerPlaybackDidFinishNotification.

- (void)playVideo:(NSString*)filePath
{
     // Pass your file path
        NSURL *vedioURL =[NSURL fileURLWithPath:filePath];
        MPMoviePlayerViewController *playerVC = [[MPMoviePlayerViewController alloc] initWithContentURL:vedioURL];

    // Remove the movie player view controller from the "playback did finish" notification observers
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMoviePlayerPlaybackDidFinishNotification
                                                  object:playerVC.moviePlayer];

    // Register this class as an observer instead
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(movieFinishedCallback:)
                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                               object:playerVC.moviePlayer];

    // Set the modal transition style of your choice
    playerVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

    // Present the movie player view controller
    [self presentViewController:playerVC animated:YES completion:nil];

    // Start playback
    [playerVC.moviePlayer prepareToPlay];
    [playerVC.moviePlayer play];
}

Dismiss controller

- (void)movieFinishedCallback:(NSNotification*)aNotification
{
    // Obtain the reason why the movie playback finished
    NSNumber *finishReason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];

    // Dismiss the view controller ONLY when the reason is not "playback ended"
    if ([finishReason intValue] != MPMovieFinishReasonPlaybackEnded)
    {
        MPMoviePlayerController *moviePlayer = [aNotification object];

        // Remove this class from the observers
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:MPMoviePlayerPlaybackDidFinishNotification
                                                      object:moviePlayer];

        // Dismiss the view controller
        [self dismissViewControllerAnimated:YES completion:nil];
    }
}

You'r Done !!!

Kampai
  • 22,848
  • 21
  • 95
  • 95
  • 2
    Thanks! Change `[self dismissModalViewControllerAnimated:YES];` to `[self dismissViewControllerAnimated:YES completion:nil];` to avoid deprecation warning on iOS 8. – Gene Z. Ragan Feb 06 '15 at 22:29
  • Found out why its not working. You need to change removeObserver:playerVC to removeObserver:self – Zia Aug 20 '15 at 18:41
2
@property (nonatomic, strong) MPMoviePlayerController *moviePlayer;

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(doneButtonClick:) 
                                             name:MPMoviePlayerDidExitFullscreenNotification 
                                           object:nil];

- (void)doneButtonClick:(NSNotification*)aNotification
{
    if (self.moviePlayer.playbackState == MPMoviePlaybackStatePaused)
    {
        NSLog(@"done button tapped");
    }
    else
    {
        NSLog(@"minimize tapped");
    }
}
iCoder
  • 1,645
  • 1
  • 15
  • 23
  • The problem here is that if the user pauses the video and then taps the "minimize" button the doneButtonClick: logic is wrong. Has anyone figured out a way to distinguish between "done" and "minimize" if the video is in a paused state? – jbolter Jan 27 '16 at 01:22
2

Swift version, for anyone who's interested:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayerDoneButtonClicked:", name: MPMoviePlayerPlaybackDidFinishNotification, object: nil)

Notification handler:

func moviePlayerDoneButtonClicked(note: NSNotification) {

    let reason = note.userInfo?[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]
    if (MPMovieFinishReason(rawValue: reason as! Int) == MPMovieFinishReason.UserExited) {
        self.exitVideo()
    }
}
Lirik
  • 3,167
  • 1
  • 30
  • 31
1

Wow, so many wrong approaches. The answer is this simple:

    moviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL fileURLWithPath:filePath]];

    [self.navigationController presentMoviePlayerViewControllerAnimated:moviePlayerViewController];

Check this link if you have a minute: https://developer.apple.com/library/prerelease/ios/documentation/MediaPlayer/Reference/UIViewController_MediaPlayer_Additions/index.html

Happy coding! Z.

Zoltán
  • 1,422
  • 17
  • 22
0

Apple's documentation is very poor on this matter. It suggests to listen for MPMoviePlayerDidExitFullscreenNotification (or WillExit...) and NOT for MPMoviePlayerDidFinishNotification as it doesn't fire when the user taps Done. This is entirely not true! I've just tested it on Xcode 6.0 with iPad Simulator (iOS 7.1 + 8.0) and only MPMoviePlayerDidFinishNotification is fired when DONE is tapped.

My compliments to user523234 who got it right on one of the comments above.

Register the following observer

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playbackStateChanged:)
                                        name:MPMoviePlayerPlaybackDidFinishNotification
                                           object:_mpc];
nstein
  • 339
  • 2
  • 14