美文网首页
jni学习笔记

jni学习笔记

作者: leaflying | 来源:发表于2021-01-06 17:33 被阅读0次

    主要涉及知识点

    1.JNI_OnLoad
    2.动态注册和静态注册
    3.多线程
    4.在子线程中回调java方法

    代码

    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Example of a call to a native method
            TextView tv = findViewById(R.id.sample_text);
            tv.setText(stringFromJNI());
    
            tv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    start_thread();
                }
            });
        }
        public native String stringFromJNI();
    
        private native void start_thread();
    
        public void callBack(){
            if(Looper.myLooper() == Looper.getMainLooper()){
                Toast.makeText(this,"jni回调",Toast.LENGTH_SHORT).show();
            }else {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"jni回调",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    }
    
    
    #include <jni.h>
    #include <string>
    #include <android/log.h>
    #include <pthread.h>
    
    
    #define LOGE(TAG,...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
    
    JavaVM *jvm = nullptr;
    
    void *testThread(void* args){
        jobject instance = static_cast<jobject>(args);
    
        JNIEnv *env = nullptr;
        //env 是一个线程相关的结构体, 该结构体代表了 Java 在本线程的执行环境,所有我们这里需要我们通过java虚拟机去获取,而不是在主线程中传递过来
    
        jvm->AttachCurrentThread(&env,NULL); //将线程连接到java虚拟机
        int status = jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4);
        //通过jvm获取java在本线程的运行环境,如果成功将返回JNI_OK
        if(status != JNI_OK){
            return 0;
        }
        jclass clazz = env ->GetObjectClass(instance);
        jmethodID callback = env->GetMethodID(clazz,"callBack","()V");
        env->CallVoidMethod(instance,callback);
    
        env->DeleteGlobalRef(instance);
    
        jvm->DetachCurrentThread(); //将线程和java虚拟机解除绑定
        return 0;
    }
    
    void start_thread(JNIEnv* env,jobject instance){
        pthread_t _pthread;
        jobject _instance = env->NewGlobalRef(instance);
        pthread_create(&_pthread,0,testThread,_instance);
    
    }
    
    
    static const JNINativeMethod jniNativeMethod[] = {
            {"start_thread", "()V", (void *) (start_thread)},
    };//需要绑定的方法
    
    
    int JNI_OnLoad(JavaVM *vm, void *reserved){
        jvm = vm;
        JNIEnv *jniEnv = nullptr;
    
        jint status = vm->GetEnv(reinterpret_cast<void **>(&jniEnv), JNI_VERSION_1_4);//通过jvm获取java在本线程的运行环境
        if(status!=JNI_OK){
            return -1;
        }
    
        jclass jniClass = jniEnv -> FindClass("com/test/myapplication/MainActivity");//需要动态注册方法的全类名
    
        jniEnv->RegisterNatives(jniClass,jniNativeMethod, sizeof(jniNativeMethod)/ sizeof(JNINativeMethod));//动态注册
        return JNI_VERSION_1_4;//指定使用的jni版本 这里只能使用JNI_VERSION_1_2、JNI_VERSION_1_4、JNI_VERSION_1_6
    }
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_com_test_myapplication_MainActivity_stringFromJNI(
            JNIEnv* env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    
    
    

    相关文章

      网友评论

          本文标题:jni学习笔记

          本文链接:https://www.haomeiwen.com/subject/sqcooktx.html