设为首页 加入收藏

TOP

Android NDK 线程回调Java层方法
2015-02-03 22:27:40 来源: 作者: 【 】 浏览:29
Tags:Android NDK 线程 Java 方法

static JavaVM* s_jVM = NULL;
static jobject s_jobj = NULL; //java object
static jmethodID s_jcallback = NULL; //方法id


static void NotifyDataCB(unsigned char flag, int x, int y, int w, int h, unsigned char* buff, mp_i64 timeStamp)
{
?//LOG_DBG("[NotifyDataCB()] enter.");
?JNIEnv* env;


?s_jVM->AttachCurrentThread(&env, NULL);?//获取当前线程的JNIEnv*


?env->CallVoidMethod(s_jobj, s_jcallback, ...); //调用java层相关方法


?s_jVM->DetachCurrentThread();?//释放当前线程的JNIEnv*


?//LOG_DBG("[NotifyDataCB()] done.");
?return;
}


此处的重点即为:


jint AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args);


Attaches the current thread to a Java VM. Returns a JNI interface pointer in the JNIEnv argument.


其中s_jVM是由JNI_OnLoad方法保存而来的;


s_jobj在自定义的jni方法里赋值,并创建了个全局引用,使其不被虚拟机释放


s_jobj = env->NewGlobalRef(thiz); //thiz为jni方法的参数,表示java层的类对象


该s_jobj需要手动释放:


env->DeleteGlobalRef(s_jobj);


s_jcallback也是在自定义的jni方法调用以下方法保存而来:


static jmethodID GetClassMethodID(JNIEnv* env)
{
?jclass clazz = env->FindClass(classPathName); //classPathName完整的包名加类名
?if (clazz == NULL)
?{
? LOG_ERR("[GetClassMethod()]Failed to find jclass");
? return NULL;?
?}



?jmethodID jcallback = env->GetMethodID(clazz, "OnNativeDataCB", "(BIIII[IJ)V"); //获取java层方法id
?if (jcallback == NULL)
?{
? LOG_ERR("[GetClassMethod()]Failed to find method OnNativeDataCB");
? return NULL;?
?}
?
?return jcallback; //返回保存为s_jcallback
}


综上所述,关键步骤为:
1. 在onload的时候保存JavaVM指针。
2. 在自定义jni方法里(该方法须在callback方法使用前调用,例如初始化方法)保存callback方法所在对象,且该对象需要创建一个全局引用以便在线程方法里使用,默认是local ref,函数执行完会被虚拟机释放;另外自定义jni方法和callback方法在同一个类里,所以在调用自定义方法时能保存一致的jobject? 。
3. 也是在自定义jni方法中,通过class获得该callback的method ID。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Spring事务管理默认只对Unchecked.. 下一篇编译安装FFmpeg 要支持xvid、x264..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: