jni学习笔记

2021-01-06  本文已影响0人  leaflying

主要涉及知识点

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


上一篇下一篇

猜你喜欢

热点阅读