I have a GLSurfaceView created in a JAR file within my Android app. In the GLSurfaceView callback for onDrawFrame, I call a native C++ method via JNI. At this point, I believe I am in the GLThread, and in that native method, I am trying to call back into a Java class in my App's namespace and NOT into the namespace which made the call. So, I am trying to explicitly attach to the UI thread before doing so, but I am not successful.
I am receiving the following error
W/dalvikvm( 4243): JNI WARNING: can't call Lcom/main/myapp;.updateView on instance of Lorg/myorg/myRenderer;
W/dalvikvm( 4243): in Lorg/myorg/ImageRenderer;.renderImageFrame:()V (CallVoidMethodV)
I/dalvikvm( 4243): "GLThread 336" prio=5 tid=16 RUNNABLE
I/dalvikvm( 4243): | group="main" sCount=0 dsCount=0 obj=0x418029f8 self=0x400988a8
I/dalvikvm( 4243): | sysTid=4268 nice=0 sched=0/0 cgrp=apps handle=1362099424
I/dalvikvm( 4243): | schedstat=( 0 0 0 ) utm=83 stm=71 core=1
I/dalvikvm( 4243): at org.myorg.ImageRenderer.renderImageFrame(Native Method)
I/dalvikvm( 4243): at org.myorg.ImageRenderer.onDrawFrame(ImageRenderer.java:93)
I/dalvikvm( 4243): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
I/dalvikvm( 4243): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
My C++ code looks like :
JavaVM * jvm;
JNIEXPORT void JNICALL Java_org_myorg_ImageRenderer_renderImageFrame
(JNIEnv *env, jobject jObj) {
jvm->AttachCurrentThread(&env, 0);
jclass javaClass = env->FindClass("com/main/myapp");
if(javaClass == NULL){
LOGD("ERROR - CANNOT FIND CLASS");
}
jfloatArray viewArray = env->NewFloatArray(16);
env->SetFloatArrayRegion(viewArray, 0, 16, glmatrix.data);
jmethodID method = env->GetMethodID(javaClass, "updateView", "([F)V");
if(method == NULL){
LOGD("ERROR - CANNOT ACCESS METHOD");
}
env->CallVoidMethod(jObj, method, viewArray);
env->DeleteLocalRef(viewArray);
jvm->DetachCurrentThread();
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){
jvm = vm;
return JNI_VERSION_1_2;
}
I am trying to call back into a Java class in my App's namespace and NOT into the namespace which made the call
Yeah, that's the problem. You have looked up a methodID in class com.main.myapp
but then you are trying to invoke that methodID on the original jobject instance of org.myorg.ImageRenderer
! If you want to invoke a method from another "namespace", you have several options:
Your function is called from Java, therefore you should not call AttachCurrentThread
.
Your function receives from Java a reference to the org.myorg.myRenderer
object, of which renderImageFrame() is a native method (every native method receives Java environment env
as the first parameter, and its object reference, often denoted as thiz
, as second parameter.
If you want to call a Java method updateView() for the app
object of class com.main.myapp
, you should first obtain a reference to this object. The easiest way is to pass it as argument to your function, so now it will be declared as
JNIEXPORT void JNICALL Java_org_myorg_ImageRenderer_renderImageFrame(JNIEnv *env, jobject thiz, jobject app);
Alternatively, you may find the app
object from thiz
, if a reference to app
is a field of the org.myorg.myRenderer
, or is returend by some method of this class.
Finally, you are probably right, and calling an updateView()
method, which requires the UI thread, from a GL thread, is not a good idea. You should probably issue a post
, or send a message, or simply call runOnUIThread()
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.