It's true that Apple doesn't expose an easy way to inject headers into a MPMoviePlayerController
's request. With a bit of effort, you can get this done using a custom NSURLProtocol. So, let's do it!
MyCustomURLProtocol.h:
@interface MyCustomURLProtocol : NSURLProtocol <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@property (nonatomic, strong) NSURLConnection* connection;
@end
MyCustomURLProtocol.m:
@implementation MyCustomURLProtocol
// Define which protocols you want to handle
// In this case, I'm only handling "customProtocol" manually
// Everything else, (http, https, ftp, etc) is handled by the system
+ (BOOL) canInitWithRequest:(NSURLRequest *)request {
NSURL* theURL = request.URL;
NSString* scheme = theURL.scheme;
if([scheme isEqualToString:@"customProtocol"]) {
return YES;
}
return NO;
}
// You could modify the request here, but I'm doing my legwork in startLoading
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
// I'm not doing any custom cache work
+ (BOOL) requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
// This is where I inject my header
// I take the handled request, add a header, and turn it back into http
// Then I fire it off
- (void) startLoading {
NSMutableURLRequest* mutableRequest = [self.request mutableCopy];
[mutableRequest setValue:@"customHeaderValue" forHTTPHeaderField:@"customHeaderField"];
NSURL* newUrl = [[NSURL alloc] initWithScheme:@"http" host:[mutableRequest.URL host] path:[mutableRequest.URL path]];
[mutableRequest setURL:newUrl];
self.connection = [NSURLConnection connectionWithRequest:mutableRequest delegate:self];
}
- (void) stopLoading {
[self.connection cancel];
}
// Below are boilerplate delegate implementations
// They are responsible for letting our client (the MPMovePlayerController) what happened
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
self.connection = nil;
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.client URLProtocol:self didLoadData:data];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
self.connection = nil;
}
@end
Before you can use your custom URL Protocol, you must register it. In your AppDelegate.m:
#import "MyCustomURLProtocol.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ... Your normal setup ...
[NSURLProtocol registerClass:[MyCustomURLProtocol class]];
return YES;
}
Finally, you need to user your custom URL Protocol with the MPMediaPlayerController.
NSString* theURLString = [NSString stringWithFormat:@"customProtocol://%@%@", [_url host],[_url path]];
_player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:theURLString]];
The MPMoviePlayerController will now attempt to make the request with customProtocol://
instead of normal http://
. Using this setup, we then intercept that request, add our headers, turn it into http, and then fire everything off.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…