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中调用这个函数
@Override protected 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 #include extern "C" JNIEXPORT jstring JNICALLJava_com_example_nativecodelearn_MainActivity_stringFromJNI( JNIEnv* env, jobject , 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.编译安装运行
这样我们就将程序拼接起来,成功显示了我是个大可爱
三、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 #include extern "C" JNIEXPORT jstring JNICALLJava_com_example_nativecodelearn_MainActivity_stringFromJNI( JNIEnv *env, jobject , 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就可以了
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");//查询构造函数的idjmethodID jcmid = env->GetMethodID(clz, "" , "()V");//创建对象jobject jobject = env->NewObject(clz, jcmid);//获取方法idjmethodID 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);
这样我们就展示了互相传参与互相返回的使用方法与使用方式。希望这个博客可以帮到你。
来源地址:https://blog.csdn.net/qq_52380836/article/details/132564192
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341