1. 静态
1.1 访问Java类public成员变量
JNIEXPORT jint JNICALL
Java_com_my_1test_jnidemo_MainActivity_addNum(
JNIEnv *env,
jobject jobj) {
jclass jclazz = env->GetObjectClass(jobj);
jfieldID fid = env->GetFieldID(jclazz, "num", "I");
jint num = env->GetIntField(jobj, fid);
num++;
return num;
}
1.2 访问Java类static成员变量
JNIEXPORT void JNICALL
Java_com_my_1test_jnidemo_MainActivity_accessStaticField(
JNIEnv *env,
jobject jobj)
{
jclass jclazz = env->GetObjectClass(jobj);
jfieldID fid = env->GetStaticFieldID(jclazz, "name", "Ljava/lang/String;");
jstring name = (jstring)env->GetStaticObjectField(jclazz, fid);
const char* str = env->GetStringUTFChars(name, JNI_FALSE);
std::string ret = "hello ";
ret.append(str);
jstring new_ret = env->NewStringUTF(ret.c_str());
env->SetStaticObjectField(jclazz, fid, new_ret);
}
1.3 访问Java类private成员变量
JNIEXPORT void JNICALL
Java_com_my_1test_jnidemo_MainActivity_accessPrivateField(
JNIEnv *env,
jobject jobj)
{
jclass jclazz = env->GetObjectClass(jobj);
jfieldID fid = env->GetFieldID(jclazz, "age", "I");
jint age = env->GetIntField(jobj, fid);
if (age > 18)
{
age = 18;
} else
{
age--;
}
env->SetIntField(jobj, fid, age);
}
1.4 访问Java类public方法
JNIEXPORT void JNICALL
Java_com_my_1test_jnidemo_MainActivity_accessPublicMethod(
JNIEnv *env,
jobject jobj)
{
jclass jclazz = env->GetObjectClass(jobj);
jmethodID mid = env->GetMethodID(jclazz, "setSex", "(Ljava/lang/String;)V");
char c[10] = "male";
jstring jsex = env->NewStringUTF(c);
env->CallVoidMethod(jobj, mid, jsex);
}
1.5 访问Java类父类方法
JNIEXPORT jstring JNICALL
Java_com_my_1test_jnidemo_MethodJni_accessSuperMethod(
JNIEnv *env,
jobject jobj)
{
jclass jclazz = env->FindClass("com/my_test/jnidemo/SuperJni");
if (jclazz == NULL)
{
char c[] = "error";
return env->NewStringUTF(c);
}
jmethodID mid = env->GetMethodID(jclazz, "hello", "(Ljava/lang/String;)Ljava/lang/String;");
char c[10] = "male11";
jstring jname = env->NewStringUTF(c);
return (jstring)env->CallNonvirtualObjectMethod(jobj, jclazz, mid, jname);
}
1.6 访问Java的int array
JNIEXPORT jint JNICALL
Java_com_my_1test_jnidemo_MainActivity_intArrayMethod(
JNIEnv *env,
jobject jobj, jintArray arr_)
{
jint len = 0, sum = 0;
jint *arr = env->GetIntArrayElements(arr_, 0);
len = env->GetArrayLength(arr_);
jint i = 0;
for (; i<len;i++)
{
sum += arr[i];
}
env->ReleaseIntArrayElements(arr_, arr, 0);
return sum;
}
1.7 访问Java传入对象的方法
JNIEXPORT jobject JNICALL
Java_com_my_1test_jnidemo_MainActivity_objectMethod(
JNIEnv *env,
jobject jobj, jobject person)
{
jclass clazz = env->GetObjectClass(person);
if (clazz == NULL){
return env->NewStringUTF("cannot find class");
}
jmethodID mid = env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V");
if (mid == NULL)
{
return env->NewStringUTF("not find constructor method");
}
jstring name = env->NewStringUTF("cfanr");
return env->NewObject(clazz, mid, 21, name);
}
1.7 访问Java传入的类的ArrayList
JNIEXPORT jobject JNICALL
Java_com_my_1test_jnidemo_MainActivity_personArrayListMethod(
JNIEnv *env,
jobject jobj, jobject persons)
{
jclass clazz = env->GetObjectClass(persons);
if (clazz == NULL)
{
return env->NewStringUTF("not find class");
}
jmethodID constructMid = env->GetMethodID(clazz, "<init>", "()V");
if (constructMid == NULL)
{
return env->NewStringUTF("not find constructormethod");
}
jmethodID addMid = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z");
jclass personCls = env->FindClass("com/my_test/jnidemo/Person");
jmethodID personMid = env->GetMethodID(personCls, "<init>", "(ILjava/lang/String;)V");
jobject arrayList = env->NewObject(clazz, constructMid);
jint i = 0;
for (;i<3;i++)
{
jstring name = env->NewStringUTF("Native");
jobject person = env->NewObject(personCls, personMid, 18+i, name);
env->CallBooleanMethod(arrayList, addMid, person);
}
return arrayList;
}
2. 动态注册
2.1 步骤
- 动态注册
- 先编写Java的native方法
- 编写JNI函数的实现(函数名可以随便命名)
- 利用结构体JNINativeMethod保存Java native方法和JNI函数对应关系
- 利用registerNatives(JNIEnv* env)注册类的所有本地方法
- 在JNI_OnLoad方法中调用注册方法
- 在java中通过System.loadLibrary加载完JNI动态库之后,会自动调用JNI_OnLoad函数完成动态注册
2.2 实现代码:
static jstring sayHello(JNIEnv *env, jobject){
LOGI("hello, this is native log.");
const char *hello = "Hello from c++";
return env->NewStringUTF(hello);
}
static JNINativeMethod jni_Methods_table[] = {
{
"getStringFromCpp", "()Ljava/lang/String;", (void*)sayHello},
};
static int registerNativeMethods(JNIEnv *env, const char *className, const JNINativeMethod *gMethods, int numMethods){
jclass clazz;
LOGI("Registering %s natives\n", className);
clazz = env->FindClass(className);
if (clazz == NULL){
LOGE("Native registration unable to find class %s\n", className);
return JNI_ERR;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0)
{
LOGE("Register natives failed for %s\n", className);
return JNI_ERR;
}
env->DeleteLocalRef(clazz);
return JNI_OK;
}
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
LOGI("call JNI_OnLoad");
JNIEnv *env = NULL;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
{
return JNI_EVERSION;
}
registerNativeMethods(env, className, jni_Methods_table, sizeof(jni_Methods_table)/sizeof(JNINativeMethod));
return JNI_VERSION_1_4;
}
JNIEXPORT void JNICALL
Java_com_my_1test_jnidemo_MainActivity_registerNatives(
JNIEnv *env, jclass clazz){
env->RegisterNatives(clazz, jni_Methods_table, sizeof(jni_Methods_table)/sizeof(JNINativeMethod));
}
#ifdef __cplusplus
}
#endif
完整代码:
链接
其他可参考文章:
链接
链接