首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从C++到java的Android JNI回调

从C++到java的Android JNI回调
EN

Stack Overflow用户
提问于 2014-11-03 00:28:55
回答 1查看 5.1K关注 0票数 2

我试图创建一个从jni到java的回调,但是当从CPP线程执行我的代码时,findClass方法返回null,但是从JNI线程(Native Thread)正确地执行相同的类路径和方法。

static JavaVM * s_Jvm;


JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
s_Jvm = vm;
return JNI_VERSION_1_4;
}


void callbackToJava() {
JNIEnv *env;

res = s_Jvm->GetEnv((void**) &env, JNI_VERSION_1_4);
        LOGI("status:%d",res);
        if(res < 0) {
                LOGI("callback_handler: failed to get JNI environment, "
                     "assuming native thread");
                res = s_Jvm->AttachCurrentThreadAsDaemon(&env, NULL);
                LOGI("res:%d",res);
                if(res == JNI_OK) {
                    LOGI("JNI_ok");
                }
                if(res < 0) {
                    LOGI("callback_handler: failed to attach "
                         "current thread");
                    return;
                }
            }

if (res < 0) {
         LOGI("Can't create Java VM\n");
         return;
     }
     cls = (env)->FindClass("com/test/controller/NativeTest");
     if (cls == NULL) {
         LOGI("Class is null"); //**Error Line**
         goto destroy;
     }

     mid = (env)->GetStaticMethodID(cls, "display",
                                     "()V");
     if (mid == NULL) {
         LOGI("Mid is null");
         goto destroy;
     }

(env)->CallStaticVoidMethod(cls, mid, "()V");

 destroy:
     if ((env)->ExceptionOccurred()) {
         (env)->ExceptionDescribe();
     }
     (jvm)->DestroyJavaVM();

}

EN

回答 1

Stack Overflow用户

发布于 2018-07-30 01:48:54

我更喜欢在jni线程中创建一个函数,然后从cpp代码的其他线程调用它。请参见示例项目https://github.com/NickZt/MyJNACallbackTest将每个侦听器保存到动态数组中

env->GetJavaVM(& jvm );//存储jvm引用供以后调用

store_env = env;

jweak store_Wlistener = env->NewWeakGlobalRef(listener);
jclass clazz = env->GetObjectClass(store_Wlistener);

jmethodID store_method = env->GetMethodID(clazz, "onAcceptMessage", "(Ljava/lang/String;)V");
jmethodID store_methodVAL = env->GetMethodID(clazz, "onAcceptMessageVal", "(I)V");

ObserverChain *tmpt = new ObserverChain(store_Wlistener, store_method, store_methodVAL);

store_Wlistener_vector.push_back(tmpt);

使用函数test_string_callback_fom_c(char *val)从C++代码回调存储的侦听器

void test_string_callback_fom_c(char *val) {
    __android_log_print(ANDROID_LOG_VERBOSE, "GetEnv:", " start Callback  to JNL [%d]  \n", val);
    JNIEnv *g_env;
    if (NULL == jvm) {
        __android_log_print(ANDROID_LOG_ERROR, "GetEnv:", "  No VM  \n");
        return;
    }
    //  double check it's all ok
    JavaVMAttachArgs args;
    args.version = JNI_VERSION_1_6; // set your JNI version
    args.name = NULL; // you might want to give the java thread a name
    args.group = NULL; // you might want to assign the java thread to a ThreadGroup

    int getEnvStat = jvm->GetEnv((void **) &g_env, JNI_VERSION_1_6);

    if (getEnvStat == JNI_EDETACHED) {
        __android_log_print(ANDROID_LOG_ERROR, "GetEnv:", " not attached\n");
        if (jvm->AttachCurrentThread(&g_env, &args) != 0) {
            __android_log_print(ANDROID_LOG_ERROR, "GetEnv:", " Failed to attach\n");
        }
    } else if (getEnvStat == JNI_OK) {
        __android_log_print(ANDROID_LOG_VERBOSE, "GetEnv:", " JNI_OK\n");
    } else if (getEnvStat == JNI_EVERSION) {
        __android_log_print(ANDROID_LOG_ERROR, "GetEnv:", " version not supported\n");
    }

    jstring message = g_env->NewStringUTF(val);//

    txtCallback(g_env, message);

    if (g_env->ExceptionCheck()) {
        g_env->ExceptionDescribe();
    }

    if (getEnvStat == JNI_EDETACHED) {
        jvm->DetachCurrentThread();
    }
}

extern "C"
JNIEXPORT void JNICALL
Java_ua_zt_mezon_myjnacallbacktest_MainActivity_nonNextListener(JNIEnv *env, jobject instance,
                                                                jstring message_) {


    txtCallback(env, message_);

}

void txtCallback(JNIEnv *env, const _jstring *message_) {
    if (!store_Wlistener_vector.empty()) {
        for (int i = 0; i < store_Wlistener_vector.size(); i++) {
            env->CallVoidMethod(store_Wlistener_vector[i]->store_Wlistener,
                                store_Wlistener_vector[i]->store_method, message_);
        }

或从java代码中使用nonNextListener方法向监听器发送消息

https://dou.ua/lenta/articles/android-jni-callbacks中的完整解释

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26701605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档