Question

I've been trying to stream a movie from a url that is protected. I can download the movie then play it, but the movie is too long so this is annoying.

Here is my code:

-(MPMoviePlayerController *)moviePlayerController
{
 NSURL *url = [NSURL URLWithString:@"http://ABcDE.com/secret/Movie.mov"];
 _moviePlayer =  [[MPMoviePlayerController alloc] initWithContentURL:url];
NSURLCredential *credential = [[NSURLCredential alloc]
                               initWithUser: @"user"
                               password: @"password"
                               persistence: NSURLCredentialPersistencePermanent];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                         initWithHost: [url host]
                                         port: 80
                                         protocol: [url scheme]
                                         realm: [url host]
                                         authenticationMethod: NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage]
 setDefaultCredential: credential
 forProtectionSpace: protectionSpace];

_moviePlayer.view.frame = CGRectMake(0, 0, 500, 500);

_moviePlayer.controlStyle = MPMovieControlStyleDefault;
_moviePlayer.shouldAutoplay = YES;
_moviePlayer.backgroundView.backgroundColor = [UIColor blackColor];
_moviePlayer.allowsAirPlay = YES;
_moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
return _moviePlayer;
}

I've tried chaining the realm to nil that didn't work. I tried moving the initWitcontnetURL after the

   [[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential: credential forProtectionSpace: protectionSpace];           

that didn't work either.

From the method -(void) moviePlayBackDidFinish:(NSNotification*)notification I get the error Error Domain=MediaPlayerDomain Code=-1013 "The operation couldn't be completed. (MediaPlayerErrorDomain error -1013.)"

Looking at apple documentation it is a CFNetwork Error kCFURLErrorUserAuthenticationRequired = -1013

Any Ideas how to solve this?

No correct solution

OTHER TIPS

I couldn't get MPMoviePlayerController to do the authentication challenge properly, even thought the Apple docs say otherwise. The VERY hacky solution I came up with was to use Apple's CustomHTTPProtocol to intercept the response and provide the authentication challenge response. I believe the original purpose for this protocol was to handle authentication for UIWebViews.

Link to CustomHTTPProtocol: https://developer.apple.com/library/ios/samplecode/CustomHTTPProtocol/Listings/Read_Me_About_CustomHTTPProtocol_txt.html

My interface declaration:

@interface SampleViewController() <CustomHTTPProtocolDelegate>

Instantiation of MPMoviePlayerController within my SampleViewController:

NSString *fullURLString = @"http://www.samplesite.com/samplemovie.mp4";
NSURL *fullURL = [NSURL URLWithString:fullURLString];

[CustomHTTPProtocol setDelegate:self];
[CustomHTTPProtocol start];

NSURLCredential *credential = [[NSURLCredential alloc]
                              initWithUser:@"username"
                              password:@"password"
                              persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                        initWithHost:fullURL.host
                                        port:80
                                        protocol:fullURL.scheme
                                        realm:nil
                                        authenticationMethod:NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];

self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:fullURL];
[self.moviePlayer prepareToPlay];
[self.moviePlayer setShouldAutoplay:NO];
[self.moviePlayer setControlStyle:MPMovieControlStyleEmbedded];
[self.moviePlayer.view setFrame:self.sampleView.bounds];
[self.moviePlayer.backgroundView setBackgroundColor:[UIColor colorWithWhite:0.9 alpha:1.0]];
[self.moviePlayer.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[self.sampleView addSubview:self.moviePlayer.view];

Also in my SampleViewController, I have a couple delegate methods. For basic authentication, it's pretty simple:

- (BOOL)customHTTPProtocol:(CustomHTTPProtocol *)protocol canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    BOOL canAuth = ([[protectionSpace authenticationMethod] isEqual:NSURLAuthenticationMethodHTTPBasic] &&
                    [[protectionSpace realm] isEqualToString:<your realm>]);
    return canAuth;
}

- (void)customHTTPProtocol:(CustomHTTPProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSURLCredential *newCredential = [NSURLCredential credentialWithUser:<username>
                                               password:<password>
                                            persistence:NSURLCredentialPersistenceForSession];
    [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}

After you call start, all http and https requests go through the CustomHTTPProtocol module

I didn't include CustomHTTPProtocol since Apple provides the source and it's really long. I made some changes to make it work with ARC but it's mostly the same code.

Hopefully this works for you.

If your video server expects Basic Authentication, it can be easily passed to the movie player controller's URL, e.g. instead of regular url you will pass url in format:

http(s)://user:password@host/path

Then video will be played.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top