androidc++cordovacordova-pluginsvisual-studio-cordova

Accessing C++ code in Apache Cordova for Android


I am developing an app to target Windows 10 and Android using Apache Cordova in Visual Studio 2015. The backend logic will be contained in a c++ project which will hopefully be compiled into a .so or .dll depending on the platform.

I have done some research into Cordova plugins for android but there haven't been any good tutorials. What specifically do I need to do (on the c++ as well as javascript sides) to connect the two code bases?


Solution

  • 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