2011-12-16 9 views
10

Chcę wywołać Java API z wątku NDK C++, ale env-> FindClass() zwraca 0. Ale kiedy wywołuję Java API w głównym wątku, działa dobrze. Już wezwałem AttachCurrentThread() w wątku, czy ktoś może mi pomóc?Jak wywołać API Java z wątku NDK C++?

Oto kod źródłowy: KOD

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++ KOD:

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); 
} 

Odpowiedz

5

mam rozwiązać go teraz. W natywnym wątku NDK można wywoływać tylko statyczne interfejsy API języka Java. Jeśli wywołasz env-> FindClass(), wywołałoby to wyjątek. http://android.wooyd.org/JNIExample podał szczegółowe informacje.

0

Zaproponuj, aby rzucić okiem na AttachCurrentThread.

Oto przykładowy kod, aby to zrobić:

// 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__); 
} 
Powiązane problemy