How to make status bar not to disappear in MPMoviePlayerController in iOS? - ios

In MPMoviePlayerController, when ever the controls disappear, even the status bar is disappearing with it. Since i want the status bar to appear even when the control disappears, i placed the below code
[[UIApplication sharedApplication] setStatusBarHidden:NO];
But the above code is not making any difference, teh status bar is getting disappeared along with the player controls. How to solve this problem.
Please find the code below, and let me know how to rectify it.
- (void) readyPlayer {
mp = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
if ([mp respondsToSelector:#selector(loadState)])
{
// Set movie player layout
[mp setControlStyle:MPMovieControlStyleFullscreen];
[mp setFullscreen:YES];
// May help to reduce latency
[mp prepareToPlay];
// Register that the load state changed (movie is ready)
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerLoadStateChanged:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
} else {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePreloadDidFinish:) name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification
object:nil];
}
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
}
- (void) moviePlayerLoadStateChanged:(NSNotification*)notification {
NSLog(#"moviePlayerLoadStateChanged");
// Unless state is unknown, start playback
if ([mp loadState] != MPMovieLoadStateUnknown)
{
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
// Rotate the view for landscape playback
[[self view] setBounds:CGRectMake(0, 0, 768, 1000)];
// Set frame of movieplayer
[[mp view] setFrame:CGRectMake(0, 0, 768, 1000)];
// Add movie player as subview
[[self view] addSubview:[mp view]];
// Play the movie
[mp play];
}
}
- (void) moviePreloadDidFinish:(NSNotification*)notification {
// Remove observer
NSLog(#"moviePreloadDidFinish");
[[NSNotificationCenter defaultCenter] removeObserver:nil
name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification
object:nil];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
// Play the movie
[mp play];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
NSLog(#"moviePlayBackDidFinish");
[[UIApplication sharedApplication] setStatusBarHidden:NO];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
[self dismissModalViewControllerAnimated:YES];
}

This is a well-known issue of MPMovieControlStyleFullscreen. Simply use the MPMovieControlStyleEmbedded controlStyle and you are good to go.
And, by the way, that is the more adequate controlStyle for embedded usage anyways.

Related

MPMoviePlayerController crash when start play a video on iOS 6

I'm using MPMoviePlayerViewController to play video. In my app I am playing video(s) that are in the app, using the standard MPMoviePlayerController class. It works fine on iOS 7 and 8
The first time around around this works great, however after watching 1 video if you try and watch something else the app crashes on MPMoviePlayerController's play method with the error:
: CGContextSaveGState: invalid context 0x0
: CGContextClipToRect: invalid context 0x0
: CGContextTranslateCTM: invalid context 0x0
: CGContextDrawShading: invalid context 0x0
: CGContextRestoreGState: invalid context 0x0
*** -[MPMoviePlayerController retain]: message sent to deallocated instance 0x1e5718b0
I can not figure out why this is happening.
Here is my code:
AFPlayerViewController.h
#property (strong, nonatomic) MPMoviePlayerViewController *playerViewController;
- (id)initWithContentURL:(NSString*)movieUrl
andSubtitlePath:(NSString*)subPath
withTypeServer:(NSString*)serverType
withName:(NSString*)name
withEpisodeId:(NSString*)episodeId
withFilmId:(NSString*)filmId
withDuration:(NSInteger)targetDuration
withSeason:(NSString*)seasonId;
AFPlayerViewController.m
#synthesize playerViewController;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (_movieURL) {
self.playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL: _movieURL];
self.playerViewController.moviePlayer.initialPlaybackTime = -1.f;
self.playerViewController.moviePlayer.shouldAutoplay = NO;
[self.playerViewController.moviePlayer setControlStyle:MPMovieControlStyleNone];
[self.playerViewController.moviePlayer setFullscreen:NO animated:YES];
self.playerViewController.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
[self.playerViewController.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.playerViewController.view];
[NSLayoutConstraint alightTopBotLeftRight:self.playerViewController.view inView:self.view];
[self.playerViewController.moviePlayer prepareToPlay];
[self.playerViewController.moviePlayer play];
[self receiveNotificationPlayerViewController];
}
}
- (void)receiveNotificationPlayerViewController {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(durationAvailable:)
name:MPMovieDurationAvailableNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(loadStateDidChange:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sourceTypeAvailable:)
name:MPMovieSourceTypeAvailableNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(readyForDisplay:)
name:MPMoviePlayerReadyForDisplayDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didFinishAVideo:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.playerViewController.moviePlayer];
}
- (void) durationAvailable: (NSNotification*) notification {
NSLog(#"1");
}
- (void) loadStateDidChange: (NSNotification*) notification {
NSLog(#"2");
if ([self.playerViewController.moviePlayer loadState] != MPMovieLoadStateUnknown) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
}
}
- (void) playbackStateDidChange: (NSNotification*) notification {
NSLog(#"3");
switch (self.playerViewController.moviePlayer.playbackState) {
case MPMoviePlaybackStateSeekingForward:
case MPMoviePlaybackStateSeekingBackward:
break;
case MPMoviePlaybackStatePaused: {
NSLog(#"pause");
}
break;
case MPMoviePlaybackStateStopped: {
NSLog(#"stop");
}
break;
case MPMoviePlaybackStateInterrupted:{
NSLog(#"interrupted");
}
break;
case MPMoviePlaybackStatePlaying: {
NSLog(#"playing");
}
break;
default:
break;
}
}
- (void) sourceTypeAvailable: (NSNotification*) notification {
NSLog(#"4");
}
- (void) readyForDisplay: (NSNotification*) notification {
NSLog(#"5");
}
- (void)orientationDidChange: (NSNotification*)notification {
NSLog(#"6");
}
- (void)didFinishAVideo:(NSNotification*)notification {
[self removeNotification];
}
- (void)removeNotification {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMovieDurationAvailableNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMovieSourceTypeAvailableNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerReadyForDisplayDidChangeNotification
object:self.playerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIDeviceOrientationDidChangeNotification
object:self.playerViewController.moviePlayer];
}
AppDelegate.h
#property (strong, nonatomic) AFPlayerViewController *player;
AppDelegate.m
+ (AppDelegate *)shareInstance{
return (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (UIViewController *)currentVisibleController{
id rootController = self.window.rootViewController;
if ([rootController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootController;
return navigationController.topViewController;
}
if ([rootController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabbarController = (UITabBarController *)rootController;
id topViewController = [tabbarController.viewControllers objectAtIndex:tabbarController.selectedIndex];
if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navi = (UINavigationController *)topViewController;
return navi.topViewController;
}
return topViewController;
}
return self.window.rootViewController;
}
When I'd like to play a video:
[AppDelegate shareInstance].player = [[AFPlayerViewController alloc] initWithContentURL:link
andSubtitlePath:subtitle
withTypeServer:serverType
withName:nameFilm
withEpisodeId:epObject.episodeId
withFilmId:filmId
withDuration:lastDuration
withSeason:epObject.id_season];
[[AppDelegate shareInstance].currentVisibleController presentViewController:[AppDelegate shareInstance].player animated:NO completion:^{
}];
You may well be getting the error because of notifications being sent to a removed controller object as #Bannings says. Nevertheless, I have a couple of other suggestions that will improve your code (and I am fairly sure will remove the error).
Firstly, the documentation says that you should register for the MPMoviePlayerLoadStateDidChangeNotification and use the loadState method to determine when the movie is ready to start playing. I strongly suggest that you do that.
Secondly, you are instantiating a MPMoviePlayerController every time your view appears. I would suggest that you create a single AFPlayerViewController and a single MPMoviePlayerController. Present the same AFPPlayerViewController whenever you wish to play another movie.
When you first instantiate the MPMoviePlayerController, you will need a a URL, for its init method, but subsequent movies can be started using the contentURL property of MPMoviePlayerController
A side advantage of my suggestion is that it will be very easy for a user to pause a movie, go to a different view, and then quickly resume when they return to the movie view.
Have you called the removeNotification if you try and watch something else? try to add viewDidDisappear:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self removeNotification];
}
I think I see the real problem here: you should be using MPMoviePlayerController not MPMoviewPlayerViewController. Make that change, and see if the crash disappears. My suggestion about loadState should be followed too.

MPMoviePlayerController seek bar is not appearing after applying natural size

I am using MPMoviePlayerController for playing video files and I am able to apply the natural size of the video with the help of MPMovieNaturalSizeAvailableNotification. But after adding this notification seek bar is not appearing in the controlStyle (all other buttons are present). If I make the video frame hard coded (i.e. without considering the natural height) I will not get this issue.
Here is my code
// Declartion class level
MPMoviePlayerController *moviePlayer;
float naturalHeight;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
moviewPlayer = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieReadyForDisplay:)
name:MPMoviePlayerReadyForDisplayDidChangeNotification
object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieNaturalSizeAvailable:)
name:MPMovieNaturalSizeAvailableNotification
object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
[self.view addSubview:moviePlayer.view];
moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
moviePlayer.fullscreen = NO;
moviePlayer.scalingMode = MPMovieScalingModeFill;
moviePlayer.shouldAutoplay = NO;
//I am able to get the seek bar here if I set the static height . But I want natural height here.
// moviePlayer.frame = CGRectMake(0, 0, self.view.frame.size.width , naturalHeight);
}
-(void) movieNaturalSizeAvailable:(NSNotification *)notification{
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMovieNaturalSizeAvailableNotification object:player];
naturalHeight = player.naturalSize.height;
if(naturalHeight > self.view.frame.size.height) {
naturalHeight = self.view.frame.size.height;
}
}
-(void) movieReadyForDisplay:(NSNotification *)notification{
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerReadyForDisplayDidChangeNotification object:player];
NSLog(#">> %f ", naturalHeight); //OK here
[player view].frame = CGRectMake(0, 0, self.view.frame.size.width , naturalHeight);
player.view.center = self.view.center;
[player prepareToPlay];
[player play];
}
- (void)moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player stop];
[player.view removeFromSuperview];
}
#end
I believe this issue might be because the natural size calculations of
video player occur after it sets its components frames. If I don't use natural size, it works perfectly. How can I fix this issue?
try this
before starting the video
player.controlStyle = MPMovieControlStyleNone;
and when movie starts playing then set
player.controlStyle = MPMovieControlStyleFullscreen;
You can get play callback from MPMediaPlayback protocol.

Video enters fullscreen but will not exit (iOS 6.1)

I am using a custom movie player to play videos with MPMoviePlayer as the base, and while the player will enter fullscreen fine when setFullscreen:YES is called, it won't exit fullscreen when setFullscreen:NO is called.
I have tried:
adding the video's view as a subview of a smaller window, and resetting the view's frame
using notifications as I show below (based on what I read in another question about this problem)
Here is the code I am currently using. None of the answers I have seen have solved the problem for me, so any help would be greatly appreciated.
- (IBAction)fullScreenPressed:(id)sender {
if ([self mediaIsVideo]){
if ([self.videoController.moviePlayer isFullscreen]){
[self.videoController.moviePlayer setFullscreen:NO animated:YES];
UIImage *full = [UIImage imageNamed:#"fullscreen-vector-icon.png"];
[self.videoFullscreenButton setImage:full forState:UIControlStateNormal];
}else{
//video is in fullscreen, add notification observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(exitFullscreen) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self.videoController.moviePlayer setFullscreen:YES animated:YES];
UIImage *undoFull = [UIImage imageNamed:#"fullscreen-exit-vector-icon.png"];
[self.videoFullscreenButton setImage:undoFull forState:UIControlStateNormal];
}
}
-(void)exitFullscreen{
if ([self mediaIsVideo]){
NSLog(#"notification selector called");
[self.videoController.moviePlayer setFullscreen:NO animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
}
}

MPMOVIEPLAYER when playing a video multple times in Landscape causes video to shift down and navigation bar disappears

I am writing an application that has imbedded videos. If I start the application in Landscape mode first and then start the video it looks good. So then I click on Done and then play the video a second time. The second time the video is now shifted down and to the left. When I click on the video the Done button does not show up. I have to switch the simulator to Portrait mode and then back to Landscape mode and then I can click on Done to stop the video. If I always start the video in Portrait mode, and then turn the simulator to landscape it will work. I can do this many times and the video will always line up properly. However if I play the application always in landscape mode, the video will always shift down and to the left for every play after the first time. I went through many of the other mpmovieplayer questions and compared my code to the other code. I am using IOS6 and Storyboard. I have copied my basic MPMOVIEPLAYER code below. I am really stuck here
MoviePlayerViewController.m
- (void) readyPlayer
mp = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
// For 3.2 devices and above
if ([mp respondsToSelector:#selector(loadState)])
{
// Set movie player layout
[mp setControlStyle:MPMovieControlStyleFullscreen];
[mp setFullscreen:YES];
// May help to reduce latency
[mp prepareToPlay];
// Register that the load state changed (movie is ready)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerLoadStateChanged:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
}
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
// Register to receive a notification when the movie has exit fullscreen mode.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
}
/*---------------------------------------------------------------------------
* For 3.2 and 4.x devices
*
*--------------------------------------------------------------------------*/
- (void) moviePlayerLoadStateChanged:(NSNotification*)notification
{
// Unless state is unknown, start playback
if ([mp loadState] != MPMovieLoadStateUnknown)
{
// Remove observer
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
// When tapping movie, status bar will appear, it shows up
// in portrait mode by default. Set orientation to `landscape`
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
// Rotate the view for landscape playback
[[self view] setBounds:CGRectMake(0, 0, 480, 320)];
[[self view] setCenter:CGPointMake(160, 240)];
[[self view] setTransform:CGAffineTransformMakeRotation(M_PI / 2)];
// Set frame of movie player
[[mp view] setFrame:CGRectMake(0, 0, 480, 320)];
} else {
// Rotate the view for landscape playback
[[self view] setBounds:CGRectMake(0, 0, 1024, 748)];
[[self view] setCenter:CGPointMake(374, 512)];
[[self view] setTransform:CGAffineTransformMakeRotation(M_PI / 2)];
// Set frame of movie player
[[mp view] setFrame:CGRectMake(0.0, 0.0, 1024.0, 748.0)];
}
// Add movie player as subview
[[self view] addSubview:[mp view]];
// Play the movie
[mp play];
}
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
// Remove observer
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}

Quitting MPMediaPlayerController view

I am writing a simple method to start a streaming video full-screen and letting the user quit pressing the "Done" button. Problem is, I can't remove the MPMediaPlayerController view, or perhaps I am doing it the wrong way.
- (IBAction)playVideoButtonPressed:(id)sender {
NSURL *url = [NSURL URLWithString:#"http://mysite.com/video.mov"];
mp = [[MPMoviePlayerController alloc] initWithContentURL: url];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerPlaybackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
if ([mp respondsToSelector:#selector(setFullscreen:animated:)]) {
mp.controlStyle = MPMovieControlStyleFullscreen;
mp.shouldAutoplay = YES;
[self.view addSubview:mp.view];
[mp.view setTag:3];
[mp setFullscreen:YES animated:YES];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:mp];
[mp play];
}
- (void)moviePlayBackDidFinish:(id)sender {
NSLog(#"Quitting MoviePlayer");
[mp.view removeFromSuperview];
}
The idea is that the MPMediaPlayerController view is called clicking on a button in the app, and it is dismissed by clicking the "Done" video or when the video ends.
I should have used MPMoviePlayerViewController.

Resources