Frontend Builds 4: Building Cross Platform Mobile Apps

Frontend Builds 4: Building Cross Platform Mobile Apps

See all articles from the series

The Idea

During this post I'll explain how to bring x-note to various mobile platforms using Apache Cordova. x-note has been built using Angular Material, so it can easily fit on any resolution no matter if customers are using a 27" Cinema Display or a 5" cellphone. We'll extend our build process to automatically build and run mobile apps.

I'll cover iOS and Android in this post, Cordova is of course supporting more platforms, but most customers only care about those popular platforms, so let's start with them. You can easily extend the build scripts to target other platforms like Firefox OS, Ubuntu OS or Windows Phone.

Installing Cordova

First you need to install cordova on your system, this can be done easily by using npm like shown below

$ npm i cordova -g

For iOS and Android are different platform guides available online. Follow these guides to turn your machine into an App Developer Machine now :)

The Android guide tells you to use Google's Android emulator for testing apps. The stock Android emulator is good, but you should checkout genymotion, compared to the regular emulator it's freakin' fast.

Create the x-note cordova project

When reading the official cordova documentation, you'll see the command cordova create hello com.example.hello HelloWorld which is responsible for creating a new cordova project within the subfolder hello.

The second parameter com.example.hello is a reverse domain name identifier for your app.

Third and last parameter of the command is HelloWorld which will become the app's display name.

When you execute the following command, cordova will automatically create a new subfolder hello/www and add a sample website to it, but that's not what we want here. We want to point the new cordova app to our existing frontend app. We want cordova to point to our dist folder where the compiled frontend-app will be placed.

In order to achieve this, you can utilize crodova's --link-to parameter which will create a symbolic link to the path you provide as argument.

Move to the root folder of the x-note project and execute the following command.

$ cordova create mobile rocks.xplatform.xnote "x-note" --link-to dist

Once the command has finished, you'll find a new subfolder named mobile which will have the following content.

mobile folder contents

Let's add some platforms

Cordova can track installed platforms and plugins using it's own config.xml file. (see blog post here). Therefor it's important to append the --save argument when you're installing platforms. Let's add iOS and Android using the following two commands.

$ cordova platform add ios --save
$ cordova platform add android --save

What has actually happened? Go and examine mobile/config.xml cordova downloaded the ios and android bits to compile your html app to native projects and it added two platform nodes to config.xml. These nodes are taken into place when anthoer dev of your team clones the project and executes cordova prepare.

There will also be a xCode project for x-note on iOS and another Java project for x-note on Android. You can find those projects after building the app for the first time directly within the mobile/platforms/ folder.

Once you've added the platforms you can easily execute cordova emulate ios to compile and run the app using the iOS Emulator on your mac. When using stock android emulator, you can start the app using cordova emulate android but if you're using genymotion you've to execute cordova run android because cordova identifies genymotion as real android device.

Integrating Cordova in the build

So far so good, but now it's time to extend our gulp build, because we'd like to automate the compilation process and - depending on the task you execute - starting the app inside of all emulators at once.

Because our gulpfile is automatically loading new gulp-task-files form the gulptasks subfolder, you can just drop new files into that folder. Remember the module.exports syntax we've used in part two of this series. If you do so, you can easily access gulp and tasks as we did before.

Let's start with the documentation, so you'll see which gulp tasks are required and see the responsibilities of each task. gulptasks/mobile.js should now look like this

(function(module) {
    'use strict';

    function RegisterTasks(gulp, tasks) {

    }


    module.exports = {
        init: RegisterTasks,
        docs: [{
            task: 'build:mobile',
            description: 'builds the mobile app for all platforms'
        }, {
            task: 'run:mobile',
            description: 'runs all mobile apps (iOS and genymotion in this case)'
        }]
    };

})(module);

Because our mobile app has a dependency on dist/ we've to ensure that the entire app has been built before we compile the mobile apps. When executing run:mobile on the other side, we've to ensure that all mobile platforms have been built. To do so, add two private tasks called private:run:mobile and private:build:mobile. That said, register those four tasks using the common gulp API. Your RegisterTasks method should look like this.

function RegisterTasks(gulp, tasks) {

    gulp.task('build:mobile', function(done){

    });

    gulp.task('run:mobile', function(done){

    });

    gulp.task('private:build:mobile', function(done){

    });

    gulp.task('private:run:mobile', function(done){

    });
}

Let's start with private:build:mobile first. When revisiting gulpfile.js you will recognize that shelljs is already loaded and exposed through tasks to all gulp-task-files.

Talking Point: There are plenty of npm modules available to use cordova in gulp. Don't get me wrong contributors did a great job and abstracted all those command line interfaces and built JavaScript API's for commonly used cordova commands. But in the end, I found myself using shelljs because it's easier, more readable and maintainable when you just use that simple module and line up all commands you would execute within a terminal instance.

Building the mobile app using cordova cli is straight forward. Just move into the mobile subfolder and execute cordova build ios and cordova build android. When using shelljs, your build:mobile task should now look like this.

gulp.task('private:build:mobile', function(done){  
    tasks.shelljs.cd('mobile');
    // 'cordova build' is short for 
    // 'cordova build ios && cordova build android'
    tasks.shelljs.exec('cordova build');
    tasks.shelljs.cd('..');
    done();
});

We've used run-sequence which is available as tasks.inSequence a few times before. Update the build:mobile task like shown below.

gulp.task('build:mobile', function(done){  
    return tasks.inSequence(
        'private:build', 
        'private:build:mobile', 
        done);
});

It's time for a test drive. Save all files and move to your terminal. Test the documentation integration first by executing gulp help. Gulp should print all tasks as shown in figure two.

gulp help

Let's build the entire app by executing gulp build:mobile. Last but not least is executing the mobile apps directly from the gulpfile.

gulp.task('private:run:mobile', function(done){  
    tasks.shelljs.cd('mobile');
    tasks.shelljs.exec('cordova emulate ios');
    // use run android for genymotion
    // use emulate android for stock emulator
    tasks.shelljs.exec('cordova run android');
    tasks.shelljs.cd('..');
    done();
});

and finally the public gulp task run:mobile here we will again use the tasks.inSequence to ensure that mobile apps are built before we start our app on iOS and Android.

gulp.task('run:mobile', function(done){  
    return tasks.inSequence(
        'private:build:mobile', 
        'private:run:mobile', 
        done);
});

Before testing the run:mobile tasks you've to start your android emulator. iOS emulator will automatically be started by cordova. Test the mobile build using gulp run:mobile. After a few seconds x-note should be started in both emulators as shown in figure three.

Mobile Apps running on Android and iOS

Comments

comments powered by Disqus