前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NDK开发(三) :JNI访问Java变量和方法

NDK开发(三) :JNI访问Java变量和方法

作者头像
103style
发布2022-12-19 13:37:33
3640
发布2022-12-19 13:37:33
举报
文章被收录于专栏:Android开发经验分享

转载请以链接形式标明出处: 本文出自:103style的博客

本文操作以 Android Studio 3.4.2 版本为例

前先阅读 JNI的数据类型


目录

  • JNI访问Java成员变量
  • JNI访问Java静态变量
  • JNI访问Java非静态方法
  • JNI访问Java静态方法
  • JNI访问Java构造方法
  • 小结
  • 参考文章

JNI访问Java成员变量

我们在 Demo HelloNDK 这里继续添加示例。

首先定义变量showText

代码语言:javascript
复制
public String showText = "Hello World";

添加native方法accessField()

代码语言:javascript
复制
public native void accessField();

选中accessField,按 Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessField

在方法中实现修改属性的逻辑:

代码语言:javascript
复制
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_accessField(JNIEnv *env, jobject instance) {
    //获取类
    jclass jcla = env->GetObjectClass(instance);
    //获取类的成员变量showText的id
    jfieldID jfId = env->GetFieldID(jcla, "showText", "Ljava/lang/String;");

    jstring after = env->NewStringUTF("Hello NDK");
    //修改属性id对应的值
    env->SetObjectField(instance, jfId, after);
}

调用验证结果:

代码语言:javascript
复制
TextView accessFiledShow = findViewById(R.id.tv_access_filed_show);
String res = "before: " + showText;
//通过ndk 修改成员变量
accessField();
res += ", after:" + showText;
accessFiledShow.setText(res);

JNI访问Java静态变量

我们在 Demo HelloNDK 这里继续添加示例。

同上添加静态属性和 native方法:

代码语言:javascript
复制
private static String staticString = "static string";

public native void accessStaticField();

Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessStaticField,添加如下代码:

代码语言:javascript
复制
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_accessStaticField(JNIEnv *env, jobject instance) {
    //获取类
    jclass oClass = env->GetObjectClass(instance);
    //获取静态变量id
    jfieldID staticFid = env->GetStaticFieldID(oClass, "staticString", "Ljava/lang/String;");

    //设置静态变量
    jstring after = env->NewStringUTF("static field update in jni");
    env->SetStaticObjectField(oClass, staticFid, after);
}

调用验证结果:

代码语言:javascript
复制
TextView accessStaticFiledShow = findViewById(R.id.tv_static_access_filed_show);
res = "before: " + staticString;
//通过ndk 修改静态变量
accessStaticField();
res += ", after:" + staticString;
accessStaticFiledShow.setText(res);

JNI访问Java非静态方法

我们在 Demo HelloNDK 这里继续添加示例。

同上添加Java非静态方法和 native方法:

代码语言:javascript
复制
public native String accessMethod();

public String getAuthName(String name) {
    Log.e(TAG, "name = " + name);
    return name;
}

Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessMethod,添加如下代码:

代码语言:javascript
复制
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_accessMethod(JNIEnv *env, jobject instance) {
    //获取类
    jclass jCla = env->GetObjectClass(instance);
    //获取方法id  第二个参数:方法名  第三个参数:(参数)返回值 的类型描述
    jmethodID methodID = env->GetMethodID(jCla, "getAuthName",
                                          "(Ljava/lang/String;)Ljava/lang/String;");
    jstring res = env->NewStringUTF("103style");
    jobject objRes = env->CallObjectMethod(instance, methodID, res);
    return static_cast<jstring>(objRes);
}

调用验证结果:

代码语言:javascript
复制
TextView tvName = findViewById(R.id.tv_auth_name);
res = "authName = " + accessMethod();
tvName.setText(res);

JNI访问Java静态方法

我们在 Demo HelloNDK 这里继续添加示例。

同上添加Java静态方法和 native方法:

代码语言:javascript
复制
private static int getRandomValue(int max) {
    return new Random().nextInt(max);
}

public native int accessStaticMethod(int max);

Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessStaticMethod__I,添加如下代码:

代码语言:javascript
复制
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapplication_MainActivity_accessStaticMethod__I(JNIEnv *env, jobject instance,
                                                                  jint max) {
    //获取类
    jclass jCla = env->GetObjectClass(instance);
    //获取静态方法的id
    jmethodID methodID = env->GetStaticMethodID(jCla, "getRandomValue", "(I)I");
    //调用静态方法
    jint res = env->CallStaticIntMethod(jCla, methodID, max);
    //返回结果
    return res;
}

调用验证结果:

代码语言:javascript
复制
TextView staticMethodShow = findViewById(R.id.tv_static_method_show);
res = "accessStaticMethod(100) = " + accessStaticMethod(100);
staticMethodShow.setText(res);

JNI访问Java构造方法

我们在 Demo HelloNDK 这里继续添加示例。

同上添加 native方法:

代码语言:javascript
复制
public native Date accessConstructor();

Alt+Enter快捷添加.cpp中方法Java_com_example_myapplication_MainActivity_accessConstructor,添加如下代码:

代码语言:javascript
复制
extern "C"
JNIEXPORT jobject JNICALL
Java_com_example_myapplication_MainActivity_accessConstructor(JNIEnv *env, jobject instance) {
    //得到TestClass对应的jclass
//    jclass jCla = env->FindClass("com/example/myapplication/TestClass");
    jclass jCla = env->FindClass("java/util/Date");
    //获取构造函数的methodId  构造函数为 void函数 对应的方法名为<init>
    jmethodID methodID = env->GetMethodID(jCla, "<init>", "()V");
    jobject jTestClass = env->NewObject(jCla, methodID);
    return jTestClass;
}

调用验证结果:

代码语言:javascript
复制
TextView staticConstShow = findViewById(R.id.tv_const_show);
res = accessConstructor().toString();
staticConstShow.setText(res);

小结

  • JNI获取类的成员变量的ID调用GetFieldID获取,通过Set[类型]Field修改变量值。
  • JNI获取类的成员变量的ID调用GetStaticFieldID获取,通过SetStatic[类型]Field修改变量值。
  • JNI获取类的方法的ID调用GetMethodID获取,通过Call[类型]Method调用方法。
  • JNI获取类的静态方法的ID调用GetStaticMethodID获取,通过CallStatic[类型]Method调用方法。
  • JNI获取类的构造方法的ID调用GetMethodID获取,通过NewObject构造,构造函数名为"<init>"
  • Demo地址

参考文章


以上

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • JNI访问Java成员变量
  • JNI访问Java静态变量
  • JNI访问Java非静态方法
  • JNI访问Java静态方法
  • JNI访问Java构造方法
  • 小结
  • 参考文章
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档