Develop an iOS Application with Node.js and Cordova

by Krzysztof Trzeciak on March 19, 2015

The modern web is always changing, and this article is more than two years old.

JXcore is an open source project that gives you the ability to run Node.js application on mobile devices, including Android and iOS. In this article, I’ll show you the process of creating a simple iOS application using the Apache Cordova platform and JXcore plugin.

A key feature in JXCore that enables it to work on mobile is its multiengine architecture that allows developers to select which JavaScript engine to use, SpiderMonkey or V8, depending on the platform. The main advantage of the SpiderMonkey engine, in this case, is that it works for both the iOS and Windows ARM platforms.

Compile JXcore for iOS

The very first step is to grab the JXcore source code and compile it. Since it is available on Github, you can download it using the git command (or via a zip). Create a folder for the tutorial and enter the following commands via the terminal:


$ mkdir ~/jxcore
$ cd ~/jxcore
$ git clone https://github.com/jxcore/jxcore.git

Once you have the source code for JXcore, you need to compile it for iOS. The steps are listed on this link already, so I will not repeat the details here. Keep in mind that you will need XCode installed to complete this process. Once you complete those steps, continue with this tutorial.

Finally, the compilation for iOS itself can be launched with the following script:

$ cd ~/jxcore/jxcore
$ ./build_scripts/ios-compile.sh

This may take a long time, especially when it’s invoked for the first time.

Install JXcore/Node.JS

Next you’ll need an OSX executable of JXcore for installing the Apache Cordova tools. However, if you have Node.js with npm already installed (or latest stable release of JXcore from the downloads page), you can use it as well. If not, let’s type one more command and compile JXcore. There is no difference here if we use a SpiderMonkey build or V8 for this purpose. Below commands will compile JXcore for your computer and make it available from the terminal.

$ ./configure
$ sudo make install

Now you have JXcore installed on your system. You can access it any time by calling jx from the terminal. Try jx -jxv, for example, to get the version number.

Install Apache Cordova

There is a very nice document describing the command-line interface of Apache Cordova, it also covers the installation process. Once we have an OSX binary ready from the previous step, we can use it the following way:

$ sudo jx install –g cordova ios-sim

Or, if you already have npm installed, you could also use:

$ sudo npm install –g cordova ios-sim

Please note that, in addition to Cordova I am also installing ios-sim module. This is not mandatory – that depends how we want to deploy your application onto an iOS device. I will mention the reason later in this article.

See Also:  How to Innovate Inside an Enterprise Organization: Matt Savino of DIRECTV

Create a Cordova application

This step is really simple and taken directly from the Cordova docs:

$ cordova create hello com.example.hello HelloWorld
$ cd hello

Then you can add JXcore-Cordova plugin to it. First, let’s download it into the project:

$ git clone https://github.com/jxcore/jxcore-cordova

The plugin’s directory also contains a sample folder, so you can copy index.html from there into a www subfolder:

plugin

The command below does does this:

$ cp ./jxcore-cordova/sample/www/index.html ./www/

Now you should add the JXcore iOS binaries, which we compiled earlier. You can simply copy the entire relevant folder:

$ cp -r ~/jxcore/jxcore/out_ios/ios/bin jxcore-cordova/io.jxcore.node/

At this point you need to enable iOS support for the application:

$ cordova platforms add ios

Having this done, you can add the plugin to the application with the following command:

$ cordova plugin add jxcore-cordova/io.jxcore.node/

Now you have two options:

  • you can either continue with the command line;
  • you can open the project in Xcode and run the application there.

Let’s take a quick look at the command line first. You can easily build and deploy your application as follows:

$ cordova build
$ cordova run ios

It’s possible that if you don’t have an iOS device currently plugged into your Mac, Cordova will try to run the application using the iOS Simulator (which comes with Xcode). However, you will need the ios-sim module for this. That’s why we installed it at the very beginning together with Cordova.

Xcode

if you want to try an Xcode project, there is a HelloWorld.xcodeproj file available under platforms/ios folder. If you double click on it, your application will be opened in the Xcode IDE.

xcode

The app.js file located in Resourcesjxcore_app folder (which can be found via the project explorer panel located on the left) is the starting point of your application’s Node.js portion.

Testing your application is quite easy – you just need to know where exactly (on which device or simulator) you want to run it. There is a default choice already made (iPhone 6 simulator in my case), but you can click and select another one:

xcode iphone 6

When you are ready you can click the grey “play” button to deploy and execute your application.

running app

Using Node on iOS

Assuming you have everything up and running, it’s time to look at some code.

Open the HelloWorld.xcodeproj file – you should see it on the left panel in XCode where it shows project files and folders. Also, open Resources/jxcore_app/app.js, this is the main application file that will work with JXcore. For example, you can put the below lines of codes into that file and it will create a running http server inside your iPhone/iPad.

function getIP() {
var os = require('os');
var nets = os.networkInterfaces();
for ( var a in nets) {
var ifaces = nets[a];
for ( var o in ifaces) {
if (ifaces[o].family == "IPv4" && !ifaces[o].internal) { return ifaces[o].address; }
}
}
return null;
}
var ip = getIP();
if (!ip) {
console.error("You should connect to a network!");
return;
}
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello from JXcore '+Date.now()+'n');
}).listen(1337, ip);
console.error('Server running at http://' + ip + ':1337/', "threadId", process.threadId);

When you run the application with the code above, watch the log window on Xcode to see the IP address that you can visit from your computer’s browser. In order to make things easier, it’s better be on the same Wifi network with your phone for this to work.

See Also:  How Microservices Saved the Day: Sean McCullough on Explosive Growth at Groupon

In addition, you can interact with the Cordova UI. Add the given code below at the end of http.createServer:

cordova('log').call('IP Address:' + param);

When you start the application you should now see the IP address on your phone’s UI.

Let’s talk a bit about the UI side. Visit index.html and you should find the scripts below:

window.onload = function() {
jxcore.isReady(function(){
// register log method from UI to jxcore instance
jxcore('log').register(log);
jxcore('app.js').loadMainFile(function (ret, err) {
if(err) {
alert(err);
} else {
jxcore_ready();
}
});
});
};
function jxcore_ready() {
// calling a method from JXcore (app.js)
jxcore('asyncPing').call('Hello', function(ret, err){
log(ret);
// register getTime method from jxcore (app.js)
var getBuffer = jxcore("getBuffer");
getBuffer.call(function(bf, err){
var arr = new Uint8Array(bf);
log("Buffer size:" + arr.length + " - first item: " + arr[0]);
});
});
}

The important ones are:

function log(x) {
var txt = document.getElementById('txt');
if (txt)
txt.innerHTML += "
" + x;
}
jxcore('log').register(log);

The last line above registers the local method function log inside index.html. Within our sample, we call this method from app.js which is hosted by JXcore.

Calling a method from the JXcore instance is also easy;

jxcore('asyncPing').call('Hello', function(ret, err){
...
});

This time we call a method asyncPing from the index.html, which was defined in app.js. We call the method using a string parameter and expecting an async callback to function(ret, err). Feel free to use as many parameters as you want. If you expect a return from the function to be called, don’t forget to put function(ret, err) at the end of the call.

JXcore supports automatic conversion between ArrayBuffer (UI side) and Node.js Buffer. For example, the method below defined under app.js returns a Node.js Buffer back to browser.

cordova('getBuffer').registerSync(function() {
console.log("getBuffer is called!!!");
var buffer = new Buffer(25000);
buffer.fill(45);
// send back a buffer
return buffer;
});

Using this method on the UI side is very easy;

var getBuffer = jxcore("getBuffer");
getBuffer.call(function(bf, err){
var arr = new Uint8Array(bf);
log("Buffer size:" + arr.length + " - first item: " + arr[0]);
});

Conclusion

In this tutorial, I’ve tried to share some key points on developing iOS application using JXCore and Node.js with Cordova. If you are looking for a similar Android sample project, please check this project as a starter.