Cordova внешнее приложение + локальное видео
у нас есть приложение iOS, построенное с PhoneGap / Cordova 4.3.0. Это приложение напрямую загружает внешний веб-сайт с помощью <content src="http://example.com/foo" />
на . Все функции содержатся на этом веб-сайте, поэтому мы фактически не используем локальные HTML или JS-файлы.
в рамках функциональности приложения, мы должны играть некоторые видео. Поскольку приложение предназначено для работы в автономном режиме, мы хотим кэшировать эти видео локально. Поэтому мы загружаем их на устройство с помощью Плагин FileTransfer, наряду с другими ресурсами, такими как изображения или PDF. После загрузки файлов мы получаем URL-адреса с помощью file://
протокол. У нас также есть возможность использовать cdvfile://
протокол. Когда мы используем cdvfile://
URLs для отображения изображений, изображения отображаются правильно. Однако видео не воспроизводятся вообще.
для воспроизведения видео мы используем стандартные видео Теги HTML5:
<video width="auto" height="100%" controls="controls" autoplay="true">
<source src="..." type="video/mp4" />
</video>
сами видео работают, и они будут правильно воспроизводиться с внешнего источник (например, они будут играть, если мы обращаемся к ним с сервера вместо локальной файловой системы). Я понимаю, что проблема связана с веб-концепциями, такими как политика того же происхождения и ограничение доступа к локальной файловой системе. Однако в то же время я должен задаться вопросом, почему изображения работают нормально при тех же ограничениях.
то, что я пробовал до сих пор:
- используя
file://
иcdvfile://
URLs какsrc
видео. Это не производит никакого визуального эффекта. Экран просто черный. - С помощью
iframe
Сsrc
установите URL видео. При использованииfile://
, экран по-прежнему черный. Однако, при использованииcdvfile://
, появляется интерфейс видеоплеера iOS с кнопкой воспроизведения и полноэкранной кнопкой, но видео не воспроизводится, и нет временной шкалы. - добавление локального файла в cordova под названием
video.html
который принимает URL как параметр и отображаетvideo
тег с этим URL какsrc
. План состоял в том, чтобы включить этот файл в качествеiframe
, но, по-видимому, я не могу сделатьiframe
в локальный файл. Я пробовал различные URL-адреса, которые могут указывать на этот конкретный (хотя, по правде говоря, я не уверен, что это возможно). Среди тех, что я пробовал, были:--19-->,http://localhost/www/video.html
,cdvfile://localhost/www/video.html
. - я искал плагин cordova, который будет воспроизводить видео, но мне не удалось найти его для iOS. Большинство плагинов, похоже, ориентированы на Андроид.
теперь, возможно, я иду по этому неправильному пути. Как я вижу, "стандартный вариант использования" для cordova заключается в том, что вы храните свои файлы HTML/JS/CSS локально. Внешний контент, подобный тому, который я использую, вероятно, немного необычен. Я объясню требования к этому приложению, которые привели меня к использованию этой функции.
- приложение должно быть построено для нескольких платформ (хотя мы начинаем с iOS). Поэтому мы используем PhoneGap.
- он должен быть доступен как онлайн, так и офлайн, хотя весь контент поступает с сервера (контент не создается локально). Вот почему мы загружаем контент и сохраняем его локально.
- он также должен автоматически обновлять любую часть себя на лету, не требуя обновления из App Store. Вот почему мы используем внешнюю страницу-потому что у нее есть
cache.manifest
это позволяет нам контролировать обновления в интернете код приложения, в то же время позволяя кэшировать его локально. Это, вероятно, самое важное, что нужно учитывать, потому что если бы мы хотели сохранить некоторые файлы локально в Cordova, нам пришлось бы повторно реализовать эту функциональность кэша в Javascript (используя как можно более тонкий слой).
в любом случае, моя главная забота-как заставить эти видео работать. Я готов попробовать hackiest обходные пути! Если это действительно невозможно с текущей разработкой решения, тогда, возможно, вы могли бы дать мне несколько советов о том, как я должен структурировать приложение, чтобы заставить его работать и по-прежнему выполнять мои требования.
большое спасибо!
2 ответов
у меня был подобный проект около года назад. Но я не помню, как столкнулся с этой проблемой, потому что мы связывали наши HTML/JS/css активы с приложением.
проблема в том, что вы пытаетесь загрузить файл:/// url протокола из html-файла, обслуживаемого из HTTP://в/ протокол, который не является чем-то, что родной UIWebView удобен.
вы можете обойти это, используя пользовательскую схему URL, такую как video://, но вам нужно написать собственный код который перехватывает эти запросы и передает фактическое видео обратно в систему Загрузки URL.
в итоге:
вот как я это сделал, используя Cordova 4.3.0 & немного ObjectiveC
- создайте новый класс Objective C с именем VideoURLProtocol, который расширяет NSURLProtocol:
VideoURLProtocol.h:
#import <Foundation/Foundation.h>
@interface VideoURLProtocol : NSURLProtocol <NSURLConnectionDelegate>
@property (strong, nonatomic) NSURLConnection *connection;
@end
VideoURLProtocol.м:
#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
-
добавить следующие строка к методу didFinishLaunchingWithOptions AppDelegate.м
. . // These lines should already be there self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; // This line [NSURLProtocol registerClass:[VideoURLProtocol class]]; . .
-
и вот код javascript, который использует эту новую схему URL
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 я загружаю файл в"/Library/Caches "вместо каталога" / Documents "(расположение по умолчанию) это потому, что каталог "/ Documents " получает резервную копию в iCloud & Apple отклоняет приложения, которые пытаются создать резервную копию более ~100 МБ. Это то, что я нашел трудный путь после того, как мое приложение было отклонено. Вы можете ознакомиться с Приложение в: Настройки > iCloud > "Хранилище" > "хранилище" > {{ваше имя iPhone}} " > " показать все приложения
вы можете автоматически воспроизводить видео, добавив следующую строку в свою конфигурацию.в XML
<preference name="MediaPlaybackRequiresUserAction" value="false" />
вы также можете воспроизводить видео inline, добавив следующую строку в свою конфигурацию.XML в дополнение к этому также нужно добавить webkit-playsinline=атрибут"true" для вашего видео:
<preference name="AllowInlineMediaPlayback" value="true" />
<video controls="controls" autoplay="true" webkit-playsinline="true" preload="auto">
</video>
вот действительно интересный учебник Рэя, который объясняет NSURLProtocol в деталях:http://www.raywenderlich.com/59982/nsurlprotocol-tutorial
по моему опыту использования file://
протокол был проблематичным на iOS, потому что протокол начинается в корне файловой системы устройства.
Я не считаю, что здесь возникают какие-либо проблемы с перекрестным происхождением, потому что Cordova не реализует запросы перекрестного происхождения, а скорее рассматривает все запросы как исходящие от источника, к которому они запрашивают. посмотреть этот ответ.
мое теоретическое решение-это использовать относительные 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()
ссылка здесь.
может потребоваться либо создать элемент видео, либо установить видео src в javascript один раз successCallback
был уволен. Опять же, вы бы установили src в качестве родственника URL-АДРЕС.
обратите внимание, что видео не будет автозапуск на мобильном
из библиотеки разработчиков Safari
в Safari на iOS (для всех устройств, включая iPad), где пользователь может находиться в сотовой сети и взимать плату за единицу данных, предварительная загрузка и автозапуск отключены.