JNI动态注册

一、概述

  案例:在AndroidStudio中使用JNI来实现动态注册

  注意事项:

    1.每一个线程中有一个JNIEnv env。JNIEnv不能夸线程使用

    2.在其他线程中使用JNIEnv ,请使用JavaVM vm (虚拟机)获取,获取方法如下:   

vm->AttachCurrentThread(&env,0);//给当前线程附加JNIEnv环境
vm->DetachCurrentThread();//分离当前线程环境

    3.jint JNI_OnLoad(JavaVM *vm,void * reserved) 方法在System.loadLibrary后执行,所以这是一个我们可以监控的so加载完成的方法

    4.关于方法签名请参考上一篇文章

二、示例代码

extern "C" {
    //全路径
static const char *classPathName = "com/yw/player/myjni/MyDynamicJNI";

jstring getMySonName(JNIEnv *env, jobject thisObj) {
    return env->NewStringUTF("洛洛杨小宝宝");
}

void setMySonName(JNIEnv *env, jobject thisObj,jstring name){
    LOGE("动态注册:从Java层传递过来的宝宝为:%s",env->GetStringUTFChars(name,0));
}


jint JNI_OnLoad(JavaVM *vm,void * reserved){
    //初始化环境,每一个JNIEnv对应一个线程环境,且JNIEnv不能夸线程使用,如果想要在其他线程中使用JNIEnv则需要给当前线程附加JNIEnv环境
    //vm->AttachCurrentThread(&env,0);//给当前线程附加JNIEnv环境
    //vm->DetachCurrentThread();//分离当前线程环境
    JNIEnv *env = NULL;

    //给JNIEnv环境赋值
    if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK){//从JavaVM(java虚拟机)中获取线程的JNIEnv环境
        return JNI_FALSE;
    }
    //获取class对象,classPathName为java类的完整包名+类名
    jclass clazz = env->FindClass(classPathName);
    if(clazz==NULL){
        return JNI_FALSE;
    }

    const JNINativeMethod methods[] = {
            {
                    "getMySonName",//java方法
                    "()Ljava/lang/String;",//java方法函数签名
                    (void *) getMySonName//C++中对应的方法
            },
            {
                    "setMySonName",//java方法
                    "(Ljava/lang/String;)V",//java方法对应的签名
                    (void *) setMySonName//C++中需要映射的方法
            }
    };
    //注册Java方法和c++方法的映射关系
    int result = env->RegisterNatives(clazz,methods,sizeof(methods)/sizeof(methods[0]));
    if(result<0){
        LOGE("方法映射失败");

    }
    return JNI_VERSION_1_4;
}


}

 

posted on 2022-08-08 10:10  飘杨......  阅读(641)  评论(0)    收藏  举报