Monday, 16 July 2012

Apache Cordova (PhoneGap) + processing.js


The problem


I wanted to be able to create cross-platform mobile applications whilst not having to do it in Javascript.  I've never liked Javascript, I'm not really sure why, maybe I don't fully understand it.

The solution


I had a brainwave that I could create a functional Java application using Processing (that I have used a lot and, hopefully, will be contributing author to a book on the subject if it ever gets published), port it to processing.js and deploy that as an Apache Cordova (PhoneGap) based mobile application.  As a short explanation, Apache Cordova is a cross-platform framework for writing and deploying HTML5 apps to most mobile platforms.  Processing is a graphical Java-based library of which processing.js is the Javascript equivalent.  Using both processing.js and Cordova, I should be able to deploy a java-based application into a cross-platform framework and run it as javascript

The code


This is the easiest way to do it (there are other ways involving deploying the procesing code as Javascript, but I have found the initial translation from Java PDE to have minimal performance impact)

This should work with any HTML5-enabled platform as supported by Cordova, though different browsers may have issues.  Either way, I have tried this on Android, but I will keep the instructions generic and only talk about how to integrate PhoneGap with processing.js

1. Create a new Cordova application (see Apache Cordova instructions) as per your phone platform

2. Download the latest processing.js library file - http://processingjs.org/ either by right-clicking and saving, or just copy the .js source into a new file.  Put this file in the same folder as your Cordova HTML file

2. In the HTML file you will need to reference the processing.js library (as well as Cordova) eg
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" charset="utf-8" src="cordova-1.8.0.js"></script>
<script type="text/javascript" src="processing-1.3.6.js"></script>
<body>
</body>
</html>

This tells the page to use these libraries

3. Copy your Processing PDE files into the same folder.  Alternatively, if you aren't writing in Processing itself, you can use javascript.  Basically this follow the quick start guide on the processing.js website:
http://processingjs.org/articles/jsQuickStart.html
http://processingjs.org/articles/p5QuickStart.html

4. If using PDE files, link the HTML page to the files using the <canvas> tag eg
<body>
<div id="processing-canvas">
<canvas id="mygame"
data-processing-sources="mygame.pde"></canvas>
</div>
<body/>

5. That's it. It will work as if by magic

Calling Cordova from Processing


If you also want to be able to call Cordova functions, which are Javascript, from your Processing sketch you need to do a little more work

6. You need to link Processing and javascript

i. Create an interface to hold the Javascript object eg
public interface JavaScript {
}
The instance will be created in Javascript, so hang in there

ii. Add any methods you want to call to the interface.  For example, I want to make the phone vibrate, so I've added
interface JavaScript {
void vibrate();
}

iii. Add an instance variable declaration
private JavaScript javascript;

iv. Add a method to inject the Javascript instance
void bindJavascript(JavaScript javascript) {
this.javascript = javascript;
}

v. Call the instance where needed eg
// defensive programming just in case
if (this.javascript != null) {
this.javascript.vibrate();
}
    At this point none of this code actually DOES anything, we're just setting up the bridge between Processing and javascript

vi. Bind the javascript in a javascript <script> tag in the HTML file
var bound = false;
function bindJavascript() {
var pjs = Processing.getInstanceById('<name of your PDE file without the .pde>');
if (pjs != null) {
pjs.bindJavascript(this);
bound = true;
}
if (!bound) {
setTimeout(bindJavascript, 2000);
}
}
bindJavascript();
At this point you have created the bridge between processing and javascript. Your JavaScript instance variable will be injected by the above javascript code.

vii. Now we need to create an equivalent javascript call for vibrate().  When the javascript.vibrate() is called in your Processing sketch, the processing.js will call the same function on the javascript object.  So we need a javascript vibrate() function to correspond to the interface method we created in Processing ie
function vibrate() {
}

viii. Now all we need to do is call Cordova from that function ie
function vibrate() {
// cordova function
navigator.notification.vibrate(1000);
}

And there we have it, Cordova called from Processing

To add other functions all you to do is:
- add the method to the interface in Processing
- call that method from your sketch
- create a corresponding javascript function
- call Cordova (or any javascript) in that function

Magic

2 comments:

  1. I've tried this multiple times for iPhone and despite a successful build, only get a blank screen on the simulator. Any Ideas ??

    Thanks.

    ReplyDelete
  2. I don't have a solution but have you tried running the page in a desktop browser? Unless you have mobile-specific javascript on the page there is no reason it shouldn't run

    Failing that, have you read my other post on this topic?
    http://antonylees.blogspot.co.uk/2012/07/phonegap-processingjs-big-problems.html

    Antony

    ReplyDelete