C/C++语言基础 –> JNI编程 –> NDK编程 –> 音视频处理 –> 图像处理等等 ,从零到一 , 零基础学习NDK开发 。学习本专题 , 你需要具备一定的Android开发知识 C/C++基础, 知道如何创建一个Android工程 , 有一定的开发经验更佳 。
本篇主要讲解JNI的一些高级写法和线程,文章内容都非常简单。
上一章讲的JNI 编程详解
Java 要调用C++的方法,都要写一大长串比如:
extern "C" JNIEXPORT void JNICALL Java_com_jnimode1_MainActivity_updateGolbal(JNIEnv *env, jobject instance, jclass jclass1)
上述相当于静态注册,而JNI_OnLoad是动态注册,两者其实没什么区别,简化了方法名让人更容易理解。
简化后
void updateGolbal(jclass cls)
下面我们看一个例子就理解了,都有注释,so easy
JavaVM *_vm; void dynamicTest() { LOGE("我是被动态注册的方法dynamicTest"); } //JNIEnv *env, jobject instance 如果传参数这两个参数必须存在 jint dynamicTest2(JNIEnv *env, jobject instance, jint i) { LOGE("我是被动态注册的方法dynamicTest2"); return i; } //静态的Jni native 方法数组 static const JNINativeMethod method[] = { //方法名 签名 本地方法 {"dynamicJavaTest", "()V", (void *) dynamicTest}, {"dynamicJavaTest2", "(I)I", (int *) dynamicTest2} }; //类名 static const char *mClassName = "com/jnimode1/MainActivity"; //返回Jni 版本 int JNI_OnLoad(JavaVM *vm, void *r) { LOGE("JNI_OnLoad"); _vm = vm; JNIEnv *env = 0; //获得JNIEnv 这里会返回一个值 小于0 代表失败 jint res = vm->GetEnv((void **) (&env), JNI_VERSION_1_6); //判断返回结果 if (res != JNI_OK) { return -1; } //根据类名找到类,注意有native的类不能被混淆 jclass jcls = env->FindClass(mClassName); //动态注册 第一个参数 类 第二个参数 方法数组 第三个参数 注册多少个方法 env->RegisterNatives(jcls, method, sizeof(method) / sizeof(JNINativeMethod)); return JNI_VERSION_1_6; }
Activity 中调用
public native void dynamicJavaTest(); public native int dynamicJavaTest2(int i);
native线程调用Java
native调用java需要使用JNIEnv这个结构体,而JNIEnv是由Jvm传入与线程相关的变量。
但是可以通过JavaVM的AttachCurrentThread方法来获取到当前线程中的JNIEnv指针。
jobject _instance; void *task(void *args){ JNIEnv *env; //将本地当前线程附加到 jvm 并获得jnienv //成功则返回0 jint res = _vm->AttachCurrentThread(&env,0); if (res != JNI_OK){ return 0; } jclass jclass1 = env->GetObjectClass(_instance); jmethodID staticMethod = env->GetStaticMethodID(jclass1,"staticMothed","(I)V"); env->CallStaticVoidMethod(jclass1,staticMethod,100); jmethodID jmethodID1 = env->GetMethodID(jclass1,"instanceMothed","(Ljava/lang/String;)V"); jstring jstring1 = env->NewStringUTF("我是C++"); env->CallVoidMethod(_instance,jmethodID1,jstring1); env->DeleteLocalRef(jclass1); env->DeleteLocalRef(jstring1); env->DeleteGlobalRef(_instance); //分离 _vm->DetachCurrentThread(); return 0; }
void nativeThread2(JNIEnv *env,jobject instace){ _instance = env->NewGlobalRef(instace);//_instacne 设置为全局引用 pthread_t pthread; pthread_create(&pthread,0,task,0); }