Saturday, January 12, 2013

Cordova File API , when getDirectory() and DirectoryReader do NOTHING!


Naturally, within a day of my first successes with PhoneGap Build, I am trying some decidedly non-trivial stuff already. I want map tiles off the Internet via HTTP, but I want them cached so the tiles will still transparently be available when I lose connectivity. My plan, is to use Cordova's File storage API.

I almost immediately hit upon an issue:

The getDirectory() method does NOTHING. Neither the success nor failure callback happen. No exception is raised. This happens in the app as it loads, and also in the weinre Console. It doesn't crash the browser, hang the iPad, create a directory, ... Nothing.

Figuring this out wasted 2 hours of my time, and in retrospect the cause seems almost trivial, almost expected, although short of obvious:

File API's getDirectory() method, cannot recursively create directories, creating required parent directories. It returns instantly, but silently fails, without a callback nor an exception.

// the set of callbacks for the two phases: requesting a handle to the filesystem,
// and requesting access to (or creation of) the specified target directory
var getFSsuccess = function(fs) {
    console.debug('Got fshandle');
    FS = fs;
    FS.root.getDirectory(tiledir, {create:true,exclusive:false}, getDIRsuccess, getDIRfail);
};
var getFSfail = function () {
    throw new Error('Could not open filesystem');
};
var getDIRsuccess = function (dir) {
    console.debug('Got dirhandle');
    cachedir = dir;
    fileurl  = fs.root.fullPath + '/' + tiledir;
};
var getDIRfail = function () {
    throw new Error('Could not open directory ' + layerinstance.options.tiledir);
};


// WORKS
// getFSsuccess will be called,
// will call FS.root.getDirectory with tiles-greeninfo.terrain
// and create the subfolder as expected
var FS, cachedir, fileurl;
var tiledir = "tiles-greeninfo.terrain";
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getFSsuccess, getFSfail);

// FAILS
// This will not create tiles/ and then tiles/greeninfo.terrain
// as it's a subfolder and getDirectory doesn't do parent creation
// The catch is that it's SILENT failure:
// the getDIRfail callback will never happen, and no exception will be raised
var FS, cachedir, fileurl;
var tiledir = "tiles/greeninfo.terrain";


If you see this blog posting in Google, and it saves you some time, let me know. I'll be glad to know that someone benefited from my wasted evening. :)

Monday, January 7, 2013

MobileMapStarter


A trivial mobile mapping app, tying together the best of Leaflet, jQuery Mobile, and Phonegap/Cordova. This will form the framework for our future generations of mobile apps at GreenInfo Network.

https://github.com/gregallensworth/MobileMapStarter

For the narrative, I'll simply quote from the README file:

A starting framework for mobile maps using Cordova/Phonegap. A minimal but functional, standalone mobile app from which to build your own creations.
This app is designed for Phonegap/Cordova, therefore it is HTML, JavaScript, and CSS.
Components of this app:
  • HTML/CSS/JS layout -- The app is ready to compile and run via Phonegap.
  • config.xml -- The app is ready to upload to Phonegap Build. The included config.xml specifies permissions, icons and splash screens, and more in an easy-to-edit template.
  • jQuery Mobile -- A mobile-style user interface theme. Includes jQuery which makes JavaScript useful.
  • Leaflet -- Quick, pretty, easy tiled maps.
  • imgcache.js -- Cache Leaflet tiles to device storage, for offline use.
     

Friday, January 4, 2013

PhoneGap Build: The Better Way


So, it's been nearly 2 months since I posted how to get set up with XCode and with Eclipse, to do Phonegap development. I've been busy since then, only about to put 10 or so hours into it. But it has not gone well.

Phonegap's .\create.bat script is messing up. It started giving cryptic "file not found" errors as it created the project. It created projects with errors, so I couldn't even run the demo app out of the box. The errors indicated something about the Android manifest, but I could never figure out what. On my HTC Incredible, I could never get a single page with a single DIV to display edge-to-edge: it would introduce some padding or margin that I didn't ask for. For my LG Spectrum, the driver packages from Google weren't applicable and the ones provided by LG still don't allow USB debugging from ADB.

XCode was a lot nicer, for a while. But on the third day, it began not updating my code changes. The new app has a black bar on top, three pages to pick through, and a Leaflet map... On the Android anyway -- on the iPad it's still Hello World on a white background, even after several reboots.

In short, it's exciting but it's difficult, and despite earlier successes, at present both of my development computers seem unable to in fact build a project.


Introduce: Phonegap Build


Adobe offers a service called Phonegap Build. It sounds great in theory: upload a ZIP file of your HTML/JS/CSS files, enter project name etc. into some control panels, and they'll compile it for you, providing you with a set of APKs and IPAs, and even packages for Blackberry and Windows Mobile and other obsolete-but-not-extinct platforms.

It sounds good in theory. But the reality... is that it works as advertised, and has additional features that are even cooler still!

So, a walkthrough:

- Sign up for an account. Their free account allows you 1 app, and for $9.99/month you can host 25 projects. Aside from these counts, you can add any number of projects from Github for free. We ourselves don't tend to host publicly-downloadable source code on Github, but if you do this is quite a deal.
- If you're developing for iOS, go to your account panel and upload your Apple Developer Key. That's a bit of a process, but is worth it.
- Upload your ZIP file of HTML/CSS/JS. A control panel allows fine-tuning such as your app's name, an icon PNG, etc.
- A bunch of little spinners start compiling your program for all these platforms. A minute later, you have 7 download links and a QR code.
- Hold up your phone and scan the QR code, download the APK or IPA, and enjoy your app.

On my HTC Incredible, the resulting packages from Phonegap Build, even work on my HTC Incredible, perfect edge-to-edge layouts. That right there exceeds my best efforts of 10 hours.




Debugging Console


So, it actually compiles and downloads, that's a huge bonus over the problems that Eclipse has been giving me. But there's more!

Upload you app with Debug mode enabled. Fire it up on your phone, then click the Debug button on the website (Chrome and Safari only). Your app was transparently rewritten so as to load its JS/CSS/etc remotely from Phonegap's servers, and the Chrome Developer Tools lookalike you're seeing in the Debug panel is tied into that.

You can now issue JavaScript commands in the Console, and examine and tweak CSS in the Elements panel. You're using your browser debugging tools, on your phone. There's a time delay of 1-2 seconds while your phone picks up the changes, which is tiny compared to repackaging, and on par with hitting Reload developing a desktop browser app. But this new ability, to examine JavaScript objects and tweak the CSS within my phone... invaluable.



The only downside at this time is that the Debug server seems to be down a lot. On December 24 it was down most of the day, after that it's up-but-slow or up-and-great or sometimes Not Responding. Hopefully they can get that solved, because it's becoming an invaluable tool worth paying for.


Conclusion


Well, it's not much of a conclusion, as much as a beginning. After weeks of arguing with Eclipse and XCode, trawling Google and StackOverflow for workarounds, fussing with driver packages, and ultimately producing nothing reliable... Phonegap Build made it possible to catch up in a single day.