Stream large movie with credential through MPMoviePlayer

我的未来我决定 提交于 2020-01-04 06:28:21

问题


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?


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/22162404/stream-large-movie-with-credential-through-mpmovieplayer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!