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.
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