What is NDK

NDK is a collection of tools, the full name is Android Native Development Kit, which is to help developers quickly develop C (or C++) dynamic libraries, and can automatically package so and java applications into apk. These tools are of great help to developers;
Why use NDK
- Easy to port source code between different platforms;
- Reuse C/C++ libraries in Android platform
- Improve performance in some cases, especially for computing-intensive applications like games;
- Use third-party libraries, many third-party libraries are all written by C/C++, Ffmpeg lib for example
- No dependences over the Dalvik Java virtual machine;
Relation between JNI and NDK
JNI is responsible for the interoperability between Java and C/C++, and NDK provides tools to facilitate the use of JNI on the Android platform;
Detailed explanation
JNI provides a series of interfaces that allow Java classes to interact with applications, modules, and libraries written in other languages such as C/C++ (in JNI, these languages are called native languages). For example, using the functions in the C language library in the Java class or using the Java class library in the C language requires the help of JNI; JNI is a bridge between Java and native language
Android NDK is a development tool set that provides a series of tools to quickly develop C/C++ dynamic libraries, and can automatically package .so/.dll and Java applications into Apk; NDK provides tools to facilitate JNI to call C/C++, and Provides a cross compilers set, you can modify the .mk file to generate a dynamic library for a specific CPU platform
NDK development example – using commands line
This section will demo how to setup NDK development environment on Ubuntu
Download NDK development package
Download NDK package from the this link: https://developer.android.google.cn/ndk/downloads/index.html
Unzip the package after downloading
Add environment variables
- 1. Open the terminal, execute following commond in the home directory
sudo gedit .bashrc
Code language: CSS (css)
- 2. Then add the following lines in the bottom, notice you need to change to your own path
# set NDK env
NDKROOT=/media/doudou/NDK/android-ndk-r23b-linux
export PATH=$NDKROOT:$PATH
Code language: PHP (php)
- 3. Execute
source .bashrc
to make the configured environment variables take effect;
NDK development steps
Writing Java source code
Source code feature: Call native add function and then display result on the TextView;
- The add function in line 16 of the code is implemented in the .so lib compiled by NDK;
- In the Java source code, the c++ function add is declared as native
- The static block is used to load the dynamic library. In this block,
System.loadLibrary()
is used to load the library, andNativeAdd
is the name of the dynamic library;
com.android.ndkdemo.MainActivity.java
package com.android.ndkdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView tv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int a = add(5,4);
tv1 = findViewById(R.id.tv);
tv1.setText("a = " + a);
}
public native int add(int a, int b);
static
{
//load lib*.so
System.loadLibrary("NativeAdd");
}
}
Code language: JavaScript (javascript)
Generate com_android_ndkdemo_MainActivity.h header file
Enter the NDK root directory and enter the command below to generate a JNI-style header file:com_android_ndkdemo_MainActivity.h
javah -jni com.android.ndkdemo.MainActivity
Code language: CSS (css)
The file contains the declaration of the JNI function (this is a static registration)
com_android_ndkdemo_MainActivity.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_android_ndkdemo_MainActivity */
#ifndef _Included_com_android_ndkdemo_MainActivity
#define _Included_com_android_ndkdemo_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_android_ndkdemo_MainActivity
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_android_ndkdemo_MainActivity_add
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
Code language: PHP (php)
Create C code and Android.mk
- Create the C code file AddNum.c :
#include "com_android_ndkdemo_MainActivity.h"
JNIEXPORT jint JNICALL Java_com_android_ndkdemo_MainActivity_add(JNIEnv *env, jobject thiz, jint a, jint b)
{
return a + b;
}
Code language: PHP (php)
- Create Android.mk:
LOCAL_PATH := $(call my-dir) # Get current path and save to LOCAL_PATH var
NDK_PROJECT_PATH := .
include $(CLEAR_VARS)
LOCAL_MODULE := NativeAdd # specify target lib name
LOCAL_SRC_FILES := AddNum.c # C source file
include $(BUILD_SHARED_LIBRARY) # change to BUILD_STATIC_LIBRARY for static lib
Code language: PHP (php)
- Create Application.mk
APP_BUILD_SCRIPT := Android.mk
APP_PLATFORM := android-17
APP_ALLOW_MISSING_DEPS := true
Code language: JavaScript (javascript)
Build dynamic link library
In the terminal, enter the NDK root directory and enter the following command to generate the dynamic link library. During the execution of this command, AddNum.c will be compiled according to the compilation rules specified in Android.mk
ndk-build NDK_PROJECT_PATH=.NDK_APPLICATION_MK=Application.mk
If the compilation is successful, the libs and obj directories will be generated in the NDK root directory. There are several subdirectories in the libs directory, each subdirectory corresponds to a different platform
Running the test
Open the AVD simulator or install the apk on the mobile phone, you can see the output result is correct
NDK development example – using Android studio
This section explains how to use the ndk-build tool for NDK development in the Linux environment, and the configuration of the ndk-build build tool in Android Stuido.
Install the NDK toolkit from Android studio
Install the NDK package in SDK Tools (File > Settings > Appearance & Behavior > System Settings > Android SDK > SDK Tools):

Create a new NDK project
- Create a new Android empty project normally;
- Enter the project display mode, and create a folder jni under src -> main for writing native code

Creating Java files
Create and edit Java files under the com.android.ndkdemo package in the java directory;
package com.android.ndkdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView tv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int a = add(5,4);
tv1 = findViewById(R.id.tv);
tv1.setText("a = " + a);
}
public native int add(int a, int b);
static
{
System.loadLibrary("NativeAdd");
}
}
Code language: JavaScript (javascript)
Generate Java header files
cd app/src/main/java javah -jni com.android.ndkdemo.MainActivity
The header file com_android_ndkdemo_MainActivity.h is generated in the java directory, the content is as follows, no need to modify jni.h;
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_android_ndkdemo_MainActivity */
#ifndef _Included_com_android_ndkdemo_MainActivity
#define _Included_com_android_ndkdemo_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_android_ndkdemo_MainActivity
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_android_ndkdemo_MainActivity_add
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
Code language: PHP (php)
Create C code and Android.mk
- Create a new AddNum.c file in the
app/src/main/jni
directory with the following content, (the same as the previous section)
#include "com_android_ndkdemo_MainActivity.h"
JNIEXPORT jint JNICALL Java_com_android_ndkdemo_MainActivity_add(JNIEnv *env, jobject thiz, jint a, jint b)
{
return a + b;
}
Code language: PHP (php)
- Create a new Android.mk file in the
app/src/main/jni
directory (right mouse button on the jni directory, New -> C/C++ File), the content is as follows;
LOCAL_PATH := $(call my-dir) # Get current path and save to LOCAL_PATH var
NDK_PROJECT_PATH := .
include $(CLEAR_VARS)
LOCAL_MODULE := NativeAdd # specify target lib name
LOCAL_SRC_FILES := AddNum.c # C source file
include $(BUILD_SHARED_LIBRARY) # change to BUILD_STATIC_LIBRARY for static lib
Code language: PHP (php)
- Create Application.mk in
app/src/main/jni
APP_BUILD_SCRIPT := Android.mk
APP_PLATFORM := android-17
APP_ALLOW_MISSING_DEPS := true
Code language: JavaScript (javascript)
ndk-build
- Copy the com_android_ndkdemo_MainActivity.h header file to the jni directory
cd jni ndk-build NDK_APPLICATION_MK=Application.mk
- After ndk-build is executed, a libs file will be generated in the same level directory where jni is located, and each subfolder(for different arch) has a libNativeAdd.so dynamic library file
Running the test
Open the AVD simulator or install the apk on the mobile phone, you can see the output result is correct
