Android JNI实现线程内部调用JAVA方法

ops/2024/9/20 7:15:16/ 标签: android, java, JNI, C++, thread
  1. JNILib.java
class JNILib() {external fun start(callBack: DataCallBack):Intinterface DataCallBack{fun onData(type:Int,data:ByteArray)}
}
  1. 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;
}
  1. 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;
};
  1. 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_);
}

http://www.ppmy.cn/ops/41487.html

相关文章

618值得入手的数码有哪些?数码好物清单推荐|款款实用闭眼冲

每年的618购物节都是消费者们翘首以盼的盛宴&#xff0c;这一天&#xff0c;各大品牌和电商平台都会推出极具吸引力的优惠活动&#xff0c;让消费者们能够以更优惠的价格购买到心仪的数码好物&#xff0c;为了帮助大家在这个购物狂欢节中挑选到真正实用、性价比高的数码产品&am…

华为涅槃,余承东重生

最近一段时间&#xff0c;余承东甚为低调。最为明显的是&#xff0c;“遥遥领先”已经听不到了&#xff0c;“余大嘴”口中的措辞越来越克制。 今后手机相关的发布会&#xff0c;或许不再看到余承东的身影。 5月10日&#xff0c;余承东的职位正式更新&#xff0c;从终端BG CE…

分布式数据库有哪几种

数据库的发展从早期的单机数据库&#xff0c;到现在的分布式数据库。在单机数据库时代&#xff0c;所有的数据都存储在单机中&#xff0c;随着计算机技术的发展&#xff0c;开始出现了多台计算机联合处理数据的需求&#xff0c;从而诞生了分布式数据库。 分布式数据库是将多个…

C++:异常

C 异常处理机制是一种用于处理程序运行过程中出现异常情况的技术&#xff1b;异常是指程序在运行过程中发生的不正常情况&#xff0c;如除零错误、访问无效内存、文件不存在等。异常处理机制允许程序在发生异常时执行特定的操作&#xff0c;以便使程序更加健壮和可靠。 C 中的…

CheckStyle静态样式之道

优质博文&#xff1a;IT-BLOG-CN 在标准化的统一样式检查规范里&#xff0c;最为常用的统一样式工具是checkstyle插件&#xff0c;而不是国内阿里的代码规约插件。 【1】下载插件 【2】配置生效 配置生效及告警设置 【3】配置checkstyle.xml 官网地址 官网最新Releases 下面…

论文阅读记录--关于水文系统的传递函数

文章目录 J-schuite的文章,地下水系统的响应的功率谱分析--传递函数1. 什么是冲激响应函数与传递函数?2. 地下水流系统中传递函数的求解3. J-schuite文章中传递函数的复现J-schuite的文章,地下水系统的响应的功率谱分析–传递函数 1. 什么是冲激响应函数与传递函数? 在信号…

一篇搞懂Web3那些东西

目录 Web3 区块链 加密货币 Web3钱包 以太坊 智能合约 DAPP 身为开发人员&#xff0c;直活在web2.0有什么意思&#xff0c;于是我打算一下子弄懂Web3.0这些东西。无论你的前端还是后端我觉得都值得一看&#xff01; Web3 Web3 已成为一个包罗万象的术语&#xff0c;代…

nginx相关配置及高并发优化

TOC 早期的业务都是基于单体节点部署&#xff0c;由于前期访问流量不大&#xff0c;因此单体结构也可满足需求&#xff0c;但随着业务增长&#xff0c;流量也越来越大&#xff0c;那么最终单台服务器受到的访问压力也会逐步增高。时间一长&#xff0c;单台服务器性能无法跟上业…

以管理员身份运行设置

在使用非 Administrator 用户操作情况下&#xff1a; 举个例子&#xff0c;因为每次想要以管理员身份运行命令提示符&#xff0c;都要右键选择才行&#xff0c;有点麻烦。 可以设置每次点开就是以管理员身份运行命令提示符&#xff0c;操作如下&#xff1a; 1.Win R 输入 s…

IPSSL证书:为特定IP地址通信数据保驾护航

IPSSL证书&#xff0c;顾名思义&#xff0c;是专为特定IP地址设计的SSL证书。它不仅继承了传统SSL证书验证网站身份、加密数据传输的基本功能&#xff0c;还特别针对通过固定IP地址进行通信的场景提供了强化的安全保障。在IP地址直接绑定SSL证书的模式下&#xff0c;它能够确保…

Visual Studio C++ 2019进行安装

Visual Studio C 2019进行下载安装 链接&#xff1a;https://my.visualstudio.com/Downloads?qvisual%20studio%202017&wt.mc_idomsftvscom~older-downloads

5.9网络协议

由网卡发送数据通过网线进行发送&#xff0c;当网卡接收到信号以后将数据传给内核数据区&#xff0c;然后由操作系统交给相应的进程。 将数据进行发送的时候需要借助于网线实现&#xff0c;这个时候会出现当传输的数据比较远的时候就借助于中继器将信号进行再生扩大&#xff0…

图文详解JUC:Wait与Sleep的区别与细节

目录 一.Wait() 二.Sleep() 三.总结Wait()与Sleep()的区别 一.Wait() 在Java中&#xff0c;wait() 方法是 Object类中的一个方法&#xff0c;用于线程间的协作。当一个线程调用wait() 方法时&#xff0c;它会释放对象的锁并进入等待状态&#xff0c;直到其他线程调用相同对…

GPT-4o API 全新版本发布:提升性能,增加性价比

5月13日&#xff0c;OpenAI 发布了全新ChatGPT模型 GPT-4o&#xff0c;它在响应速度和多媒体理解上都有显著提升。在这篇文章中&#xff0c;我们将介绍 GPT-4o 的主要特点及其 API 集成方式。 什么是 GPT-4o&#xff1f; GPT-4o 是 OpenAI 于5月13日发布的最新多模态 AI 模型…

软件3班20240513

java.util.PropertyResourceBundle4554617c package com.yanyu;import java.sql.*; import java.util.ResourceBundle;public class JDBCTest01 {public static void main(String[] args) throws SQLException { // 获取属性配置文件ResourceBundle bundle Res…

SpringMVC 注解详解

SpringMVC 注解详解 1. 引言 SpringMVC 是 Spring 框架中的 Web 层解决方案&#xff0c;它通过注解的方式来简化 MVC 模式的实现。本篇将详细介绍 SpringMVC 中常用的注解及其用法。 2. SpringMVC 注解分类 SpringMVC 的注解主要分为以下几类&#xff1a; 2.1 核心注解 C…

qt 麒麟系统 connot find /usr/local/lib

目录 解决方法&#xff1a; 后来又报错&#xff1a; cannot find -lopencv_world3.4.6 connot find /usr/local/lib 解决方法&#xff1a; LIBS -L/usr/local/lib -lopencv_world3.4.6QMAKE_LFLAGS -Wl,-rpath,/usr/local/lib 后来又报错&#xff1a; cannot find -lopencv…

软件测试面试78问

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、问&#xff1a;你在测试中发现了一个bug&#xff0c;但是开发经理认为这不是一个bug&#xf…

Pycharm所有快捷键的使用

1.编辑 快捷键作用Ctrl Space基本的代码完成&#xff08;类、方法、属性&#xff09;Ctrl Alt Space快速导入任意类Ctrl Shift Enter语句完成Ctrl P参数信息&#xff08;在方法中调用参数&#xff09;Ctrl Q快速查看文档Shift F1外部文档Ctrl 鼠标简介Ctrl F1显示错…

从零开始详解OpenCV条形码区域分割

前言 在识别二维码之前&#xff0c;首先要划分出二维码的区域&#xff0c;在本篇文章中将从零开始实现二维码分割的功能&#xff0c;并详细介绍用到的方法。 我们需要处理的图像如下&#xff1a; 完整代码 首先我们先放出完整代码&#xff0c;然后根据整个分割流程介绍用到…