2012-09-10 51 views
1

我試圖從c> java調用來打開URL(即啓動Web瀏覽器)。我有在java中的代碼啓動URL(這是我的主要活動的一種方法)。當我在同一個線程上進行調用時,它正在工作,但是,因爲我已經從另一個線程調用了它,所以它已經中斷了。在不同線程調用c> java

我收到以下錯誤:http://pastie.org/4696174

09-10 15:59:49.405: W/dalvikvm(31430): JNI WARNING: threadid=11 using env from threadid=1 
09-10 15:59:49.405: E/dalvikvm(31430): JNI ERROR: env->self != thread-self (0x12988 vs. 0x200fb0); auto-correcting 
09-10 15:59:49.405: W/dalvikvm(31430): JNI WARNING: threadid=11 using env from threadid=1 
09-10 15:59:49.405: W/dalvikvm(31430): JNI WARNING: 0x41578910 is not a valid JNI reference 
09-10 15:59:49.405: W/dalvikvm(31430):    in Lcom/mrqwak/app/AppRenderer;.onDrawFrameN:()V (CallVoidMethodV) 
09-10 15:59:49.415: I/dalvikvm(31430): "GLThread 876" prio=5 tid=11 RUNNABLE 
09-10 15:59:49.415: I/dalvikvm(31430): | group="main" sCount=0 dsCount=0 obj=0x4157b270 self=0x200fb0 
09-10 15:59:49.415: I/dalvikvm(31430): | sysTid=31443 nice=0 sched=0/0 cgrp=default handle=1986128 
09-10 15:59:49.420: I/dalvikvm(31430): | schedstat=(1035202257 457143963 4029) utm=80 stm=23 core=0 
09-10 15:59:49.420: I/dalvikvm(31430): at com.mrqwak.app.AppRenderer.onDrawFrameN(Native Method) 
09-10 15:59:49.420: I/dalvikvm(31430): at com.mrqwak.app.AppRenderer.onDrawFrame(AppActivity.java:289) 
09-10 15:59:49.425: I/dalvikvm(31430): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1462) 
09-10 15:59:49.425: I/dalvikvm(31430): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216) 
09-10 15:59:49.425: E/dalvikvm(31430): VM aborting 
09-10 15:59:49.430: A/libc(31430): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1) 

這裏是我的C代碼:http://pastie.org/4696207

我稱之爲從C> Java中,對主UI線程,如創建主要活動:

JNIEnv*  g_envApp   = 0; 
jobject  g_objApp   = 0; 
jclass  g_classApp   = 0; 
jmethodID g_methodOpenURL  = 0; 

JNIEXPORT void JNICALL Java_com_mrqwak_app_AppActivity_onCreateN(JNIEnv *env, jobject obj) 
{ 
    g_envApp = env; 
    g_objApp = obj; 
    g_classApp = env->GetObjectClass(obj); 
    if (g_classApp) 
    { 
     g_methodOpenURL = env->GetMethodID(g_classApp,"openURL","(Ljava/lang/String;)V"); 
    } 
} 

我稍後從c> java調用此函數,而不是在主UI上,當用戶按下按鈕打開一個url時:

extern JNIEnv*  g_envApp; 
extern jobject  g_objApp; 
extern jclass  g_classApp; 
extern jmethodID g_methodOpenURL; 

void cHTTP::OpenURL(const char* psURL) 
{ 
    if (g_methodOpenURL) 
    { 
     jstring jstr = g_envApp->NewStringUTF(psURL); 
     g_envApp->CallVoidMethod(g_objApp,g_methodOpenURL,jstr); 
    } 
} 

感謝,

+0

在Wikipedea:甲JNI接口指針(JNIEnv的*)作爲映射到用於每個本地函數參數傳遞Java方法,允許與本地方法內的JNI環境進行交互。這個JNI接口指針可以被存儲,但只在當前線程中保持有效。其他線程必須先調用AttachCurrentThread()將自己附加到VM並獲得一個JNI接口指針...所以我相信我需要在C中AttachCurrentThread? – cosmic4z

回答

1

我相信你需要連接到UI線程 - jobjects沒有在線程之間共享,能 - 這是這個效果:

JNIEnv *env; 
jvm->AttachCurrentThread(&env, 0); 
jmethodID mid = env->GetMethodID(g_classApp, "openURL", "(Ljava/lang/string)V"); 
env->CallVoidMethod(g_objApp, mid, url); 

而在你的第一個電話到JNI,在這裏設置這些其他變量,添加一個JVM對象:

JavaVM *jvm; 
... 
env->GetJavaVM(&jvm); 
+0

謝謝JRaymond。只需要弄清楚如何獲得'jvm'? – cosmic4z

+0

剛剛看過:http://stackoverflow.com/questions/7268450/calling-java-class-member-from-native-c-c-code - 我是否需要在c中創建JNI_OnLoad?它是否被自動調用? – cosmic4z

+0

@ cosmic4z添加了一些關於JVM – JRaymond