NDK-CMAKE

C++全局调用Java方法

2019-01-04  本文已影响12人  张俊峰0613

C++主线程调用Java方法

主要步骤

jclass clz = env->GetObjectClass(jobj);
jmethodid  jmid = 
        env->GetMethodID(clz, "onError", "(ILjava/lang/String;)V")
jenv->CallVoidMethod(jobj, jmid, code, jmsg)

C++子线程调用Java方法

在子线程中调用java方法却不能采用在主线程中调用的方式,因为调用java方法是要用JNIEnv去调用的,但是JNIEnv是线程相关的,子线程中不能直接使用创建线程的JNIEnv,所以需要JVM进程相关的,可以通过JVM来获取当前线程的JNIEnv,然后就可以调用java方法了。

主要步骤

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
JNIEnv *env;
jvm->AttachCurrentThread(&env,0);//拿到env
/**
 * Call Java Method
 */
jvm->DetachCurrentThread(); 

示例

JavaListener.h

class JavaListener {

public:
    JavaVM *jvm;
    jobject jobj;//类的对象
    _JNIEnv *jenv;
    jmethodID jmid;
public:
    JavaListener(JavaVM *vm,_JNIEnv *env,jobject obj);
    ~JavaListener();

    /**
     * threadType:
     *      1-主线程
     *      0-子线程
     */
    void onError(int threadType,int code, const char *msg);
};

JavaListener.cpp

/**
 * 构造方法,做初始化
 */
JavaListener::JavaListener(JavaVM *vm, _JNIEnv *env, jobject obj) {
    jvm = vm;
    jobj = obj;
    jenv = env;
    jclass clazz = env->GetObjectClass(jobj);
    if (!clazz) {
        return ;
    }
    jmid =  env->GetMethodID(clazz,"onError","(ILjava/lang/String;)V");
}


void JavaListener::onError(int threadType, int code, const char *msg) {
    if (threadType == 1){//
        jstring jmsg = jenv->NewStringUTF(msg);
        jenv->CallVoidMethod(jobj,jmid,code,jmsg);
        jenv->DeleteLocalRef(jmsg);
    } else {
        JNIEnv *env;
        jvm->AttachCurrentThread(&env,0);//拿到env

        jstring jmsg = env->NewStringUTF(msg);
        env->CallVoidMethod(jobj,jmid,code,jmsg);
        env->DeleteLocalRef(jmsg);

        jvm->DetachCurrentThread();
    }
}

源码地址:https://github.com/Xiaoben336/JniThread.git

上一篇 下一篇

猜你喜欢

热点阅读