2015-04-05 87 views
13

我們有一個使用PhoneGap/Cordova 4.3.0構建的iOS應用程序。此應用程序通過在​​3210文件中使用<content src="http://example.com/foo" />直接加載外部網站。所有的功能都包含在這個網站中,所以我們實際上並沒有使用任何本地的HTML或JS文件。科爾多瓦外部應用程序+本地視頻

作爲應用功能的一部分,我們必須播放一些視頻。由於該應用也可以離線工作,因此我們希望在本地緩存這些視頻。因此,我們使用FileTransfer插件將它們下載到設備,以及其他資源(如圖像或PDF)。在下載文件後,我們獲得了file://協議的URL。我們也可以選擇使用cdvfile://協議。當我們使用cdvfile://網址顯示圖片時,圖片顯示正確。但是,視頻根本不能播放。

要發揮我們使用標準的HTML5視頻標籤的視頻:

<video width="auto" height="100%" controls="controls" autoplay="true"> 
    <source src="..." type="video/mp4" /> 
</video> 

本身工作的視頻,他們會從外部源正常播放(如,他們將發揮,如果我們訪問它們服務器而不是本地文件系統)。我意識到這個問題與網絡相關的概念有關,例如同源策略和訪問本地文件系統的限制。然而,同時我也想知道爲什麼在這些相同的限制條件下圖像工作正常。

我迄今爲止嘗試:

  1. 使用file://cdvfile://網址作爲視頻src。這不會產生任何形式的視覺效果。屏幕只是黑色的。
  2. 使用iframe並將src設置爲視頻網址。當使用file://時,屏幕仍然是黑色的。但是,使用cdvfile://時,會出現iOS視頻播放器界面,帶有播放按鈕和全屏按鈕,但視頻不播放,也沒有時間線。
  3. 將一個本地文件添加到cordova,名爲video.html,它將URL作爲參數並將該網址的video標記呈現爲src。該計劃是將此文件包含爲iframe,但顯然我無法將iframe作爲本地文件。我嘗試了各種可能指向該特定video.html文件的URL(儘管實際上我不確定這是可能的)。我試過的是:cordova.file.applicationDirectory + 'www/video.html'http://localhost/www/video.htmlcdvfile://localhost/www/video.html
  4. 我找了一些可以播放視頻的cordova插件,但是我一直沒有找到適用於iOS的插件。大多數插件似乎都針對Android。

現在,我有可能以錯誤的方式解決這個問題。正如我所看到的,cordova的「標準用例」是您在本地存儲HTML/JS/CSS文件。像我使用的外部內容可能有點不尋常。我將解釋這個應用程序的要求,這些要求使我可以使用此功能。

  • 該應用程序應該爲多個平臺構建(儘管我們從iOS開始)。因此我們使用PhoneGap。
  • 它應該可以在線和離線訪問,儘管所有內容都來自服務器(本地不生產內容)。這就是我們下載內容並在本地保存的原因。
  • 它也應該自動更新其本身的任何部分,而不需要從App Store進行更新。這就是我們使用外部頁面的原因 - 因爲它有一個cache.manifest,它允許我們控制Web應用程序代碼的更新,同時允許它在本地緩存。這可能是最重要的考慮因素,因爲如果我們想在Cordova中本地保留一些文件,我們將不得不在JavaScript內重新實現此緩存功能(儘可能使用盡可能薄的層)。

在任何情況下,我最關心的是如何得到這些視頻的工作。我願意嘗試最黑暗的解決方法!如果目前的開發決策確實無法實現,那麼也許你可以給我一些提示,告訴我應該如何構建應用程序以使其運行並且仍能滿足我的要求。

非常感謝!

+0

我推薦使用遠程調試器並查看網絡中發生了什麼。也許mime文件類型不正確。 – 2015-04-14 14:31:05

+0

你是否在任何地方使用'.toURL()'?如果是這樣,請嘗試用'.toNativeURL()替換' – FlyingLemon 2015-04-16 13:29:13

+0

我已經嘗試了這些建議,我的發現是: @SergeySnegirev我調試了傳入的文件。 MIME類型沒問題。文件已成功下載到設備。但是,我無法調試通過'file://'或'cdvfile://'協議創建的請求,因爲它們實際上並不通過網絡。 (),'.toNativeURL()'和'.toInternalURL()'。前兩個給我一個'file://'URL,而最後給我一個'cdvfile://'URL。 'cdvfile://'網址適用於圖片,但不適用於視頻。 – Grampa 2015-04-17 08:42:47

回答

3

我有大約一年前,一個類似的項目。但我不記得遇到這個問題,因爲我們捆綁了我們的html/js/css資源與應用程序。

問題是,您正試圖從http:///協議提供的html文件中加載file:///協議url,這不是本地UIWebView所適用的。

您可以通過使用如視頻自定義URL方案繞過這個://,但你需要寫一個攔截這個請求,管道實際的視頻回網址加載系統一些本地代碼。

最終結果是:

The end result

這裏是我是如何做到的使用科爾多瓦4.3.0 &一點的ObjectiveC的

  1. 創建一個新的目標C類名爲VideoURLProtocol延伸NSURLProtocol :

VideoURLProtocol.h:

#import <Foundation/Foundation.h> 

@interface VideoURLProtocol : NSURLProtocol <NSURLConnectionDelegate> 

@property (strong, nonatomic) NSURLConnection *connection; 

@end 

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 
  • 以下行添加到AppDelegate.m

    的didFinishLaunchingWithOptions方法
    . 
    . 
    // These lines should already be there 
    self.window.rootViewController = self.viewController; 
    [self.window makeKeyAndVisible]; 
    
    // This line 
    [NSURLProtocol registerClass:[VideoURLProtocol class]]; 
    . 
    .  
    
  • 而這裏的使用這種新的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); 
    
  • 一些附加分值得一提的是:在我的javascript代碼

    通知我下載的文件「/庫/緩存」,而不是「/ Documents」目錄(默認位置),這是因爲將「/ Documents」目錄備份到iCloud & Apple拒絕嘗試備份超過〜100 MB的應用程序。這是我的應用程序被拒絕後發現的難題。 你可以看到你的應用程序所採取的空間:設置>的iCloud>存儲>管理存儲> {{您的iPhone名稱}}>顯示所有應用

    可以自動播放由以下行添加到您的config.xml視頻

    ​​

    你也可以通過添加下面一行到你的config.xml除此之外,你還需要WebKit的playsinline =「true」屬性添加到您的視頻播放視頻內嵌:

    <preference name="AllowInlineMediaPlayback" value="true" /> 
    
    <video controls="controls" autoplay="true" webkit-playsinline="true" preload="auto"> 
    </video> 
    

    這是Ra的一個非常有趣的教程y非常詳細地解釋NSURLProtocol:http://www.raywenderlich.com/59982/nsurlprotocol-tutorial

    +0

    這原來是工作解決方案!完全按照這些說明並將從'toURL()'獲得的'file:///'URL重寫爲'video://'鏈接很好地解決了這個問題。對於任何試圖在自己的項目中使用此解決方案的人,請特別注意搜索和替換:帶有3個斜線的'file:///'被替換爲帶有2個斜槓的'video://'。 – Grampa 2015-04-21 13:40:33

    +0

    在嘗試了這個解決方案之後的一段時間,我想指出一個問題(不是用海報的解釋,而是用iOS本身)。如果您使用上述方法插入標記爲「

    0

    根據我的經驗,使用file://協議在iOS上有問題,因爲協議從設備文件系統的根目錄開始。

    我不相信任何跨來源問題正在這裏面臨着因爲科爾多瓦沒有實現跨域請求,而是將所有請求從原點來它們請求。 See this answer

    我的理論解決方案是使用相對 URL,而不是嘗試使用任何協議。但是,實現這一點的方式可能取決於文件何時成功下載。

    <video width="auto" height="100%" controls="controls" autoplay="true"> 
        <source src="/localhost/www/video.mp4" type="video/mp4" /> 
    </video> 
    

    哪裏cdvfile://localhost/www/是你的target參數設置,當你叫fileTransfer.download()referenced here的路徑。

    要麼創建視頻元素或者設置視頻SRC在JavaScript一旦successCallback已解僱這可能是必要的。再次,您可以將src設置爲相對URL。

    請注意影片將不會在移動

    From the Safari Developer Library

    在Safari自動播放iOS上(對於所有設備,包括iPad的),用戶可以是蜂窩網絡上進行充電每個數據單元,預加載和自動播放都被禁用。

    +0

    我剛試過這種方法,但不幸的是它不起作用。我已經用'cdvfile:// localhost/...',把它們變成'/ localhost/...'以及'file:/// var/...'到'/ var/...'。公平,最後一個是有點延伸,但我絕望在這裏:)將URL注入源並不是一個大問題,因爲我的視頻是由Javascript添加。 – Grampa 2015-04-21 10:05:03

    相關問題