Java Native Interface for Android

by Gwenn Guihal.

What ?

JNI allows to use C++ code with Java, on Android for example.

For what ?

For few stuff :

  1. To not rewrite in Java a useful existing library.
  2. To use the same library on Android and IOS.
  3. At my mind, point 2 is essential.
  4. For many things, C++ is faster than Java.

How to proceed ?

Because I don’t know C++, I will be brief. I looked the AndEngine‘s guys job and reproduce it for my works.
You would only need to copy and edit two or three files, install Cygwin (with c++ extensions) if you are on Windows and that’s all !

Sample ?

Yes, print a random number in console : the best example never seen before.
1) Install the last improved Android NDK from Dmitry Moskalchuk aka CrystaX.
He says :

You shouldn’t care about wide chars/strings/streams anymore when porting existing code to Android – just compile it using my NDK and go further. Download and enjoy!

I used ndk6 for the sample.
2) Create a new android project in eclipse, call it « HelloJNI », choose SDK 2.1.
3) Create a folder « jni » and copy files from the same folder on the github repository.
4) The C++ lib is called myGreatLib and contains one function : « giveMeANumber »  which returns a random int.
5) Now, we have to write a little bit of java code! Create « HelloJNI.java » then declare required native and java methods.

// native methods
private native int jniGiveMeANumber();

// java methods
public void giveMeANumber()
{
	int num = jniGiveMeANumber();
	Log.e("JNI", "Number : " + num );
}

With this class, we generate a header C++ file with which we will write the C++ code to call our amazing lib.
Open a shell, go to HelloJNI/bin/classes then run command:

javah fr.myrddin.hellojni.HelloJNI

This command generates a C++ header file at the root of your bin/classes folder. Copy the « fr_myrddin_hellojni_HelloJNI.h » file into the « jni » folder and rename it « HelloJNI.h ».

Well done. We write now the cpp file HelloJNI.cpp from the generated header :

#include "HelloJNI.h"
#include "myGreatLib/Hello.cpp"

#ifdef ANDROID
#include
#endif

JNIEXPORT jint JNICALL Java_fr_myrddin_hellojni_HelloJNI_jniGiveMeANumber(JNIEnv *, jobject)
{
	Hello hello;
	return hello.giveMeANumber();
}

6) We just have to compile our C++ lib. For that, I took Android.mk, Application.mk, and build.sh files from the port of Box2D by Libgdx (Mario Zechner) and AndEngine (Nicolas Gramlich).
Edit Android.mk file :

...
LOCAL_MODULE := libHelloJNI
...
LOCAL_SRC_FILES := \
HelloJNI.cpp

Edit build.sh to set the project place and change the ndk folder by yours.
Run Cygwin, then launch build.sh.

Yes! It works! In the project, we have now a libs folder which contains the compiled lib : armeabi-v7a/libHelloJNI.so. Add it to build path.
Add that code in HelloJNI.java, it allows to load the library.

static
{
	System.loadLibrary("HelloJNI");
}

Edit HelloJNIActivity to test your library :

HelloJNI test = new HelloJNI();
test.giveMeANumber();

Compile and run, …, look at the console, …, it works, you are the best!

Next

For more information, look a these links :
Android NDK
What is the NDK?
The Java Native Interface, Programmer’s Guide and Specification

For more detailled samples, there is a couple of library of my github :
- AndroidClipper : JNI wrapper of Angus Johnson’s Polygon clipping library (my fist JNI library)
- Triangulate : JNI wrapper of John W. Ratcliff’s Triangulate library.*
- AndroidPoly2Tri : JNI wrapper of poly2tri, a 2D constrained Delaunay triangulation library.

Good luck !