Mozilla

Building Cordova apps for Firefox OS

Update: In addition to the Cordova integration described below, Firefox OS is now supported in the 3.5 release of Adobe PhoneGap.

If you’re already building apps with PhoneGap, you can quickly and easily port your existing apps to Firefox OS. We think this is so cool that we’ve launched a Phones for PhoneGap Apps program, focused specifically on compelling apps built with PhoneGap and/or Cordova. Got a great PhoneGap app? We’d love to send you a device!

Cordova is a popular Apache Foundation open source project providing a set of device APIs to allow mobile application developers to access native device functions—such as the camera or the accelerometer—from JavaScript. HTML5 applications can be packaged as native apps via the framework and made available for installation from the app stores of supported platforms, including iOS, Android, Blackberry, Windows Phone—and now Firefox OS. Cordova is also the underlying software in the Adobe product PhoneGap.

Over the past few months, Mozilla has been working with the Cordova team to integrate Firefox OS into the Cordova framework, making it possible to release Cordova apps on the Firefox OS platform. While this is an ongoing project, significant functionality is available now with the 3.4 release of Cordova. In this post we will describe how to use these new capabilities.

Creating and building a Firefox OS app in Cordova

The Cordova site explains how to install the software. Note the installation procedure requires Node.js and can be executed from the command line.

$ sudo npm install -g cordova

Once Cordova is installed, an application can be built with the Cordova create command. (Parameters for the command are described in the Cordova documentation linked above.)

$ cordova create hello com.example.hello HelloWorld

This will create a directory named hello that contains the project and a basic web app in the hello/www directory. In order to produce a Firefox OS app, the proper platform needs to be added next.

$ cd hello
$ cordova platform add firefoxos

With some of the other supported platforms, you would generally run a build command at this stage to produce the output for the platform. Because Firefox OS is an HTML5-based operating system, no compile step is needed to process and produce the app. The only step required is a prepare statement to package the app.

$ cordova prepare firefoxos

Those are the basic steps to generate a simple Firefox OS app from a Cordova project. The output for the project will be located in the hello/platforms/firefoxos/www directory.

Debugging the app

With most other Cordova platforms you would use the emulate or run commands to test an app. With Firefox OS you currently need to use the App Manager, which is the primary tool for debugging and interrogating a Firefox OS app. The tool offers many capabilities including JavaScript debugging and live editing of the CSS while connected to a device.

The above link explains how to install and start the App Manager. Once the App Manager is running, you can click the Add Packaged App button and select the hello/platforms/firefoxos/www directory of your app and press the Open button.

appmanager

This will add the basic app to the App Manager. You will notice no icons are present. This is because the framework integration does not provide them currently and only a bare-bones manifest.webapp is created. From here you can update the app or debug it. Note that between updates you must run a cordova prepare firefoxos command as this step packages the app and puts it in the platforms/firefoxos/www directory. Below is a screenshot of the Cordova HelloWorld app being debugged.

debugger

The Firefox OS Manifest

Firefox OS apps are essentially HTML5 applications that are described by a manifest file. This manifest file points to artifacts like icons, start page, etc. that will be used by the application. In addition, the manifest controls privilege levels and device-specific APIs that are needed by the app. The manifest documentation is available on MDN.

With the default integration in Cordova, a very generic manifest is created and placed in the platforms/firefoxos/www directory. In almost all cases this will not suffice, as you will at least want to provide icons for your app. The App Manager will complain if the app does not contain at least a 128×128 pixel sized icon. This does not prevent you from testing your app, but it is required to upload your app to the Firefox Marketplace. The manifest can be created with a simple text editor or you can modify the manifest in the App Manager. An example manifest.webapp is shown below.

{
  "name": "My App",
  "description": "My elevator pitch goes here",
  "launch_path": "/",
  "icons": {
    "128": "/img/icon-128.png"
  },
  "developer": {
    "name": "Your name or organization",
    "url": "http://your-homepage-here.org"
  },
  "default_locale": "en"
}

Make sure the manifest is created or copied into the project/www folder. Subsequent cordova prepare commands will replace the auto-generated manifest with your application-specific manifest.

Start Up Code

When creating a Cordova app, the starter code generated includes index.html, css/index.css, img/logo.png and js/index.js files. The code in index.js is initiated in index.hml like this:

<script type="text/javascript">
  app.initialize();
</script>

The initialize function essentially sets up the event trigger for the onDeviceReady event, which signifies that the Cordova framework is loaded and ready. The generated code is sufficient for Firefox OS unless you want to implement a privileged App. Privileged apps are Marketplace-signed apps that require the use of more sensitive APIs–for example, Contacts API. See the Packaged apps documentation for more information. For privileged Apps, code like this violates CSP restrictions because of the inline script tag. To get around this, remove the inline script and initiate the app using a window.onload event in the js/index.js file.

Sample App

To test and debug the Cordova/Firefox OS integration we developed a sample app. This application is available on GitHub. It illustrates use of the device-specific plugins. The images and code snippets in the following sections were taken from the sample app. If you want to check out the code and work with it, first create a Cordova project and check the code into the project/www directory. You can then run cordova prepare firefoxos to package the app. Run and debug as described earlier in this post.

app

Device APIs

Cordova uses a plugin architecture to implement device APIs, such as Accelerometer, Geolocation or Contacts. These APIs are very similar to Firefox OS Web APIs and Web Activities and are documented on the Cordova website. Below are the current plugins implemented for Firefox OS and a brief description of how you can include them in your app. You can always see the current status of plugin development for the Firefox OS Platform by checking Jira on the Apache website.

Notification API

The notification API is used to alert the user of your app and is implemented in two plugins: org.apache.cordova.dialogs and org.apache.cordova.vibration. Currently we have implemented the alert, confirm, prompt and vibrate functions. To use this functionality, add the plugins to your project with the following commands:

$ cordova plugin add org.apache.cordova.dialogs
$ cordova plugin add org.apache.cordova.vibration

To get proper styling of popup boxes in Firefox OS, you will need to add the notification.css file to your project. After adding the dialogs plugin, change to the project/plugins/org.apache.cordova.dialogs/www/firefoxos directory and copy the notification.css file to your project/www/css folder. Link the CSS file in head element of index.html.

<link rel="stylesheet" type="text/css" href="css/notification.css" />

You can now use the notification functions.

function onPrompt(results) {
    alert("You selected button number " +
          results.buttonIndex +
          " and entered " + results.input1);
}
navigator.notification.vibrate(500);
navigator.notification.prompt(
      'Enter Name', // message
       onPrompt, // callback to invoke
       'Prompt Test', // title
        ['Ok', 'Exit'], // buttonLabels
         'Doe, Jane' // defaultText
);

prompt

Compass API

The compass API is implemented using the org.apache.cordova.device-orientation plugin. This plugin implements the compass getCurrentHeading and watchHeading functions. To use it simply run the plugin add command:

$ cordova plugin add org.apache.cordova.device-orientation

Once the plugin is added, you can use the get or watch heading function to get compass information.

function onSuccess(heading) {
    var element = document.getElementById('heading');
    myHeading = (heading.magneticHeading).toFixed(2);
    console.log("My Heading = " + myHeading);
}
function onError(compassError) {
    alert('Compass error: ' + compassError.code);
}
var options = {
    frequency: 500
};
watchID = navigator.compass.watchHeading(onSuccess, onError, options);

compass

Accelerometer API

The Accelerometer is accessed using the org.apache.cordova.device-motion plugin and gives the developer access to acceleration data in x, y and z directions. This plugin implements the getCurrentAcceleration and watchAcceleration functions.

To use these functions, add the device-motion plugin to your project by executing the following command.

$ cordova plugin add org.apache.cordova.device-motion

You can then monitor the acceleration values using code similar to this:

var options = {
    frequency: 100
};
watchIDAccel = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
function onSuccess(acceleration) {
  var acX = acceleration.x.toFixed(1) * -1;
  var acY = acceleration.y.toFixed(1);
  var acZ = acceleration.z.toFixed(1);
  var vals = document.getElementById('accvals');
  var accelstr = "<strong>Accel X: </strong>" + acX + "<br />" + "<strong>Accel Y: </strong>" + acY + "<br />" + "<strong>Accel Z: </strong>" + acZ;
  vals.innerHTML = accelstr;
}
function onError() {
  alert('Could not Retrieve Accelerometer Data!');
}

You can also monitor the device orienttation event and retrieve alpha, beta, and gamma rotation values like:

function deviceOrientationEvent(eventData) {
    //skew left and right
    var alpha = Math.round(eventData.alpha);
    //front to back - neg back postive front
    var beta = Math.round(eventData.beta);
    //roll left positive roll right neg
    var gamma = Math.round(eventData.gamma);
    console.log("beta = " + beta + " gamma = " + gamma);
}
window.addEventListener('deviceorientation', deviceOrientationEvent);

Camera API

The camera API is used to retrieve an image from the gallery or from the device camera. This API is implemented in the org.apache.cordova.camera plugin. To use this feature, add the plugin to your project.

$ cordova plugin add org.apache.cordova.camera

In the Firefox OS implementation of this plugin, the getPicture function will trigger a Web Activity that allows the user to select where the image is retrieved.

Code similar to the following can be used to execute the getPicture function:

navigator.camera.getPicture(function (src) {
    var img = document.createElement('img');
    img.id = 'slide';
    img.src = src;
  }, function () {}, {
      destinationType: 1
});

Contacts API

The contacts API is used to create or retrieve contacts on the device and is implemented in the org.apache.cordova.contacts plugin. To access this feature, run the following command:

$ cordova plugin add org.apache.cordova.contacts

Apps that access contacts must be privileged with the appropriate permission set in the manifest file. See “The Firefox OS Manifest” section earlier in this post to understand how to create a custom manifest for your application. For this API, you will need to add the following permissions to the manifest:

"permissions": {
  "contacts": {
    "access": "readwrite",
    "description": "creates contacts"
  }
}

See the manifest documentation for specific access rights. In addition, you will need to change the type of app to privileged in the manifest.

"type": "privileged",

Once the manifest has been changed, you can add contacts with code like the following.

// create a new contact object
var contact = navigator.contacts.create();
var name = new ContactName();
name.givenName = fname;
name.familyName = lname;
contact.name = name;
contact.save(onSuccess, onError);

contact

Geolocation API

The geolocation API is used to retrieve the location, time and speed values from the devices GPS unit and is implemented in the org.apache.cordova.geolocation device plugin.

$ cordova plugin add org.apache.cordova.geolocation

You can retrieve the device latitude, longitude and a timestamp using this API on Firefox OS, but it does require the addition of a permission to the manifest file. See “The Firefox OS Manifest” section earlier in this post to understand how to create a custom manifest for your application.

"permissions": {
    "geolocation": {
      "description": "Marking out user location"
    }
}

Adding this permission causes the app to prompt the user for permission to retrieve the GPS data. You can use either getCurrentPosition to read the GPS once or watchPosition to get an interval based update.

var onSuccess = function (position) {
    console.log('Latitude: ' + position.coords.latitude + 'n' +
    'Longitude: ' + position.coords.longitude + 'n');
};
function onError(error) {
    console.log('Error getting GPS Data');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);

geolocation

Join Us

This post covered some of the basics of the new Firefox OS Cordova integration. We will continue to add more device APIs to the project, so stay tuned. If you are interested in working on the integration or need support for a specific device plugin, please contact us on Stack Overflow under the firefox-os tag or in #cordova on Mozilla IRC.

In the meantime, if you have a Cordova app that makes use of the APIs discussed above, please try generating it for Firefox OS and submitting it to the Firefox Marketplace!

13 comments

Comments are now closed.

  1. Hugo wrote on February 20th, 2014 at 12:43:

    I’d rather like Mozilla to encourage pure and real HTML5 apps development and make sure we can deliver them on all platforms thanks to Web apps in FFOS, Firefox for Android, Firefox Desktops and not thanks to Cordova.

    By supporting Cordova it’s like saying to the devs :”HTML5 is not mature for cross platform development, use Cordova API instead”

    It’s not really the message FFOS & Mozilla is meant to bring to the world.

    The universal platform for all OSes must be HTML5 web apps, not Cordova.

    1. James Long wrote on February 20th, 2014 at 13:12:

      The gist of your comment is correct, HTML will be the platform for writing apps that compete fiercely with native. But we have to be strategic about getting there. It will be a long and hard process, honestly, but with huge rewards (and I do believe we will get there).

      Part of the strategy is to get everyone writing HTML5 apps as much as possible, even if it’s Cordova apps. The Web APIs pioneered by Firefox OS (and more generally various initiatives between browser vendors) are very new and they are not mature enough yet. For now, working with Cordova APIs allows you to write cross-platform HTML5 apps, and that is *huge*. Once people get addicted to that awesomeness, we can work on changing the APIs over to standard Web APIs so people can just write normal JS and have it work everywhere.

      The more people writing HTML5 apps the better, and it’s just part of the process of getting there.

      1. debbie wrote on February 20th, 2014 at 17:21:

        I really do want to bathe in your enthusiasm and look towards the bright future, but have you tried deploying html5 targeted at the android native browser or even mobilesafari on ios7? I feel like the cross-platform utopia dissipates really quickly after a reality check on the state of mobile browser support. Things aren’t much different in the native binary world I suppose, there are device quirks everywhere, but even being an html5 developer i’m not sure if trading in control and performance for purely theoretical cross-compatibility is a reasonable trade off at this point. We’ll see where things go I guess! Which might be easier with more mature developer tools…

      2. Luke wrote on February 20th, 2014 at 19:39:

        Why won’t XUL be the platform for writing FirefoxOS apps? That’s the major advantage of Firefox vs Chrome or others that don’t have a system that lets you use flex, hbox tag, vbox tag, etc. instead of having to figure out all the display, float, margin, padding, etc.

        1. Robert Nyman [Editor] wrote on February 21st, 2014 at 05:48:

          Because we want developers to use the de-facto way to build things with open technologies, i.e. HTML5. XUL is only supported in Firefox web browsers, and that would mean yet another platform/technology to develop for.

          With Firefox OS, we want developers to reuse their existing HTML5 skills while getting even more access with a bunch of JavaScript APIs.

      3. Hugo wrote on February 21st, 2014 at 15:15:

        @James Long : I didn’t see things like that but you’re right actually, it can be a good transition while having HTML5 maturing. Thanks for your reply.

        @Debbie : You’re right, the native android webview is just horrible for web apps, (I haven’t tried on IOS). But it doesn’t tell us anything about the capability of HTML5 to do good apps if there was a good webview.
        I don’t know which kind of device you have but I tried many websites/webapps in chrome&firefox for android on a nexus 7 and honestly there was many times where I wouldn’t be able to tell the difference with a native app if there wasn’t chrome’s url bar at the top of the screen. You can definitely get a super smooth app in html on recent devices, but you need a good html engine.
        (btw google annouced in KitKat a new webview based on chrom(ium) so it should be better…)

    2. Arul Selvan wrote on February 21st, 2014 at 09:46:

      While we write HTML5 apps for Firefox OS, Cordova lets us write HTML5 apps for anything else. Result HTML5 grows.

  2. towfique anam rine wrote on February 20th, 2014 at 12:55:

    great article,
    want to translate it in my native Bengali :)

  3. sintaxi wrote on February 20th, 2014 at 15:26:

    Hugo, while I agree with you, the fact is device APIs are not widely available on the web yet as it is in FXOS. Cordova is there to help until the other browsers catch up. Cordova is doing for device access what JQuery did for the DOM. The web deserves to have device APIs.

  4. ozten wrote on February 20th, 2014 at 15:56:

    Great work!

    This is a nice option where a user can’t or doesn’t want to use Firefox and the project has enough resources to progressively enhance into a Cordova app.

    Of course, where one is using Firefox, we’re getting closer and closer to natively installed apps across Desktop, Android and FxOS with the Open Web App APIs.

  5. Sébastien Blanc wrote on February 21st, 2014 at 03:22:

    Really nice !

    We already started to update our plugin to support firefox :)

    What would be nice is the ability to put json snippets in the plugin.xml that can be merged into the manifest file (like you can do for xml congif files), but I suppose that is something to add in cordova core.

  6. dac san wrote on February 23rd, 2014 at 17:26:

    The gist of your comment is correct, HTML will be the platform for writing apps that compete fiercely with native. But we have to be strategic about getting there. It will be a long and hard process, honestly, but with huge rewards (and I do believe we will get there).

    Part of the strategy is to get everyone writing HTML5 apps as much as possible, even if it’s Cordova apps. The Web APIs pioneered by Firefox OS (and more generally various initiatives between browser vendors) are very new and they are not mature enough yet. For now, working with Cordova APIs allows you to write cross-platform HTML5 apps, and that is *huge*. Once people get addicted to that awesomeness, we can work on changing the APIs over to standard Web APIs so people can just write normal JS and have it work everywhere.

    The more people writing HTML5 apps the better, and it’s just part of the process of getting there.

  7. grigio wrote on February 24th, 2014 at 07:51:

    I like Cordova FirefoxOS integration, it’s a huge opportunity to deploy Cordova apps in a non webkit environment.

Comments are closed for this article.