What is the NDK
The NDK stands for Native Development Kit, a tool that allows you to invoke C or C++ code in Android applications.
The NDK benefits
1. NDK can generate.so files to facilitate code sharing;
2, increase the difficulty of decompilation;
3, improve performance.
The NDK build
Release notes
-
Android Studio: 3.0.1
-
Android Plugin for Gradle: com. Android. View the build: Gradle: 3.0.1
-
Gradle: 4.1
Results the preview
As shown in the figure, the corresponding SO file is generated by using the command ndk-build.
start
To start, we need to create new android. mk, application. mk, and hellocpp.cpp files in the jni directory.
Android.mk
You must create the Android.mk configuration file in the JNI folder, which the NdK-build script looks at and defines the module and its name, the source file to compile, the version flag, and the library to link to.
LOCAL_PATH := $(call my-dir) # will clear many LOCAL_XXX variables LOCAL_PATH will not be cleared, it is basically fixed, do not need to remove include $(CLEAR_VARS) # to build the module name, the corresponding libndksample. so file will be generated automatically, each module name must be unique, LOCAL_MODULE := NDKSample # Contains a list of C or C++ source files to be built into the module. LOCAL_SRC_FILES := hellocpp. CPP # specifies which native apis will be used in the module. https://developer.android.google.cn/ndk/guides/stable_apis.html LOCAL_LDLIBS: = # - llog help system connect everything together, fixed, Don't need to include $(BUILD_SHARED_LIBRARY)Copy the code
Application.mk
Used to describe native modules required by an application. Modules can be static libraries, shared libraries, or executable files. Application.mk is also typically located in the JNI directory.
All APP_ABI := all # Specifies the runtime APP_STL := gnuSTL_static to useCopy the code
Call C or C++
With Android.mk and application. mk configured, there are two ways to call C or C++ code. Now let’s write a method, and we’ll show you how to call it on Android.
HelloCPP.cpp
Simply return a string, C or C++ this I am not very understand, can understand the general meaning, will call good.
#include <jni.h> extern "C" JNIEXPORT jstring JNICALL Java_com_wuxiaolong_ndksample_HelloLibrary_sayHello(JNIEnv *env, Jobject instance) {// pass string from C++ to Java return env->NewStringUTF("Hello from C++"); }Copy the code
Description:
Extern “C” : implement C and C++ mixed programming, used for C++ code to call C functions;
2. JNIEXPORT and JNICALL, two macros used to identify the purpose of the function;
Jstring, JNI, jSTRING, jCHAR, jshort, Jint, jlong, jfloat, jdouble, jBoolean Reference data types jintArray, jshortArray, jlongArray, etc.
Java_com_wuxiaolong_ndksample_HelloLibrary_sayHello; Java_com_wuxiaolong_ndksample_HelloLibrary_sayHello;
The function takes at least two arguments. The first argument is: JNIEnv* is the first parameter to define any native function (including the RegisterNatives function of JNI), a pointer to the JVM function table, and each entry in the function table points to a JNI function. Each function is used to access a specific data structure in the JVM; Second argument: call an instance or Class object of a Java native method, jobject if the native method is an instance method, or jclass if it is static.
Automatically compile C or C++ code
Direct calls to C or C++ code can also be used for debugging.
build.gradle
Android {compileSdkVersion 27 defaultConfig {//...... ExternalNativeBuild {ndkBuild {/ / specified Application. The path of the mk the arguments "NDK_APPLICATION_MK: = SRC/main/jni/Application. Mk." " //abiFilters "armeabi-v7a", "armeabi" //cFlags and cppFlags are used to set environment variables. Generally, cFlags "-dtest_c_FLAG1" is not needed. "-DTEST_C_FLAG2" cppFlags "-DTEST_CPP_FLAG2", "-dcpp_flag2"}}} externalNativeBuild {ndkBuild {// Specify an android. mk path "SRC /main/jni/ android. mk"}}Copy the code
Sync Now, you’ll see more projects. ExternalNativeBuild folder:
So file output directory
app/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libNDKSample.so
The NDK compiler
Using the command dk-build, you can also generate the corresponding so file and call it in the project. Bugs C or C++ code changes and needs to be compiled again.
Download the NDK
Configuring environment Variables
After downloading the NDK address: / Users/wuxiaolong/Library/Android/SDK/the NDK – bundle, to the NDK environment variable configuration.
The NDK compiler
Go to the jNI directory and run the command dk-build as follows:
So file output directory
Libs are generated in the same directory as JNI with the corresponding ABI.
build.gradle
Gradle requires app/build.gradle to specify so file path.
Android {/ /... sourceSets.main { jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' } }Copy the code
You can use either of the above two methods.
HelloLibrary
Create a HelloLibrary to call C or C++ code.
Public class HelloLibrary {static {// LOCAL_MODULE := NDKSample system. loadLibrary("NDKSample"); } // use the native keyword to indicate the method implemented in the form of native code. }Copy the code
Call HelloLibrary
You can call it in your own Activity.
TextView text = findViewById(R.id.text);
text.setText(new HelloLibrary().sayHello());Copy the code
debugging
To debug C or C++ code, use LLDB to detect breakpoints in C or C++ code. In this case, the C/C++ code must be automatically compiled using externalNativeBuild to enter the breakpoint for debugging.
Native mode
Select Run to drop down the item and select Edit Configurations. 2. Command app-native, specialized in debugging C/C++; 3. Module or APP; 4. The Debugger selects Native and only uses LLDB to debug code, ignoring breakpoints in Java code.
The source code
If you need the source code of Sample this time, you can reply NDKSample on my official account “Wu Xiaolong”.
reference
Android.mk
Application.mk
ABI management
This section describes and uses examples of the Android NDK
NDK development (2) JNI pass parameters and return values
How to configure the DEBUG environment for NDK development