都知道基础很重要,那我就把基础写一下,这样显得自己记住了一样。
JniHelper ,顾名思义。就是帮助使用JNI的一个办法。他的存在就是为 让我们在游戏开发中调用Java变得更加简单。
要使用JniHelper,首先得知道它的头文件在哪 platform/android/jni/下的JniHelper.h。那先打开这个这个头文件,看看给我们提供了什么。我把cocos3.3版的这个头文件的对外接口折叠贴在这了。
【JniHelper.h】
typedef struct JniMethodInfo_ { JNIEnv * env; jclass classID; jmethodID methodID; } JniMethodInfo; public: static void setJavaVM(JavaVM *javaVM); static JavaVM* getJavaVM(); static JNIEnv* getEnv(); static bool setClassLoaderFrom(jobject activityInstance); static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode); static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode); static std::string jstring2string(jstring str); static jmethodID loadclassMethod_methodID; static jobject classloader;
首先是要给结构体,里面三个成员 第一个JNIEnv* 先知道通过他可以操作javaVm, 然后他的本质其实首先指向一个线程相关的结构,该结构又指向一个指针数组,在这个指针数组中的每个元素最终指向一个JNI函数。所以可以通过JNIEnv去调用JNI函数。这里记住就好了。而通过jclass 和jmethod 这两个结构体成员 就可以实现需要操作哪个Java类中的哪个成员方法了。
这一快说的就是如何通过这个神器调用java的静态成员函数和普通成员函数。
【静态函数的调用】
静态函数,可以说是属于这个类的,在OC上就是类方法的概念(ps,今天刚刚开始着手ios平台,看了一点)。也就是说这个方法是属于这个类的,而这个类的所有实例共享这个方法。所以访问这个方法应该是简单一点的。思路呢,首先是得到得到结构体,因为里面存着那么重要的信息。通过getStaticMethodInfo就可以得到这个参数,有了这些参数就好说了,下面看代码
void JniUCPlatform::dologout() { JniMethodInfo info;//定义结构体 jobject obj; /** * 得到info信息 * * @param info 这个是个传出参数,也就是我们需要得到的info * @param "String" 类路径 * @param "String" 静态函数名 * @param "String" 函数参数和返回值 */ if(JniHelper::getStaticMethodInfo(info,"android/ucplatform/UCPlatform","getObj","()Ljava/lang/Object;")) { obj = info.env->CallStaticObjectMethod(info.classID, info.methodID); } info.env->DeleteLocalRef(info.classID);//这个Delete一下吧。你会感谢自己的这个动作的
}
就跟上面代码一样,这样就完成了调用java层的静态函数。这个例子的函数参数是空,如果有参数的话,只按照JNI的规则来进行转换就好了。其中String操作的比较常见,类似下面的这样的配套使用,JNI文档上是有一大堆的。
jstring jRoleId = info.env->NewStringUTF(roleId);
info.env->DeleteLocalRef(jRoleId);
const char * _productid = info->GetStringUTFChars(productid, NULL);
info->ReleaseStringUTFChars(productid, _productid);
【非静态函数的调用】
非静态函数,在OC中叫实例方法,就是属于某一个实例的,只能通过一个实例访问它,那么问题也就来了,我们先要得到这个类的Object,才可以拿到这个非静态函数的使用权力。所以流程是这样的:可以写一个JAVA静态方法,这个方法是得到Objec的。然后用JniHelper调用这个函数拿到Object,再通过这个Object调用非静态函数。下面看代码
void JniUCPlatform::dologin() { JniMethodInfo info; jobject obj; if(JniHelper::getStaticMethodInfo(info,"android/ucplatform/UCPlatform","getObj","()Ljava/lang/Object;")) { obj = info.env->CallStaticObjectMethod(info.classID, info.methodID); } //这里就是调用普通函数,只要注意Call方法中的第一参数不再是classID,而是上一步得到的obj; if(JniHelper::getMethodInfo(info,"android/ucplatform/UCPlatform","login", "()V")) { info.env->CallVoidMethod(obj, info.methodID); } info.env->DeleteLocalRef(info.classID); }