JNI中C调用Java方法
背景需求
我们需要在JNI的C代码调用Java代码。实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用。
JNI关键方法讲解。
1. 在同一个类中,调用其他方法
JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod1
(JNIEnv * env, jobject obj){
//在c代码里面调用java代码里面的方法
// java 反射
//1 . 找到java代码的 class文件
// jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
if(dpclazz==){
LOGI("find class error");
return;
}
LOGI("find class "); //2 寻找class里面的方法
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
if(method1==){
LOGI("find method1 error");
return;
}
LOGI("find method1 ");
//3 .调用这个方法
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,obj,method1);
}
注意: 看红色的内容,如何获得呢? 这个是函数的签名。函数签名借住命令 javap -p -s(这两个参数一定要加入)来获得,放到第二个参数即可。

注意:
1. 要加入上面的参数 -p -s
2. signature后面有时候带“;”,不要丢掉。 主要要仔细检查
示例:
void notifyOnStatusReport(int32_t status)
{
if (curEnv != NULL && curObj != NULL) {
jclass clsstring = curEnv->FindClass("com/baidu/tieba/liveSdk/publisher/LiveNativeSender");
jfieldID mUsercommandCallbackEventListnerFieldId = curEnv->GetFieldID(clsstring,"mStatusEventListener","Lcom/baidu/tieba/liveSdk/publisher/OnStatusEventListener;");
jobject mUsercommandCallbackEventListner = curEnv->GetObjectField(curObj,mUsercommandCallbackEventListnerFieldId); jclass onStatusEventListenerClsstring = curEnv->FindClass("com/baidu/tieba/liveSdk/publisher/OnStatusEventListener");
jmethodID onStatusReport = curEnv->GetMethodID(onStatusEventListenerClsstring, "onStatusReport",
"(I)V");
curEnv->CallVoidMethod(mUsercommandCallbackEventListner, onStatusReport, status);
}
}
这样就可以调用DataProvider中的helloFromJava方法了。
2. 上面的方法是调用的返回值为void的java方法。如果想调用其他类型的。JNI中还提供的许多其他返回类型的方法。
jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
3. 如果java中的方法是静态的,就需要调用GetStaticMethodID 和 CallStaticVoidMethod 方法。
JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod4
(JNIEnv * env, jobject obj){
//1 . 找到java代码的 class文件
// jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
if(dpclazz==){
LOGI("find class error");
return;
}
LOGI("find class "); //2 寻找class里面的方法
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
// 注意 :如果要寻找的方法是静态的方法 那就不能直接去获取methodid
//jmethodID method4 = (*env)->GetMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
// jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID method4 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
if(method4==){
LOGI("find method4 error");
return;
}
LOGI("find method4 "); //3.调用一个静态的java方法
// void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
(*env)->CallStaticVoidMethod(env,dpclazz,method4,(*env)->NewStringUTF(env,"static haha in c"));
}
4. 如果C调用的Java方法不在一个类中。
分析:JNI提供的方法都有两个参数:(JNIEnv *env , jobject obj)。 env是JNI提供的方法集合。 obj是上线文。下面的例子的obj不是所需要的上下午,所以要重新创建。
//obj DemoActivity
JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DemoActivity_call_1dp_1method1
(JNIEnv * env, jobject obj){
//在c代码里面调用java代码里面的方法
// java 反射
//1 . 找到java代码的 class文件
// jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
if(dpclazz==){
LOGI("find class error");
return;
}
LOGI("find class "); //2 寻找class里面的方法
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
if(method1==){
LOGI("find method1 error");
return;
}
LOGI("find method1 ");
//3 .调用这个方法
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
// jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
// jobject (*AllocObject)(JNIEnv*, jclass);
jobject dpobj= (*env)->AllocObject(env,dpclazz); (*env)->CallVoidMethod(env,dpobj,method1);
}
5. 提示
为了避免4中的内容,我们尽量让C要调用的Java方法在同一个类中
JNI中C调用Java方法的更多相关文章
- Android JNI中C调用Java方法
背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...
- JNI C反射调用java方法
前面记录了调用C的学习笔记,现在来记录一下C反射调用Java的笔记.JNI开发学习之调用C方法 Android开发中调用一个类中没有公开的方法,可以进行反射调用,而JNI开发中C调用java的方法也是 ...
- jni中调用java方法获取当前apk的签名文件md5值
相应的java方法: void getsign(Context context) throws Exception { PackageInfo localPackageInfo = context.g ...
- HAL中通过JNI调用java方法【转】
转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...
- cocos2d-x中使用JNI的调用JAVA方法
用cocos2d-x公布Android项目时.都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface).JNI是JAVA的一个通用接口.旨在本地化 ...
- Android Studio NDK开发-JNI调用Java方法
相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需 ...
- java native interface JNI 调用Java方法
在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...
- C++调用JAVA方法详解
C++调用JAVA方法详解 博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...
- C#调用Java方法(详细实例)
C#可以直接引用C++的DLL和转换JAVA写好的程序.最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方法转换成可以由C#直接调用的DLL C#调用c++ C#调用 ...
随机推荐
- Collections.reverse 代码思考-超越昨天的自己系列(13)
点进Collections.reverse的代码瞄了眼,然后就开始了一些基础知识的收集. 现在发现知道的越多,知道不知道的越多. 列几个记录下: reverse方法源码: /** * Reverses ...
- java一行一行写入或读取数据
原文:http://www.cnblogs.com/linjiqin/archive/2011/03/23/1992250.html 假如E:/phsftp/evdokey目录下有个evdokey_2 ...
- struts2 数据校验
通过struts2中延续自xwork框架的validation.xml配置方式进行数据校验,因struts2 下存在三种请求参数的注入方式,固按照不同注入方式对validation.xml的配置进行总 ...
- Android 性能测试
写在前面: 测试一道,博主接触的也是皮毛而已,没有接触过rom的测试,下边所说的都是博主接触过的app的性能测试.我只谈方法,少提概念.各位大神不喜勿喷. 概述 除启动时间外,我们应该做的测试,可能需 ...
- iOS开发之cell多按钮
iOS开发经常出现cell需要多个按钮,一般以为要导入第三方框架.但其实iOS 8以后,系统提供了UITableViewRowAction以及新的delegate方法,使得自定义一些操作变得非常容易. ...
- 【引】runtime全解析,P2:关于Class 和 MetaClass
几个基本的概念: id,id的定义是,typedef struct objc_object { Class isa;} *id; id是指向struct objc_object的一个指针.这个意思是, ...
- 2016HUAS_ACM暑假集训4C - 递推
题目大意:给你一个高为n ,宽为m列的网格,计算出这个网格中有多少个矩形. 这里我们可以这样看: 对于行:假如是m单位长度,则长度为1的矩形有m个,长度为2的矩形有m-1个......长度为m的只有1 ...
- shiro 自动登录
1.出现的错误:did not match the expected credentials---密码不匹配,后来自己写密码验证,其实作用不大: 配置 <!-- Shiro权限过滤过滤器定义 - ...
- SQL总结系列
SQL总结系列 总结SQL基本知识.用法,并结合多年的应用对SQL有关的相关知识进行总结.希望这些分享能给大家带来一些帮助,如有不足或错误,请批评指正. 主要内容 1)编辑相关,包括:数据库的创建与删 ...
- GitLab常见使用方法
1.GitLab配置 git config --global user.name "xxx" -- 配置用户名,上传本地 repository 到服务器上的时候,在 Github ...