PSA: Hard Won Tips For Cordova/Phonegap

The last couple of months I’ve been diving deep into a project built with Cordova/Phonegap and React.js. Of those two I think React has been the bigger revelation to me, but today’s topic is a couple of tips for Cordova that were hard won.

Causes of ‘deviceready has not fired after 5 seconds’ message

In the console you may see the message deviceready has not fired after 5 seconds along with one or more other messages about channels not firing. This is a particularly difficult error to troubleshoot because there are several possible causes. Basically anytime Cordova fails to start properly this error will display after a 5 second timeout.

The problem is often related to a plugin, because plugins are loaded before the deviceready event is announced. So the first thing to do is to identify the plugin that is causing the problem. Three methods;

  • look at the other messages that are logged, they may identify which plugin didn’t load.
  • remove plugins one by one until deviceready event does fire.
  • create a new empty Cordova project and add plugins into it one at a time until it fails.

If you are able to identify a plugin that is at fault then look to see if there are any updates that may fix the problem. If not you can file an issue against the plugin or contact the maintainers for support. If nothing else you’ll have narrowed your search terms to look for a solution.

However, if it is one of the plugins that is failing, it might not necessarily be an error with that plugin. So try removing your application javascript and only including the cordova.js script to confirm that the plugin fails in an empty app.

In my case a boilerplate project I was using was overriding the global object window.prompt. This is a problem because Cordova actually uses window.prompt as a backup method for bridging between javascript and native API.

So why would window.prompt be overridden if it’s so necessary? I’m guessing because until recently Cordova didn’t have the Browser platform. Instead you could use phonegap serve or cordova serve to run a webserver that serves /www/assets. But this will cause a prompt to appear in the browser, several thousand of them in fact.

Which leads me to my next bit of knowledge…

Serve Platform Browser Instead of Serving www/assets

Cordova recently introduced a Browser platform which is meant to support development by allowing the app to be run in a web browser on the developers desktop workstation (instead of a WebView on the device). Core plugins are being updated to support this platform and third party plugins are being encouraged to do the same.

Now, I’ve not figured out all the differences between phonegap serve and cordova serve, but I think phonegap serve is meant to serve pages to the Phonegap Developer App that is installed on a device. So it serves the Android platform when the app is installed on an Android device. This is pretty nifty, but I’m more comfortable in a web browser for some development modes. It doesn’t appear to offer any way to serve the Browser platform to a web browser.

However, cordova serve does serve the Browser platform. Run cordova serve then browse to http://127.0.0.1:8000/browser/www/. Replace the port with the port indicated by cordova.

If your plugins support the Browser platform then your app should play nice with a web browser. If not, well then you’ll probably have to add some conditional code into your app for alternate behavior in the browser where the plugin isn’t available.

Written on February 11, 2015