本文主要是介绍Android JNI实现线程内部调用JAVA方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- JNILib.java
class JNILib() {external fun start(callBack: DataCallBack):Intinterface DataCallBack{fun onData(type:Int,data:ByteArray)}
}
- jni.cpp
static MessageUtil messageUtil;
// 全局变量,表示 Java 虚拟机
JavaVM* g_vm = nullptr;
// 用于保存回调对象的全局引用
jobject callBack = nullptr;
// 在 JNI 库加载时保存 Java 虚拟机的引用
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {g_vm = vm;return JNI_VERSION_1_6;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_test_jni_JNILib_start(JNIEnv *env, jobject thiz, jobject call_back) {// 创建回调对象的全局引用callBack = env->NewGlobalRef(call_back);// 获取回调对象的类jclass callbackClass = env->GetObjectClass(callBack);// 启动线程并传递 Java 虚拟机、JNIEnv、回调对象及其类messageUtil.startThread(g_vm,env,callBack,callbackClass);return 0;
}
- message_.h
#include <jni.h>
#include <queue>
#include <pthread.h>
#include "logcat.h"
#include <string>struct Message {int type;const char* data;size_t length;
};class MessageUtil{
public:std::queue<Message> dataQueue;pthread_mutex_t mutex_;pthread_cond_t condition_;bool isThreadRunning = false;pthread_t msgThread;// 线程函数static void* threadFunction(void* arg);// 开始线程void startThread(JavaVM* gVm,JNIEnv* env,jobject callback,jclass callbackClass);// 停止线程void stopThread();// 添加数据void addMessage(Message msg);jobject callback;JavaVM* g_vm;jmethodID dataMethod;
};
- message.cpp
JNIEnv* AttachCurrentThreadIfNeeded(JavaVM* g_vm) {LogUtil::info(Message_TAG, "AttachCurrentThreadIfNeeded");// 声明 JNIEnv 指针JNIEnv* env;// 获取当前线程的 JNIEnvjint result = g_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);if (result == JNI_EDETACHED) {g_vm->AttachCurrentThread(&env, nullptr);}// 返回 JNIEnv 指针return env;
}
// 线程函数
void* MessageUtil::threadFunction(void* arg) {// 将参数转换为 MessageUtil 对象指针MessageUtil* messageUtil = static_cast<MessageUtil*>(arg);// 在当前线程附加到 Java 虚拟机JNIEnv* env = AttachCurrentThreadIfNeeded(messageUtil ->g_vm);// 线程主循环while (messageUtil ->isThreadRunning) {// 加锁互斥量pthread_mutex_lock(&messageUtil ->mutex_);// 当数据队列为空时,线程等待条件变量while (messageUtil ->dataQueue.empty()) {pthread_cond_wait(&messageUtil ->condition_, &messageUtil ->mutex_);}// 检查线程是否需要退出if (!messageUtil ->isThreadRunning) {pthread_mutex_unlock(&messageUtil ->mutex_);break;}// 从队列中获取数据if (!messageUtil ->dataQueue.empty()){
// LogUtil::info(Message_TAG,"成功发送数据");Message message = messageUtil ->dataQueue.front();messageUtil ->dataQueue.pop();// 创建字节数组并复制数据jbyteArray retData = env->NewByteArray(message.length);env->SetByteArrayRegion(retData, 0, message.length, reinterpret_cast<const jbyte*>(message.data));// 调用 Java 中的回调方法env->CallVoidMethod( messageUtil ->callback, messageUtil ->dataMethod,message.type, retData);}// 解锁互斥量pthread_mutex_unlock(&messageUtil ->mutex_);}// 从 Java 虚拟机中分离当前线程messageUtil ->g_vm->DetachCurrentThread();// 删除全局引用的回调对象env->DeleteGlobalRef(messageUtil ->callback);// 退出线程pthread_exit(NULL);
}// 开始线程
void MessageUtil::startThread(JavaVM* gVm,JNIEnv* env,jobject callback,jclass callbackClass) {// 保存 Java 虚拟机、回调对象及其类MessageUtil::callback = callback;MessageUtil::g_vm = gVm;// 获取回调方法的 IDdataMethod = env->GetMethodID(callbackClass, "onData", "(I[B)V");isThreadRunning = true;// 创建线程pthread_create(&msgThread, NULL, &threadFunction, this);
}// 停止线程
void MessageUtil::stopThread() {isThreadRunning = false;// 等待线程退出pthread_join(msgThread, NULL);
}void MessageUtil::addMessage(Message message) {// 加锁互斥量pthread_mutex_lock(&mutex_);// 将消息添加到队列中dataQueue.push(message);if (dataQueue.size() > 20){LogUtil::info(Message_TAG,("dataQueue size = "+std::to_string(dataQueue.size())).c_str());dataQueue.pop();}// 发送条件信号pthread_cond_signal(&condition_);// 解锁互斥量pthread_mutex_unlock(&mutex_);
}
这篇关于Android JNI实现线程内部调用JAVA方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!