Android Studio jni C Hello World

Prerequisites & Knowledge base

  • Installed Android Studio.
  • NDK support for Android Studio. You can install it from SDK Manager.
  • A little bit of C and java knowledge
  • Testing on Android device or simulators.

Create Android Project

  • Open Android Studio.
  • Select Start new Android Studio Project.
  • Set Application name. In this guide I will use HelloC.
  • Set Company name. In this guide I will use ratikal.eu.
  • hit Next
  • In the Select the form factors your app will run on I used Phone and Tablet and selected API 9: Android 2.3 (Gingerbread) but you can try other setups.
  • hit Next.
  • Select Empty Activity and hit Next.
  • Leave Activity Name and all the other fields as is and hit Next.

Android Studio should do its thing and create an open the new project. You may check its running by clicking the green play symbol from the toolbar.

On the left side of Android Studio you will see a file tree view, on the top of that there is a selection box set to Android change it to Project.

jni folder

  • In the Project file viewer find path HelloC / app / src
  • On src folder do Right Click -> New -> Directory Name it jni and hit OK.

This will be the main directory to keep the native c files and the instruction files for ndk-build.

C library file

  • In the folder jni folder do Right Click -> New -> File name it HelloC.c and hit OK.
  • Add the following code to HelloC.c
#include <jni.h>

jstring Java_eu_ratikal_helloc_MainActivity_getString( JNIEnv* env, jobject thiz ) {
    return (*env)->NewStringUTF(env, "Hello from C World");
}

The function name Java_eu_ratikal_helloc_MainActivity_getString is based on this pattern Java_<package-name>_<activity-name>_<function-name>.
* <package-name> can be found in the fist line of project’s MainActivity.java file.
* <activity-name> can also be found in MainActivity.java file and is the class name, in this case MainActivity.
* <function-name> you decide it! In this example id getString.

Android.mk

Inside jni folder create a file named Android.mk (same procedure with HelloC.c).

Android.mk is a the file that instructs ndk-build how to compile and create the library for java to call the C.

Add the following code in Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := helloc
LOCAL_SRC_FILES := HelloC.c
include $(BUILD_SHARED_LIBRARY)

Application.mk

Inside jni folder create a file named Application.mk (same procedure with HelloC.c and Android.mk).

Application.mk is a the file that instructs ndk-build how to compile and create the library for java to call the C.

Add the following code in Application.mk

APP_ABI := armeabi armeabi-v7a mips x86
APP_PLATFORM := android-9

You can skip creating Application.mk if you now that armeabi is fine for your test device. If you don’t understand this, create the file and probably you are going to be ok!

ndk-build

Now lets build the library!

You might don’t know it but Android Studio comes with a console go to terminal tab on the bottom of Android Studio and navigate to the jni folder to run ndk-build.

All the commands are for unix type consoles I don’t know and I don’t care how to do it in windows! I also don’t care about macs I think but it’s the same cause mac is based on *nix.

$ cd app/src/jni
app/src/jni $ ndk-build

You should get an output like this..

[armeabi] Compile thumb : helloc <= HelloC.c
[armeabi] SharedLibrary : libhelloc.so
[armeabi] Install : libhelloc.so => libs/armeabi/libhelloc.so
[armeabi-v7a] Compile thumb : helloc <= HelloC.c
[armeabi-v7a] SharedLibrary : libhelloc.so
[armeabi-v7a] Install : libhelloc.so => libs/armeabi-v7a/libhelloc.so
[mips] Compile : helloc <= HelloC.c
[mips] SharedLibrary : libhelloc.so
[mips] Install : libhelloc.so => libs/mips/libhelloc.so
[x86] Compile : helloc <= HelloC.c
[x86] SharedLibrary : libhelloc.so
[x86] Install : libhelloc.so => libs/x86/libhelloc.so

Move files to jniLibs

jniLibs is the folder where function System.loadLibrary(..) searches for native libraries.

ndk-build created folder HellloC/app/src/libs. Rename and move this folder to HelloC/app/src/main/jniLibs.

To rename libs folder Right Click on libs -> Refactor -> Rename change name to jniLibs hit OK .
To move you can drag n drop it inside main folder.

Load and call native C function from java

Go to MainActivity.java and add in MainActivity class add some code so it look like this.

package eu.ratikal.helloc;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    // Use native C to create a log message
        Log.d("HelloC", getString() );
    }

    // loading native helloc module/lib
    static {
        try {
            System.loadLibrary("helloc");
        } catch (UnsatisfiedLinkError ule) {
            Log.e("HelloC", "WARNING: Could not load native library: " + ule.getMessage());
        }
    }
    public native String getString();
}

Done it!

Run the project with Android Studio and check the logcat logs to see the output. You should see something like

11-05 10:02:29.027 4887-4887/eu.ratikal.helloc D/HelloC: Nick from C

Ndk build from Shell

$ mkdir -p jniHelloC/jni
$ cd jniHelloC/jni
jniHelloC/jni $ touch Android.mk
jniHelloC/jni $ touch Application.mk
jniHelloC/jni $ touch HelloC.c

Fill the files with the code found in this code.

To create library with ndk-build

jniHelloC/jni $ ndk-build

Folder jniHelloC/libs created, you can copy and rename folder where you needed.