Question

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;
}
Was it helpful?

Solution

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:

  1. the method must be static so that finding a class is enough and you don't need an object
  2. the another object must be passed in the native method as a parameter
  3. the another object must be accessible as member/getter of the original object (which declared your native method) and then accessed via JNI method lookup and call

OTHER TIPS

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().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top