Escribo una aplicación OpenGL C/C++ que estoy migrando a Android a través de Android NDK, soporte JNI. Tengo dificultades para ejecutar el código de devolución de llamada de JAVA desde el origen.Llamando al miembro de la clase JAVA desde el código nativo C/C++
Aquí está el código:
class OpenGLSurfaceView extends GLSurfaceView
{
…
public OpenGLSurfaceView(Context context, int deviceWidth, int deviceHeight)
{
super(context);
nativeObj = new NativeLib();
mRenderer = new OpenGLRenderer(context, nativeObj, deviceWidth, deviceHeight);
setRenderer(mRenderer);
setRenderMode(RENDERMODE_WHEN_DIRTY);
}
…
private void CallBack()
{
// force redraw
requestRender();
}
}
class OpenGLRenderer implements GLSurfaceView.Renderer
{
…
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
nativeObj.init(…);
nativeObj.cachejavaobject(JNIEnv *env, jobject obj); // for caching obj on native side
}
public void onSurfaceChanged(GL10 gl, int w, int h)
{
}
public void onDrawFrame(GL10 gl)
{
nativeObj.draw(…);
}
}
Y en código nativo Tengo una función texturesLoaded() que se señala cuando algunas texturas se cargan por completo en otro hilo y tengo que forzar una actualización de nativeLib.draw (...) en el lado de JAVA. Así es como lo hago:
cacheamos la JavaVM, JClass, jMethodID en JNI_OnLoad y gJObjectCached
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
gJVM = jvm; // cache the JavaVM pointer
LogNativeToAndroidExt("JNILOAD!!!!!!!!!!");
JNIEnv *env;
int status = gJVM->GetEnv((void **)&env, JNI_VERSION_1_6);
if(status < 0)
{
LogNativeToAndroidExt("Failed to get JNI environment, assuming native thread");
status = gJVM->AttachCurrentThread(&env, NULL);
if(status < 0)
{
LogNativeToAndroidExt("callback_handler: failed to attach current thread");
return JNI_ERR;
}
}
gJClass = env->FindClass("com/android/newlineactivity/NewLineGLSurfaceView");
if(gJClass == NULL)
{
LogNativeToAndroidExt("Can't find Java class.");
return JNI_ERR;
}
gJMethodID = env->GetMethodID(gJClass, "callback", "()V");
if(gJMethodID == NULL)
{
LogNativeToAndroidExt("Can't find Java method void callback()");
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
JNIEXPORT void Java_com_android_OpenGL_NativeLib_cachejavaobject(JNIEnv* env, jobject obj)
{
// cache the java object
gJObjectCached = obj;
...
}
y luego en texturesLoaded() Yo:
void texturesLoaded()
{
// Cannot share a JNIEnv between threads. You should share the JavaVM, and use JavaVM->GetEnv to discover the thread's JNIEnv
JNIEnv *env = NULL;
int status = gJVM->GetEnv((void **)&env, JNI_VERSION_1_6);
if(status < 0)
{
LogNativeToAndroidExt("callback_handler: failed to get JNI environment, assuming native thread");
status = gJVM->AttachCurrentThread(&env, NULL);
if(status < 0)
{
LogNativeToAndroidExt("callback_handler: failed to attach current thread");
return;
}
}
LogNativeToAndroidExt("Calling JAVA method from NATIVE C/C++");
env->CallVoidMethod(gJObjectCached, gJMethodID);
LogNativeToAndroidExt("DONE!!!");
}
Resultado ... del lado nativo obtengo la clase, obtengo el método, se llama al método, pero cuando alcanza/cal ls requestRender() dentro (o tratando de acceder a cualquier otro método miembro de GLSurfaceView se bloquea!)
No puedo probar con CallStaticVoidMethod (gJClass, gjMethodID); porque entonces no tengo acceso a requestRender();
Cualquier idea u opinión, tal vez estoy haciendo algo mal aquí.
Gracias
'requestRender()' es en Java, por lo que los accidentes suelen ir acompañados de una excepción. ¿Podría mencionar cuál es esa excepción? Los registros de ADB de Android deberían revelar dicha información. Vaya [Aquí] (http://developer.android.com/guide/developing/debugging/debugging-log.html) para obtener información sobre los registros – Warpspace