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);
/* 回调函数类构造函数ID和对象的获取 */
constructID=env->GetMethodID(clazz,"","()V");
/* 得到回调函数类的对象tempObject以供调用CallVoidMethod*/
tempObject=env->NewObject(clazz,constructID);
/* 参数类类构造函数ID和对象的获取 */
paraID=env->GetMethodID(paraclazz,"","()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();/*释放线程*/
}
PARAMETER结构体很简单,就一个数据,u32 matchStatus.可以根据需求对结构体进行添加,相应的对应的数据类也要进行添加相应的成员变量。
通过注册函数(这个注册函数需要开放接口给java层调用???)将jni中的该回调函数指针赋值给特定的函数指针,则在特定的需求底下可以向java层传递包含有数据信息的类
xxx/xxx/xxxx/xxxxPARA
在回调函数类中实现对应的回调方法,可提取相应的数据信息。