我需要使用http协议实现视频流服务。 我知道如何将url设置为MPMoviePlayerController,以及如何将headerField设置为NSMutableURLRequest,但我不知道如何组合它们。 我实现如下代码,但不工作,我假设因为二进制数据中没有文件信息。
- (void) openUrl
{
NSMutableURLRequest *reqURL = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:@"http://111.222.33.44/MOV/2013/4/123123123"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
[reqURL setHTTPMethod:@"GET"];
[reqURL setValue:@"Mozilla/4.0 (compatible;)" forHTTPHeaderField:@"User-Agent"];
[reqURL setValue:@"AAA-bb" forHTTPHeaderField:@"Auth-Token"];
[reqURL setValue:@"bytes=0-1024" forHTTPHeaderField:@"Range"];
[reqURL setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[NSURLConnection connectionWithRequest:reqURL delegate:self];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"Received");
NSError * jsonERR = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"myMove.ts"];
[data writeToFile:path atomically:YES];
NSLog(@"copied");
NSURL *moveUrl = [NSURL fileURLWithPath:path];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc]init];
[player setContentURL:moveUrl];
player.view.frame = self.view.bounds;
player.controlStyle = MPMovieControlStyleEmbedded;
[self.view addSubview:player.view];
[player play];
}
我确认委托方法中有数据,但我不知道如何播放它。 请有人让我知道怎么玩。 Auth-Token和Range是必要的参数。
感谢。
答案 0 :(得分:7)
Apple确实没有公开一种将标头注入MPMoviePlayerController
请求的简单方法。通过一些努力,您可以使用自定义NSURLProtocol完成此操作。那么,让我们做吧!
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
在使用自定义URL协议之前,必须先注册它。在你的AppDelegate.m中:
#import "MyCustomURLProtocol.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ... Your normal setup ...
[NSURLProtocol registerClass:[MyCustomURLProtocol class]];
return YES;
}
最后,您需要使用MPMediaPlayerController来使用自定义URL协议。
NSString* theURLString = [NSString stringWithFormat:@"customProtocol://%@%@", [_url host],[_url path]];
_player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:theURLString]];
MPMoviePlayerController现在将尝试使用customProtocol://
而非普通http://
发出请求。使用此设置,我们然后拦截该请求,添加我们的标头,将其转换为http,然后关闭所有内容。
答案 1 :(得分:1)
返回并阅读NSURLConnection
的文档以及一般的URL加载系统。 -connection:didReceiveData:
可能会被调用多次,因为文件的每个块都会到达。你需要处理它,而不是假设只有完整的数据一次到达。