主要涉及知识点
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());
}