iOS4 gotchas – video

Remember there are several places you will need to touch your code to allow the app to work seamlessly in iOS4. possibly the biggest headache is the change to the video player.

I have just completed an app for a client. I finished the coding a couple of months ago. Unfortunately (from the development perspective) the client then got embroiled in a takeover which dragged on. By the time the waters settled, the app no longer worked as Apple had released iOS4 with the new video architecture. Although a fairly small change, imagine the client’s surprise when all of the video content suddenly disappeared!

So, how do you fix it? In my case, it was fairly simple. The first function was to check the version of the device/os being used with the following utility function:

-(BOOL) isOS4 {
    static BOOL _isOS4 = FALSE;
    static BOOL _checkOSVersion = YES; // Only perform check once

    if (_checkOSVersion) {
        NSString *osVerStr = [[UIDevice currentDevice] systemVersion];
        if ([osVerStr characterAtIndex:0] >= '4') {
            _isOS4 = TRUE;
        }
        _checkOSVersion = FALSE;
    }
    return _isOS4;
}

In the routine that plays a video resource, simply call that routine to launch an OS specific version:

-(void) playMovieWithName:(NSString *)name {
    if (!name) {
        NSLog(@"No movie found - No action possible");
        return;
    }

    NSLog(@"Play Movie: %@", name);

    NSString *moviePath = [[[NSBundle mainBundle] resourcePath]
                            stringByAppendingPathComponent:name];
    NSURL *movieURL = [NSURL fileURLWithPath:moviePath];

    if ([self isOS4]) {
        [self playMovieDirectAtURL_OS4:movieURL];
    } else {
        [self playMovieDirectAtURL:movieURL];
    }
}

Now to the differences. Firstly, the established pre iOS4 version:

-(void) playMovieDirectAtURL: (NSURL*) theURL {

    MPMoviePlayerController* theMovie =
            [[MPMoviePlayerController alloc] initWithContentURL: theURL];

    theMovie.scalingMode = MPMovieScalingModeAspectFit;
    theMovie.movieControlMode = MPMovieControlModeHidden;

    // Register for the playback finished notification
    [[NSNotificationCenter defaultCenter] addObserver: self
            selector: @selector(myMovieFinishedCallback:)
            name: MPMoviePlayerPlaybackDidFinishNotification
            object: theMovie];

    // Movie playback is asynchronous, so this method returns immediately.
    [theMovie play];	

#ifdef DEBUG_MODE
    theMovie.movieControlMode = MPMovieControlModeDefault;
#endif
}

(note the optional debug section – if I am in debug mode, I want the option to skip out of a long video. In the final app, my client does not want the user to skip the video).

And the iOS4 version:

#define degreesToRadian(x) (M_PI * (x) / 180.0)

-(void) playMovieDirectAtURL_OS4: (NSURL*) theURL {
    MPMoviePlayerController* theMovie =
            [[MPMoviePlayerController alloc] initWithContentURL: theURL];
    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.controlStyle = MPMovieControlStyleNone;
    theMovie.shouldAutoplay = TRUE;
    theMovie.fullscreen = TRUE;

    // Register for the playback finished notification
    [[NSNotificationCenter defaultCenter] addObserver: self
            selector: @selector(myMovieFinishedCallback:)
            name: MPMoviePlayerPlaybackDidFinishNotification
            object: theMovie];

    // Movie playback is asynchronous, so this method returns immediately.
    [[[UIApplication sharedApplication] keyWindow] addSubview:movieView];
    [[UIApplication sharedApplication] setStatusBarHidden:TRUE];

#ifdef DEBUG_MODE
    theMovie.controlStyle = MPMovieControlStyleDefault;
#endif
}

And finally, the callback routine, which must also determine the os version:

-(void) myMovieFinishedCallback: (NSNotification*) aNotification {
    MPMoviePlayerController* theMovie = [aNotification object];

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

    if ([self isOS4]) {
        [[UIApplication sharedApplication] setStatusBarHidden:FALSE];
        [theMovie.view removeFromSuperview];
        // Belt and braces - force a redraw of what is underneath
        [self.view setNeedsDisplay];
    } else {
        [theMovie stop];
    }

    // When the movie is done, release the controller.
    [theMovie release];
}

And that’s it. A new video handling system that will work on each os version without loads of compiler directives.

Enjoy!

This entry was posted in iOS Development. Bookmark the permalink.

2 Responses to iOS4 gotchas – video

  1. Reposted this. Greetings from the Speedy DNS