Android pro tip: call Java methods from C++ using JNI

Sending data from C++ to Java can be done in several ways. One method was presented in one of our old posts, you can write a C++ method that returns a data type. You can call this method from Java to pass data from C++ to Java.

A different approach is to call Java methods directly from C++ using JNI. We use it in DriveAssist to send information about cars that is displayed in the UI.
Below is a trivial example.

 

The C++ part

Declare the following globally:

You will have a global reference to the class containing the method, and the method to be called from C++.
The next part should be called only once, you can place it in the initialization of the native method:

Use findClass to find the corresponding class, in this case it’s MainActivity in the package net.mobileway.driveassist. Save the class reference in the global reference variable so that you don’t have to find the same class each time you want to pass data. Then, you find the method you want to call by using getMethodID, which takes as input the class reference, the method name and the type signature. The method reference is also saved in the global method reference variable that is used in the next step.
Call the Java method like this:

The code is self-explanatory, we use CallVoidMethod to invoke the method from JNI. You have to call the method from the same class object, in this case the native code was called from CameraActivity, and the method is in MainActivity, so we need a class object to make the call (use NewObject to create it). If you have the native part called from the same class as your method, you can use directly the jobject from your C++ method signature, for example:

 

The Java part

Now, in your Java class, in MainActivity you should have something like this:

Java method signatures can be written in C++ using type signature, the following table is useful:

Type Signature Java Type
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L fully-qualified class ; fully-qualified class
[ type type[]
(arg-types) ret-type method type

So, for example the updateData(float length, float length) method from Java, is written as (FF)V. The “V” indicates the return type void. You can use “javap -s” from command line to find out the method signatures more easily:

public void updateData(float, float);
Signature: (FF)V

public void onCreate(android.os.Bundle);
Signature: (Landroid/os/Bundle;)V

protected void onDestroy();
Signature: ()V

That’s it! This way you can pass data from C++ to Java by calling a Java method directly by using JNI.

 

Additional reading

More information can be found here:
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
http://adndevblog.typepad.com/cloud_and_mobile/2013/08/android-ndk-passing-complex-data-to-jni.html

  • David Ou

    Looks good to me, but you might want to reconsider storing the method id because it can change between different threads.

  • Zeeshan Safder

    how to set “env” variable?