cnwutianhao 发表于 2023-4-19 16:54

【Android】在 Android 应用中调用 C++ 代码并在新线程中执行 Java 静态方法

本帖最后由 cnwutianhao 于 2023-4-20 16:03 编辑

**Kotlin 代码:**
```kotlin
package com.tyhoo.jni

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.tyhoo.jni.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)

      binding = ActivityMainBinding.inflate(layoutInflater)
      setContentView(binding.root)

      binding.sampleText.setOnClickListener {
            Log.d(TAG, "nativeMethod")
            nativeMethod()
      }
    }

    private external fun nativeMethod()

    companion object {
      private const val TAG = "Tyhoo"

      // Used to load the 'jni' library on application startup.
      init {
            System.loadLibrary("jni")
      }

      @JvmStatic
      fun staticMethod() {
            Log.d(TAG, "staticMethod")
      }
    }
}
```
这是 Kotlin 语言编写的 Android 应用程序中的 MainActivity 类,其中声明了一个名为 nativeMethod 的本地方法。该方法会在点击 sampleText 视图时被调用,从而触发 native 方法的执行。在 companion object 中还定义了一个名为 staticMethod 的静态方法,它会在应用程序启动时被加载,用于在 Java 层调用本地方法。这个静态方法可以从 Java 代码中直接调用,而不需要使用 JNI 接口函数。

**C++ 代码:**
```cpp
#include <jni.h>
#include <string>
#include <android/log.h>

#define LOG_TAG "Tyhoo"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

#define CLASSNAME "com/tyhoo/jni/MainActivity"

typedef struct {
    JavaVM *vm;
    jclass clazz;
} tyhoo_vm;

static tyhoo_vm javaVM;

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *unused) {
    JNIEnv *env = nullptr;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
      LOGD("JNI_OnLoad GetEnv failed\n");
      return -1;
    }

    jclass clazz = env->FindClass(CLASSNAME);
    if (!clazz) {
      LOGD("FindClass %s failed\n", CLASSNAME);
      return -1;
    }

    javaVM.vm = vm;
    javaVM.clazz = (jclass) env->NewGlobalRef(clazz);

    LOGD("JNI_OnLoad, vm: %p, clazz: %p \n", javaVM.vm, javaVM.clazz);
    return JNI_VERSION_1_6;
}

void JNI_OnUnload(JavaVM *vm, void *unused) {
    JNIEnv *env = nullptr;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
      LOGD("JNI_OnLoad GetEnv failed\n");
      return;
    }
    env->DeleteGlobalRef(javaVM.clazz);
}

void callJavaStaticMethod() {
    JNIEnv *env = nullptr;
    jint res = javaVM.vm->AttachCurrentThread(&env, nullptr);
    if (res != JNI_OK) {
      return;
    }

    jclass clazz = javaVM.clazz;
    if (clazz == nullptr) {
      return;
    }

    jmethodID method = env->GetStaticMethodID(clazz, "staticMethod", "()V");
    env->CallStaticVoidMethod(clazz, method);
}

void *thread_func(void *arg) {
    callJavaStaticMethod();
    return nullptr;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_tyhoo_jni_MainActivity_nativeMethod(JNIEnv *env, jobject thiz) {
    pthread_t thread;
    pthread_create(&thread, nullptr, thread_func, nullptr);
}
```
这是 C++ 语言编写的 JNI 接口函数,用于在 Java 层调用本地方法。这个接口函数的作用是创建新线程,并在新线程中调用 callJavaStaticMethod 方法,这个方法会获取当前线程的 JNIEnv 对象和 Java 类对象,并通过这些对象调用 Java 层的静态方法 staticMethod。

> 同步发布到我的 GitHub Blog 里:
> https://github.com/cnwutianhao/blog/issues/1

px307 发表于 2023-4-19 18:26

楼主真强,学以了,谢谢

xiexiaoxi 发表于 2023-4-19 19:23

学习学习了

Murph 发表于 2023-4-24 20:50

真的有用欸,谢谢分享

ax1xa 发表于 2024-7-15 14:39

谢谢大佬,感谢分享
页: [1]
查看完整版本: 【Android】在 Android 应用中调用 C++ 代码并在新线程中执行 Java 静态方法