Accessing C++ code in Apache Cordova for Android
After some more research and and a lot of dead ends, I was able to get my C++ code to run on Cordova. I'm replying here to document some of my problems and give some good resources for others attempting a similar thing.
Cordova plugin development
A good tutorial that explains each part of the plugin better than the official documentation: https://blogs.oracle.com/mobile/entry/introduction_to_custom_cordova_plugin
My biggest problem with this part of development was that the Cordova plugin removal in VS 2015 does a crap job and sometimes looks for files in the wrong places. Be wary of this if you need to change your plugin xml file.
Communicating with C++
I used VS to build the code into a .so shared library (new project --> android shared library). Make sure that you build it in ARM, not x86 or another configuration. Place the .so file in /libs/armeabi so the .java file can find it using the loadLibrary() method.
Here is my .java file for loading and calling a function from the library:
package com.example.plugin.cpp;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.PluginResult;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
public class Cpp extends CordovaPlugin {
public static final String ACTION_SEVEN = "seven";
public Cpp() { }
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
if (ACTION_SEVEN.equals(action)) {
alert("Message from Java", "Grabbed the number " + get7() + " from C++", "dismiss", callbackContext);
callbackContext.success();
return true;
}
return false;
}
private synchronized void alert(final String title,
final String message,
final String buttonLabel,
final CallbackContext callbackContext) {
new AlertDialog.Builder(cordova.getActivity())
.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setNeutralButton(buttonLabel, new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int which) {
dialogInterface.dismiss();
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0));
}
})
.create()
.show();
}
public native int get7();
static {
System.loadLibrary("CppLibrary");
}
}
And here is the corresponding C++ code:
CppLibrary.cpp:
#include "CppLibrary.h"
extern "C" {
JNIEXPORT int JNICALL Java_org_example_plugin_cpp_Cpp_get7(JNIEnv* env, jobject thiz)
{
return 7;
}
}
Cpp.h:
#pragma once
extern "C" {
JNIEXPORT int JNICALL Java_org_example_plugin_cpp_Cpp_get7(JNIEnv* env, jobject thiz);
}
C-side implementation resources:
http://developer.android.com/ndk/samples/sample_hellojni.html#ci
http://developer.android.com/training/articles/perf-jni.html#faq_ULE