2011-12-16 18 views
10

私はNDK C++スレッドからJava APIを呼び出したいが、env-> FindClass()は0を返す。しかし、メインスレッドでJava APIを呼び出すとうまくいく。私はすでにスレッドでAttachCurrentThread()を呼びましたが、誰でも助けてくれますか?NDK C++スレッドからJava APIを呼び出す方法は?

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

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

答えて

5

私は今、それを解決した。ここ

は、ソースコードです。 NDKネイティブスレッドでは、静的Java APIのみを呼び出すことができます。 env-> FindClass()を呼び出すと、例外が発生します。 http://android.wooyd.org/JNIExample詳細情報を取得しました。

0

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__); 
} 
関連する問題