We have a fairly complex JS webapp that loads different resources (HTML templates, extra JS/CSS files, JSON data, images, videos, sounds) in different ways (string, arrayBuffer, base64, binary) online in the browser (just reading no writing). Now we'd like to make changes to it to have everything work offline (resources included) on different platforms as a Cordova mobile app.
Problem #1 - loading files from the local filesystem
It turns XHR requests for local file:// resources work everywhere but with Chrome which is a show stopper now since Android is internally transitioning towards Chrome.
Ok, there were still 2 other options left:
- fake-load everything within JSONP with script tags, HTML with iframes, etc. - which is not a really nice option because it requires changes to the resources themselves + its kind of hacky and it costs us a lot of functionality (string load only for JS/HTML, arrayBuffer, binary, etc.)
- use the File API
Plain vanilla File API unfortunately always requires user interaction (like a click on an input box) to get a file reference plus IE10 is a no-no. Okay, so the only option there is to use the customized File API plugin for PhoneGap - which brings us the next problem.
Problem #2 - (cross-platform?) file paths in PhoneGap
I like PhoneGap CLI - you enter a few commands in the terminal and it manages files and builds for different platforms for you. Or does it?
As far as I can tell according to PhoneGap you're supposed to put everything in the WWW folder - however (once you build the app), the crazy thing is - there is no easy way to read those files (via File API plugin) from where PhoneGap puts them.
You'd think that fileSystem.root
(LocalFileSystem) is pointing to that folder, but at least on iOS the WWW folder is inside your app but the fileSystem.root
reference is pointing to an external Documents folder (still have to test this on Android but I'm guessing its again something different there).
After a bit of tinkering I figured out how to get to the WWW folder but its unflexible, hacky and feels like it shouldn't work (iOS only at the moment):
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getDirectory("../HelloWorld.app/www", {create: true}, function(entry) {
entry.getFile("test.json", {create: false}, function(fileEntry) {
fileEntry.file(function(file){
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log(evt.target.result);
};
reader.readAsText(file);
}, fail);
}, fail);
});
}, fail);
This cannot be the best way to do this. If nothing else, the JS code now needs to now the name of the app to be able to access the WWW folder (BTW is there a system shortcut for this or a system variable that would make accessing the app's folder generic?).
But this would again be something different on other platforms anyway.
I could theoretically "download" the images from the internal WWW folder to the external Documents folder but:
- download a 50mb app and then internally copy 40mb of its resources to another folder just so that it can be accessed properly doesn't seem that proper to me
- is Documents the proper root folder (on iOS) at all?
Problem #3 - best way to organize local resources in PhoneGap?
So why is /Documents the filesystem root in PhoneGap at all? According to Apple's File System Programming Guide Documents folder might even not be a best fit for something like this. It seems that Documents should be used for user-generated content only and app's data files/resources should in fact go into '/Library' folder. This is amongst other things important since some apps seem to get rejected by Apple for doing this wrong + this also of course influences iTunes/cloud backups.
So now that we've established all of that:
- how do you structure local files/resources properly in PhoneGap?
- where/how do I put our resources (JS, JSON, HTML, CSS, media, etc.) so that they could be copied/installed to a proper folder for every platform (like /Library or ok even /Documents on iOS - but not remain app internal). And of course also for other platforms.
- how to access all of it properly and cross-platform?
- (side question) is cordova.js really needed? we've worked really hard to exclude external libraries and vanilla optimize performance so I'm not too crazy about including another one to again take over events and different things. I realize that there might be some internal hooks used here - but maybe we could just include ourselves what we need?
This turned out to be way more complex than I though it would be.
And as much as I tried not to and I appreciate the effort lots of people have put into PhoneGap - my mind kept drawing parallels between all this illogical cross-platform behavior and browser wars a decade ago. In my mind, other than displaying browser apps full screen cross-platform - the most important feature of PhoneGap should be an easy way to access local files and resources.
Any tidbits of knowledge and feedback is as always greatly appreciated!