PhoneGap CLI (Preview)

Jun 22, 2013

Overview

One of the upcoming features of PhoneGap 3.0 is the command-line interface, which is what has been keeping me busy.

The PhoneGap CLI is open sourced, under active development, and available for you to use today. I would be more than stoked if you gave it a shot, reported an issue, or requested a feature.

A unique feature of the PhoneGap CLI is its ability to compile a project on your local system or PhoneGap Build. Whenever your system is properly configured, it will build the project locally. When something is missing, then it will upload your app to PhoneGap Build. Of course, you can also selectively choose the environment that you want to use.

It's also 100% compatible with Apache Cordova projects and backwards compatible with the cordova-cli.

Install

$ npm install -g phonegap

Usage

Help

$ phonegap
$ phonegap help
$ phonegap --help

Create a project

A quickie:

$ phonegap create path/to/my-app

A custom app name and package ID:

$ phonegap create path/to/my-app --name "My App" --id "ca.michaelbrooks.my-app"

You can always change the application name and ID with www/config.xml.

Build and install the app

$ phonegap run ios

Force a build environment:

$ phonegap local run ios
$ phonegap remote run ios

Acknowledgment

The PhoneGap CLI is an accumulation of effort from the entire Apache Cordova team and many PhoneGap Build team members. However, if you have something to complain about, then I can be your punching bag.

PhoneGap 3.0 Coming Soon

Jun 22, 2013

The cat is out of the bag for our official PhoneGap 3.0 lineup.

Although, that's probably the wrong way to phrase it.

If you've been following Apache Cordova and PhoneGap GitHub, then none of the upcoming features are new to you. If you haven't been following the nitty-gritty details of both projects, then think of the PhoneGap lineup as a summary of the features to come.

Needless to say, we've been hard at a work breaking apart and reassembling the code to make your app development experience better!

QR Code Terminal

Mar 10, 2013

Overview

Have you ever wanted to display a QR code in the terminal using node? Probably not, but if your answer is yes then you'll be happy to know about qrcode-terminal!

qrcode-terminal is a tiny npm module that allows you to encode text as a QR code and render it to a UNIX-compatible terminal.

Usage

It looks something like this:

Basic Example

And has a very simple JavaScript interface:

// render QR code to the console
qrcode.generate('http://michaelbrooks.ca');

// return QR code as a string
qrcode.generate('http://michaelbrooks.ca', function (qrcode) {
    console.log(qrcode);
});

And a command-line interface:

$ qrcode "http://michaelbrooks.ca"

Gotcha

One gotcha is that the size of the QR code is related to the amount of data encoded. For longer URLs, I recommend you use a URL shortener service, otherwise the QR code may be larger than the terminal screen!

Why

Gord Tanner and I created this library because there are no functional QR code libraries for node that can render to text or the terminal.

We needed the library for the PhoneGap/Build CLI. The library has to be lightweight, because we expect average users to be downloading and installing it. It also has to work on both Windows, OS X, and ideally Linux.

Alternatives

There are existing QR code libraries for node. Almost all of them will render to a Canvas object and at least one can render as text.

Text from Canvas

With the Canvas object, you can get a text representation of a QR code. This is done by rendering the canvas image to a 2D context, getting the image data from the context, and then converting each pixel value to the appropriate binary text value. But why would you want to do this? It requires the canvas npm module and does double duty processing by rendering the QR code twice - once as an image and once as text.

node-qrcode

There is also a rich QR code library for node called node-qrcode. However, the library is primarily focused on server-side rendering. It does have a client-side text rendering option, but I could not successfully scan the QR code on an iPhone, Android, or BlackBerry. Perhaps it's my terminal's font, but the user should be free to change their font.

Here is an example of node-qrcode rendering to the terminal:

Node QRCode Rendering

Now, why not contributor back to node-qrcode? It's a heavy library with a compiled dependency (canvas). As I mentioned before, my project requires a light-weight library that works on both Windows and OS X.

PhoneGap Build API for Node.js

Jan 10, 2013

Adobe PhoneGap Build has a powerful RESTful API that you can use to tap into PhoneGap Build's functionality. With the API, you can authenticate as a user and create, build, update, and download PhoneGap applications.

RESTful APIs are great but not without annoyances. All of the popular programming languages (and not so popular ones) have HTTP libraries for RESTful access. The downside is that you still need to implement the HTTP request and response communication logic. It's not complicated, except with some authentication types. But it is more code to manage and grows as you encounter API quirks.

This is why we use libraries.

phonegap-build-api-js is a published NPM module for accessing the PhoneGap Build API with node.js. It abstracts the HTTP communication, deals with the API quirks, and leaves the rest untouched. In other words, it simplifies accessing the PhoneGap Build API, so that you can focus on integrating it with your product.

For your coding pleasure, here is an exhaustive list of usage examples:

Authentication

var client = require('phonegap-build-api');

client.auth({ username: 'zelda', password: 'tr1f0rce' }, function(e, api) {
    // use `api` to make requests
});

GET https://build.phonegap.com/api/v1/me

api.get('/me', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

GET https://build.phonegap.com/api/v1/apps

api.get('/apps', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

GET https://build.phonegap.com/api/v1/apps/:id

api.get('/apps/199692', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

GET https://build.phonegap.com/api/v1/apps/:id/icon

api.get('/apps/199692/icon').pipe(fs.createWriteStream('icon.png'));

GET https://build.phonegap.com/api/v1/apps/:id/:platform

api.get('/apps/199692/android').pipe(fs.createWriteStream('app.apk'));

GET https://build.phonegap.com/api/v1/keys

api.get('/keys', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

GET https://build.phonegap.com/api/v1/keys/:platform

api.get('/keys/ios', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

GET https://build.phonegap.com/api/v1/keys/:platform/:id

api.get('/keys/ios/917', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

POST https://build.phonegap.com/api/v1/apps

var options = {
    form: {
        data: {
            title: 'My App',
            create_method: 'file'
        },
        file: '/path/to/app.zip'
    }
};

api.post('/apps', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

PUT https://build.phonegap.com/api/v1/apps/:id

var options = {
    form: {
        data: {
            debug: false
        },
        file: '/path/to/app.zip'
    }
};

api.put('/apps/197196', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

POST https://build.phonegap.com/api/v1/apps/:id/icon

var options = {
    form: {
        icon: 'my-icon.png'
    }
};

api.post('/apps/232741/icon', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

POST https://build.phonegap.com/api/v1/apps/:id/build

Build all platforms:

api.post('/apps/232741/build', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

Build specific platforms:

var options = {
    form: {
        data: {
            platforms: [ 'android', 'blackberry', 'ios', 'winphone', 'webos' ]
        }
    }
};

api.post('/apps/232741/build', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

POST https://build.phonegap.com/api/v1/apps/:id/build/:platform

api.post('/apps/232741/build/android', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

POST https://build.phonegap.com/api/v1/apps/:id/collaborators

var options = {
    form: {
        data: {
            email: 'michael@michaelbrooks.ca',
            role: 'dev'
        }
    }
};

api.post('/apps/232741/collaborators', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

PUT https://build.phonegap.com/api/v1/apps/:id/collaborators/:id

var options = {
    form: {
        data: {
            role: 'tester'
        }
    }
};

api.put('/apps/232741/collaborators/263955', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

POST https://build.phonegap.com/api/v1/keys/:platform

var options = {
    form: {
        data: {
            title: 'My BlackBerry Signing Key',
            password: 'my-password'
        },
        db: '/path/to/sigtool.db',
        csk: '/path/to/sigtool.csk'
    }
};

api.post('/keys/blackberry', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

PUT https://build.phonegap.com/api/v1/keys/:platform/:id

var options = {
    form: {
        data: {
            password: 'my-updated-password'
        }
    }
};

api.put('/keys/blackberry/1505', options, function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

DELETE https://build.phonegap.com/api/v1/apps/:id

api.del('/apps/14450', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

DELETE https://build.phonegap.com/api/v1/apps/:id/collaborators/:id

api.del('/apps/232741/collaborators/263955', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

DELETE https://build.phonegap.com/api/v1/keys/:platform/:id

api.del('/keys/ios/2729', function(e, data) {
    console.log('error:', e);
    console.log('data:', data);
});

Enjoy!

Update 2013-02-16: I have transferred ownership to the PhoneGap GitHub organization from my personal GitHub account. This is good because it gives the library move exposure, broadens the contributor community, and reinforces the open source commitment of PhoneGap and Adobe.