【问题标题】:How to insert header info into MPMoviePlayerController url?如何将标题信息插入 MPMoviePlayerController url?
【发布时间】:2023-03-16 06:42:01
【问题描述】:

我需要使用 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];
}

我确认delegate方法中有数据,但是不知道怎么玩。 请有人告诉我怎么玩。 Auth-Token 和 Range 是必要的参数。

谢谢。

【问题讨论】:

    标签: xcode nsurlconnection mpmovieplayercontroller nsurlrequest


    【解决方案1】:

    确实,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,然后关闭所有内容。

    【讨论】:

    • 遗憾的是,这不适用于设备,只能在模拟器上运行。 iOS 9
    【解决方案2】:

    返回并阅读NSURLConnection 的文档以及一般的 URL 加载系统。 -connection:didReceiveData: 可能被多次调用,因为文件的每个块都到达了。您需要处理这个问题,而不是假设一次只有完整的数据到达。

    【讨论】:

    • 顺便问一下怎么处理?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多