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

news2024/11/27 8:30:39

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

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

package com.example.myndkapplication

import 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.java
    interface 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_jvm
    return 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);

    // 获取回调方法的方法ID
    jclass 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在一直发送消息给安卓界面 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1625628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学浪批量下载器,超适合小白一键式操作#小浪助手

2024/04/26 更新最新最新版本 另外 大家有任何建议请联系我 更新软件 大家如果觉得好用请帮我到处分享一下 工具我已经打包好了,有需要的自己取一下 学浪下载器链接&#xff1a;https://pan.baidu.com/s/1nyjXc88BWbF8jnfQWUGLZQ?pwd1234 提取码&#xff1a;1234 --来自百…

深度学习pytorch实战4---猴逗病识别·

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](https://mtyjkh.blog.csdn.net/)** 引言 1.复习上周并反思 K同学针对大家近…

C++算法题 - 链表

目录 141. 环形链表2. 两数相加21. 合并两个有序链表138. 随机链表复制92. 反转链表Ⅱ25. K个一组翻转链表19. 删除链表的倒数第N个结点82. 删除排序链表中的重复元素Ⅱ61. 旋转链表86. 分隔链表146. LRU缓存 141. 环形链表 LeetCode_link 给你一个链表的头节点 head &#xf…

TCP/IP协议(二)

一、TCP-选项 1.简介 在TCP/IP报文中&#xff0c;固定头部下边就是 "选项"部分。 (1)TCP头部的选项部分是TCP为了适应复杂的网络环境和更好的服务应用层而进行设计的 (2)大多数的TCP选项部分出现在TCP连接建立阶段 2.构成 2.1 最大报文传输段 最大报文传输段(Ma…

代码随想录训练营Day 33|Python|Leetcode|● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

理论基础 动态规划五步曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509. 斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始…

c++11详解

目录 1.列表初始化 2.声明 3.右值引用和移动语句 4. c11新的类功能 5. 可变参数模板 6.lambda表达式 7.包装器 8. 后言 1. 列表初始化 1.1 {}的初始化 (1) c98标准规定可以使用{}对数组以及结构体进行统一的列表初始化. struct Point {int _x;int _y; };int main() {in…

Kubernetes:云原生时代的核心引擎

文章目录 一、Kubernetes简介&#xff1a;引领云原生潮流二、K8s的核心特性&#xff1a;自动化与智能化三、K8s的实践应用&#xff1a;打造高效云原生应用架构四、K8s的挑战与应对&#xff1a;安全与性能并重五、K8s的未来展望&#xff1a;无限可能与挑战并存《Kubernetes快速进…

YOLOv8-pose针对视频实时提取打印对应关节点序号及坐标

因为我在找如何提取YOLOv8-pose的关键点的时候&#xff0c;大多都是针对静态图像&#xff0c;视频直接套用不太行&#xff0c;因此就改进了一下&#xff0c;如下&#xff1a; 初步代码&#xff1a; import torch # 导入PyTorch库 import cv2 as cv # 导入OpenCV库并重命名为…

上位机图像处理和嵌入式模块部署(树莓派4b进行自动化测试)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 硬件、软件功能开发ok只是产品开发的第一步。怎么做到自动化测试、保证产品质量才是关键。很多时候&#xff0c;我们给客户提供了功能&#xff0c;…

Rust HTTP 客户端:易于使用、功能强大 | 开源日报 No.228

seanmonstar/reqwest Stars: 8.9k License: Apache-2.0 reqwest 是一个易于使用且功能强大的 Rust HTTP 客户端。 异步和阻塞客户端支持普通数据、JSON、urlencoded 和 multipart 数据格式可定制的重定向策略支持 HTTP 代理和系统原生 TLS 或 rustls 的 HTTPSCookie 存储功能…

一、路由基础

1.路由协议的优先级 路由器分别定义了外部优先级和内部优先级&#xff08;越小越优&#xff09; 路由选择顺序&#xff1a;外部优先级>>内部优先级&#xff08;相同时&#xff09; ①外部优先级&#xff1a;用户可以手工为各路由协议配置的优先级 ②内部优先级&#xf…

Nuxt3 实战 (五):Header 头部布局

前言 这两周一直忙公司系统的迭代需求&#xff0c;没啥时间捣鼓自己的小项目&#xff0c;趁着项目进入测试收尾阶段&#xff0c;抽空把 Layout 布局的 Header 部分先搞好。 需求拆分 顶部左侧放 Logo&#xff0c;右边放社交图标&#xff0c;暗黑模式切换提前准备好 Logo 和网…

Centos8操作系统安装mysql5.7版本以及报错解决

目录 一、卸载MySql 1.首先查看已安装的mysql 2.逐个或者执行一下命令统一卸载掉 注意&#xff1a; 3. 卸载其他相关文件 二、安装MySql 1.安装mysql的rpm源 2.安装MySql 如果遇到以下错误&#xff1a; 问题一: 解决方法&#xff1a; 问题二、 解决方法&#xff1…

【一刷《剑指Offer》】面试题 9:斐波那契数列(扩展:青蛙跳台阶、矩阵覆盖)

力扣对应链接&#xff1a;LCR 126. 斐波那契数 - 力扣&#xff08;LeetCode&#xff09; 牛客对应链接&#xff1a;斐波那契数列_牛客题霸_牛客网 (nowcoder.com) 核心考点&#xff1a;空间复杂度&#xff0c;fib 理解&#xff0c;剪枝重复计算。 一、《剑指Offer》内容 二、分…

Linux多进程(二)进程通信方式三 共享内存

共享内存提供了一个在多个进程间共享数据的方式&#xff0c;它们可以直接访问同一块内存区域&#xff0c;因此比使用管道或消息队列等通信机制更高效。在多进程程序中&#xff0c;共享内存通常与信号量一起使用&#xff0c;以确保对共享内存的访问是线程安全的。 一、打开/创建…

俊杰测评:电视盒子什么牌子好?电视盒子品牌排行榜

欢迎各位来到俊杰的数码测评频道&#xff0c;每年我会进行数十次电视盒子测评&#xff0c;今年已经买过二十多款电视盒子了&#xff0c;本期的测评主题是电视盒子什么牌子好&#xff0c;通过十天的深入详细对比后我整理了电视盒子品牌排行榜&#xff0c;近期想买电视盒子的可以…

代码随想录算法训练营第五十一天| 309.最佳买卖股票时机含冷冻期,714.买卖股票的最佳时机含手续费,总结

题目与题解 参考资料&#xff1a;买卖股票总结 309.最佳买卖股票时机含冷冻期 题目链接&#xff1a;309.最佳买卖股票时机含冷冻期 代码随想录题解&#xff1a;309.最佳买卖股票时机含冷冻期 视频讲解&#xff1a;动态规划来决定最佳时机&#xff0c;这次有冷冻期&#xff01;|…

python获取文件路径

文件&#xff1a;allpath_parameter.py # 获取当前目录路径 # current_dir os.getcwd() # 获取当前目录路径 realpath00 os.path.abspath(os.path.join(os.path.dirname(os.path.split(os.path.realpath(__file__))[0]), .)) print(realpath00)# 获取当前目录的上级目录路…

Centos安装/更新Docker

首先要配置好Centos 配置好静态IP 替换yum源为阿里云 Docker是什么&#xff1f; Docker 是一种开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后部署到任何流行的 Linux 机器上。是一种虚拟化的技术&#xff0c;可以把…

linux 编译opencv遇到问题

linux编译opencv4.8的时候遇到问题 Error: suffix or operands invalid for vpand看到很多说法是升级as这个工具的版本&#xff0c;自测是从2.20升级到2.27就可以了