🔥 Android Studio 版本 🔥
🔥 Java 基础类型数据对应 Native层的字母 🔥
通过 jni 查找java某个类中相应字段对应的数据类型 , 需要使用到 jni 中的 GetFieldID() 函数
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) { return functions->GetFieldID(this, clazz, name, sig); }
* |Java |JNI | * |boolean |Z | * |byte |B | * |char |C | * |short |S | * |int |I | * |long |J | * |float |F | * |double |D |
🔥 Java 引用类型数据对应 Native层字符串 🔥
* |Java |JNI | * |String |Ljava/lang/String; | * |Class |Ljava/lang/Class; | * |Throwable |Ljava/lang/Throwable;| * |int[] |[I | * |Object[] |[Ljava/lang/Object; |
🔥 创建 JNIAccessField 文件 🔥
package com.cmake.ndk1.jni; import com.cmake.ndk1.model.Animal; public class JNIAccessField { static { System.loadLibrary("access-field-lib"); } public static int num; public native void accessInstanceField(Animal animal); }
🔥 配置动态库名称 🔥
add_library( #动态库名称 access-field-lib access-field-lib SHARED jni/jni_access_field.cpp )
🔥 生成可关联的库链接 🔥
为了让Java能够调用 access-field-lib 库中的函数,您需要使用 CMake 构建脚本中的 target_link_libraries() 命令来关联 access-field-lib 库
target_link_libraries( # Specifies the target library. ndk1 person-lib dynamic-lib basic-type-lib string-lib reference-type-lib access-field-lib # Links the target library to the log library # included in the NDK. ) )
🔥 提供给 Native层调用的日志库链接 🔥
target_link_libraries( # Specifies the target library. access-field-lib # Links the target library to the log library # included in the NDK. ${log-lib})
🔥 Native层实现 JNIAccessField 类的JNI的相关函数🔥
对Animal对象实例字段name的修改
//对Animal对象实例字段name的修改 extern "C" JNIEXPORT void JNICALL Java_com_cmake_ndk1_jni_JNIAccessField_accessInstanceField(JNIEnv *env, jobject thiz, jobject animal) { jclass cls = env->GetObjectClass(animal); //获取参数对象参数名字name jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;"); //创建字符串用于对象中name字段的值 jstring str = env->NewStringUTF("this is new name"); //为Animal对象中name设置值 env->SetObjectField(animal, fid, str); }
对Animal对象静态字段num的修改
extern "C" JNIEXPORT void JNICALL Java_com_cmake_ndk1_jni_JNIAccessField_accessStaticField(JNIEnv *env, jobject thiz, jobject animal) { jclass cls = env->GetObjectClass(animal); //获取参数对象参数名字num对应的ID jfieldID fid = env->GetStaticFieldID(cls, "num", "I"); //获取num的值 int num = env->GetStaticIntField(cls, fid); //修改num的值(++num) env->SetStaticIntField(cls, fid, ++num); }
此函数不会获取jclass,进而操作 num 的值
// 此函数不会获取jclass,进而操作 num 的值 extern "C" JNIEXPORT void JNICALL Java_com_cmake_ndk1_jni_JNIAccessField_staticAccessInstanceField(JNIEnv *env, jclass clazz) { //获取参数对象参数名字num对应的ID jfieldID fid = env->GetStaticFieldID(clazz, "num", "I"); //获取num的值 int num = env->GetStaticIntField(clazz, fid); //修改num的值(++num) env->SetStaticIntField(clazz, fid, ++num); }
#include <jvm.h> #include <base.h> #include <string> #include <jni.h> /** * |Java |JNI | * |boolean |Z | * |byte |B | * |char |C | * |short |S | * |int |I | * |long |J | * |float |F | * |double |D | */ /** * |Java |JNI | * |String |Ljava/lang/String; | * |Class |Ljava/lang/Class; | * |Throwable |Ljava/lang/Throwable;| * |int[] |[I | * |Object[] |[Ljava/lang/Object; | */ //对Animal对象实例字段name的修改 extern "C" JNIEXPORT void JNICALL Java_com_cmake_ndk1_jni_JNIAccessField_accessInstanceField(JNIEnv *env, jobject thiz, jobject animal) { jclass cls = env->GetObjectClass(animal); //获取参数对象参数名字name jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;"); //创建字符串用于对象中name字段的值 jstring str = env->NewStringUTF("this is new name"); //为Animal对象中name设置值 env->SetObjectField(animal, fid, str); } //对Animal对象静态字段num的修改 extern "C" JNIEXPORT void JNICALL Java_com_cmake_ndk1_jni_JNIAccessField_accessStaticField(JNIEnv *env, jobject thiz, jobject animal) { jclass cls = env->GetObjectClass(animal); //获取参数对象参数名字num对应的ID jfieldID fid = env->GetStaticFieldID(cls, "num", "I"); //获取num的值 int num = env->GetStaticIntField(cls, fid); //修改num的值(++num) env->SetStaticIntField(cls, fid, ++num); } // 此函数不会获取jclass,进而操作 num 的值 extern "C" JNIEXPORT void JNICALL Java_com_cmake_ndk1_jni_JNIAccessField_staticAccessInstanceField(JNIEnv *env, jclass clazz) { //获取参数对象参数名字num对应的ID jfieldID fid = env->GetStaticFieldID(clazz, "num", "I"); //获取num的值 int num = env->GetStaticIntField(clazz, fid); //修改num的值(++num) env->SetStaticIntField(clazz, fid, ++num); }
🔥 调用Native层相关函数操作Animal 🔥
package com.cmake.ndk1; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.cmake.ndk1.jni.JNIAccessField; import com.cmake.ndk1.jni.JNIReferenceType; import com.cmake.ndk1.model.Animal; public class MainActivity6 extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); JNIAccessField jniAccessField=new JNIAccessField(); Animal animal=new Animal("animal"); final TextView textView=findViewById(R.id.sample_text); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { jniAccessField.accessInstanceField(animal); jniAccessField.accessStaticField(animal); JNIAccessField.staticAccessInstanceField(); Log.i("MainActivity6","name is "+animal.getName()); Log.i("MainActivity6","num is "+Animal.num); Log.i("MainActivity6","num is "+JNIAccessField.num); } }); } }
运行结果 :
D/Animal: call getName method I/MainActivity6: name is this is new name I/MainActivity6: num is 1 I/MainActivity6: num is 1 D/Animal: call getName method I/MainActivity6: name is this is new name I/MainActivity6: num is 2 I/MainActivity6: num is 2 D/Animal: call getName method I/MainActivity6: name is this is new name I/MainActivity6: num is 3 I/MainActivity6: num is 3