Android JNI 进阶(含完整 Demo)

news/2024/12/2 15:03:14/

GetObjectArrayElement解释:

在JNI 中只有基本类型和引用类型,String 是引用类型,所以遍历 String[]的时候,采用GetObjectArrayElement()来接收

  • 参数一:jobjectArray:所有的元素
  • 参数二:jsize:当前的位置

ReleaseIntArrayElements解释:

ReleaseIntArrayElements()方法是 C++通知 JNI 改变 java 的值,在代码中 java层 传递过来一个数组,然后修改完成后再返回给 java 层

  • 参数一:jintArray:java 传递过来的数组
  • 参数二:修改后的数组
  • 参数三:修改的模式,填 0 就好

ReleaseStringChars解释:

ReleaseStringChars是用来释放 JNI 内存的,虽然说不释放也可以,因为在方法结束的时候会弹栈,一旦弹栈就会自动释放内存,但是如果说一个方法中有 5000 行代码,在一直不释放,等待到 JNI 弹栈自动释放,那么就会引起 JNI 在调用该方法的时候占用空间略大(养成好习惯)

运行结果:

native 运行结果:
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数一为42
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数二为24.420000
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数三为1
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数四为李元霸
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数五为成龙
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数五为李小龙
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数五为松井宝
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数五为迪丽热巴
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 参数五为ohh
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 第六个参数为:101
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 第六个参数为:104
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 第六个参数为:102
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 第六个参数为:162
2021-04-28 17:36:22.217 6501-6501/com.example.jni E/szj: 第六个参数为:161

java 运行结果:
2021-04-28 17:36:22.217 6501-6501/com.example.jni I/szjjava 层打印: 101
2021-04-28 17:36:22.217 6501-6501/com.example.jni I/szjjava 层打印: 104
2021-04-28 17:36:22.217 6501-6501/com.example.jni I/szjjava 层打印: 102
2021-04-28 17:36:22.217 6501-6501/com.example.jni I/szjjava 层打印: 162
2021-04-28 17:36:22.217 6501-6501/com.example.jni I/szjjava 层打印: 161

[](()引用类型 静态/动态 方法调用

java 代码:

public native void nativeMethod(Persion persion);

辅助图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-12xx8o5B-1651545697610)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c7159fd2c4a04fa5b12a7234d859d472~tplv-k3u1fbpfcp-zoom-1.image)]
右侧的红框是需要调用的方法;

  • void setName()
  • void setAge()
  • static void show(String name)

native 代码:

extern “C”
JNIEXPORT void JNICALL
Java_com_example_jni_activity_AdvancedActivity_nativeMethod(JNIEnv *env, jobject thiz,
jobject persion) {

/**

  • 获取 Persion 的 class
  • 源码: jclass FindClass(const char* name)
    */
    jclass j_class = env->FindClass(“com/example/jni/bean/Persion”);

/**

  • 获取方法 ID:
  • jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
    */
    jmethodID j_method_id = env->GetMethodID(j_class, “getName”, “()Ljava/lang/String;”);

//获取 Persion getName方法返回值
jstring j_strName = static_cast(env->CallObjectMethod(persion, j_method_id));

//修改为 C++认识的 char*类型
char *j_char_name = const_cast<char *>(env->GetStringUTFChars(j_strName, NULL));
LOGE(“通过 getName获取值为:%s”, j_char_name)

//获取 setName的 ID
jmethodID j_setName_id = env->GetMethodID(j_class, “setName”, “(Ljava/lang/String;)V”);
//获取静态的 show 方法
jmethodID j_show_id = env->GetStaticMethodID(j_class, “show”, “(Ljava/lang/String;)V”);

env->CallVoidMethod(persion, j_setName_id, env->NewStringUTF(“糖果超甜”));
env->CallStaticVoidMethod(j_class, j_show_id, env->NewStringUTF(“糖果超甜”));
}

这个方法中没有陌生方法,大家应该都认识,看不懂记得评论区留言哦~

运行结果为:

native运行结果:
2021-04-28 17:44:29.775 6501-6501/com.example.jni E/szj: 通过 getName获取值为:洪静宝

java 运行结果:
2021-04-28 17:44:29.775 6501-6501/com.example.jni I/szjjava 层 setName方法:: 糖果超甜
2021-04-28 17:44:29.775 6501-6501/com.example.jni I/szjjava 层show方法:: 糖果超甜

[](()引用类型进阶

java 定义native方法:

public native void nativeMethod2(Dog dog);

辅助图:
在这里插入图片描述

native 层代码:

extern “C”
JNIEXPORT void JNICALL
Java_com_example_jni_activity_AdvancedActivity_nativeMethod2(JNIEnv *env, jobject thiz,
jobject dog_jobj) {

//获取 Dog 类的 Class
jclass j_dog_class = env->GetObjectClass(dog_jobj);

//获取 Dog 类中的 DogShow 方法 ID
jmethodID jmethodId = env->GetMethodID(j_dog_class, “DogShow”,
“(Lcom/example/jni/bean/Persion;)V”);

//获取 Persion 的 jclass
jclass j_persion_class = env->FindClass(“com/example/jni/bean/Persion”);
//获取 Persion 的 jobj //AllocObject只实例化对象,不会调用构造函数
jobject j_persion_job = env->AllocObject(j_persion_class);

//给 Persion 赋值
jmethodID j_setName_id = env->GetMethodID(j_persion_class, “setName”, “(Ljava/lang/String;)V”);
jmethodID j_setAge_id = env->GetMethodID(j_persion_class, “setAge”, “(I)V”);

//调用 Persion 的 setName 和 setAge 给 name 和 age 赋值
env->CallVoidMethod(j_persion_job, j_setName_id, env->NewStringUTF(“蔡徐坤”));
env->CallVoidMethod(j_persion_job, j_setAge_id, 52);

//调用 Dog 的 DogShow(Persion)方法
env->CallVoidMethod(dog_jobj, jmethodId, j_persion_job);

//释放引用类型 class 和 job 都建议释放
env->DeleteLocalRef(j_dog_class);
env->DeleteLocalRef(j_persion_class);
env->DeleteLocalRef(j_persion_job);
}

思路:

  • 创建 Persion 对象
  • 调用 Persion 的 setName() / setAge() 方法给 name/age 赋值
  • 创建 Dog 对象
  • 调用 Dog 对象中的 DogShow(Persion) 方法,把 Persion 传递进去即可

AllocObject解释:

AllocObject 只实例化对象,不会调用构造函数,在新创建对象(不是传递过来的)的时候,必须用这个来实例化对象,否则调用 实例化的对象不起作用

[](()构造函数调用

java 定义 native 方法:

public native void nativeStructure(Dog dog);

native 代码:

extern “C”
JNIEXPORT void JNICALL
Java_com_example_jni_activity_AdvancedActivity_nativeStructure(JNIEnv *env, jobject thiz,
jobject dog) {

//获取 Dog 的 jclass
jclass j_dog_class = env->GetObjectClass(dog);

//获取构造方法
jmethodID id1 = e 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 nv->GetMethodID(j_dog_class, “”, “()V”);
jmethodID id2 = env->GetMethodID(j_dog_class, “”, “(II)V”);
jmethodID id3 = env->GetMethodID(j_dog_class, “”, “(III)V”);

//调用构造方法
env->CallVoidMethod(dog, id1);
env->CallVoidMethod(dog, id2, 100, 200);
env->CallVoidMethod(dog, id3, 300, 400, 500);
}

这里非常好理解:

构造方法用表示即可,其余的都没变

[](()全局引用

java 定义 native 代码:

//全局引用测试
public native void nativeAllQuote();

native代码(局部引用):

发现错误找到错误

jclass dogClass;//注意这里定义到外边也是局部引用(和 java 不一样)
extern “C”
JNIEXPORT void JNICALL
Java_com_example_jni_activity_AdvancedActivity_nativeAllQuote(JNIEnv *env, jobject thiz) {
if (NULL == dogClass) {
//这个是局部引用,(和 java 不同)
dogClass = env->FindClass(“com/example/jni/bean/Dog”);
}
//获取 Dog 的 jclass
jclass j_dog_class = env->GetObjectClass(dogClass);

//获取构造方法
jmethodID id1 = env->GetMethodID(dogClass, “”, “()V”);
jmethodID id2 = env->GetMethodID(dogClass, “”, “(II)V”);
jmethodID id3 = env->GetMethodID(dogClass, “”, “(III)V”);

//调用构造方法
env->CallVoidMethod(j_dog_class, id1);
env->CallVoidMethod(j_dog_class, id2, 100, 200);
env->CallVoidMethod(j_dog_class, id3, 300, 400, 500);
// dogClass = NULL;//专门注释掉的!
dID id3 = env->GetMethodID(dogClass, “”, “(III)V”);

//调用构造方法
env->CallVoidMethod(j_dog_class, id1);
env->CallVoidMethod(j_dog_class, id2, 100, 200);
env->CallVoidMethod(j_dog_class, id3, 300, 400, 500);
// dogClass = NULL;//专门注释掉的!


http://www.ppmy.cn/news/633837.html

相关文章

Java多线程导出Excel表格, 100w数据量

海量数据报表导出 背景 大数据量的报表导出&#xff0c;单线程的情况下&#xff0c;很大概率会导致OOM问题&#xff0c;而且导出时间长。 解决方法&#xff1a;多线程导出报表 多线程的优势就是可以同时处理多个任务&#xff0c;提高效率&#xff0c;减少接口的响应时间。…

《图解密码技术》笔记

《图解密码技术》是一本非常适合新手密码学入门的书籍&#xff0c;对于密码学相关的概念讲解的的非常清楚到位。本文是本人阅读该书做的笔记&#xff0c;供大家参考&#xff0c;不足之处&#xff0c;请批评指正。 第一部分 密码 第一章 环游密码世界 公钥密码&#xff08;pub…

2022年券商行业发展和产品研究报告

第一章 行业概况 证券行业指专门从事有价证券买卖的法人企业。分为证券经营公司和证券登记公司。狭义的证券公司是指证券经营公司&#xff0c;是经主管机关批准并到有关工商行政管理局领取营业执照后专门经营证券业务的机构。它具有证券交易所的会员资格&#xff0c;可以承销发…

MySQL随机生成customers表姓名,密码,性别,出生日期,电话,邮箱,收货地址,客户等级创建账号时间(function函数)

在设计图书书店数据库的customers客户表时,记录一些花了时间的成果。 首先创建客户表 drop table if exists customers; create table customers(customerid BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,customername varchar(50) not null COM…

【Autojs】京东自动退货脚本

声明 此脚本只用于读者学习使用&#xff0c;禁止用于非法用途。 环境 app版本Autojs4.1.1 Alpha京东11.3.6 直接分享源码 // 悬浮窗按钮 run.js var path "./jd.js"; if (!files.exists(path)) {toast("脚本文件不存在: " path);exit(); } var wind…

mysql+php数据库大作业之世界杯比赛系统

说明&#xff1a;此项目为本人大三数据库课程的课程大作业。由于只学习过相关的sql知识&#xff0c;对于前端的知识并不是很了解&#xff0c;只花了一周的时间来学习前端&#xff0c;所以此版本只能算是一个阉割版&#xff0c;有很多功能还未实现&#xff0c;希望以后能有机会继…

jmeter常用随机函数

jmeter常用随机函数 邮箱类&#xff1a; ${__RandomString(8,abcdefghijklmnopqrstuvwxyz,)}http://126.com手机号类&#xff1a; ${__Random(18000000000,18999999999,)}银行卡号类16位&#xff1a; ${__Random(1000000000000000,9999999999999999,)}银行卡号类19位&#xff…

MySQL自定义函数

⚠不推荐将业务逻辑存储在数据库中. MySQL不仅提供了很多很方便的内置函数&#xff0c;用户还可以自定义函数。 不同于MongoDB对Js函数的良好支持&#xff0c;MySQL的自定义函数用起来感觉处处掣肘&#xff0c;不推荐用来处理复杂的业务逻辑。 MySQL自定义函数默认是和库进行绑…