Android JNI static and dynamic injection methods

Author: MiniCode

One of the more popular ways for Android to call C/C++ code is through JNI. There are two ways to implement local methods: static and dynamic

Create a C project or C Module:

After successful creation, the following files (CMakeLists.txt, nativelib.cpp) will be generated:

Among them:
CMakeLists file is used to package cpp (c++ code file) into a so library;
nativelib.cpp is mainly a file for writing C++ code
1. Static injection method
The newly created good project or module is a static method, which will directly compile the C++ code into an so library and package it into an apk file

Local method declaration:

Local method call:

Local method injection into so library:

After building, the so library will be generated:

Compile as a static library:

2. Dynamic injection method:

Configuration in CMakeLists:

cpp file:

#include <jni.h>
#include <string>
#include <android/log.h>
#define LOG_TAG "XXX"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

static jint JNICALL cAdd(JNIEnv *env, jobject jobj, jint x, jint y){
LOGI("cAdd x is :%d y is :%d", x, y);
return x + y;
}

static jstring JNICALL cSayHi(JNIEnv *env, jobject jobj, jint x, jint y){
LOGI("cSayHi runs... will return a string in c");
return env->NewStringUTF("hello from cSayHi");
}

/**
   The first parameter: javaAdd is the method name in java
   The second parameter: (II)I is the signature of the method in java, which can be viewed through javap -s -p classname.class
   The third parameter: (jstring *)cSayHi (return value type) is mapped to the native method name

*/
static const JNINativeMethod gMethods[] = {
        {"javaAdd", "(II)I", (jint *)cAdd},
        {"javaSayHi","()Ljava/lang/String;",(jstring *)cSayHi}
};


static jclass myClass;
//Here is the class path where java calls C's Native method.
static const char* const className="com/example/jni/dynamic/JniOnloadTest";
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){
    LOGI("jni onload called");
    JNIEnv* env = NULL; //It is implemented in JNIEnv when registering, so it must be obtained first
    jint result = -1;
    if(vm->GetEnv((void **) & amp;env, JNI_VERSION_1_4) != JNI_OK) { //Get JNIEnv from JavaVM, generally use version 1.4
        return -1;
    }
    // Get the mapped java class
    myClass = env->FindClass(className);
    if(myClass == NULL)
    {
        printf("cannot get class:%s\
", className);
        return -1;
    }
    //Dynamic registration through RegisterNatives method
    if(env->RegisterNatives(myClass, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0)
    {
        printf("register native method failed!\
");
        return -1;
    }
    LOGI("jni onload called end...");
    return JNI_VERSION_1_4; //This is very important, the version must be returned, otherwise the loading will fail.
}

Note that the above is equivalent to: passing JNI_OnLoad to the com/example/jni/dynamic/JniOnloadTest class to dynamically implement the methods in gMethods, but the methods in gMethods need to cache data in a fixed format. Finally, look at the JniOnloadTest class:

package com.example.jni.dynamic;

public class JniOnloadTest {
    public native int javaAdd(int x, int y);
    public native String javaSayHi();

    static {
        System.loadLibrary("test-dynamic");
    }
}
Log.e("TAG", "onCreate: " + JniOnloadTest().javaAdd(Random .nextInt(5),Random .nextInt(6)) )

Summary: Regardless of whether it is static or dynamic injection of local methods, in the package generated in the Android Studio compilation tool, you can view the injected methods through the command, execute: nm -D xxx.so

The dynamic injection method will have the JNI_OnLoad method

Static injection will have code starting with Java_:

Thinking: Is there any other way to directly call the code in the so library?

Android learning notes

Android performance optimization: https://qr18.cn/FVlo89
The underlying principles of Android Framework: https://qr18.cn/AQpN4J
Android car version: https://qr18.cn/F05ZCM
Android reverse security study notes: https://qr18.cn/CQ5TcL
Android audio and video: https://qr18.cn/Ei3VPD
Jetpack family bucket article (including Compose): https://qr18.cn/A0gajp
OkHttp source code analysis notes: https://qr18.cn/Cw0pBD
Kotlin article: https://qr18.cn/CdjtAF
Gradle article: https://qr18.cn/DzrmMB
Flutter article: https://qr18.cn/DIvKma
Eight major bodies of Android knowledge: https://qr18.cn/CyxarU
Android core notes: https://qr21.cn/CaZQLo
Android interview questions from previous years: https://qr18.cn/CKV8OZ
The latest Android interview question set in 2023: https://qr18.cn/CgxrRy
Interview questions for Android vehicle development positions: https://qr18.cn/FTlyCJ
Audio and video interview questions: https://qr18.cn/AcV6Ap