Android Native Code开发学习(二)JNI互相传参返回调用

Android Native Code开发学习(二)

本教程为native code学习笔记,希望能够帮到有需要的人

我的电脑系统为ubuntu 22.04,当然windows也是可以的,区别不大

一、native code介绍

native code就是在android项目中混合C++或者C语言进行开发,这样的好处是很多底层的东西需要使用C++/C的语言进行操作,而且在android开发中,使用C++和C混合开发能够大大增强逆向的难度,同时还能提升程序运行的效率,毕竟C++/C的效率不是其他语言能比得上的。

二、NDK的开发流程

1.声明native方法

首先我们要先在你android的java文件中进行一个声明,声明的格式是这种

public native String stringFromJNI();

当然也可以加上参数

public native String stringFromJNI(String str);

然后我们在android activity中调用这个函数

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());// 我们调用这个方法,并且使用TextView显示出来TextView tv = binding.sampleText;tv.setText(stringFromJNI("我宣布个事"));}

2.实现这个方法

在生成的cpp文件中我们添加以下代码

#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
Java_com_example_nativecodelearn_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */, jstring str) {char* str_cpp =(char *)env ->GetStringUTFChars(str,NULL); // 我们首先要读取出来这个char* str_cpp_2 = "我是个大可爱";strcat(str_cpp,","); // 合并起来strcat(str_cpp,str_cpp_2);return env->NewStringUTF(str_cpp); // 格式需要转成UTF
}

下面我们介绍一下上面出现的参数

**JNIEnv*😗*这个鬼东西是一个指向JNI环境的指针,可以通过它来访问JNI提供的接口方法;

**jobject:**表示Java对象中的this

**JNIEXPORT,JNICALL:**这是JNI定义的宏。可以在jni.h中找到。

还有一个东西就是jstring,这个代表的是java文件中的string类型,就是在这种情况下我们我们是需要一一对应的,比如用jint代表java中的int,具体对比可以去查相关资料。

3.编译安装运行

这样我们就将程序拼接起来,成功显示了我是个大可爱

20230829095055

三、JNI调用java方法

1.静态方法的调用

根据上文我们了解了如何进行java调用cpp的代码,下面我们就介绍如何在cpp中调用java代码。

如果是静态的java代码,cpp调用Java的基本步骤是先通过类名找到类,再根据方法名找到方法的id,最后就可以调用这个方法了。如果是非静态的,那么需要构造出类的对象后才可以调用。

下面我们开始介绍静态方法的JNI调用

首先新建一个类,并且创建一个静态的方法

public class JavaForJNI {public static String str_From_JNI(){System.out.println("java code running");return "全体目光向我看齐\n";}
}

下面就是要在cpp文件中调用这个方法了

#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
Java_com_example_nativecodelearn_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */, jstring str) {char *str_cpp = (char *) env->GetStringUTFChars(str, NULL); // 我们首先要读取出来这个char *str_cpp_2 = "我是个大可爱";jclass java_class = env->FindClass("com/example/nativecodelearn/JavaForJNI");if (java_class == NULL) {printf("Class not found");}jmethodID id = env->GetStaticMethodID(java_class, "str_From_JNI", "()Ljava/lang/String;");if (id == NULL) {printf("MethodID not found");}jstring string_from_java =(jstring) env->CallStaticObjectMethod(java_class, id);char* string_2=(char *) env->GetStringUTFChars(string_from_java, NULL);printf("test in cpp");strcat(str_cpp, ","); // 合并起来strcat(str_cpp, str_cpp_2);strcat(string_2,str_cpp);return env->NewStringUTF(string_2); // 格式需要转成UTF
}

下面我们主要讲解一下cpp中的调用代码,首先就是要获取这个类,就是代码中

jclass java_class = env -> FindClass("com/example/nativecodelearn/JavaForJNI");

这一段主要就是指定好运行的类名,

jmethodID id = env->GetStaticMethodID(java_class, "str_From_JNI", "()Ljava/lang/String;");

这一段主要是用来获取类中的方法名,至于第三个参数是方法的签名,这个其实不需要去了解,一般android studio可以自动给你补全的。最后的话使用CallStaticObjectMethod调用,不过要注意返回值,至于返回值是一个类怎么处理,我们下一节讲。

如果返回是空的话直接调用CallStaticVoidMethod就可以了

20230829155426

2.非静态方法的调用

非静态方法调用相对比较麻烦,当然跟类有关的我们下一节再讲。

public String str_From_JNI_2(String string_from_cpp){return string_from_cpp+"\n谢谢各位!\n";}

调用方法为(这次只贴部分代码)

//查询类名
jclass clz = env->FindClass("com/example/nativecodelearn/JavaForJNI");
//查询构造函数的id
jmethodID jcmid = env->GetMethodID(clz, "<init>", "()V");
//创建对象
jobject jobject = env->NewObject(clz, jcmid);
//获取方法id
jmethodID jmeid = env->GetMethodID(clz, "str_From_JNI_2","(Ljava/lang/String;)Ljava/lang/String;");
//准备传入参数
jstring  string_from_cpp = env->NewStringUTF(string_2);
//调用方法
jstring final_string=(jstring) env ->CallObjectMethod(jobject,jmeid,string_from_cpp);

20230829161952

这样我们就展示了互相传参与互相返回的使用方法与使用方式。希望这个博客可以帮到你。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/59139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++与C#随笔

C/C与C#中的值类型和引用类型 /* C/C code */ int i0; //声明值类型变量i,值为0 int &i_refi; //声明引用类型变量i_ref,是i的引用,与i等价,可作为引用传参int *i_ptr&i; //声明指针类型变量i_ptr&#xff0c;指向 int *i_ptr2&i_ref; //与上面…

LeetCode第21~25题解

CONTENTS LeetCode 21. 合并两个有序链表&#xff08;简单&#xff09;LeetCode 22. 括号生成&#xff08;中等&#xff09;LeetCode 23. 合并K个升序链表&#xff08;困难&#xff09;LeetCode 24. 两两交换链表中的节点&#xff08;中等&#xff09;LeetCode 25. K 个一组翻转…

Mac系统Anaconda环境配置Python的json库

本文介绍在Mac电脑的Anaconda环境中&#xff0c;配置Python语言中&#xff0c;用以编码、解码、处理JSON数据的json库的方法&#xff1b;在Windows电脑中配置json库的方法也是类似的&#xff0c;大家可以一并参考。 JSON&#xff08;JavaScript Object Notation&#xff09;是一…

使用nps实现内网穿透

1、介绍 ​ 当我们想把内网的一些资源暴露在公网上时&#xff0c;可以使用内网穿透功能。比如公司的内网服务器&#xff0c;部署了平时需要开发的项目&#xff0c;但是回到家中无法访问&#xff0c;就可以使用内网穿透&#xff0c;将公司内网的接口映射到一台公网的服务器上&a…

C语言每日一练------Day(5)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;错误的集合 密码检查 &#x1f493;博主csdn个人主页&#xff1a;小小u…

Sympy 微分方程符号解

常微分方程符号解 从数学的角度出发 只支持对形如 y f(x, y)f(x, y) 只能是 x&#xff08;与其指数幂&#xff09; 与 y&#xff08;只支持一次&#xff09; 的非线性组合example import sympy as sp# 定义变量 x sp.symbols("x") y1 sp.Function("y1&quo…

DTO,VO,PO的意义与他们之间的转换

DTO&#xff08;Data Transfer Object&#xff09;&#xff1a;数据传输对象&#xff0c;这个概念来源于J2EE的设计模式&#xff0c;原来的目的是为了EJB的分布式应用提供粗粒度的数据实体&#xff0c;以减少分布式调用的次数&#xff0c;从而提高分布式调用的性能和降低网络负…

分类预测 | MATLAB实现MIV-SVM的平均影响值MIV算法结合支持向量机分类预测

分类预测 | MATLAB实现MIV-SVM的平均影响值MIV算法结合支持向量机分类预测 目录 分类预测 | MATLAB实现MIV-SVM的平均影响值MIV算法结合支持向量机分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 先利用平均影响值MIV算法对特征进行排序&#xff0c;确定分类特征…

基于PHP的电脑商城系统

有需要请加文章底部Q哦 可远程调试 基于PHP的电脑商城系统 一 介绍 此电脑商城系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。用户可注册登录&#xff0c;购物下单&#xff0c;评论等。管理员登录后台对电脑商品&#xff0c;用户&#xff0c;订单&a…

五、多表查询-3.4连接查询-联合查询union

一、概述 二、演示 【例】将薪资低于5000的员工&#xff0c;和 年龄大于50岁的 员工全部查询出来 1、查询薪资低于5000的员工 2、查询年龄大于50岁的员工 3、将薪资低于5000的员工&#xff0c;和 年龄大于50岁的 员工全部查询出来&#xff08;把上面两部分的结果集直接合并起…

十二、集合(2)

本章概要 添加元素组集合的打印列表 List 添加元素组 在 java.util 包中的 Arrays 和 Collections 类中都有很多实用的方法&#xff0c;可以在一个 Collection 中添加一组元素。 Arrays.asList() 方法接受一个数组或是逗号分隔的元素列表&#xff08;使用可变参数&#xff…

VMware标准虚拟交换机和分布式交换机

一、虚拟交换机 初期的网络虚拟化&#xff0c;是非常狭义的概念&#xff0c;主要指的是因为计算资源虚拟化&#xff0c;每台物理宿主机上安装了虚拟化软件&#xff0c;同时会部署了虚拟交换机&#xff0c;负责物理机上面承载的VM&#xff08;虚拟机&#xff09;之间与对外的通…

C++ Day7

一、auto关键字 1.1 概念 C11中引出了变量的类型自动推导&#xff0c;它和Python 不一样&#xff0c;C需要用auto关键字来引导 1.2 作用 auto修饰变量&#xff0c;可以自动推导出变量的数据类型 1.3注意 1> 使用auto修饰变量时&#xff0c;必须初始化 2> auto的右值…

便携式明渠流量计工作原理

便携式明渠流量计工作原理是什么&#xff1f; 简单来说便携式明渠流量计是一种用于测量明渠水流量的仪器。它的工作原理基于流速-水位关系&#xff0c;通过测量水流速度和水位差来计算明渠的流量。 具体原理如下&#xff1a; 1.测量水流速度&#xff1a;通常使用悬挂在水中的水…

Java-day13(枚举与注解)

枚举与注解 枚举 1.自定义枚举 如果枚举只有单个成员&#xff0c;则可以作为单例模式的实现方式 public class test{ public static void main(String[] args) { Season spring Season.spring;System.out.println(spring);spring.show();System.out.println(…

SAP_ABAP_接口技术_PI实践总结

SAP ABAP顾问能力模型梳理_企业数字化建设者的博客-CSDN博客SAP Abap顾问能力模型https://blog.csdn.net/java_zhong1990/article/details/132469977一、背景说明 1.1 案例介绍 1.1.1 实现OA系统 --> PI系统 --> SAP系统的过程 二、实现步骤 1.2 PI中间件的实现过程 …

钉钉小程序引用阿里巴巴图标

2.打开的界面如图&#xff0c;先建一个iconfont.acss文件&#xff0c;全选浏览器打开的样式代码&#xff0c;复制粘贴进新建的iconfont.acss文件中 3.使用

高教社杯数模竞赛特辑论文篇-2015年B题:“互联网+”时代的出租车资源配置(附获奖论文及MATLAB代码实现)

目录 赛题 摘要 一、问题重述 1.1 背景资料与条件 1.2 需要解决的问题 二、问题分析

hashlib 模块学习

hashlib 是 Python 标准库中用于散列和摘要算法的模块。散列算法将输入数据转换为固定长度的散列值&#xff08;也称为摘要&#xff09;&#xff0c;并且对于相同的输入始终生成相同的散列值。这对于存储密码、数字签名、数据完整性验证等领域非常有用。以下是对 hashlib 模块的…

openCV实战-系列教程4:图像梯度计算(Sobel算子/开运算/梯度计算方法/scharr算子/lapkacian算子)、源码解读

&#x1f9e1;&#x1f49b;&#x1f49a;&#x1f499;&#x1f49c;OpenCV实战系列总目录 打印一个图片单独做出一个函数&#xff1a; def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 1、sobel算子 先读进来一个原型白色图 img cv2.…