Android 使用 jni Demo示例

news2024/10/6 18:30:14

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.coloradmin.cn/o/78025.html

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

相关文章

RabbitMQ - 安装和使用

RabbitMQ - 安装和使用一. 安装二. RabbitMQ的简单使用2.1 创建交换机2.1.1 交换机类型2.1.2 持久化方式2.2 创建队列2.3 绑定交换机和队列2.4 SpringBoot整合2.5 另外一种监听写法一. 安装 一键安装&#xff1a; docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 …

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…

Java基础之《netty(10)—Reactor三种模式》

一、单Reactor单线程模式 1、工作原理图 2、方案说明 &#xff08;1&#xff09;Select是前面I/O复用模型介绍的标准网络编程API&#xff0c;可以实现应用程序通过一个阻塞对象监听多路连接请求。 &#xff08;2&#xff09;Reactor对象通过Select监控客户端请求事件&#xf…

一元钱注册 chatGPT账号

文章目录打开 openai chatgpt 主页注册 chatGPT 账号找境外的电话号码激活账号查看服务价格账号注册充值成功参考视频 打开 openai chatgpt 主页 打开之前首先登录 vpn。但是使用 vpn 有可能还是会被告知 当前国家没有开放服务个人建议&#xff1a; 使用美国的 ip 地址我使用…

PIN TO PIN替代GM8775C|DSI转LVDS转换方案芯片CS5518|CS5518完全替代GM8775C

GM8775C 型 DSI 转双通道 LVDS 发送器产品主要实现将 MIPI DSI 转单/双通道 LVDS 功能&#xff0c;MIPI 支持 1/2/3/4 通道可选&#xff0c;最大支持 4Gbps 速率。LVDS 时钟频率最高 154MHz&#xff0c; 最大支持视频格式为 FULL HD&#xff08;1920 x 1200&#xff09; CS551…

网络安全观察报告

攻击类型分析 2018 年&#xff0c;主要的攻击类型 1 为 SYN Flood&#xff0c;UDP Flood&#xff0c;ACK Flood&#xff0c;HTTP Flood&#xff0c;HTTPS Flood&#xff0c; 这五大类攻击占了总攻击次数的 96&#xff05;&#xff0c;反射类攻击不足 3%。和 2017 年相比&…

测评报告:文件导入哪家强?

文件导入哪家强&#xff1f; 引子 最近业务上遇到一个场景&#xff0c;需要将一个/多个文本文件导入到与其结构对应的表中。功能需求比较简单&#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电平信…

78.【大二实训--《宿舍管理系统》】

大二实训--《宿舍管理系统》1.在JSP中&#xff0c;如果想要获取后端传过来的数据2.在Dao层我们用数据库的属性给实体类赋值的时候3.在一个Servlet中&#xff0c;如果想要使用多个Service4.字符串yyyy-mm-dd格式转换为Date型5.在设置实体类的时候&#xff0c;属性名开头一定要小…

IDEA创建JavaWeb项目并配置Tomcat

本文教给各位使用IDEA创建web项目&#xff0c;配置tomcat进行访问&#xff0c;好了&#xff0c;下面进入正题 IDEA分为社区版和企业版&#xff0c;区别在于&#xff0c;社区版免费&#xff0c;企业版收费&#xff0c;但有30天免费使用期&#xff0c;到期后会提示你进行激活&am…

MySQL 单表查询

1.简单查询 1.1 SELECT语句 SELECT [DISTINCT] * |字段名1&#xff0c;字段名2&#xff0c;... FROM 表名 [WHERE 条件表达式1] [GROUP BY 字段名 [HAVING 条件表达式2]] [GROUP BY 字段名 [ASC | DESC]] [LIMIT [OFFSET] 记录数]1.2 查询指定字段 SELECT 字段1,字段2,... F…

【深入理解 —— js闭包】

&#x1f9c1;个人主页&#xff1a;个人主页 ✌支持我 &#xff1a;点赞&#x1f44d;收藏&#x1f33c;关注&#x1f9e1; 文章目录js闭包&#x1f380; 什么是闭包&#xff1f;&#x1fa70; 执行上下文&#xff08;执行环境&#xff09;&#x1f367;解释闭包的含义&#x…

Linux 黑马

1.1虚拟机介绍1.2VMware Workstation虚拟化软件 下载CentOS; 5分钟教你下载安装VMware16虚拟机&#xff08;含许可证密钥&#xff09;【全免费VMware虚拟机 上集】_哔哩哔哩_bilibili 1.3远程链接Linux系统 &FinalShell 1.4拓展WSL(Ubuntu)环境 Win11>可选功能>…

愿你被这个世界温柔以待(第二十课)最优秀的仓库Gitee

愿你被这个世界温柔以待(第二十课)最优秀的仓库Gitee 在追梦的道路上 相信自己一定能变的更加优秀 看下面操作流程图:如果你觉自己的学习能力很强跟着下面的流程图片去走 图片教学 上传一份项目如何做 下面的是图片教学 看到上面的图片操作可能看不懂 Giteej基本操作命令行 初…

Photoshop简单案例(9)——利用PS去水印的四种方法

目录一、项目介绍二、简单水印2.1 水印原图2.2 去除步骤2.3 去除效果三、文件水印3.1 水印原图3.2 去除步骤3.3 去除效果3.4 拓展四、内容识别法4.1 水印原图4.2 去除步骤4.3 去除效果一、项目介绍 本文将介绍利用PhotoShop去水印的四种方法。 二、简单水印 2.1 水印原图 对…

我敢打赌,90%的测试人员都不理解Git

01 概念 1、Git本地有四个工作区域&#xff1a; 工作目录&#xff08;Working Directory&#xff09; 暂存区&#xff08;Stage/Index&#xff09; 资源库&#xff08;Repository或Git Directory&#xff09; git仓库&#xff08;Remote Directory&#xff09; 文件在这四…

深度学习设计模式(一):编写高质量代码的基础(多例子+代码)

学习如何编写高质量代码前言面向对象面向对象编程&#xff0c;面向对象编程语言面向对象分析 &#xff0c;面向对象设计封装&#xff0c;抽象&#xff0c;继承&#xff0c;多态封装抽象继承多态面向对象比面向过程有哪些优势&#xff0c;面向过程过时了&#xff1f;什么是面向过…

MyBatisPlus入门

目录 概述 SpringBoot继承MyBatisPlus CRUD 新增 删除 修改 查询 条件构造器 全局配置 相关注解 ActiveRecord 插件 分页插件 防止全表删除插件 乐观锁插件 乐观锁插件的使用 逻辑删除 使用逻辑删除 扩展 自动填充 Sql注入器 代码生成器Generator 代码生成器MyBa…

Seata 分布式事务你懂吗?学习了大咖的笔记,公司说要给我涨薪 8K

分布式事务处理过程的-ID三组件模型&#xff1a; 关于事务的基本概念 Seata 是阿里开源的分布式事务解决方案中间件&#xff0c;对业务侵入小&#xff0c;在应用中 Seata 整体事务逻辑基于两阶段提交的模型&#xff0c;核心概念包含三个角色&#xff1a; TM&#xff1a;事务发…

听说你还在自己做重复劳动?看我一键生成错误码映射

大家在工作中定义错误码的时候都是如何处理的&#xff1f; xdm 可以评论区交流交流 我看到过有的是这样定义错误码的&#xff1a; m : make(map[int]string)m[0] "OK"m[1] "链接失败"m[2] "文件类型错误"... 还看到过这样定义错误码的&#x…