如何从NDK C ++线程调用Java API?

我想从NDK C ++线程调用Java API,但env-> FindClass()返回0.但是,当我在主线程中调用Java API时,它运行良好。 我已经在线程中调用了AttachCurrentThread(),任何人都可以帮助我吗?

这里是源代码:

JAVA代码:

public class simple_test extends Activity { ... // This functin will be called in C++ public void PrintNdkLog(String slog) { Log.e(logTagNDK, slog); return; } } 

C ++代码:

 static JavaVM* g_JavaVM = NULL; jobject getInstance(JNIEnv *env, jclass obj_class) { jmethodID c_id = env->GetMethodID(obj_class, "<init>", "()V"); jobject obj = env->NewObject(obj_class, c_id); return obj; } // JNI OnLoad JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { g_JavaVM = jvm; return JNI_VERSION_1_6; } // Call JAVA API "PrintNdkLog" in this function void PrintNdkLog(char *lpLog) { if (g_JavaVM == NULL) return; JNIEnv *env = NULL; g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6); if (env == NULL) return; jclass cls = env->FindClass("com/myndk/simple_test"); if (cls != 0) // **cls will be 0 when PrintNdkLog() is called in thread** { LOGE("FindClass error %p", cls); } else { jmethodID mid; jobject obj; obj = getInstance(env, cls); mid = env->GetMethodID(cls, "PrintNdkLog", "(Ljava/lang/String;)V"); if (mid != 0) { jstring jstrMSG = env->NewStringUTF(lpLog); env->CallVoidMethod(obj, mid, jstrMSG); } } } // Call JAVA API in thread static void* thread_test(void* ptr) { JNIEnv *envLocal; int status = g_JavaVM->GetEnv((void **) &envLocal, JNI_VERSION_1_6); if (status == JNI_EDETACHED) { status = g_JavaVM->AttachCurrentThread(&envLocal, NULL); if (status != JNI_OK) LOGE("AttachCurrentThread failed %d",status); } PrintNdkLog("bbb"); // This JAVA callback failed, and printed "FindClass error" } // Create thread int NdkThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority) { PrintNdkLog("aaa"); // This JAVA callback runs well pthread_t pid; pthread_create(&pid, NULL, thread_test, pParam); } 

Solutions Collecting From Web of "如何从NDK C ++线程调用Java API?"

我现在已经解决了。 在NDK本地线程中,只能调用静态Java API。 如果你调用env-> FindClass(),它会触发一个exception。 http://android.wooyd.org/JNIExample给出详细信息&#x3002;

build议看看AttachCurrentThread 。

这里是一个示例代码来做到这一点:

 // Global variable JavaVM *g_jvm = NULL; //Get g_jvm from jni main thread use env->GetJavaVM(&g_jvm); jobject g_obj = NULL; //Where the java function exist. (some activity) //Get env in thread function and attach the env JNIEnv *env; if(g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGD("%s: AttachCurrentThread() failed", __FUNCTION__); } const char * fnName ="somFunctionInYourJava"; //which should be "pulic void somFunctionInYourJava(String input);" jstring retStr = env->NewStringUTF(str); jclass cls = env->GetObjectClass(thiz); jmethodID messageMe = env->GetMethodID(cls, fnName, "(Ljava/lang/String;)V"); env->CallVoidMethod(thiz, messageMe, retStr); //Detach thread and release related resource if(g_jvm->DetachCurrentThread() != JNI_OK) { LOGD("%s: DetachCurrentThread() failed", __FUNCTION__); }