MoviePlayer in iOS 4
June 24th by Tommy Leung
In the quest to make Propaganda Lander run under iPhone SDK 4.0 and eventually utilize Game Center, I’ve run across some problems/solutions with multitasking. The most recent problem was with MPMoviePlayer. Propaganda Lander plays a movie on each planet plus a nice little video after you’ve beaten the game so movie playing had to work.
SDK 4.0 changes how the MPMoviePlayer works. I think it is now much better than it was before. You have more control over it. It will also, by default, mix with other audio as well. Right now, Propaganda Lander will kill your iPod if a movie plays. We didn’t particularly like that but, there was no choice in the matter. There is now! The iOS 4 version of Propaganda Lander will have this feature.
So, Apple has created an MPMoviePlayerViewController that you can use as a view to control the movie. MPMoviePlayerController still exists but is slightly different. In the past, creating an MPMoviePlayerController would just take over the device and play the movie. You now need to add your MPMoviePlayerController’s view to a UIView or UIWindow.
The MPMoviePlayerViewController will auto rotate if the device’s orientation changes. This was not ideal for Propaganda Lander as it only plays in one orientation: OrientationLandscapeRight. In order to get around that, we had to use the UIView from the MPMoviePlayerController and transform it accordingly.
Here is some code straight out of Propaganda Lander for movie player in iOS 4
You’ll need this for the degrees to radians conversion
#define degreesToRadian(x) (M_PI * (x) / 180.0)
This is the actual code:
MPMoviePlayerController * theMovie; theMovie = [[MPMoviePlayerController alloc] initWithContentURL: movieURL]; UIView * movieView = [theMovie view]; [movieView setFrame: CGRectMake(0, 0, 480, 320)]; CGAffineTransform landscapeTransform; landscapeTransform = CGAffineTransformMakeRotation(degreesToRadian(90)); landscapeTransform = CGAffineTransformTranslate(landscapeTransform, 80, 80); [movieView setTransform: landscapeTransform]; theMovie.scalingMode = MPMovieScalingModeAspectFit; theMovie.fullscreen = TRUE; theMovie.controlStyle = MPMovieControlStyleNone; theMovie.shouldAutoplay = TRUE; [[[UIApplication sharedApplication] keyWindow] addSubview: movieView];
If you would like to use the MPMoviePlayerViewController that has all the auto rotation features, it would look like this:
MPMoviePlayerViewController * movieView; movieView = [[MPMoviePlayerViewController alloc] initWithContentURL: movieURL]; MPMoviePlayerController * theMovie = [movieView moviePlayer]; theMovie.scalingMode = MPMovieScalingModeAspectFit; theMovie.fullscreen = TRUE; theMovie.controlStyle = MPMovieControlStyleNone; theMovie.shouldAutoplay = TRUE; [[[UIApplication sharedApplication] keyWindow] addSubview: movieView.view]
When you the movie is done playing, you will want to remove it. You can do so by using the NSNotificationCenter to get a callback when the movie is done.
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(movieFinishedCallback:) name: MPMoviePlayerPlaybackDidFinishNotification object: theMovie];
When the movie is finished, it will call the movieFinishedCallback method which would look something like this:
- (void)movieFinishedCallback: (NSNotification*) notification;
{
[[NSNotificationCenter defaultCenter] removeObserver: self
name:MPMoviePlayerPlaybackDidFinishNotification
object: [notification object]];
MPMoviePlayerController * theMovie = [notification object];
[theMovie.view removeFromSuperview];
[theMovie release];
}
This ONLY works in iOS 4 devices. If you also need to target iPhone OS 3.0 or 2.0, you will need to check for the OS and then have the former MPMoviePlayer code as well. Since Propaganda Lander still targets iPhone OS 3.0, we made this function to check for the OS.
std::string getOS()
{
UIDevice * device = [UIDevice currentDevice];
NSString * os = [device systemVersion];
if([os isEqualToString:@"4.0"])
return "4.0";
if([os isEqualToString:@"3.0"])
return "3.0";
if([os isEqualToString:@"3.1"])
return "3.1";
if([os isEqualToString:@"3.2"])
return "3.2";
if([os isEqualToString:@"3.1.2"])
return "3.1.2";
if([os isEqualToString:@"3.1.3"])
return "3.1.3";
return "";
}
And for a much more robust way of determining iOS version that can be compared as numbers:
float getOSf()
{
UIDevice * device = [UIDevice currentDevice];
NSString * os = [device systemVersion];
float osAsFloat = [os floatValue];
return osAsFloat;
}
There’s some C++ and Objective-C in there as you can see. I actually wanted to return numbers but, strings will do for now. You can just as well return NSString’s exclusively if you’d like. As you can also see, we don’t care about OS’s below 3.0. OS 3.2 is the iPad OS and should have no effect for iPhone development but, I left it in there anyway. I believe 3.2 uses the same MPMoviePlayer code as iOS 4.0.
So if your movie player suddenly stops working in iOS 4.0, this is why and this is how to fix it.
| Tweet |

