When you have been developing Android applications for a while, there comes a moment that you want to leverage the power of some lib in native c in one of your applications. For doing ocr, for example.
This tutorial describes how to call native c-code in an Android application using the Android Native Development Kit.

JNI

The first thing to learn is how to call native c-code from regular Java through JNI, the Java Native Interface. Most Java developers are aware of the native keyword, but most never have to use it in practice. Therefore basic JNI usage will be discussed first.

Your Java source code has to declare one or more methods with the native keyword to indicate that they are implemented through native code:

native String getJniString();

These native methods obviously dont have a Java implementation. You must provide a native shared library that contains the implementation of these methods. This library must be named according to the standard Unix conventions as lib<name>.so and needs to contain the standard JNI entry point. For our method above, the implementation in c could look like:

#include <string.h>
#include <jni.h>

jstring
Java_com_integratingstuff_jni_HelloJni_getJniString(JNIEnv* env, jobject thiz){
    return (*env)->NewStringUTF(env, "Hello from JNI!");
}

in which case our native method would have to reside in the HelloJni class in the com.integratingstuff.jni package. The naming is obvious if you take a closer look.

Finally, your application must explictly load the library(elsewise you will get an UnsatisfiedLinkError). To load it at application startup, add the following code:

static {
        System.loadLibrary("hello-jni");
}

In this case, the name of the shared library would need to be libhello-jni.so. The lib prefix and so suffix should not be included here.

Note that you are not supposed to be following this tutorial in your IDE right now. If you just want to make this jni part work, and dont care about Android for now, you would need to compile the above c-file into the required so file first, dealing with the jni.h dependency yourself. This is trivial with gcc though, especially on a linux machine(on Windows, you probably need to install something extra: I would use Cygwin myself, but you could use some Windows C compiler like MinGW too).

The Android native development kit

If you’re going down the Android path, you need to download the Android Native development kit now. Basically, the android ndk is a c-compiler/builder that ships with all the important c-libs present on the Android OS. It comes with one important command: ndk-build.

To follow this tutorial, you can just create a new Android project in Eclipse. When the project is created, make a new folder in the project root, called “jni”. You copy the above hello-jni.c file into this folder, together with the following Android.mk file:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

When the ndk-build command is run, it always looks for the Android.mk file and reads it to know what variables to use and what to build. Linux users are probably familiar with these mk makefile files. If you are not, dont worry about it.
An Android.mk file always has to begin with the LOCAL_PATH definition. It is used to locate the source files. In this case, we are setting this to the directory the Android.mk file is residing in.
Then all local variables are cleared(LOCAL_MODULE and LOCAL_SRC_FILES etc.. this is important because all builds run in a single context and you dont want to keep some variable from another run filled in.)
Then the local module is set – this is going to be the name of the .so file in this case(thus, libhello-jni.so) and then all the source files that belong in the module are declared.
Finally, include $(BUILD_SHARED_LIBRARY) will generate the .so lib.

Now, add the following method to your activity:

public native String getJniString();

, add the static block

static {
	System.loadLibrary("hello-jni");
}

and change your onCreate implementation to:

TextView tv = new TextView(this);
tv.setText(getJniString());
setContentView(tv);

When you try to run this, your new android application will exit with an UnsatisfiedLinkError. This is because we did not yet build the .so native shared library.

The only thing left to do is to run the ndk-build shell script, found in the $ANDROID-NDK folder, in the jni directory you created(the folder with the mk and c file in).
This will generate the output

Building the so shared lib

and create the required so.file.
When you run your application now, the string coming from the c file is displayed on the screen:

JNI Test on Android

Check the other ndk samples too

This tutorial is a wrapup of the hello-jni sample the android ndk ships with. In the samples directory of the ndk, there are a lot of other interesting examples. There is even one that shows you how to write and declare your whole activity in c: the native-activity sample. Whether doing that is a good idea, is something else entirely though.