android jni

 Tue, 13-Jun-2023 01:31:43

In android studio, move cursor to a directory which has the c plus plus source files, right click, and select ''Add C++ to Module' on the context menu,

:

the studio will create CMakeLists.txt which is use to build cpp files, and add following text to gradle file:

android {
     // externalNativeBuild is use to tell gradle which CMakeLists.txt to use
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.18.1'
        }
    }
}

create java file, to declear native method,and load native library:

package com.miaolimin.scopedstorage;

public class Jni {
    static {
        System.loadLibrary("scopedstorage");
    }

    static public native void  test();
    static public native int test2(int a, String b);
}

create cpp file to implement native mehod:

#include <android/log.h>
#include <jni.h>

JNIEnv *env = nullptr;
jclass nativeClass;

#if 1
static  void test(JNIEnv *ev, jclass object)
{
    __android_log_print(ANDROID_LOG_FATAL, "Main", "I'm from cpp!");
}

static  jint test2(JNIEnv *ev, jclass object, int a, jstring b)
{
    const char *nativeString = ev->GetStringUTFChars(b, 0);
    __android_log_print(ANDROID_LOG_FATAL, "Main", "I'm from cpp! %d, %s", a, nativeString);
    ev->ReleaseStringUTFChars(b, nativeString);
    return 0;
}

static JNINativeMethod methods[] = {
        {"test", "()V", (void *)test},
        {"test2", "(ILjava/lang/String;)I", (void *)test2}
};

jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)

{
    __android_log_print(ANDROID_LOG_ERROR, "Main", "jni ON LOAD########");


    if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) {
    __android_log_print(ANDROID_LOG_FATAL, "Main", "GetEnv failed");
    return -1;
    }

    jclass mint = env->FindClass("com/miaolimin/scopedstorage/Jni");

    nativeClass = (jclass)env->NewGlobalRef(mint);


    if (env->RegisterNatives(nativeClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
        __android_log_print(ANDROID_LOG_FATAL,"Main", "RegisterNatives failed");
        return JNI_FALSE;
    }

    __android_log_print(ANDROID_LOG_ERROR, "Main", "jni register native ok");
    return JNI_VERSION_1_6;
}

#else  // following code can be generate with android studio,  the function is the same  with above
extern "C"
JNIEXPORT void JNICALL
Java_com_miaolimin_scopedstorage_Jni_test(JNIEnv *env, jclass clazz) {
    // TODO: implement test()
    __android_log_print(ANDROID_LOG_FATAL, "Main", "I'm from cpp 2!");
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_miaolimin_scopedstorage_Jni_test2(JNIEnv *env, jclass clazz, jint a, jstring b) {
    // TODO: implement test2()
    const char *nativeString = env->GetStringUTFChars(b, 0);
    __android_log_print(ANDROID_LOG_FATAL, "Main", "I'm from cpp! %d, %s", a, nativeString);
    env->ReleaseStringUTFChars(b, nativeString);
    return 0;
}
#endif

 

Tips:

1. create a native implement from java file:

2. if you don't know how to write the signature of method, let android studio to specify it.

JNI各种签名以及例子

1. 基本类型签名:
Java    Native    Signature
byte    jbyte    B
char    jchar    C
double    jdouble    D
float    jfloat    F
int    jint    I
short    jshort    S
long    jlong    J
boolean    jboolean    Z
void    void    V

2. 引用数据类型的转换
Java           Native     Signature 
所有对象     jobject    L+classname +;
Class          jclass      Ljava/lang/Class;
String         jstring      Ljava/lang/String;
Throwable    jthrowable    Ljava/lang/Throwable;
Object[]    jobjectArray    [L+classname +;
byte[]    jbyteArray    [B
char[]    jcharArray    [C
double[]    jdoubleArray    [D
float[]    jfloatArray    [F
int[]    jintArray    [I
short[]    jshortArray    [S
long[]    jlongArray    [J
boolean[]    jbooleanArray    [Z