Tôi đang viết một ứng dụng OpenGL C/C++ mà tôi đang chuyển sang Android thông qua hỗ trợ Android NDK, JNI. Tôi gặp khó khăn khi thực thi mã từ cuộc gọi lại JAVA được báo hiệu từ gốc.Gọi cho thành viên của lớp JAVA từ mã Native C/C++
Đây là mã:
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(…);
}
}
Và trong mã nguồn gốc tôi có một chức năng texturesLoaded() mà là báo hiệu khi một số kết cấu được nạp hoàn toàn vào thread khác và tôi cần phải buộc một refresh từ nativeLib.draw (…) Về phía JAVA. Dưới đây là làm thế nào tôi làm điều đó:
Tôi cache JavaVM, jClass, jMethodID trên JNI_OnLoad, và 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;
...
}
và sau đó trên texturesLoaded() i làm:
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!!!");
}
Kết quả… từ bên gốc tôi có được lớp, tôi nhận được phương pháp, phương pháp được gọi, nhưng khi đạt đến/cal l requestRender() bên trong (hoặc cố gắng truy cập bất kỳ phương pháp thành viên nào khác của GLSurfaceView nó bị treo!)
Tôi không thể thử với CallStaticVoidMethod (gJClass, gjMethodID); bởi vì sau đó tôi không có quyền truy cập vào requestRender();
Bất kỳ ý tưởng hoặc ý kiến nào, có thể tôi đang làm điều gì đó sai ở đây.
Cảm ơn
'requestRender() 'là trong Java, vì vậy tai nạn thường được đi kèm với một ngoại lệ. Bạn có thể đề cập đến ngoại lệ đó là gì không. Nhật ký của Android ADB sẽ tiết lộ thông tin đó. Truy cập [Here] (http://developer.android.com/guide/developing/debugging/debugging-log.html) để tìm hiểu về nhật ký – Warpspace