JniHelper详细说明

JniHelper详细说明,第1张

概述1.Jni的介绍 先简单介绍一下,Jni简称(Java Native Interface)Java原生接口,在Java里面用Native修饰的方法由另外一种语言实现的本地方法,意思就是说,这个用native修饰的方法在Java里面只能看到声明看不到定义。 再简单来说,这个Jni的作用就是Java和其他语言的交互,其他语言可以调用Java相关环境,Java也可以用Jni技术来调用其他语言来弥补自身的 1.Jni的介绍 先简单介绍一下,Jni简称(Java Native Interface)Java原生接口,在Java里面用Native修饰的方法由另外一种语言实现的本地方法,意思就是说,这个用native修饰的方法在Java里面只能看到声明看不到定义。 再简单来说,这个Jni的作用就是Java和其他语言的交互,其他语言可以调用Java相关环境,Java也可以用Jni技术来调用其他语言来弥补自身的不足,例如访问系统底层,嘿嘿。 下面这张图介绍了JNI的基本结构描述图:

2.在C++中调用Java方法 c++调用java需要获取java的运行环境和JVM。 JVM:是java虚拟机,所有的交互工作都是从获取jvm开始的,获取JVM的时候需要注意下面,就是要告知系统使用哪一版本的JNI不规定的话默认使用1.1版本。最好是使用新版本JNI_VERSION_1_4,就是1.4版本。
    JavaVM* JniHelper::_psJavaVM = nullptr;    jmethodID JniHelper::loadclassMethod_methodID = nullptr;    jobject JniHelper::classloader = nullptr;    JavaVM* JniHelper::getJavaVM() {        pthread_t thisthread = pthread_self();        LOGD("JniHelper::getJavaVM(),pthread_self() = %ld",thisthread);        return _psJavaVM;    }    voID JniHelper::setJavaVM(JavaVM *javaVM) {        pthread_t thisthread = pthread_self();        LOGD("JniHelper::setJavaVM(%p),javaVM,thisthread);        _psJavaVM = javaVM;        pthread_key_create(&g_key,_detachCurrentThread);    }
这上面的代码是Cocos里面封装好的JniHelper里面的获取JVM的一些相关 *** 作,
voID _detachCurrentThread(voID* a) {    cocos2d::JniHelper::getJavaVM()->DetachCurrentThread();}

这个方法要Detach以下当前线程。 然后及时获取环境了,我把里面的代码都贴出来
#include "JniHelper.h"#include <androID/log.h>#include <string.h>#include <pthread.h>#define  LOG_TAG    "JniHelper"#define  LOGD(...)  __androID_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)#define  LOGE(...)  __androID_log_print(ANDROID_LOG_ERROR,__VA_ARGS__)static pthread_key_t g_key;//用于声明线程IDjclass _getClassID(const char *classname) {//获取类ID    if (nullptr == classname) {        return nullptr;    }    jnienv* env = cocos2d::JniHelper::getEnv();//环境变量    Jstring _JstrClassname = env->NewStringUTF(classname);//需要调用java的类名    jclass _clazz = (jclass) env->CallObjectMethod(cocos2d::JniHelper::classloader,cocos2d::JniHelper::loadclassMethod_methodID,_JstrClassname);    if (nullptr == _clazz) {        LOGE("Classloader Failed to find class of %s",classname);        env->ExceptionClear();    }    env->DeleteLocalRef(_JstrClassname);            return _clazz;}voID _detachCurrentThread(voID* a) {    cocos2d::JniHelper::getJavaVM()->DetachCurrentThread();//撤销当前线程}namespace cocos2d {    JavaVM* JniHelper::_psJavaVM = nullptr;    jmethodID JniHelper::loadclassMethod_methodID = nullptr;    jobject JniHelper::classloader = nullptr;    JavaVM* JniHelper::getJavaVM() {        pthread_t thisthread = pthread_self();        LOGD("JniHelper::getJavaVM(),thisthread);        return _psJavaVM;    }    voID JniHelper::setJavaVM(JavaVM *javaVM) {        pthread_t thisthread = pthread_self();//是获得线程自身的ID        LOGD("JniHelper::setJavaVM(%p),_detachCurrentThread);    }    jnienv* JniHelper::cacheEnv(JavaVM* jvm) {        jnienv* _env = nullptr;        // get jni environment        jint ret = jvm->GetEnv((voID**)&_env,JNI_VERSION_1_4);//获取1.4的Jni环境                switch (ret) {        case JNI_OK :            // Success!            pthread_setspecific(g_key,_env);            return _env;                        case JNI_EDETACHED :            // Thread not attached            if (jvm->AttachCurrentThread(&_env,nullptr) < 0)                {                    LOGE("Failed to get the environment using AttachCurrentThread()");                    return nullptr;                } else {                // Success : Attached and obtained jnienv!                pthread_setspecific(g_key,_env);                return _env;            }                        case JNI_EVERSION :            // Cannot recover from this error            LOGE("JNI interface version 1.4 not supported");        default :            LOGE("Failed to get the environment using GetEnv()");            return nullptr;        }    }    jnienv* JniHelper::getEnv() {        jnienv *_env = (jnienv *)pthread_getspecific(g_key);        if (_env == nullptr)            _env = JniHelper::cacheEnv(_psJavaVM);        return _env;    }    bool JniHelper::setClassLoaderFrom(jobject activityinstance) {        JniMethodInfo _getclassloaderMethod;        if (!JniHelper::getmethodInfo_DefaultClassLoader(_getclassloaderMethod,"androID/content/Context","getClassLoader","()Ljava/lang/ClassLoader;")) {            return false;        }        jobject _c = cocos2d::JniHelper::getEnv()->CallObjectMethod(activityinstance,_getclassloaderMethod.methodID);        if (nullptr == _c) {            return false;        }        JniMethodInfo _m;        if (!JniHelper::getmethodInfo_DefaultClassLoader(_m,"java/lang/ClassLoader","loadClass","(Ljava/lang/String;)Ljava/lang/Class;")) {            return false;        }        JniHelper::classloader = cocos2d::JniHelper::getEnv()->NewGlobalRef(_c);        JniHelper::loadclassMethod_methodID = _m.methodID;        return true;    }    bool JniHelper::getStaticmethodInfo(JniMethodInfo &methodinfo,//下面重点说一下这个函数                                        const char *classname,const char *methodname,const char *paramCode) {        if ((nullptr == classname) ||            (nullptr == methodname) ||            (nullptr == paramCode)) {            return false;        }        jnienv *env = JniHelper::getEnv();        if (!env) {            LOGE("Failed to get jnienv");            return false;        }                    jclass classID = _getClassID(classname);        if (! classID) {            LOGE("Failed to find class %s",classname);            env->ExceptionClear();            return false;        }        jmethodID methodID = env->GetStaticmethodID(classID,methodname,paramCode);        if (! methodID) {            LOGE("Failed to find static method ID of %s",methodname);            env->ExceptionClear();            return false;        }                    methodinfo.classID = classID;        methodinfo.env = env;        methodinfo.methodID = methodID;        return true;    }    bool JniHelper::getmethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo,const char *classname,const char *paramCode) {        if ((nullptr == classname) ||            (nullptr == methodname) ||            (nullptr == paramCode)) {            return false;        }        jnienv *env = JniHelper::getEnv();        if (!env) {            return false;        }        jclass classID = env->FindClass(classname);        if (! classID) {            LOGE("Failed to find class %s",classname);            env->ExceptionClear();            return false;        }        jmethodID methodID = env->getmethodID(classID,paramCode);        if (! methodID) {            LOGE("Failed to find method ID of %s",methodname);            env->ExceptionClear();            return false;        }        methodinfo.classID = classID;        methodinfo.env = env;        methodinfo.methodID = methodID;        return true;    }    bool JniHelper::getmethodInfo(JniMethodInfo &methodinfo,const char *paramCode) {        if ((nullptr == classname) ||            (nullptr == methodname) ||            (nullptr == paramCode)) {            return false;        }        jnienv *env = JniHelper::getEnv();        if (!env) {            return false;        }        jclass classID = _getClassID(classname);        if (! classID) {            LOGE("Failed to find class %s",methodname);            env->ExceptionClear();            return false;        }        methodinfo.classID = classID;        methodinfo.env = env;        methodinfo.methodID = methodID;        return true;    }    std::string JniHelper::Jstring2string(Jstring Jstr) {        if (Jstr == nullptr) {            return "";        }                jnienv *env = JniHelper::getEnv();        if (!env) {            return nullptr;        }        const char* chars = env->GetStringUTFChars(Jstr,nullptr);        std::string ret(chars);        env->ReleaseStringUTFChars(Jstr,chars);        return ret;    }} //namespace cocos2d

这里面实现了在C++方面获取到Java的虚拟机,还有java运行环境,还有需要调用的类名等,上面的getStaticmethodInfo方法用来判断Java的类静态函数是否存在,并且初始化info。下面介绍一下参数 JniMethodInfo &methodinfo
const char *classname
const char *methodname
const char *paramCode
这里重点说明一下这些参数的作用, methodinfo:是一个结构体参数,jnienv*和java.lang.class对象、函数ID。 这样就可以使用jnienv*调用 CallStaticXXXMethod(jclass clazz,jmethodID methodID,…)和 CallXXXMethod(jobject obj,…)等常用函数(XXX替换为函数返回值类型,如:VoID,Int等)。 classname:这是你需要调用的函数所在的类。 methodname:这个是方法名,就是你想调用的方法。 paramCode:这是参数签名,因为java是支持多态的,如果不加这个参数,java无法判断到具体函数。 有关签名类型可以参考一下说明:

如果一切正常这个getStaticmethodInfo会返回真,并且初始化info结构体,现在和java交互的工作就已经完成的差不多了,下面就是我们需要用info这个结构体要做的一些事情了: 这里要贴这个结构体的有关信息
typedef struct JniMethodInfo_{    jnienv *    env;    jclass      classID;    jmethodID   methodID;} JniMethodInfo;


Oracle上面有关jni的文档,走你
下面我把info的代码贴出来。
bool isHave = JniHelper::getStaticmethodInfo(minfo,JAVA_CLASSname,"LoginWX","(Ljava/lang/String;Ljava/lang/String;)V");		if (isHave)		{			Jstring jAPP_ID = minfo.env->NewStringUTF(APP_ID);										 			Jstring jAppSecret = minfo.env->NewStringUTF(AppSecret);			minfo.env->CallStaticVoIDMethod(minfo.classID,minfo.methodID,jAPP_ID,jAppSecret);			minfo.env->DeleteLocalRef(jAPP_ID);			minfo.env->DeleteLocalRef(jAppSecret);			minfo.env->DeleteLocalRef(minfo.classID); 			cocos2d::log("JniFun call LoginWX over!");		}		else		{			//NoticeMsg::Instance().Showlogon(false);			cocos2d::log("JniFun call LoginWX error!");		}


上面再C++这方面就调用了Java里面的有关微信登录的函数。 这里就先这样吧,简简单单说了一下Jni的作用,后面更详细的内容深入了解之后再做记录,就这样。 QQ:763949771,有问题加我QQ深入交流一下,备注:csdn 总结

以上是内存溢出为你收集整理的JniHelper详细说明全部内容,希望文章能够帮你解决JniHelper详细说明所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1082674.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存