jni层连接了C++/C编写的库与java层应用,调用jni层的回调函数可以将底层的数值返还给java层,使应用层可以根据相应的数据信息进行相关的处理,话不多说上代码。
test.h
/* 定义回调函数的methodID */
static jmethodID callback_ID;
/* 定义回调函数函数指针*/
typedef void (*callback_t)(PARAMETER* myStruct);
typedef struct{
/*如果有多个回调函数的话可以进行添加,相应的methodID也需要添加*/
callback_t my_callback;
}CallBack_t;
test.cpp
由于回调函数中需要用到JNIEnv* env,在java层调用jni层中有相应的变量,而在jni调用java层中没有相应的参数,而且该参数是线程相关的,不同线程的不能互相调用。但是JVM是只有一个的,可以声明一个JavaVM *变量,在JNI_onLoad函数中对变量进行保存以备后用。
JavaVM *g_JavaVM;
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;
g_JavaVM=vm;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
goto fail;
}
if(env == NULL){
goto fail;
}
if (registerMethods(env) != 0) { /*方法注册函数*/
goto fail;
}
result = JNI_VERSION_1_4;
fail:
return result;
}
定义回调函数的具体实现:
static CallBack_t mCLCallBack={
native_callback,
};
native_callback的具体实现为:
#define callback_method_class "xxx/xxx/xxx/xxxCallBack"/*回调类包名*/ #define CLASS_PARAMETER "xxx/xxx/xxxx/xxxxPARA" /*参数类*/ #define CALLBACK_FUNC_NAME "xxxxx_callback" /* 回调的java中方法名*/ #define SIGN_CALLBACK "(Lxxx/xxxx/xxxx/xxxxPARA;)V" /*调用函数的签名,参数为参数类*/ void native_callback(PARAMETERS* myStruct) { int status; bool isAttached = false; JNIEnv* env = NULL; /*回调方法类*/ jclass clazz; /* 结构体对应的参数类*/ jclass paraclazz; /* 回调方法类对应的对象*/ jobject tempObject; /* 结构体参数类对应的对象*/ jobject paraObject; /* 回调方法类构造函数的methodID*/ jmethodID constructID; /* 参数类构造函数的methodID*/ jmethodID paraID; /* 参数类中对应的参数ID*/ jfieldID mStatusID; / status = g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_4); if(status < 0) { g_JavaVM->AttachCurrentThread(&env,NULL); isAttached = true; } clazz=env->FindClass(callback_method_class); paraclazz=env->FindClass(CLASS_PARAMETER); callback_ID=env->GetMethodID(clazz,CALLBACK_FUNC_NAME,SIGN_CALLBACK);
PARAMETER结构体很简单,就一个数据,u32 matchStatus.可以根据需求对结构体进行添加,相应的对应的数据类也要进行添加相应的成员变量。/* 回调函数类构造函数ID和对象的获取 */ constructID=env->GetMethodID(clazz,"<init>","()V"); /* 得到回调函数类的对象tempObject以供调用CallVoidMethod*/ tempObject=env->NewObject(clazz,constructID); /* 参数类类构造函数ID和对象的获取 */ paraID=env->GetMethodID(paraclazz,"<init>","()V"); /* 同上,获取该参数类的对象,当需要对参数类中的数据进行赋值操作时有用*/ paraObject=env->NewObject(paraclazz,paraID); /* 获取与结构体PARAMETERS对应的参数类中的int类型成员变量mStatus的jfieldID*/ mStatusID=env->GetFieldID(paraclazz,"matchStatus","I"); /* 将结构体中的数据传给参数类中的变量 */ env->SetIntField(paraObject,mStatusID,myStruct->matchStatus); /*调用回调方法,参数为一个引用jobject*/ env->CallVoidMethod(tempObject,callback_ID,paraObject); checkAndClearExceptionFromCallback(env, __FUNCTION__); if(isAttached) g_JavaVM->DetachCurrentThread();/*释放线程*/ }
通过注册函数(这个注册函数需要开放接口给java层调用???)将jni中的该回调函数指针赋值给特定的函数指针,则在特定的需求底下可以向java层传递包含有数据信息的类
在回调函数类中实现对应的回调方法,可提取相应的数据信息。xxx/xxx/xxxx/xxxxPARA