Meteor and Phonegap / Cordova 3.x to build a native app for Android and iOS

Since Meteor 0.9.2 the Cordova support is already available inside Meteor

The web is continuosly improving but if you need to build a native app right now you have to use the native SDKs for Android, iOS, Firefox OS, Ubuntu Phone, Chrome OS.. an this is a pain because probably you "need an app" just to send a native notification or access to the camera (See the native features wrapped and plugins in javascript), the rest is already a working webapp.

Step 1: Cordova 3 / Phonegap / Google Chrome Mobile Apps

If you want to access to the native hardware and you don't care about Objective-c or Android Java, you have to use a bridge. It means that you can use the same javascript to develop to multiple platforms, but you need also the native SDK to compile the app.

Many alternatives use Cordova as base, which is an Open Source project from Apache. The most recent Cordova -based wrapper is the Mobile Chrome Apps (cca), which is backed by Google and it supports also Chrome / Chrome OS as platform.

I assume you already have installed NPM (Node.JS package manager), Meteor JS and the Android (adb shell) or iOS SDK.

sudo npm install -g cordova
cordova --version # => 3.3.1-0.4.2
sudo npm install -g ripple # a Cordova 3.x simulator (optional)

The first mobile multiplatform native app

The Cordova CLI works as expected, you can use also use it to install "native plugins" from the repository and don't need the Eclipse IDE.

cordova create cordova-info-app
cd cordova-info-app
cordova platform add android # or ios
cordova plugin add org.apache.cordova.device

Now open "www/index.html" and paste some code :

<script type="text/javascript">
    var display = document.body;
    display.innerHTML += '<div id="deviceProperties">waiting..</div>';
    setTimeout(function (argument) {
      var element = document.getElementById('deviceProperties');
      if (typeof device !== 'undefined'){
        element.innerHTML = 'Device Model: '    + device.model    + '<br />' +
                            'Device Cordova: '  + device.cordova  + '<br />' +
                            'Device Platform: ' + device.platform + '<br />' +
                            'Device Version: '  + device.version  + '<br />';

      } else {
        element.innerHTML = "You aren't inside Cordova / Phonegap";     
      }
    }, 3000); // just to ensure deviceready or domready event is fired
    app.initialize(); // already present in the stub app
</script>

The info app is ready, now you have several option to run it:

cordova run android --device

PROS: Native features CONS: Slow to deploy

ripple emulate # this will open a web browser with the Phonegap stub js and data

PROS: Fast to deploy CONS: Several native feature missing

cordova run android --emulator # set up with: android avd

PROS: Almost native CONS: Slow and it needs RAM, better with x86 image and GPU Host acceleration

cordova serve # then you need to open the url in a cordova app browser

PROS: Native and fast CONS: you need to redeploy and sync cordova on updates, it doesn't work with Meteor

In a ideal world the best approch would be: develop the UI and CSS in the browser in a responsive way and test the native feature on the device. You would notice that the HTML JS CSS inside Cordova / Phonegap works differently from the Web browser (e.g authentication) for SPA Single Page Applications.

Step 2: Meteor JS

Meteor JS isn't strictly related to native apps, but it is a so nice web framework with a lot realtime and SPA features which make it a good candidate. There are several unofficial ways to integrate it with Phonegap. Let's see the MeteorRider way.

The first Meteor app

meteor create meteor-inner-app
cd meteor-inner-app

open "meteor-inner-app.js" and paste something like code above

if (Meteor.isClient) {
  Meteor.startup(function (argument) {
    // THE CODE ABOVE
  });
}

Now go to the terminal and deploy the code to the Meteor web service

meteor deploy my-meteor-inner-app.meteor.com

You should see loading.. and then "You aren't inside Cordova / Phonegap".

Step 3: The first Phonegap + Meteor app

MeteorRider is a simple way to expose the "Native Phonegap js" to the Meteor app.

git clone https://github.com/zeroasterisk/MeteorRider
cp MeteorRider/www/js/* cordova-app/www/js/

Now replace the www/index.html body in the working Phonegap app 

    <body>
        <div class="app">
            <h1>Meteor Rider, Loading</h1>
            Loading....
            <div id="phonegapapp-test" style="display: none;"></div>
        </div>

        <!-- Load phonegap scripts & MeteorRider zepto is a MeteorRider dependacy -->
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/zepto.min.js"></script>
        <script type="text/javascript" src="js/phonegapapp.js"></script>
        <script type="text/javascript" src="js/meteor-rider.js"></script>

        <script type="text/javascript">
          // set url to import, keep track of phonegap versions
          var __MeteorRiderConfig__ = {
            meteorUrl:  "http://meteor-inner-app.meteor.com",
            // meteorUrl:  "http://192.168.1.8:3000", // don't work out of the box
            phonegapVersion: 3.0,
            phonegapAppVersion: 0.1
          };

           // Start phonegap
           phonegapapp.initialize();
        </script>
    </body>

Congratulations, you should now have a remote but native Meteor app like this!

Yeah there are some sharp edges, Meteor changes, some Meteor plugins may be unsupported, authentication works differently, but the Meteor and Cordova / Phonegap / Chrome Mobile Apps communities are improving fast.

Thanks to @zeroasterisk@AdamBrodzinski and @mstn for the support.

corso javascript