Android Java代码与JNI交互 JNI方法Java类字段 (六)

🔥 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

 下载案例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️ 邪神

你自己看着办,你喜欢打赏我就赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值