Categories

OCaml + Cordova = more secured, typed and hybrid mobile applications.

Since several months, I began to be interested in mobile development. I found a job in Brussels in July 2015 where I learned how to develop hybrid mobile applications (one code = available for multiple mobile platforms) with Cordova and web technologies. I found it very interesting and after several month I continue to develop applications with this technology. I discovered a very great community about mobile development and some awesome frameworks like Ionic.

The majority of these frameworks use JavaScript as programming language but I don’t really like this language because you have no types, some weird things (equality between string and integer), parameters are sent as undefined if not passed, etc. I don’t really like to develop applications with JavaScript because it’s very ugly (even if I think it’s OK for prototyping, but not in production).

I discovered OCaml at the university, a very powerful programming language with inferred static type, type checking at compilation time, an extraordinary community and… a compiler from OCaml to JavaScript! So, I wanted to use this language to develop mobile applications with Cordova: it will be my university project for a semester.

The goal of my project is to be able to use native components of smartphones such like accelerometer, camera, send sms, etc in OCaml.

What are Cordova, js_of_ocaml and gen_js_api?

Cordova allows you to develop hybrid mobile applications using web technologies such as HTML, CSS and JavaScript. For more information, see the official website. Through Cordova plugins, you can access to the native components. To learn how to make Cordova plugins, see the official tutorial. You can find the official Cordova plugin list here.

js_of_ocaml provides a compiler from OCaml to JavaScript. Since Cordova applications use JavaScript, js_of_ocaml provides a way to develop mobile application using OCaml. For more info, see the Ocsigen project which contains js_of_ocaml.

gen_js_api aims at simplifying the creation of OCaml bindings for JavaScript libraries. It must currently be used with the js_of_ocaml compiler, although other ways to run OCaml code “against” JavaScript might be supported later with the same binding definitions (for instance, Bucklescript, or direct embedding of a JS engine in a native OCaml application).

All bindings are developed with gen_js_api and aims to be functional, typed and very close to the JavaScript interface.

How can I use a binding?

Needs compiler >= 4.03.0

I created a GitHub listing all bindings: ocaml-cordova-plugin-list. Each binding is an opam package and so can be installed with opam. It is recommended to add this repository as a remote opam package provider with

Each binding can now be installed. For example, the binding to the camera plugin is cordova-plugin-camera. So, if you want to install the camera binding, you need to use

opam install cordova-plugin-camera

The appropriate opam package is given in the appropriate GitHub repository (list is given here).

If the plugin needs the binding to the standard js library such as device-motion, you need to pin the ocaml-js-stdlib first. If the plugin needs it, it is mentioned in the GitHub repository.

If you don’t want to add this repository, you can manually pin each repository.

What about documentation for each bindings?

Bindings interface are very close to initial plugins JavaScript interface. For example, for the cordova-plugin-camera allowing you to take a picture through navigator.camera.getPicture JavaScript function, you use Cordova_camera.get_picture OCaml function. The equivalent OCaml code to

(supposing Jsoo_lib.console_log is the binding to console.log function, see jsoo_lib). Most functions are implemented with optional arguments and these arguments are at the end of the arguments list, so unit is often mandatory.

As the OCaml interface is very close to JavaScript interface, no OCaml documentation is done yet. Feel free to contribute.

Most of bindings have an example application showing you how to use it. Bindings which don’t have example application are not tested. Please give a feedback about it and open issues if it’s the case.

Be careful: device_ready event

Most of plugins create new objects which are only available when the deviceready event fires. You need to have as first lines:

1234

let on_device_ready ()=(* Your code using plugins here *)

let _ = Cordova.Event.device_ready on_device_ready

The module Cordova comes from the binding to the cordova object so you need to add it for each project. This module can be installed with

opam install cordova

Could you give an entire example please?

Of course. I will show you how to write a hybrid application allowing you to send a SMS to someone. If we succeed to send the SMS, a dialog appears saying everything is OK, else a dialog shows an error message.
You can find all the code in this repository

Mobile application written in OCaml using Cordova showing a toast (Android)

Mobile application written in OCaml using Cordova showing a toast (iOS)

Set up the development environment

First thing to do is to set up the development environment. What we need is:

Cordova distributed as a NodeJS package. To install NodeJS, I recommend to use nvm. Read the GitHub instructions to install nvm and a NodeJS version. After that, install globally Cordova with

npm install -g cordova

OCaml 4.03.0 and opam. See ocaml.org to install OCaml and opam for your distribution. After that, install OCaml 4.03.0 by using

opam switch 4.03.0

Now we have a basic development environment. We will install all Cordova plugins we need and all opam package (included bindings to Cordova plugins).

Create the Cordova project and install the needed plugins

Create a Cordova project by using

cordova create ocaml-cordova-plugin-sms-example

A basic Cordova project is created in the ocaml-cordova-plugin-sms-example directory. Go in this directory with

cd ocaml-cordova-plugin-sms-example

In this directory, you find a www directory which will be included in the final package you will install on the smartphone. It works exactly like a website. It contains a index.html file which is the first executed file (Cordova uses a WebView in which web files are executed, like a standard website).

We have to add the platform we need to build for. If you want to build for iOS (you need Mac OS X with XCode installed), use

I don’t give the example for Windows/Windows Phone because it’s very hard to install natively OCaml on Windows and you need to be on Windows to build for Windows/Windows Phone. However, with Bash on Windows eveything is working like on a common Linux Distrbution.

As you can see in the index.html, we add a script named js/main.js: it will be the JavaScript code generated by js_of_ocaml ie our OCaml code compiled in JavaScript.

Now the best moment, the OCaml code!

The plugin cordova-plugin-sms defines a function Sms.send phonenumber message success_cb error_cb to send a message. The OCaml binding defines a module Cordova_sms and the binding to the Sms.send function send which uses labeled arguments and can be used in this way

Here the logic: the user writes the phonenumber he wants to send the SMS to in the phonenumber input and the SMS content in the message input. When he touched the submit button, we get the contents of these input and call the function Cordova_sms.send with the right arguments.

Compile the OCaml code in JavaScript

It’s time to compile our code in JavaScript. For that, we use js_of_ocaml. As we use some opam package, we will use ocamlfind and the -package argument to link all packages. Js_of_ocaml needs an OCaml bytecode, so first we compile the code in bytecode. Second, we use js_of_ocaml and output the JavaScript in js/main.js.