Android NDK JNI using C++ Programming Tutorial

Mostly we develop an android application by using SDK which is java programming language. Other than that, NDK is very important for us to develop some specific features such as OpenGL in the android application. It is written in C and C++ programming language which is more powerful than Java programming language. Native C/C++ perform much faster than Java because it can manage memory and bytes/bits usage. In order to use it, we need to use Android NDK JNI interface translate to readable form in java and compile the .so library. In this tutorial, I will teach you how to compile the so library and how to use C/C++ programming language in the android application.

Creating a New Project

1. Open Android Studio IDE in your computer.
2. Create a new project and Edit the Application name to “NDKExample”.
(Optional) You can edit the company domain or select the suitable location for current project tutorial. Then click next button to proceed.
3. Select Minimum SDK (API 15:Android 4.0.3 (IceCreamSandwich). I choose the API 15 because many android devices currently are support more than API 15. Click Next button.
4. Choose “Empty Activity” and Click Next button
5. Lastly, press finish button.

Note : You must download NDK package in the SDK Manager to proceed.

Setup External Tools

In your android studio menu go to File > Settings. Expand the Tools section you will see “External Tools” and Click it. After that create two external tools which are javah and ndk-build.

set android ndk jni external tools

Click the Plus(+) button to create a new external tool. Below are my javah and ndk-build settings, you can refer it and write it in your external tools settings.

javah

ndk-build setting

Add a java class for Java Native Interface

Right click package name > new > Java class and name it as “TestNDK“. This class will add static and load the library which name is “MyLibrary”. The library name is followed by the so file, we will compile .so file later. And the native method is to get the method from the C and C++ source code.

Edit TestNDK.java class

Go to the file and copy the following code in your class.

package com.example.questdot.ndkexample;

/**
 * Created by HP on 17/7/2016.
 */
public class TestNDK {
    static{
        System.loadLibrary("MyLibrary");
    }

    public native String getNDKString();

}

Edit build.gradle (Module:app)

Add ndk and sourceSets.main in the defaultConfig. NDK is to specific what module name you use, for example our module name will be MyLibrary. The moduleName will follow by the C or C++ files so we will create later. In SourceSets.main section the jni.srcDirs =[] mean disable auto and jniLibs.src are specify which jni library located.

 defaultConfig {
        applicationId "com.example.questdot.ndkexample"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        ndk{
            moduleName "MyLibrary"
        }

        sourceSets.main {
            jni.srcDirs = []
            jniLibs.srcDir "src/main/libs"
        }

    }

Edit gradle-properties

You will occur an error if you do not add the following code

android.useDeprecatedNdk=true

Add a JNI folder

From Android navigate to Project Files, after that right click main folder > New > Folder > JNI Folder. You will see a new JNI folder was added in.

jni folder

Add new C++ files

Right click your folder name jni > New > C++ class and name it as “MyLibrary“. This name must be same as ModuleName in build.gradle.

Generate Header files for MyLibrary.cpp

Go to your java folder and Right click TestNDK.java class > NDK >javah. It will automatically create a header file in your jni folder.

For example, It will look like this.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_questdot_ndkexample_TestNDK */

#ifndef _Included_com_example_questdot_ndkexample_TestNDK
#define _Included_com_example_questdot_ndkexample_TestNDK
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_questdot_ndkexample_TestNDK
 * Method:    getNDKString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_questdot_ndkexample_TestNDK_getNDKString
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Edit MyLibrary.cpp files

Copy the method header from Auto-generated header files and paste it into this file. After that, add the parameter variable and return a value by using C++ code style. You must include the header file.

#include "com_example_questdot_ndkexample_TestNDK.h"

JNIEXPORT jstring JNICALL Java_com_example_questdot_ndkexample_TestNDK_getNDKString
  (JNIEnv* env, jobject obj){
  return (*env).NewStringUTF("My Jni Text");
  }

Create two MakeFiles .mk

Right click jni folder > New > File and name it to Android.mk. Add the following code to your file.

LOCAL_PATH := $(call my-dir)
include  $(CLEAR_VARS)

LOCAL_MODULE := MyLibrary
LOCAL_SRC_FILES := MyLibrary.cpp
include $(BUILD_SHARED_LIBRARY)

Create another makefile which names it to Application.mk then add the following code.

APP_MODULES := MyLibrary

APP_ABI := all

Compile .so files (Shared Library)

Right-click main folder > NDK > ndk-build. You will see new so files will appear in your libs folder as the picture below. The folders separate by different CPUs name.

android ndk so library folders

Edit activity_main.xml layout

Add id in the textview so we can use it later. You can copy and paste the following example.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="//schemas.android.com/apk/res/android"
    xmlns:tools="//schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.questdot.ndkexample.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:text="Hello World!"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

Edit MainActivity.java class

Go to the class and set the textview to the string get from ndk.

package com.example.questdot.ndkexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

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

        textView=(TextView)findViewById(R.id.textView);

        TestNDK testNDK= new TestNDK();

        textView.setText(""+testNDK.getNDKString());

    }
}

Run your project

Yes, you have complete the NDK tutorial and now you can start it to see what will happen on your device.

(Android NDK JNI C/C++)

Source Code

(Visited 4,990 times, 1 visits today)
Advertisements

Yong Loon Ng

Ng Yong Loon, better known as Kristofer is a software engineer and computer scientist who doubles up as an entrepreneur.

You may also like...

1 Response

  1. sunny says:

    First of all thanks for this tutorial can you explain me how i can use lame library like this .

Leave a Reply

Your email address will not be published. Required fields are marked *