问题
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