Android jni引用第三方so动态库和.a静态库并且调用(c)方法

最近花了一周时间来入门学习 Android JNI方面的知识,因为后续的工作很多需要用到c c++库,我需要用jni来包装一下c函数,来提供给上次java调用。总之多学点知识对自己有好处。

案例效果:
在这里插入图片描述
上文我们讲解了
android studio cmake生成.a文件(静态库)及调用(c c++)静态库.a

本文接着上文,这次我们利用JNI 来引用第三方动态库so文件,并且让Java调用它的函数。

第一步:生成.so动态库文件

编写C文件和头文件

DynamicLibraryTest.h

//
// Created by Administrator on 2023/9/5/005.
//#ifndef ANDROIDCMAKE_DYNAMICLIBRARYTEST_H
#define ANDROIDCMAKE_DYNAMICLIBRARYTEST_H#endif //ANDROIDCMAKE_DYNAMICLIBRARYTEST_Hint dynamicAdd(int a,int b,int c);char * getDynamicName(char * firstName,char * lastName);

DynaminLibraryTest.cpp

//
// Created by Administrator on 2023/9/5/005.
//#include "../include/static/DynamicLibraryTest.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int dynamicAdd(int a,int b,int c){return a+b+c;
}char * getDynamicName(char * firstName,char * lastName){char *name = (char *) malloc(strlen(firstName) + strlen(lastName));strcpy(name, firstName); // 把firstName复制到name中strcat(name, lastName); // 把lastName追加到name中return name;
}

编写CmakeLists文件

    add_library(${CMAKE_PROJECT_NAME} SHARED   src/DynaminLibraryTest.cpp   )

make project之后,生成了.so动态库文件。
在这里插入图片描述

生成动态库之后,我把文件复制到了jni目录下面.
在这里插入图片描述

第二步:JNI动态注册.so动态库中的函数

编写cmakeList文件


cmake_minimum_required(VERSION 3.22.1)project("cmake")add_library(${CMAKE_PROJECT_NAME} SHAREDnative-lib.cppsrc/libtest.c# 编写动态库用到的文件,已经生成了deynaminLibraryTest.so文件就注释掉这个代码
#        src/DynaminLibraryTest.cpp   )#导入已经编译好的第三方静态库 或者 动态库  本例导入的静态库
add_library(calStatic STATIC IMPORTED)
#设置静态库(.a)导入的路径
set_target_properties(calStatic PROPERTIES IMPORTED_LOCATION${CMAKE_CURRENT_SOURCE_DIR}/jni/${CMAKE_ANDROID_ARCH_ABI}/libcalStatic.a
)#添加第三方 动态库
add_library(dynamicLibraryTest SHARED IMPORTED)
#设置动态库(.so)导入的路径
set_target_properties(dynamicLibraryTest PROPERTIES IMPORTED_LOCATION${CMAKE_CURRENT_SOURCE_DIR}/jni/${CMAKE_ANDROID_ARCH_ABI}/libdynamicLibraryTest.so)#通过target_link_libraries命令指明库文件,且通过target_include_directories命令指明相应的库头文件
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include/static/)
#需要链接或者编译的库
target_link_libraries(${CMAKE_PROJECT_NAME}# List libraries link to the target libraryandroid# 第三方静态库。calStatic# 第三方动态库dynamicLibraryTestlog)

JNI动态注册函数

#include <jni.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>#include "libtest.h"//内部头文件,cmake需要连接源文件地址
#include "CalculStatic.h"//第三方静态库 .a
#include "DynamicLibraryTest.h"//第三方动态库 .so#include <android/log.h>
#define LOG_TAG "YIQI"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)//静态注册和动态注册,函数名一样的时候,优先用动态注册的,动态注册效率高。
//静态注册
//extern "C" JNIEXPORT jstring JNICALL
//Java_com_gitbaike_cmake_MainActivity_stringFromJNI(
//        JNIEnv* env,
//        jobject /* this */) {
//    std::string hello = "Hello from C++ 静态注册";
//    return env->NewStringUTF(hello.c_str());
//}//静态注册
extern "C" JNIEXPORT void JNICALL
Java_com_gitbaike_cmake_MainActivity_HNPCInit(   JNIEnv* env,jobject /* this */){HNPC_Init();
}//动态注册
extern "C" {//调用了libcalStatic.a静态库中的方法jint addSum(JNIEnv *env,jobject instance,jint a,jint b,jint c){ //调用静态库return  calculAdd(a,b,c);}//调用了libDynamicLibraryTest.so动态库中的方法jint jDynamicAdd(JNIEnv *env,jobject instance,jint a,jint b,jint c){return dynamicAdd(a,b,c);}//调用了libDynamicLibraryTest.so动态库中的方法jstring jGetDynamicName(JNIEnv *env,jobject instance,jstring firstName,jstring lastName){char * name= getDynamicName((char*)env->GetStringUTFChars(firstName,0),(char*)env->GetStringUTFChars(lastName,0));return env->NewStringUTF(name);;}//入门程序  hello form c++
jstring stringFromJNI(JNIEnv *env, jobject instance) {std::string hello = "Hello from C++  动态注册";return env->NewStringUTF(hello.c_str());
}//内部自定义c函数的调用,非第三方库
jint add(JNIEnv *env, jobject clazz, jint a, jint b) {return a + b;
}/*** Native层,改变Java层对象的属性*/
void changeName(JNIEnv *env, jobject clazz, jobject person){//获取person class对象//FindClass("com/gitbaike/cmake/model/Person"); 这里获取的是class类,不是对象jclass  personObject=env->GetObjectClass(person);//这里获取的是对象//获取setName方法的方法IDjmethodID setNameId=env->GetMethodID(personObject,"setName", "(Ljava/lang/String;)V");char *setNewName="Native 层赋予你的新名字:";jstring str=env->NewStringUTF(setNewName);//这里注意,第一个参数需要是jobject对象,所以传入的是person,而不是personObject(jclass对象)env->CallVoidMethod(person,setNameId,str);
}/*** Native层,返回一个新的Person对象*/
jobject getNewPerson(JNIEnv *env,jobject clazz){jclass newPerson= env->FindClass("com/gitbaike/cmake/model/Person");jmethodID personMethod=env->GetMethodID(newPerson,"<init>", "(ILjava/lang/String;)V");jint  age=88;char * name="gitbaike";jstring jName=env->NewStringUTF(name);jobject  person=env->NewObject(newPerson,personMethod,age,jName);return person;
}/*** Native层,返回一个新的Person对象集合* 返回java层一个list*/
jobject getListPerson(JNIEnv *env,jobject clazz){
//因为list是无法实例对象,找到Arraylist,返回class对象jclass jclass1 = env->FindClass("java/util/ArrayList");//拿到构造函数idjmethodID contructMethod = env->GetMethodID(jclass1,"<init>","()V");//生成一个Arraylist对象,就是我们要返回的对象jobject list = env->NewObject(jclass1,contructMethod);//拿到 list的 add方法的methodId,准备往method添加几个数据jmethodID methodAdd = env->GetMethodID(jclass1,"add","(Ljava/lang/Object;)Z");//拿到Person的class对象jclass studentClass = env->FindClass("com/gitbaike/cmake/model/Person");//拿到person的构造函数的methodIdjmethodID jmethodID1 = env->GetMethodID(studentClass, "<init>", "(ILjava/lang/String;)V");for(int i =1;i<=4;i++){char * name="tl";char newName[50]="";
//        std::to_string(i)
//       char * iStr=( char *)i;strcat (newName, name);char * is=reinterpret_cast<char*>(&i);strcat (newName, is);jobject person = env->NewObject(studentClass,jmethodID1,i,env->NewStringUTF(newName));//调用 list的add方法,因为返回时boolean值,所以CallBooleanMethodenv->CallBooleanMethod(list,methodAdd,person);}return list;
}//动态注册
jint RegisterNatives(JNIEnv *env) {jclass clazz = env->FindClass("com/gitbaike/cmake/MainActivity");if (clazz == NULL) {LOGE("con't find class: com/gitbaike/cmake/MainActivity");return JNI_ERR;}JNINativeMethod methods_MainActivity[] = {{"stringFromJNI", "()Ljava/lang/String;", (void *) stringFromJNI},{"add",           "(II)I",                (void *) add},{"changePersonName", "(Lcom/gitbaike/cmake/model/Person;)V",(void *) changeName},{"getPerson", "()Lcom/gitbaike/cmake/model/Person;",(void *)getNewPerson},{"getPeronList", "()Ljava/util/List;",(void *) getListPerson},{"addSum", "(III)I",(void *)addSum},{"dynamicAdd", "(III)I",(void *) jDynamicAdd},{"getDynamicName", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",(void *) jGetDynamicName}};// int len = sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]);return env->RegisterNatives(clazz, methods_MainActivity,sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]));
}jint JNI_OnLoad(JavaVM *vm, void *reserved) {JNIEnv *env = NULL;if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {return JNI_ERR;}jint result = RegisterNatives(env);LOGD("RegisterNatives result: %d", result);return JNI_VERSION_1_6;
}}

第三步:Android Java层调用JNI native函数

java调用:

package com.gitbaike.cmake;import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;import com.gitbaike.cmake.databinding.ActivityMainBinding;
import com.gitbaike.cmake.model.Person;
import com.google.gson.Gson;import java.util.List;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";// Used to load the 'cmake' library on application startup.static {System.loadLibrary("cmake");}private ActivityMainBinding binding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());//         Example of a call to a native methodTextView tv = binding.sampleText;tv.setText(stringFromJNI());HNPCInit();Person person=new Person();person.setAge(12);person.setName("java person");Log.d(TAG,"调用本地方法前: person.getName:"+person.getName());changePersonName(person);Log.d(TAG,"调用本地方法后: person.getName:"+person.getName());Person nPerson=getPerson();Log.d(TAG,"调用本地方法 getPerson()后: person:"+nPerson.toString());List<Person> personList=getPeronList();Log.d(TAG,"调用本地方法 getPerson()后: personList:"+new Gson().toJson(personList) );Log.d(TAG,"调用本地方法 (引用第三方静态库.a)addSum:"+addSum(10,15,65));Log.d(TAG,"调用本地方法 (引用第三方动态库.so)dynamicAdd:"+dynamicAdd(100,200,300));Log.d(TAG,"调用本地方法 (引用第三方动态库.so)getDynamicName:"+getDynamicName("hello","  https://nav.vpssw.com  --->程序员网址导航<---"));}/*** A native method that is implemented by the 'cmake' native library,* which is packaged with this application.*/public native String stringFromJNI();public native void HNPCInit();public native int add(int a,int b);public  native void changePersonName(Person mPerson);public native Person getPerson();public native List<Person> getPeronList();public native int addSum(int a,int b,int c);public native int dynamicAdd(int a,int b,int c);public native String getDynamicName(String firstName,String lastName);}

源码已经上传:https://download.csdn.net/download/qingfeng812/88301421

android studio cmake生成.a文件(静态库)及调用(c c++)静态库.a
android studio cmake生成so文件(动态库)及调用(c c++)动态库.so
java调用c函数 c函数调用java
jni静态注册与动态注册。
代码都是我跑通过的。
运行环境
as版本:Android Studio Giraffe | 2022.3.1 Patch 1
android AGP 8.1.1
gradle 版本8.0
jdk 17

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MASM32编程状态栏显示字符动画,按钮跑马灯

一、需求分析 由于sysInfo扫描的内容比较多&#xff0c;打算为它增加一点动画效果&#xff0c;提醒用户程序正在运行&#xff0c;耐心等待。 二、构建测试窗口 测试窗口上放置有一个按钮&#xff0c;按钮上的初始文字是“开始扫描”&#xff1b;并使用状态栏&#xff0c;状态…

微波系统中散射参量S、阻抗参量Z及导纳参量Y之间的关系及MATLAB验证

微波系统中散射参量S、阻抗参量Z及导纳参量Y之间的关系及MATLAB验证 用HFSS设计了一微波元件&#xff0c;仿真出了其散射参量S、阻抗参量Z及导纳参量Y&#xff0c;用MATLAB验证他们之间的关系 HFSS设计螺旋线圈 用HFSS设计了一个螺旋线圈&#xff0c;如上图所示。 进行仿真&…

框架分析(8)-React Native

框架分析&#xff08;8&#xff09;-React Native 专栏介绍React Native特性和优势跨平台开发&#xff1a;热更新原生性能组件化开发第三方库支持社区支持 限制和挑战性能问题第三方库兼容性学习曲线 总结 专栏介绍 link 主要对目前市面上常见的框架进行分析和总结&#xff0c…

用「渣男」心态去面试,爽翻!

转载自博学谷公众号&#xff01; 面试是一场“销售”自己的考试&#xff0c;很多程序员掌握的技术、知识都非常过关&#xff0c;但在面试中却不能完全展现出来&#xff0c;屡屡发挥失常。 同样是天选打工人 别人的offer&#xff0c;像猴子摘苞谷&#xff0c;应接不暇 而你的of…

NFTScan 浏览器正式版上线 2 周年!

NFTScan 成立于 2021 年 4 月份&#xff0c;总部位于香港。在 2021 年的 7 月份&#xff0c;NFTScan 团队对外发布了 NFTScan 浏览器公测版&#xff0c;并在同年的 9 月 4 号&#xff0c;对外发布了 NFTScan 浏览器正式版&#xff0c;同步启用了全球品牌域名&#xff1a;NFTSCA…

pycharm创建的虚拟环境为什么用conda env list命令查询不到?

问题描述&#xff1a;pycharm创建的虚拟环境为什么用conda env list命令查询不到。 pycharm开发环境可以创建虚拟环境&#xff0c;目的是为隔绝其他环境种库带来的版本干扰&#xff0c;但是发现一个问题&#xff0c;无论是在windows终端、anaconda终端、Pycharm开发环境中的终…

WebStorm软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 WebStorm是一款由JetBrains开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专门用于开发Web应用程序。它支持多种前端技术&#xff0c;如HTML、CSS、JavaScript、TypeScript等&#xff0c;并提供了丰富的功能和工具&…

第三方软件检测机构有哪些资质,2023年软件测评公司推荐

软件第三方测试报告 伴随着软件行业的蓬勃发展&#xff0c;软件测试也迎来了热潮&#xff0c;但是国内的软件测试行业存在着测试入行门槛低、测试投入少、测试人员专业性不足等问题&#xff0c;这些问题不但会阻碍软件测试行业的良性发展&#xff0c;而且难以保证软件产品的质…

DR IP-SoC China 2023 Day演讲预告 | 龙智Perforce专家解析芯片开发中的数字资产管理

2023年9月6日&#xff08;周三&#xff09;&#xff0c;龙智即将亮相于上海举行的D&R IP-SoC China 2023 Day&#xff0c;呈现集成了Perforce与Atlassian产品的芯片开发解决方案&#xff0c;助力企业更好、更快地进行芯片开发。 D&R IP-SoC China 2023 Day 是中国首个…

html 标签简介

概述 标签的效果不重要&#xff0c;重要的是标签的语义。 文本标签 文本标签用于包裹&#xff1a;词汇、短语等。排版标签&#xff0c;比如div,p,h1等。排版标签更宏观&#xff08;大段的文字&#xff09;&#xff0c;文本标签更微观&#xff08;词汇、短语&#xff09;。文…

uniapp中UView中 u-form表单在v-for循环下如何进行表单校验

1、数据data格式 注&#xff1a;rule绑定的tableFromRule中要和表单tableFrom下面放置一个同名数组&#xff0c;确保u-form能找到 tableFrom: {tableData: [//数据详情列表]},tableFromRule: {//校验tableData: [//数据详情列表]},formRules:{localation:[{required: true,mes…

css让多个盒子强制自动等宽

1.width: calc( 100 / n‘%" ) 2.display:flex; flex:1;width:100px;&#xff08;width是几都行 只要保证一样就可以 会自动等分&#xff09; 3.display:grid;grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); 但是其中某一个内容较长的时候 会破坏1:1:1的…

MySQL的内置函数复合查询内外连接

文章目录 内置函数时间函数字符串函数数学函数其他函数 复合查询多表笛卡尔积自连接在where中使用子查询多列子查询在from中使用子查询 内连接外连接左外连接右外连接 内置函数 时间函数 函数描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳…

HarmonyOS—UI开发性能提升的推荐方法

注&#xff1a;本文转载自HarmonyOS官网文档 开发者若使用低性能的代码实现功能场景可能不会影响应用的正常运行&#xff0c;但却会对应用的性能造成负面影响。本章节列举出了一些可提升性能的场景供开发者参考&#xff0c;以避免应用实现上带来的性能劣化。 使用数据懒加载 开…

【OpenCV入门】第五部分——图像运算

文章结构 掩模图像的加法运算图像的位运算按位与运算按位或运算按位取反运算按位异或运算图像位运算的运用 合并图像加权和覆盖 掩模 当计算机处理图像时&#xff0c;有些内容需要处理&#xff0c;有些内容不需要处理。能够覆盖原始图像&#xff0c;仅暴露原始图像“感兴趣区域…

基本介绍——数据挖掘

1.数据挖掘的定义 数据挖掘是采用数学的、统计的、人工智能和神经网络等领域的科学方法&#xff0c;如记忆推理、聚类分析、关联分析、决策树、神经网络、基因算法等技术&#xff0c;从大量数据中挖掘出隐含的、先前未知的、对决策有潜在价值的关系、模式和趋势&#xff0c;并…

串的定义,实现和模式匹配

串的相关概念及操作 串的定义 串&#xff1a;是由零个或多个字符组成的有限序列。 空串&#xff1a;不包含任何字符的串称为空串。 子串&#xff1a;串中任意个连续的字符组成的子序列称为该串的子串。 空格串&#xff1a;由一个或多个空格组成的串称为空格串&#xff08;空格…

冯诺依曼体系结构/什么是OS?

一、体系结构图 示意图 控制器可以控制其它4个硬件&#xff0c;四个硬件直接可以进行数据传输。 5大硬件 但是这些个体需要用“线”连接。 为什么要有存储器&#xff1f; 如果没有&#xff0c;实际速度则为输入、输出设备的速度。 加上后&#xff0c;变为内存的速度。&#…

SquirrelMail实现Web方式收发邮件_xionglling的博客-CSDN博客

SquirrelMail实现Web方式收发邮件_xionglling的博客-CSDN博客小松鼠实现Web邮件服务SquirrelMail 是一个用PHP开发的Web邮件系统。它内置纯PHP支持的IMAP和SMTP协议&#xff0c;所有页面都遵循 HTML 4.0标准(没有使用任何 JavaScript 代码)&#xff0c;以便最大限度兼容各种多浏…

【程序员必知必会3】你还不懂ClickHouse和Hive的区别?!

ClickHouse和Hive究竟哪些区别 ClickHouse和Hive都是用于大数据处理和分析的分布式存储和计算系统&#xff0c;但它们之间存在一些区别&#xff1a; 架构&#xff1a;ClickHouse采用列式存储和向量化执行引擎&#xff0c;可以实现亚秒级别的数据查询。而Hive采用基于Hadoop的数…