Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resource structure in Apache Cordova (PhoneGap) and loading the files from the filesystem

Tags:

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:

  1. 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.)
  2. 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:

  1. 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
  2. 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!

like image 335
Michael Avatar asked Jan 31 '14 12:01

Michael


People also ask

Which event allows us to know when the Cordova application is fully loaded?

The deviceready event fires when Cordova is fully loaded. This event is essential to any application. It signals that Cordova's device APIs have loaded and are ready to access.

What technology does Cordova uses for cross-platform mobile application development?

Cordova is powered by Apache Foundation. It is an open-source mobile development framework. You can use standard web technologies like HTML5, CSS3, and JavaScript to build cross-platform mobile applications like Android, iOS and Blackberry apps.


1 Answers

As far as I can see, there are three ways to put content on the screen when using cordova/phonegap:

  1. Make an ajax call to a template file and then $(div).append
  2. Have it all included in index.html and show/hide
  3. Have the content inline in js files and $(content).appendTo(div)

I've been playing around seeing if any has advantages and here's what I've (in my limited tests) found out:

At first load, templates have the smallest memory footprint, followed by inline js and included in the index.html the highest.

But, after navigating around the app for a while, this changes and they all balance out to roughly the same (between 1.8 and 2.1 MB in my tests).

For speed, index.html is fastest, followed by inline js and templates is slowest. However, the difference is negligible, tens of milliseconds worth.

I honestly don't see any real difference between the methods, except for the fact that templates don't seem to work on Windows Phone (maybe that will change with 10, don't know). I guess it's more of a coding style thing rather than a hard and fast rule. Although input from cordova/phonegap devs would be nice.

like image 84
hdezela Avatar answered Oct 28 '22 11:10

hdezela