Gra*_*mpa 13 javascript html5-video ios cordova phonegap-build
我们有一个使用PhoneGap/Cordova 4.3.0构建的iOS应用程序.此应用程序通过<content src="http://example.com/foo" />在config.xml文件中使用直接加载外部网站.所有功能都包含在本网站中,因此我们实际上并没有使用任何本地HTML或JS文件.
作为应用功能的一部分,我们必须播放一些视频.由于该应用程序也设计为脱机工作,因此我们希望在本地缓存这些视频.因此,我们使用FileTransfer插件将其下载到设备,以及其他资源,如图像或PDF.下载文件后,我们将获得带有file://协议的URL .我们也可以选择使用该cdvfile://协议.当我们使用cdvfile://URL显示图像时,图像会正确显示.但是,视频根本不播放.
要播放视频,我们使用标准HTML5视频标记:
<video width="auto" height="100%" controls="controls" autoplay="true">
<source src="..." type="video/mp4" />
</video>
Run Code Online (Sandbox Code Playgroud)
视频本身正在工作,它们将从外部源正确播放(如果我们从服务器而不是本地文件系统访问它们,它们将播放).我意识到问题与Web相关的概念有关,例如同源策略和访问本地文件系统的限制.然而,与此同时,我必须想知道为什么图像在这些相同的约束下工作正常.
到目前为止我尝试了什么:
file://和cdvfile://URL作为src视频.这不会产生任何视觉效果.屏幕简直是黑色.iframe带有src设置的视频URL.使用时file://,屏幕仍为黑色.但是,在使用时cdvfile://,会出现iOS视频播放器界面,带有播放按钮和全屏按钮,但视频无法播放,也没有时间线.video.html,该文件将URL作为参数并video使用该URL 呈现标记src.计划是将此文件包含在内iframe,但显然我无法创建iframe本地文件.我尝试过各种可能指向该特定video.html文件的URL (虽然实际上我不确定这是否可行).在我试过的人分别为:cordova.file.applicationDirectory + 'www/video.html',http://localhost/www/video.html,cdvfile://localhost/www/video.html.现在,我可能会以错误的方式解决这个问题.正如我所看到的,cordova的"标准用例"是您在本地存储HTML/JS/CSS文件.像我正在使用的外部内容可能有点不寻常.我将解释这个使我使用此功能的应用程序的要求.
cache.manifest允许我们控制Web应用程序代码的更新,同时允许它在本地缓存.这可能是最重要的考虑因素,因为如果我们想在Cordova中本地保留一些文件,我们将不得不在Javascript中重新实现这个缓存功能(尽可能使用尽可能薄的层).无论如何,我主要关注的是如何让这些视频正常运行.我愿意尝试最骇客的解决方法!如果当前的开发决策真的不可能,那么也许你可以给我一些关于如何构建应用程序以使其工作并仍然满足我的要求的提示.
非常感谢你!
大约一年前我有一个类似的项目。但我不记得遇到过这个问题,因为我们将 html/js/css 资源与应用程序捆绑在一起。
问题是您正在尝试从http:///协议提供的 html 文件加载 file:/// 协议 url,这不是本机 UIWebView 所熟悉的。
您可以通过使用自定义 URL 方案(如 video://)来绕过此问题,但您需要编写一些本机代码来拦截此请求并将实际视频传输回 URL 加载系统。
最终结果:

这是我使用 Cordova 4.3.0 和一些 ObjectiveC 的方法
VideoURLProtocol.h:
#import <Foundation/Foundation.h>
@interface VideoURLProtocol : NSURLProtocol <NSURLConnectionDelegate>
@property (strong, nonatomic) NSURLConnection *connection;
@end
Run Code Online (Sandbox Code Playgroud)
VideoURLProtocol.m:
#import "VideoURLProtocol.h"
@implementation VideoURLProtocol
@synthesize connection;
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
return [[[request URL] absoluteString] rangeOfString:@"video://"].location != NSNotFound;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.client URLProtocol:self didLoadData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
}
- (void)startLoading {
NSString *currentURL = [[self.request URL] absoluteString];
NSString *newURL = [currentURL stringByReplacingOccurrencesOfString:@"video://" withString:@"file:///"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:newURL]];
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
- (void)stopLoading {
[self.connection cancel];
self.connection = nil;
}
@end
Run Code Online (Sandbox Code Playgroud)
将以下行添加到 AppDelegate.m 的 didFinishLaunchingWithOptions 方法中
.
.
// These lines should already be there
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
// This line
[NSURLProtocol registerClass:[VideoURLProtocol class]];
.
.
Run Code Online (Sandbox Code Playgroud)这是利用这个新 URL 方案的 javascript 代码
document.addEventListener('deviceready', function(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
var caches = fileSystem.root.nativeURL.replace("Documents", "Library/Caches"),
videoPath = caches + "video.mp4";
new FileTransfer().download("http://clips.vorwaerts-gmbh.de/VfE_html5.mp4", videoPath, function(entry){
document.getElementsByTagName("video")[0].src = caches.replace("file:///", "video://") + "video.mp4"
}, function(error){
alert("unable to download file: " + error);
});
});
}, false);
Run Code Online (Sandbox Code Playgroud)一些值得一提的额外要点:
请注意,在我的 javascript 代码中,我将文件下载到“/Library/Caches”而不是“/Documents”目录(默认位置),这是因为“/Documents”目录被备份到 iCloud,并且 Apple 拒绝尝试尝试的应用程序备份超过 ~100 MB。这是我的应用程序被拒绝后我发现的困难。您可以在以下位置查看您的应用占用的空间:设置 > iCloud > 存储 > 管理存储 > {{您的 iphone 名称}} > 显示所有应用
您可以通过将以下行添加到 config.xml 来自动播放视频
<preference name="MediaPlaybackRequiresUserAction" value="false" />
Run Code Online (Sandbox Code Playgroud)
您还可以通过将以下行添加到 config.xml 来内嵌播放视频,此外您还需要向视频添加 webkit-playsinline="true" 属性:
<preference name="AllowInlineMediaPlayback" value="true" />
<video controls="controls" autoplay="true" webkit-playsinline="true" preload="auto">
</video>
Run Code Online (Sandbox Code Playgroud)
这是 Ray 的一个非常有趣的教程,详细解释了 NSURLProtocol:http://www.raywenderlich.com/59982/nsurlprotocol-tutorial
| 归档时间: |
|
| 查看次数: |
3195 次 |
| 最近记录: |