linux+ndk把jni制作成so库供apk使用(带线程的回调)

2024-04-26 12:36

本文主要是介绍linux+ndk把jni制作成so库供apk使用(带线程的回调),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们就不墨迹了,直接开始,往往我们需要jni给我们回调一些数据,并且是实时的回调,这里我们就需要多写一些东西了

1.先在安卓里面设置好接口以及回调,我自己给你们看源代码

package com.example.myndkapplicationimport android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() {// java回调接口 INativeListener.javainterface INativeListener {fun onCall(str:String)}external fun nativeCallBack(callBack: INativeListener?)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Log.e("TAG","nativeCallBack================onCreate")nativeCallBack(object : INativeListener {override fun onCall(str: String) {Log.e("TAG","nativeCallBack================onCall()====$str")runOnUiThread { sample_text.text = str }}})stringFromJNI()}external fun stringFromJNI()companion object {// Used to load the 'native-lib' library on application startup.init {System.loadLibrary("test")}}
}

2.我们再来修改jni里面的test.c 

这里我们新增了一个线程pthread,一个Java_com_example_myndkapplication_MainActivity_nativeCallBack方法,以及JNI_OnLoad虚拟机环境方法

JNI_OnLoad这个方法不需要任何调用,在jni跑起来以后会自动运行

Android JNI 规定,在非主线程中调用 JNI 函数时需要先通过 AttachCurrentThread 方法将当前线程附加到 Java 虚拟机上,以确保 JNI 调用的上下文正确。

#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/time.h>
#include <android/log.h>
#define TAG "TAG" // 指定您的日志标签//##########################################################新增内容#######################################################include <pthread.h> // 包含线程相关的头文件// 全局变量,用于存储 Java 虚拟机环境
JavaVM *g_jvm = NULL;
jobject global_callback = NULL;
jmethodID gCallBackMid;
JNIEnv *env;void *thread_function(void *arg) {// 将当前线程附加到Java虚拟机上,获取JNIEnv指针if ((*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL) != JNI_OK) {// 获取JNIEnv失败return NULL;}while (true) {// 在这里执行你的应用逻辑,生成新的 ch 数据jstring jstr = (*env)->NewStringUTF(env, "write success");// 回调到java层(*env)->CallVoidMethod(env, global_callback, gCallBackMid, jstr);// 释放本地引用(*env)->DeleteLocalRef(env, jstr);// 等待一段时间,比如 1 秒sleep(1); // 单位是秒}// 将当前线程从Java虚拟机上分离(*g_jvm)->DetachCurrentThread(g_jvm);return NULL;
}// JNI 初始化函数,保存 Java 虚拟机环境
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {g_jvm = vm; // 保存 Java 虚拟机环境到全局变量 g_jvmreturn JNI_VERSION_1_6;
}// JNI 回调函数,保存回调对象
JNIEXPORT void JNICALL 
Java_com_example_myndkapplication_MainActivity_nativeCallBack(JNIEnv *env, jobject thiz, jobject call_back) {// 创建一个 JNI 全局引用global_callback = (*env)->NewGlobalRef(env, call_back);// 获取回调方法的方法IDjclass cls = (*env)->GetObjectClass(env, call_back);gCallBackMid = (*env)->GetMethodID(env, cls, "onCall", "(Ljava/lang/String;)V");__android_log_print(ANDROID_LOG_DEBUG, TAG, "Java_com_example_myndkapplication_MainActivity_nativeCallBack\n");	// 创建新线程并启动pthread_t thread;pthread_create(&thread, NULL, thread_function, NULL);
}//######################################################################################################################################JNIEXPORT jstring JNICALL
Java_com_example_myndkapplication_MainActivity_stringFromJNI(JNIEnv *env, jobject obj) {__android_log_print(ANDROID_LOG_DEBUG, TAG, "test_begain\r\n: %s", "===========stringFromJNI=======1======");//pthread_t thread;//pthread_create(&thread, NULL, start_app, NULL);__android_log_print(ANDROID_LOG_DEBUG, TAG, "test_end\r\n: %s", "===========stringFromJNI=======2======");return (*env)->NewStringUTF(env, "===========stringFromJNI=======3======");
}

3.运行并生成so库供apk使用 

然后就可以看到jni在一直发送消息给安卓界面 

这篇关于linux+ndk把jni制作成so库供apk使用(带线程的回调)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/937602

相关文章

rust打包编译为mac或者linux可执行文件,发送到别的电脑不能运行

如果使用rust项目编译为linux或者mac可执行文件,发送到别的电脑之后,不可以直接运行,而是显示一个空白文件,双击也没有反应,其实这是因为这个文件没有可执行权限导致的,添加可执行权限就可以了: 使用命令添加可执行权限: chmod 777 文件名 添加完成之后,就显示可执行了: 然后再双击或者命令行运行就可以了:

谈一谈rem的应用场景及其如何使用

rem rem是什么 相信大多数同学都写过移动端,那么对rem就很熟悉了,它是相对长度单位。相对于根元素(即html元素)font-size计算值的倍数的一个css单位,也就是我们 前端常说的适配单位rem。 认识rem 当浏览器解析HTML文档时,创建了一个用来代表页面元素的集合,叫做DOM(文档对象模型,Document Object Model)。树状结构,每一个节点代表一个

【转】Vue2.0 Vue.set的使用

这里我定义了一个列表数据,我将通过三个不同的按钮来控制列表数据。 首先在列表中动态新增一条数据:   <!DOCTYPE html><html><head lang="en"><meta charset="UTF-8"><title></title></head><body><div id="app2"><!--想了解这里key的作用请访问:(https://cn.vuejs.o

linux 权限和权限的设置

在Linux中,文件和目录的权限是一个重要的安全特性。这些权限决定了哪些用户可以读取、写入或执行某个文件或目录。以下是关于Linux权限和如何设置它们的基本信息。 权限类型 Linux中有三种基本的权限类型: 读取(r):允许用户读取文件的内容或列出目录的内容。写入(w):允许用户修改文件的内容或在目录中创建和删除文件。执行(x):允许用户执行文件(如果它是一个程序或脚本)或进入目录(即cd

机器学习:基于TF-IDF算法、决策树,使用NLTK库对亚马逊美食评论进行情绪分析

前言 系列专栏:机器学习:高级应用与实践【项目实战100+】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目,每个项目都处理一组不同的问题,包括监督和无监督学习、分类、回归和聚类,而且涉及创建深度学习模型、处理非结构化数据以及指导复杂的模型,如卷积神经网络、门控循环单元、大型语言模型和强化学习模型 对于文本分析,我们将使用 NLTK 库。NLTK 是构建 Pyth

快速掌握并使用Apache POI

Apache POI Apache POl是一个处理Miscrosoft Ofice各种文件格式的开源项目。简单来说就是,我们可以使用 POI在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 简单使用 快速入门 第一步:导入Apache POI的maven坐标: <dependency><groupId>org.apache.poi</g

LINUX下安装卸载软件

1、源代码包的安装       gzip   -d   apache_1.3.20.tar.gz   (解压)       tar   xvf   apache_1.3.20.tar   (解包)       cd   apache_1.3.20       ./configure   (配置)   ----./configure   --help(查看configure选项)

Seata之XA 模式的使用

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一

Android后台线程拍照卡顿问题(回调函数与Looper)

前段时间做了一个项目,要求后台拍照,经过努力完成了需求。 方法如下:     // 启动相机 new Thread(new Runnable() { @Override public void run() { if (myCamera != null) { ol.disable(); myCamera.stopPreview(); myCamera.release();

Android之线程的简单使用

注意 本文章只讲使用原生android来达到开启线程的目的 使用简单线程的三种方法 第一种,继承Thread,重写run 代码 class TestThread extends Thread {@Overridepublic void run() {/*逻辑代码*/}} 然后new TestThread().start();这样就会在开辟出来的线程中执行run方法,如果想让