Guest posts about Cordova CLI

I’ve recently had the good fortune to write a couple of guest posts at some blogs to promote my book about the Cordova CLI.

First, I wrote a post on the CloudFour blog: “PhoneGap makes mobile development more accessible”.

But PhoneGap, a four year old project, now lets developers leverage standard web technologies such as CSS, HTML and JavaScript to build mobile applications. Designers who know CSS and HTML can create fantastic mobile friendly user interfaces (leveraging frameworks like Topcoat and Junior) and developers can focus on functionality and performance.

CloudFour is a consultancy based in Portland OR that my company has worked with in the past. They focus on the mobile web, and are very sharp.

Second, I wrote a post about hooks on Devgirl’s weblog: “Three hooks your Cordova/PhoneGap project needs”.

These hooks automate three common scenarios that will take place in almost any Cordova application–adding plugins to an app, switching between deployment environments, and adding custom icons and splash screens.

Write a hook anytime you have a build process that is tedious, repetitive, or required to build your app. Look carefully at any documented manual build processes. If you need to perform steps to build your app (copying icon files to various directories under platforms, for example), see if you can automate them in a hook script to make your build process quicker, easier, and more repeatable.

Devgirl, aka Holly Schinsky, is a developer evangelist for Adobe who has written about a wide variety of topics, including push notifications and Flex.

PhoneGap Usage Survey Results

A few weeks ago, I asked the PhoneGap google group members to fill out a simple usage survey. I was interested in versions of Cordova/PhoneGap used, as well as what device platforms were targeted. I had 30 responses over just under two weeks. Note that this survey closed on the 29th, before Cordova 3.1 was released.

Here are the results. (Some questions allowed multiple answers, so the number of responses may exceed 30.)

“What version of Cordova/PhoneGap do you mainly use?” A solid majority was on a modern version, either 2.9 or 3.0.
Which version of cordova do you use?

“What device platforms do you target?” The vast majority of respondents target iOS and, to a slightly lesser extent, Android. There are a smattering of other platforms being targetted.

“What versions do you have in production?” Every version of the 2.x line was represented. I think this shows that upgrading PhoneGap/Cordova projects used to be a pain (and, once an app is finished, there often times is no need to revisit).
Which versions do you have in production?

“Do you use Cordova or PhoneGap?” This is interesting to me because I think there is a lot of confusion around the difference. Most people were pretty clear.

The results of this survey was interesting to me and I hope to you as well.

How to collect usage statistics in your phonegap/cordova application

My company recently wrote a couple of mobile applications. Since one is for consumer use (search for ’8z neighborhood’ in the App Store/Google Play if you live in Colorado or the Bay area and want to check it out), I wanted to know what type of users were downloading and installing it, what was being used, and other general usage statistics.

I asked a mobile app vendor we’ve worked with what they used for usage stats, and they said Flurry. I also looked at Google Analytics, Mobile–this is a nice q&a explaining the major players in the mobile analytics market. We didn’t want anything complicated, just basic stats with the possibility of collecting further information in the future, so I went with the vendor recommendation. Flurry also works with the two platforms we were targeting: IOS and Android, as well as many others.

Flurry is zero cost, but nothing’s free–they want your data and you grant them a “right, for any purpose, to collect, retain, use, and publish in an aggregate manner” all data collected from your application. I’ve seen similar TOS from most of the free analytics vendors, so this was no surprise.

To use Flurry with cordova/phonegap, and with plugman, I was ready to plugmanify an existing Flurry phonegap plugin. Luckily, someone else had already done it. All I had to do was update the plugin to work with Cordova 2.9, and to use the latest IOS7 compatible Flurry library.

After you install the plugin (I recommend doing so in an after_platform_add hook script), you simply add this to your code after the deviceready event fires: window.plugins.flurry.startSession(sessionkey). I inject the session key using a hook script, because I wanted a different key for stage and production builds, and also for each device platform (Flurry requires the latter). Because hooks only get the root directory as context (although this is supposed to change) I had to put some logic in the javascript to call startSession with the appropriate key:

 App.config.flurryid = "";
    if (window.device && window.device.platform) {
        if (window.device.platform == "Android") {
            App.config.flurryid = /*REP*/ 'notreallyanandroidflurryid' /*REP*/ ;
        if (window.device.platform == "iOS") {
            App.config.flurryid = /*REP*/ 'notreallyaniosflurryidxxx' /*REP*/ ;

Although I have not used any of the more specific event tracking, the basic statistics are a great start (including new users, retained users, device versions, etc).

Don’t fly blind when you release your phonegap/cordova mobile app–use Flurry or something simliar.

Releasing with Cordova CLI

When you are done developing your mobile application, you will want to release the binary, and have it distributed by whatever means is typical for that platform (typically some kind of app store).

How does Cordova CLI help with this? It doesn’t.

Typically, the best way to release a cordova/phonegap application for a given platform is to find out how to do a release for that platform from the platform’s documentation, and follow that. For instance, for android, you can run ant release and sign an apk with custom keys–all of that process is independent of Cordova CLI.

It’s worth reiterating that cordova CLI is a toolset to help with development of applications–deployment is still platform specific.

Next up, a conclusion.

Subscribe to my infrequent Cordova newsletter

How to ‘plugman’ify an existing plugin

In a previous post, I talked about adding a new plugin that you wrote to your Cordova CLI project. However, there are a ton of existing plugins out there, and many of them haven’t yet migrated over to the new plugman architecture. What should you do when there is a plugin that solves your problem, but is not installable via plugman?

Your options include:

  • install the plugin the old fashioned way, by downloading and copying its files into your project directory. This is a a bad idea because if there are future bug fixes or feature improvements to the plugin, you’ll have to manually pull them in.
  • forego the plugin. But you are looking at it specifically to save you time or allow you to implement a feature that would otherwise be too hard or time consuming–so you can’t exactly ignore it.
  • search for another plugin that does the same thing–great, if you can find it.
  • make the plugin plugman compatible–this is the best option.

The first step to making a plugin plugman compatible is to file a bug/issue with the project. Perhaps they are already planning to do this work, and a request from you will get it moved up the queue. If so, fantastic–see when they think it will be done. If not, at least you’ve let them (and others who look at the issues list) know that this is something they should do.

If it won’t be done in your timeframe (or at all), you can do it yourself. The main tassks are writing a plugin.xml file, and possibly modifying some javascript files. Start with the plugin.xml spec.

Before you plunge in, though, think about the licensing surrounding the plugin, as, unless you are replacing everything or the license is extremely permissive, your contributions will need to be under the same or a compatible license as the original code, especially if you want to contribute the changes back.

You want to make sure you use version control. If you are modifying a plugin on github, it is as simple as forking that project. You may be able to take the plugin code and import it into your version control system.

Write the plugin.xml file, and make sure to check it into the version control system. Writing a plugin.xml file is straightforward; however, there are two ways to handle javascript–you can treat it as an asset, where plugman dumbly copies it to the www directory wherever you tell it to, or you can treat it as a js-module. Plugman does some extra work for js-module javascript, including injecting it into the index.html and adding the created javascript object to the window object. Using js-module is the preferred method, but you may have to edit the javascript files and remove any cordova.define syntax. Also, if you need to move plugin files around, or rename them to help code maintainability, do so.

Test and install it just as you would any other plugman managed plugin (cordova plugins add http://...).

Once you’ve done this and it works, consider pointing to your plugin.xml in your open bug. Some authors may be receptive to code contributions or pull requests.

In the next post, I’ll discuss how Cordova CLI helps you release your application.

Subscribe to my infrequent Cordova newsletter

How to set up a new plugin for use with Cordova CLI

The first step whenever you feel you need access to native functionality for a phonegap/cordova application is to search for a pre written plugin. Unfortunately, at this time there is no central repository. There is phonegap plugins github repo, but I always find myself reverting to searching with google–there are lots of plugins that are described on blogs (web intent, application preferences) that are not present in the phonegap plugins github repository.

However, if you can’t find a plugin that does something you want, you will have to write your own. First, get the plugin working using an IDE or placing the code directly under the platforms directory in a new project (so that you can minimize external complexities). Get the plugin running in your phone and/or emulator. There are plenty of tutorials on writing a cordova plugin, not least of which is the one in the phonegap docs.

After it is running, you want to convert it to a plugman compatible plugin. Plugman is a tool for managing cordova plugins (and, incidentally, is planning to support a directory of plugins). You configure how plugins are installed by writing a plugin.xml file; here’s the plugin.xml spec. This document well worth reading a couple of times closely, as it specifies what you can ask plugman to do when installing a plugin.

Create a new project in your version control system and copy in the plugin files previously tested, as well as the plugin.xml. Make sure they are all committed.

Then you go to your project and run cordova plugins add From the plugman documentation, it looks like you can install a plugin from a local path, rather than a URL, but I have not done so.

Note that when you check out the source tree on a different machine, you will want to run cordova plugins add again. Putting a list of these in an after_platform_add hook script will ensure that this happens automatically.

The next post will discuss how to take an existing plugin and have it work with Cordova CLI.

Subscribe to my infrequent Cordova newsletter

Platform specific configuration files with Cordova CLI

I previously posted about using the merges directory to handle situations where your css or javascript differed between platforms.

However, there are cases where platform specific Cordova configuration differs from that created by cordova platforms add [platform]. In this case, if you want to version control the configuration changes (and you should) you need to write a hook to copy over the configuration file from a well known location. I create a top level directory called config and underneath that have platform specific directories.

However, there are two types of platform specific configuration to consider. The first type aren’t modified by any other processes–application icons and splash screen images are examples of this. In this case, your hook script can live in .cordova/hooks/after_prepare and be run every time. Therefore, if you switch out a splash screen with a new image, it will show up the very next time you run cordova build.

The second type of platform specific configuration file is one that is modified by other processes; for example, plugins often modify AndroidManifest.xml. In this case, if you were to put the copying script into after_prepare, your plugin changes would be removed unless you reinstalled your plugins every time. The better part of the build lifecycle in which to execute your copy script is after_platform_add. This means, however, that when you need to change such files, you’ll need to remove and re add the platform (or merge your changes manually).

In the next post, I will discuss adding plugins using Cordova CLI.

Subscribe to my infrequent Cordova newsletter

Platform Specific CSS/Javascript with Cordova CLI

Cordova CLI has a really good setup for merging in content that is platform specific under the www directory.

Basically, under the merges directory, you can place platform specific directories; mimic the names under platforms. Under that you can create directories named the same as directories under wwwcssor js, for example, and the files under those directories will be copied to the platforms build directories by the cordova prepare command.

The merges directory is useful, but limited.

When we had a Cordova app mocked up by a great phonegap consultancy, the end deliverable included large chunks of common css, but some platform specific CSS. Cordova CLI has no issue with this. Another use case would be presenting a common interface for plugins for different platforms that have slightly different APIs–you can write platform specific adapter objects, and place the platform specific javascript into merges. Here’s an article about another purpose for merges.

merges are limited, because only directories under www is merged. If there is anything else you want to modify that is outside of that directory (like, say, AndroidManifest.xml), well, you are out of luck.

Luckily, hooks come to the rescue again. In the next post, I will discuss how to update platform specific files using Cordova CLI.

Subscribe to my infrequent Cordova newsletter

Setting up CORS

So, this is not Cordova CLI specific, but being able to develop as much as possible in your web browser (with the quick feedback) is one of the benefits of Cordova, so I’ll cover it briefly.

If your data sources and your application are served from the same server (or proxied so that they look like they are) then you are good to go–no violation of the Same Origin Policy occurs.

If they are on different servers, then your browser is going to restrict access. However, if you aren’t sending any special headers and are only interested in reading data from your remote data source, or POSTing using limited mime types, you can get away with setting the Access-Control-Allow-Origin header to * on your data sever, and everything should work OK.

If you are using PUT, or sending special headers, or doing anything outside the box, you will want to preflight your requests with an OPTIONS header, as outlined here.

Basically, when a request comes in, you have to send back these headers:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 1728000

For development, the * for Access-Control-Allow-Origin is again fine. Note that if you specify a host and the server caches the response (if it is a proxying cache, for example) and you lock down Access-Control-Allow-Origin and more than one host tries to access this server, it will cause issues. Like, “the second request will fail” issues. This is not really a concern for development servers.

In addition, make sure that OPTIONS request can get through (another SO question I asked).

Note that this is only for development in the web browser (including ripple). Once you move to emulators and phones, you will be concerned about Cordova whitelists and not CORS.

In my next post, I will cover the merges directory.

Subscribe to my infrequent Cordova newsletter

Configuration management using Cordova CLI

Managing different builds of your Cordova application is relatively easy using hooks.

I actually have a number of deployment environments, all built from my local source tree.

  • web development, which lets me crank out the non cordova specific look and feel
  • test, which runs qunit/sinon unit tests
  • ripple development, which lets me run in the browser, but still test cordova specific events (online/offline, for example)
  • staging, which is used to build a phone distributable binary, but runs against our QA servers
  • production, the same as stage, but against our production servers

The first two don’t require a cordova prepare but the last three do. The first three let you make changes in files and reload your web browser, where the last two require a phone or emulator to run.

For a while I was switching between these manually, but eventually it became a pain, so I automated it. The automation is driven off an environment variable, which is accessed by a after_prepare hook: TARGET=stage cordova build android sets target to stage, and process.env.TARGET is the nodejs code in the hook script that can access that environment variable.

There is a config directory in the top level of the project and in there is a project.json file that contains project specific configuration for each target environment, like the server hostname.

One wrinkle that took me some time to figure out was how to have code that was in the www directory ‘just work’ out of the version control system, so I could do quick web development. In the end, I have code like this in my javascript files

App.config = {};
App.config.datahostname = /*REP*/''/*REP*/;

and then this regular expression to replace it with the value from the configuration file when file is being prepared:

function replace_string_in_file(filename,to_replace,replace_with) {
  var data = fs.readFileSync(filename, 'utf8');
  var result = data.replace(new RegExp(to_replace,"g"), replace_with);
  fs.writeFileSync(filename, result, 'utf8');

// iterate over files to be updated with config info

Note that I don’t read/write files async–this happens rarely enough that the performance increase isn’t worth some of the weirdness you will see if more than one hook acts on your file, or if you edit the file right after running the hook.

Since /*REP*/stuff/*REP*/ isn’t likely to match anything inadvertently, you could probably parse all your files, but my configuration is limited to 3-4 files, so it is easier just to name them explicitly.

Note that if during development, your javascript needs to access data served by a different web server (an API somewhere, for example), you’ll need to set up CORS correctly. We’ll set that up in the next blog post.

Subscribe to my infrequent Cordova newsletter

© Moore Consulting, 2003-2014 +