Android JNI 开启子线程后调用 Activity 方法更新UI

  • MainActivity 代码
    点击按钮调用 native 方法,开启线程,调用MainActivity 方法更新UI
class MainActivity : AppCompatActivity() {

    companion object {
        private const val TAG: String = "MainActivity";

        init {
            System.loadLibrary("native-lib")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }

    fun onClick(view: View) {
        useThread()
    }

    private external fun useThread();

    // AndroidUI操作,让C++线程里面来调用
    fun updateUI() {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            showDialog()
        } else {
            Log.d("MainActivity", Thread.currentThread().name)
            runOnUiThread {
                showDialog();
            }
        }
    }

    private fun showDialog() {
        AlertDialog.Builder(this@MainActivity)
            .setTitle("hello!!!")
            .setMessage("updateUI run ...")
            .setPositiveButton("确定", null)
            .show()
    }

}
  • native 方法 具体作用都在注释里面了
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>

#define TAG "ld"
#define log_debug(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
#define log_info(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)

jobject mainActivityObj;
JavaVM *jvm;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *javaVm, void *pVoid) {
    // 获取 javaVM
    jvm = javaVm;
    return JNI_VERSION_1_6;
}

void *customerThread(void *pVoid) {
    // JVM 是可以跨线程使用的
    // JNIEnv是不可以跨线程的 所以需要通过 JVM创建当前线程使用的 JNIEnv
    JNIEnv *env = nullptr;
    jint result = jvm->AttachCurrentThread(&env, 0);
    log_debug("创建env结果为:%d", result);
    if (result != JNI_OK) {
        return 0;
    }
    // 获取 MainActivity 的 jclass
    jclass mainActivityClass = env->GetObjectClass(mainActivityObj);
    const char *sig = "()V";
    jmethodID mainMethodId = env->GetMethodID(mainActivityClass, "updateUI", sig);
    // 调用 updateUI 方法
    env->CallVoidMethod(mainActivityObj, mainMethodId);
    // 解除线程 释放挂在 JVM的native线程
    jvm->DetachCurrentThread();
    return 0;
};

// 入口
extern "C"
JNIEXPORT void JNICALL
Java_com_lu_jni_MainActivity_useThread(JNIEnv *env, jobject thiz) {
    // 必须创建一个 全局变量 来公用参数 如果是局部变量方法出栈后 对象将被释放
    mainActivityObj = env->NewGlobalRef(thiz);
    // 定义 pthread_t 线程标识
    pthread_t pthreadID;
    // 创建线程  调用 customerThread 
    pthread_create(&pthreadID, 0, customerThread, mainActivityObj);
    // 用来等待一个线程的结束,线程间同步的操作
    pthread_join(pthreadID, 0);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章