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);
}