22 JNI - 动态注册与JNI线程

Android Ndk 学习笔记(目录)

// 1 静态注册 native 函数
    public native void staticRegister();
// ---------------------------静态注册---------------------------------
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity2_staticRegister(JNIEnv *env, jobject thiz) {
// 静态注册: 优点:开发简单
// 缺点
// 1.JNI函数名非常长
// 2.捆绑 上层 包名 + 类名
// 3.运行期 才会去 匹配JNI函数,性能上 低于 动态注册
    LOGI("我是静态注册的函数 Java_com_cn_mynativestudy_MainActivity2_staticRegister...");
}
// ---------------------------静态注册---------------------------------


public void test01(View view) {
        staticRegister();
    }
// 2 动态注册 native 函数
    public native void dynamicRegister();
    public native int dynamicRegister2(String valueStr);
// ---------------------------动态注册----------------------------------

JavaVM *jvm = nullptr; // 定义一个 局部变量 jvm 并赋null


void jni_dynamicRegister(JNIEnv *env, jobject thiz){
    LOGI("我是动态注册的函数 dynamicMethod01...");
}
int jni_dynamicRegister2(JNIEnv *env, jobject thiz, jstring value_str){

    char * str  = const_cast<char *>(env->GetStringUTFChars(value_str, NULL));
    LOGI("我是动态注册的函数 dynamicMethod01...%s",str);
    env->ReleaseStringUTFChars(value_str,str);
    return 100 ;
}

JNINativeMethod jniNativeMethod[] = {
        {"dynamicRegister","()V",(void *)(jni_dynamicRegister)},
        {"dynamicRegister2","(Ljava/lang/String;)I",(int *)(jni_dynamicRegister2)}

};

// 类似 java 的构造函数 ,C++ 初始化时 static { System.loadLibrary("native-lib"); } 调用 JNI_OnLoad方法
extern "C"
JNIEXPORT jint JNI_OnLoad(JavaVM * javaVm ,void *){

    ::jvm = javaVm ;// 赋值,获取进程唯一 javaVM对象

    JNIEnv *jnienv = nullptr;// 声明一个当前jnienv ;

    // 通过 javavm 获取 jnienv 并赋值 ,返回 0 为成功
    int result = javaVm->GetEnv(reinterpret_cast<void **>(&jnienv), JNI_VERSION_1_6);

    if(result != JNI_OK){
        return -1 ;
    }

    // 获取 activity  class 对象
    jclass main2_class = jnienv->FindClass("com/cn/mynativestudy/MainActivity2");

    jnienv->RegisterNatives(main2_class,jniNativeMethod,
            sizeof(jniNativeMethod)/sizeof(JNINativeMethod));

    return JNI_VERSION_1_6; //  // AS的JDK在JNI默认最高1.6
}
// ---------------------------动态注册----------------------------------

public void test02(View view) {
        dynamicRegister();
    }
public void test03(View view) {
        int string_valueStr = dynamicRegister2("String valueStr");
        Log.i("info",string_valueStr+"");
    }
 /** log打印
     *  我是静态注册的函数 Java_com_cn_mynativestudy_MainActivity2_staticRegister...
     *  我是动态注册的函数 dynamicMethod01...
     *  我是动态注册的函数 dynamicMethod01...String valueStr
     *  100
     */
// 3JNI 线程 实例

    public native void naitveThread(); // Java层 调用 Native层 的函数,完成JNI线程
    public native void closeThread(); // 释放全局引用
// ---------------------------JNI 线程----------------------------------

// JNIEnv  线程绑定 不能跨线程
// jobject   线程绑定 不能跨线程

class MyContext{

public:
    JNIEnv * jniEnv = nullptr;
    jobject  j_obj = nullptr;
};

void * runTask(void *pVoid){

    MyContext * myContext = static_cast<MyContext *>(pVoid);

// 全新的JNIEnv  异步线程里面操作
    JNIEnv *jniEnv = nullptr;
    // 附加当前异步线程后,会得到一个全新的 env,此env相当于是子线程专用env
    jint attachResult = ::jvm->AttachCurrentThread(&jniEnv, nullptr);
    if (attachResult != JNI_OK) {
        return 0; // 附加失败,返回了
    }
    // 1.拿到class
    jclass mainActivityClass = jniEnv->GetObjectClass(myContext->j_obj);

    // 2.拿到方法
    jmethodID updateActivityUI = jniEnv->GetMethodID(mainActivityClass, "updateActivityUI", "()V");

    // 3.调用
    jniEnv->CallVoidMethod(myContext->j_obj, updateActivityUI);

    ::jvm->DetachCurrentThread(); // 必须解除附加,否则报错

    return nullptr;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity2_naitveThread(JNIEnv *env, jobject thiz) {

    MyContext * myContext = new MyContext();

    myContext->jniEnv = env ;
    myContext->j_obj = env->NewGlobalRef(thiz);//提升成全局变量;

    pthread_t pid ;
    pthread_create(&pid, nullptr, runTask, myContext);
    pthread_join(pid, nullptr);

}

extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity2_closeThread(JNIEnv *env, jobject thiz) {

}
// ---------------------------JNI 线程----------------------------------


public void test04(View view) {
        naitveThread();
    }
 /**
     * TODO 下面是 被native代码调用的 Java方法
     * 第二部分 JNI线程
     */
    public void updateActivityUI() {
        if (Looper.getMainLooper() == Looper.myLooper()) { // TODO C++ 用主线程调用到此函数 ---->  主线程
            new AlertDialog.Builder(MainActivity2.this)
                    .setTitle("UI")
                    .setMessage("updateActivityUI Activity UI ...")
                    .setPositiveButton("知道了", null)
                    .show();
        } else {  // TODO  C++ 用异步线程调用到此函数 ---->  异步线程
            Log.i("info", "updateActivityUI 所属于子线程,只能打印日志了..");

            runOnUiThread(new Runnable() { // 哪怕是异步线程  UI操作 正常下去 runOnUiThread
                @Override
                public void run() {

                    // 可以在子线程里面 操作UI
                    new AlertDialog.Builder(MainActivity2.this)
                            .setTitle("updateActivityUI")
                            .setMessage("所属于子线程,只能打印日志了..")
                            .setPositiveButton("知道了", null)
                            .show();
                }
            });
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值