Steve Davis
Cordova Development (don’t forget your cordova.js script tag!)
Someone working at a desk writing code.

Recently we have begun to create a few projects using Apache Cordova. It is a great system that has come a long way from the last time I looked into using it (when it was still "PhoneGap"). It allows you to create a cross-platform mobile app using HTML/CSS/JS, which is great for us as we have plenty of experience using web technologies. There are some limitations as to what native APIs are supported but overall there is a ton that you can do! In addition it creates a great dev environment for us, as we don't have an abundance of Apple development workstations, but using Cordova you can do a large bulk of your testing with just a web browser (and further testing on the Android emulator available on most hardware). Most everything related to packaging is completely automated, and a single config file controls preferences in a cross-platform manner. In short -- I was very impressed. With Cordova you can create a "Hello World" app for multiple platforms, in seconds (literally).

So have I convinced you Cordova is amazing yet?

An Easy Mistake

Now let me share one pitfall that took a chunk of my time today. (Not that this can be blamed on Cordova in any way, but it was easy for me to miss and took me surprisingly long to correct).

In order for Cordova to introduce all of the awesome native support it (and its plugins) provide, you need to include a reference to cordova.js, a Javascript file that gets packaged with your app during the build phase. The thing is, that file isn't in your source tree. In fact, when you look at your console log, if debugging in a web browser, you will notice an error attempting to fetch that file.

Today, I was working on the last few polishing steps for a simple Codon Chart app that we have been creating, and so far most of our developer's debugging has been done with a web browser. The app is so simple, it doesn't need any of the native Cordova awesomeness. But when I ran it on an iOS device, I realized we have a problem with the transparent status bar overlapping our app. No big deal, they have an awesome statusbar plugin for that. In order to get the look I wanted in our final app, I also had to make use of the device plugin to add some CSS classes to our top menu bar element:

  // Statusbar overlay handling
  if (window.device.platform == "iOS" && window.device.version >= 7)
  {
    $("body").addClass("pushStatusBar");
    $("#codon").addClass("pushStatusBar");
  }

Now where to place that snippet? To be accurate, as this will never be needed in a web browser environment (and hey, with this Cordova setup we have the option of releasing this as a Web App too!), I decided to place this inside of a callback for the ondeviceready event (a Cordova event). Now there are many other ways I could have handled this (simply checking for the presence of window.device for example) but the point is, this is the way I decided to do it. ...And for the next few hours I regretted it.

The code wouldn't work. Why? It is dirt simple and obvious. Was it a JS error I can't see? Issue with the Cordova device plugin? I wasn't sure.

Debugging

I am new to Cordova so even things like seeing the console.log() messages required me to do a little digging. Alternatively, I decided to quickly add a simple alert() to my ondeviceready handler. Then, I launched the modified code on my iPad:

  $ cordova run

(Pretty simply eh?)

No alert... Umm, what is going on?

The Cause

More code review, everything looks right. A few more alerts() later and I realized... the ondeviceready event is simply never happening. For some reason, that finally sparked a thought in my mind: Where did my link to the cordova.js file go??.

After a review of our git history, I realize... the initial commit was missing that <script> tag.

ARGGGG!!!

Fool me once...

So, there you have it. A simple problem (most likely obvious to any heavy Cordova user), that caused much unnecessary headache, mainly because it was a silent failure at all stages of the game.

No longer! I know it might not be useful or necessary for a more seasoned Cordova developer, but until I can call myself that, I simply wrote a basic NodeJS script that will be included in ALL of our projects until we don't need it anymore. Feel free to copy, use, modify as you wish! Send any comments to me. Cheers!

hooks/before_build/010_check_cordovalib.js
#!/usr/bin/env node

// This hook ensures no one has accidentally deleted the "cordova" script tag

var fs = require('fs');
var path = require('path');
var sys = require('sys')

var rootdir = process.argv[2];


var config = fs.readFileSync(path.join(rootdir, 'config.xml'));
var content = "";
if (matches = /]*src=['"]cordova.js['"].*\/script>/.exec(content))
  {
    sys.puts('  Looks like you are including the cordova libs:');
    sys.puts('    ' + matches2[0]);
    sys.puts('');
  }
  else
  {
    sys.puts('  Cannot find the Cordova lib script tag :(');
    sys.puts('  (If you verify it is included, check my RegExp, it might need to be adjusted)');
    sys.puts('');
    process.exit(1);
  }
}

Also available as a Gist.

Follow us on LinkedIn for all of our news!