Android 使用 jni Demo示例

news/2024/4/29 21:56:02/文章来源:https://blog.csdn.net/gvvbn/article/details/128262987

Android 使用 jni Demo示例

  • 简介
    • 1. NDK的介绍
      • 1.1 NDK 简介
      • 1.2 NDK 特点
    • 2. JNI介绍
      • 2.1 JNI 简介
      • 2.2 为什么要有 JNI?
    • 3. NDK 与 JNI 的关系
  • NDK下载及环境配置
    • 1. 使用Android studio SDK Manager下载
    • 2.配置NDK
      • 2.1 配置环境变量
      • 2.2 Android studio配置NDK
  • 示例Demo流程
    • 1.版本介绍
    • 2.Demo创建到运行流程
    • 3.添加JNI LOG
    • 4.生成SO
    • 5. Demo 地址

简介

1. NDK的介绍

1.1 NDK 简介

NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

Native Development Kit,是 Android的一个工具开发包
NDK是属于 Android 的,与Java并无直接关系

应用场景:在Android的场景下 使用JNI


即 Android开发的功能需要本地代码(C/C++)实现

1.2 NDK 特点


特点
在这里插入图片描述

额外注意
在这里插入图片描述

2. JNI介绍

2.1 JNI 简介

定义:Java Native Interface,即 Java 本地接口
作用: 使得 Java 与本地其他类型语言(如C、C++)交互

即在 Java 代码里调用 C、C++ 等语言的代码或  C、C++ 代码调用 Java 代码

特别注意:

  1. JNI 是 Java 调用 Native 语言的一种特性
  2. JNI 是属于 Java 的,与 Android 无直接关系

2.2 为什么要有 JNI?

背景:实际使用中,Java 需要与 本地代码 进行交互
问题:因为 Java 具备跨平台的特点,所以Java 与 本地代码交互的能力非常弱
解决方案: 采用 JNI特性 增强 Java 与 本地代码交互的能力

3. NDK 与 JNI 的关系

在这里插入图片描述

NDK下载及环境配置

1. 使用Android studio SDK Manager下载

点击Android studio 工具栏的 SDK Manager:
在这里插入图片描述
或者按照路径 File > Settings > Appearance & Behavior > System Settings > Android SDK或者Tool > SDK Manager打开SDK Manager 界面
在这里插入图片描述
选择SDK Tools 条目,勾选NDK和CMake后点击apply按钮等待下载完即刻
在这里插入图片描述
下载完成之后,ndk的位置在你的Android sdk目录下方,有一个ndk的文件夹。

2.配置NDK

2.1 配置环境变量

点击我的电脑右键,选择属性
在这里插入图片描述
关于里面找到高级系统设置 ,点击
在这里插入图片描述
点击环境变量
在这里插入图片描述
点击系统变量Path
![在这里插入图片描述](https://img-blog.csdnimg.cn/fe4e6e88e0be42358822301d042739a3.png
添加ndk地址
在这里插入图片描述
在CMD窗口输入ndk-build 验证成功
在这里插入图片描述

2.2 Android studio配置NDK

下面是网上的流程,如果你可以用就直接用这个方法:
在这里插入图片描述
在这里插入图片描述

注意:实际上在我自己在我的Android studio中配置时,NDK Location是不可选择的状态,download也是如此,我来分享一下我在Android studio的配置过程

首先,我在 local.properties 中手动添加本地ndk.dir路径
在这里插入图片描述

但是,实际上这样仅仅是在刚刚的NDK Location显示了路径,查阅了官方文档,发现ndk.dir已弃用。
按照官方文档的说明,在我们从 SDK Manager 下载完成后,应该自动同步build文件
在这里插入图片描述

那么,你可以试着进入File — > Project Structure —> Modules
在这里插入图片描述
在这里插入图片描述

这样,我的问题就已经解决了,希望能给你带来参考!

示例Demo流程

1.版本介绍

Android Studio版本
在这里插入图片描述
在这里插入图片描述

2.Demo创建到运行流程

新建项目,创建成功后,
在这里插入图片描述

接下来开始写自定义的一个 native方法,新建一个 JniText.java文件,里面写一个 sayHello() 方法
在这里插入图片描述
点击Terminal cd 进入 java目录下 ,执行 javah -classpath . -jni com.android.test.jnidemo.JniText ,生成 com_android_test_jnidemo_JniText.h

// javah -classpath . -jni 包名.类名。
javah -classpath . -jni com.android.test.jnidemo.JniText

在这里插入图片描述

com_android_test_jnidemo_JniText.h 代码如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_android_test_jnidemo_JniText */#ifndef _Included_com_android_test_jnidemo_JniText
#define _Included_com_android_test_jnidemo_JniText
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_android_test_jnidemo_JniText* Method:    sayHello* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_com_android_test_jnidemo_JniText_sayHello(JNIEnv *, jclass);#ifdef __cplusplus
}
#endif
#endif

main新建JNI Folder,将com_android_test_jnidemo_JniText.h 移到jni目录xia
在这里插入图片描述
在这里插入图片描述
点击jni文件夹选择C++ Class 新建一个C++类, 在这里插入图片描述
名字命名为JNIHello(这里会自动创建一个.h和.cpp文件,只用.cpp文件即可)
在这里插入图片描述
在这里插入图片描述
复制com_android_test_jnidemo_JniText.h 中的方法到JNIHello.cpp,并引用#include "com_android_test_jnidemo_JniText.h"
修改后的JNIHello.cpp如下:
注意:com_android_test_jnidemo_JniText.h中的是接口方法中的参数是(JNIEnv *, jclass)
JNIHello.cpp中的是实现方法中的参数是(JNIEnv *env, jclass type)

//
// Created by on 2022/12/10.
//#include "com_android_test_jnidemo_JniText.h"JNIEXPORT jstring JNICALL Java_com_android_test_jnidemo_JniText_sayHello(JNIEnv *env, jclass type){return env->NewStringUTF("Hello World From JNI!!!!!");
}

在jni目录下,添加一个Android.mk文件,其目录结构如下:
在这里插入图片描述
Android.mk文件里面编写如下内容

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)# 定义生成的so库名称(Hello.so),以及编译该库包含的源文件,
LOCAL_MODULE  := Hello
LOCAL_SRC_FILES := JNIHello.cpp# 定义生成动态so库
include $(BUILD_SHARED_LIBRARY)

关于Android.mk语言后面会单独写一篇文章进行讲解,这里重点说上面代码的内容

LOCAL_PATH := $(call my-dir):每个Android.mk文件必须以定义开始。它用于在开发tree中查找源文件。宏my-dir则由Build System 提供。返回包含Android.mk目录路径。
include $(CLEAR_VARS) :CLEAR_VARS变量由Build System提供。并指向一个指定的GNU Makefile,由它负责清理很多LOCAL_xxx。例如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES等等。但不是清理LOCAL_PATH。这个清理是必须的,因为所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能便面相互影响。
LOCAL_MODULE := ndkdemotest-jni:LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格。Build System 会自动添加适当的前缀和后缀。例如,demo,要生成动态库,则生成libdemo.so。但请注意:如果模块名字被定义为libabd,则生成libabc.so。不再添加前缀。
LOCAL_SRC_FILES := ndkdemotest.c:这行代码表示将要打包的C/C++源码。不必列出头文件,build System 会自动帮我们找出依赖文件。缺省的C++ 源码的扩展名为.cpp。
include $(BUILD_SHARED_LIBRARY):BUILD_SHARED_LIBRARY是Build System提供的一个变量,指向一个GUN Makefile Script。它负责收集自从上次调用include $(CLEAR_VARS)后的所有LOCAL_xxxxinx。并决定编译什么类型
BUILD_STATIC_LIBRARY:编译为静态库
BUILD_SHARED_LIBRARY:编译为动态库
BUILD_EXECUTABLE:编译为Native C 可执行程序
BUILD_PREBUILT:该模块已经预先编译

在jni目录下,在添加一个Android.mk文件,其目录结构如下:
在这里插入图片描述
Application.mk文件里面编写如下内容

 
APP_ABI := all

然后在build.gradle中添加如下代码:

 ndk {//如果要答应log就需要添加, 否者会报log函数未定义// ldLibs "log"指定生成模块名字,也就是最终的动态库名hello-jni,相应库文件名libhello-jni.so moduleName "hello-jni"moduleName "Hello"// 设置支持的SO库架构,根据实际系统配置so库存放路径abiFilters  'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'}
externalNativeBuild {ndkBuild {path "src/main/jni/Android.mk"}}

在这里插入图片描述
JniText添加如下代码:

 static  {System.loadLibrary("Hello");}

在这里插入图片描述
MainActivity调用JniText中的sayHello,代码如下:

 String result=JniText.sayHello();// 打印JNI本地方法返回的字符串。Log.d(TAG, "the string from JNC C '"+result + "'");

在这里插入图片描述
点击运行:
在这里插入图片描述
成功!!!!!!

3.添加JNI LOG

Android.mk配置文件里面加上下面的代码

LOCAL_LDLIBS :=-llog

注意Android.mk里有一行include $(CLEAR_VARS) 必须把LOCAL_LDLIBS :=-llog放在它后面才有用, 否则相当于没写

然后在jni文件集里面写log_help.h文件,内容如下

#ifndef JNIUTILSAS_ANDROID_UTILS_H
#define JNIUTILSAS_ANDROID_UTILS_H#include <android/log.h>#define TAG "TAG_JNI"#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) // 定义LOGD类型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) // 定义LOGI类型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) // 定义LOGW类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE类型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG, __VA_ARGS__) // 定义LOGF类型#endif //JNIUTILSAS_ANDROID_UTILS_H

使用,在.h或者.cpp文件中引用log_help.h,然后, LOGD("Hello World JNI LOG");


//
// Created by on 2022/12/10.
//
#include "android_utils.h"
#include "com_android_test_jnidemo_JniText.h"extern "C" JNIEXPORT jstring JNICALL Java_com_android_test_jnidemo_JniText_sayHello(JNIEnv *env, jclass type){LOGD("Hello World JNI LOG");return env->NewStringUTF("Hello World From JNI!!!!!");
}

运行结果如下:
在这里插入图片描述

4.生成SO

点击Terminal cd进入jni目录下 ,执行 ndk-build ,如下:
在这里插入图片描述
生成SO文件在libs文件下:
在这里插入图片描述

5. Demo 地址

AndroidJNIDemo

到此结束。

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

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

相关文章

【云原生】devops之jenkins中pipeline语法(2)

前言&#xff1a; pipeline语法分类一般来说&#xff0c;有四种。分别是环境配置、阶段步骤、行为动作、逻辑判断。 二、阶段步骤 &#xff08;1&#xff09;post 根据pipeline块或者stage块&#xff08;阶段&#xff09;完成的状态来进行一个或者多个附加步骤&#xff08;取决…

Gaussian 计算静电云图确定吸附位点

计算背景&#xff1a; 利用高分子有机物等活性材料对有毒分子、原子、离子在真空、水溶液、有机溶液等环境下吸附&#xff0c;已是当今环境科学、矿物学、土壤化学等学科领域研究的热点。但如何确定最佳吸附位点以计算其吸附能就显得尤为重要。 现阶段多数物质的吸附均依据粒…

【通信基础】TTL、RS232、RS485

TTL1、TTL简介RS2321、RS232基本概念2、DB9串口定义及接线参考3、RS232经典电路4、特点RS4851、RS485简介2、特点3、传输距离4、经典电路5、传输差分电平信号TTL 1、TTL简介 TTL的英文全称是Transisor-Transisor Logic. 翻译过来就是晶体管与晶体管之间的逻辑电路。 TTL电平信…

Java搭建宝塔部署实战毕设项目springboot销售培训考评系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的毕业设计项目springboot销售培训考评系统源码。 技术架构 技术框架&#xff1a;jQuery MySQL5.7 mybatis shiro Layui HTML CSS JS jpa运行环境&#xff1a;jdk8 IntelliJ…

Python 可迭代对象(Iterable)、迭代器(Iterator)与生成器(generator)之间的相互关系

1、迭代 通过重复执行的代码处理相似的数据集的过程&#xff0c;并且本次迭代的处理数据要依赖上一次的结果继续往下做&#xff0c;上一次产生的结果为下一次产生结果的初始状态&#xff0c;如果中途有任何停顿&#xff0c;都不能算是迭代。 # 非迭代例子 n 0 while n < …

java之注解的定义和使用

初识注解&#xff1a; 注解的概念&#xff1a; 注解是从JDK5.0开始引入的新技术&#xff0c;它不是程序本身&#xff0c;但是和注释有相同的作用&#xff0c;都能够对程序做出一定的解释&#xff0c;并且注解能够被其他编译器所读取 注解的格式&#xff1a; 注解是以“注释…

平均月薪15k+?自动化测试工程师?3个月教你从“点工”蜕变为“码农”

前言 一、自动化测试工程师平均收入【看图&#xff08;来自职友集&#xff09;】 基本收入都在15k左右&#xff0c;随着技术的越来越牛逼工资也就会越来越高。 我的职业生涯开始和大多数测试人一样&#xff0c;刚开始接触都是纯功能界面测试。那时候在一家电商公司做测试&…

[附源码]计算机毕业设计基于人脸识别的社区防疫管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SSRF漏洞详解与利用

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是SSRF漏洞详解与利用。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未授权设…

迭代器和生成器

文章目录迭代器和生成器图解迭代器和生成器的关系迭代器容器生成器yield函数生成器表达式总结迭代器和生成器 图解迭代器和生成器的关系 图1-1​ 不管是生成器还是我们的容器&#xff0c;最终都是迭代器&#xff0c;使用next方法进行有规律的获取元素&#xff0c;不需要将元素…

五问补盲(二) | 补盲激光雷达,角分辨率真的是越小越好吗?

HiEV消息&#xff08;文&#xff1a;爱LiDAR的小飞哥&#xff09; 如何简单地判断一款补盲激光雷达的成像效果&#xff1f; 业界通常有几个指标&#xff1a;视场角大小、测距范围&#xff0c;以及角分辨率。 一款优秀的补盲激光雷达&#xff0c;通俗来说&#xff1a;既要看得…

rtl8221b+mcu,2.5g光纤收发器的开发备份

1、rtl8221b是一款2.5g的光电转换的phy 系统的构建如下 为了省成本&#xff0c;不用mac来对接其中的gmii接口直接接光模块 2、mdio和mdc由mcu的gpio来模拟&#xff0c;在csdn上有很多的文章来参考 mdio的参数如下 不想看英文可以参考下面的文章 MDIO(clause 22 与 clause 4…

微服务框架 SpringCloud微服务架构 微服务保护 31 限流规则 31.2 流控模式【关联】

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务保护 文章目录微服务框架微服务保护31 限流规则31.2 流控模式【关联】31.2.1 流控模式31.2.2 流控模式 - 关联31.2.3 小结31 限流规则…

Python模块fileinput操作文件和目录操作总结

前言 之前介绍Python的 pathlib 模块可以有效的路径及文件查找等方便操作&#xff0c;本篇介绍一个相对 readlines() 获取文件内容更高效的用法 fileinput模块 对一个或者多个文件的内容迭代遍历&#xff08;类似文件操作的readlines()&#xff09;,但是返回的是迭代对象&…

【Linux】四、Linux 进程概念(三)|进程优先级|环境变量

目录 七、进程优先级 7.1 基本概念 7.1.1 什么是优先级 7.1.2 为什么存在优先级 7.1.3 Linux 优先级特点 7.2 查看系统进程 7.3 PRI 和 IN 7.4 查看进程优先级和更改进程优先级 7.5 其它概念 7.6 进程切换 八、环境变量 8.1 环境变量基本概念 8.2 常见环境变量 8…

English Learning - L1 站在高处建立灵魂 2022.12.5 周一

English Learning - L1 站在高处建立灵魂 2022.12.5 周一1.1 到底什么是语法1.2 为什么要学习语法口语分广义和狭义讲母语的人为啥不学语法&#xff1f;作为一名二语习得者口语中可不可以没有有语法&#xff1f;1.3 英语&#xff08;听说读写&#xff09;的核心金字塔理论关于词…

与图相关的一些矩阵

目录前言正文邻接矩阵(Adjacency matrix)度矩阵(Degree matrix)关联矩阵(Incidence matrix)拉普拉斯矩阵常规拉普拉斯矩阵拉普拉斯矩阵标准化前言 以无向图为例&#xff0c;介绍与图相关的各种矩阵。我们定义下面的图为 GGG&#xff1a; import networkx as nx import matplo…

redis cluster 集群安装

redis cluster 集群安装 redis集群方案 哨兵集群 如图&#xff0c;实际上还是一个节点对外提供服务&#xff0c;所以虽然是三台机器&#xff0c;但是还是一台机器的并发量&#xff0c;而且master挂了之后&#xff0c;整个集群不能对外提供服务 cluster集群 多个主从集群节点…

编写高质量代码 - 多线程和并发(2)

文章目录1. 使用线程异常处理器提升系统可靠性2. volatile不能保证数据同步3. 异步运算考虑使用Callable接口1. 使用线程异常处理器提升系统可靠性 我们要编写一个Socket应用&#xff0c;监听指定端口&#xff0c;实现数据包的接收和发送逻辑&#xff0c;这在早期系统间进行数据…

微信群营销方式微信群建群营销案例

今天我们以小区微信群营销为例&#xff0c;聊一聊具体的步骤和流程&#xff1a; 1、社群的建立&#xff0c;就是如何找到合适的小区&#xff0c;建立小区专属社群?因此&#xff0c;终端在做小区社群营销之前&#xff0c;需要先对当地所有的潜在小区做一个综合性的分析和评估&a…