NDK(一):NDK 的集成
文章目录
- 一、JNI 简介
- 二、NDK是什么
- 三、NDK配置
- 四、NDK 工程目录
- 4.1 目录结构
- 4.2 build.gradle
- 4.3 CMakeLists文件
- 五、工程实践
一、JNI 简介
JNI (Java Native Interface,Java本地接口)是一种编程框架,使得Java虚拟机中的Java程序可以调用本地应用/或库,也可以被其他程序调用。 本地程序一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。
关联文章:
- NDK(一):NDK的集成
- NDK(二):JNI的数据结构
- NDK(三):JNIEnv解析
- NDK(四):Native与Java层互调
- NDK(五):JNI静态注册与动态注册
要编写 JNI 就得需要集成 JNI的开发环境(NDK)。接下来我们看一下如何编写Android JNI ,以及需要的流程。
二、NDK是什么
NDK(Native Development Kit缩写)一种基于原生程序接口的软件开发工具包,可以让您在 Android 应用中利用 C 和 C++ 代码的工具。通过此工具开发的程序直接在本地运行,而不是虚拟机。
在Android中,NDK是一系列工具的集合,主要用于扩展Android SDK。NDK提供了一系列的工具可以帮助开发者快速的开发C或C++的动态库,并能自动将so和Java应用一起打包成Apk。同时,NDK还集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so文件。
三、NDK配置
Step1: NDK 相关工具的下载。
Step2: 配置好后,新建一个 Native 工程。
Step3: 选择C++的版本。
到这里,一个 Native 的工程就已经创建完成了。下面我们看下这个 NDK 工程的相关信息。
四、NDK 工程目录
4.1 目录结构
整体工程目录结构如下图所示,与普通的 Android 工程目录相比,Native工程目录中多了一个 cpp 目录,以及目录内对应的 CMakeList.txt
文件。
4.2 build.gradle
除了 cpp 文件夹的区别外,我们再来看下 build.gradle 的区别。
可以看到,相比普通的 Android 应用,build.gradle 配置中多了两个 externalNativeBuild
配置项。
- defaultConfig里面的的 externalNativeBuild 主要是用于配置Cmake的命令参数。
- 外部的 externalNativeBuild 的主要是定义了 CMake 的构建脚本 CMakeLists.txt 的路径。
4.3 CMakeLists文件
接下来我们来看一下 CMakeLists.txt 文件,CMakeLists.txt 是 CMake 的构建脚本,作用相当于 ndk-build 中的 Android.mk,代码如下。
# 设置CMake最小版本
cmake_minimum_required(VERSION 3.18.1)# 设置项目名称
project("jnitestdemo")# 编译library,生成链接库jnitestdemo。如果当前这个链接库与其它库有关联,可以使用target_link_libraries进行关联。
add_library(# 设置library名称jnitestdemo # 设置library模式# SHARED模式会编译so文件,STATIC模式不会编译SHARED# 设置原生代码路径native-lib.cpp)# 查找log的路径,并赋值给log-lib这个变量。
find_library(log-lib log)# 将两个链接库关联到一起。
target_link_libraries(# 指定要关联其它lib的库,这里指当前的jnitestdemo。jnitestdemo# 将log-lib关联到jnitestdemo上(相当于是jnitestdemo依赖log-lib)。${log-lib})
关于 CMake 部分的相关内容,可以查看 CMake 教程。
五、工程实践
上面介绍了工程的配置部分,下面我们来具体看下项目中的代码。
JNI开发流程
- 编写 Java 类,声明了Native方法。
- 编写 Native 代码。
- 将 Native 代码编译成so文件。
- 在 Java 类中引入so库,调用 Native 方法。
其中第1,4步在Java层,第2步在Native层,第3步属于打包编译流程。
Java 层:
下面演示的是 Java 代码调用 Native 代码获取一个字符串的流程。
package com.elson.jnitestdemo;public class MainActivity extends AppCompatActivity {static {// 1.加载动态链接库System.loadLibrary("jnitestdemo");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView textView = findViewById(R.id.sample_text);// 2.通过JNI从Native层获取数据。textView.setText(stringFromJNI());}// 3.定义一个Native函数。public native String stringFromJNI();
}
Java层主要做了3件事。
- 加载动态链接库 jnitestdemo,这个库的名字在 CMakeLists.txt 文件中的 add_library() 中声明指定。
- 通过 JNI 从 Native 层获取 String 类型的数据。
- 定义一个返回String类型的 Native 函数给步骤2中使用。
Native 层:
下面看下 Native 层的代码实现。
#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
Java_com_elson_jnitestdemo_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}
小结:
- JNIEXPORT 和 JNICALL 是JNI中所定义的宏,所以需要引入 <jni.h> 这个头文件。
- 因为方法返回了一个 String 类型的数据,所以引入 C++ 的 <sting> 库。
- extern “C” 的作用:指示编译器按C语言(而不是C++)的方式进行编译。
- C编译:C语言的方法签名只包含方法名,不包含参数,所以C语言中不存在方法重载。
- C++编译: C++的方法签名包含方法名和含参数,所以存在方法重载。
- jobect对象:jobject 表示Java对象中的this,如果是静态方法则表示jclass。
- JNIEnv对象:代表Java调用Native层的环境,一个封装了几乎所有的JNI方法的指针。其只在创建它的线程有效,不能跨线程传递,不同的线程的JNIEnv彼此独立。
到这里,一个简单的 Native 工程就已经构建完成了,也完成了 Java 对 Native 方法的调用。
NDK(一):NDK 的集成相关推荐
- 【Android NDK 开发】NDK 交叉编译 ( NDK 函数库目录 | Linux 交叉编译环境搭建 | 指定头文件目录 | 指定函数库目录 | 编译 Android 命令行可执行文件 )
文章目录 I . NDK platforms 目录下的 函数库 II . Ubuntu 配置 NDK 交叉编译环境 III . 同时指定编译的头文件和库文件 IV . 指定编译的头文件 V . 指定编 ...
- NDK from ndk.dir at ndk-bundle had version [22.1.7171670] which disagrees with android.ndkVersion [2
NDK from ndk.dir at C:\Users\FT\AppData\Local\Android\Sdk\ndk-bundle had version [22.1.7171670] whic ...
- NDK R20编译Ffmpeg集成Android命令
本次编译环境为windows,linux和mac大同小异(windows都异类了,其他环境编译没啥问题) 下载好MINGW,咋个配置的,百度吧,忘了. 下载好NDK文件,我是R20版本的:在从ffmp ...
- android studio ndk 书籍,NDK 在AndroidStudio3.2.1版本集成方法(ndk-build方式)
在 java 类里写个native方法 public class Java2CJNI { public native String java2C(); } 复制代码 javah 生成jni样式的标准头 ...
- 【Android NDK 开发】Android NDK 下载 ( 下载指定历史版本 NDK | Android NDK r10e - 2015 年 5 月 )
文章目录 一.下载指定历史版本 NDK 一.下载指定历史版本 NDK 进入到 ndk 下载的 " 修订历史记录 " 页面 https://developer.android.goo ...
- linux下配置ndk路径,NDK调试arm-linux-androideabi-addr2line工具的使用
作用 arm-linux-androideabi-addr2line看工具名称就知道是将内存地址转换成行号,具体点就是根据so库抛出的Error日志的中内存地址,找到具体是在那个文件的哪一行出现的该错 ...
- eclipse adt开发android ndk没有NDK选项问题的解决方案
原创 2015年01月28日 09:38:40 标签: android ndk / eclipse / adt 15989 今天是2015年1月28号,整理一下昨天使用eclipse adt搭建的an ...
- android ndk 10d,NDK r10d 升级 NDK r16b
NDK 升级变化 一. r10c 添加clang 3.5 的支持,NDK_TOOLCHAIN_VERSION=clang 会使用3.5版本的clang 弃用gcc 4.6 ,并且会在后续版本中移除gc ...
- android jni不适用ndk,Android NDK编译之undefined reference to 'JNI_CreateJavaVM'
利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...
- android 不会ndk,Android ndk找不到atof功能
我试图在我的 Android项目中使用开源C库.该库使用atof()函数.我知道atof()是标准C库(stdlib.h)中定义的函数.因此,它应该在Android NDK(仿生库)上的标准C库中实现 ...
最新文章
- C++:MFC SetTimer定时执行某一函数;
- 自然语言处理笔记2-哈工大 关毅
- zigbee 万能遥控器 裸机发送和协议栈发送
- 图论 —— 环与块 —— 连通块的计数
- JSP页面是否需要重新编译--checkInterval
- 80 后技术人的中年危机
- Mybatis-plus的两种分页插件的配置方式
- 【LeetCode 剑指offer刷题】发散思维题2:43 n个骰子的点数
- UVA-10859 - Placing Lampposts(树形DP)
- instanceof constructor Object.prototype.tostring.call ( [] )区别 数组和 对象的3中方法
- Java设计模式-工厂模式
- PHPExcel 插件使用详解
- 用友畅捷通T+漏洞学习——DownloadProxy.aspx 任意文件读取漏洞
- CMMI 4高级别过程改进案例介绍
- 参考文献引用详细教程
- excel如何把多张表合并成一个表_如何将多个 Excel 工作簿的工作表合并成一个工作表?...
- 慕课软件工程(第五章.初始模块结构图的设计)
- pthread_cond_wait pthread_cond_broadcast
- 陶朗食品业务调整为两个业务版块,专注新鲜食品和加工食品
- 易拉罐被证实能增强WiFi信号 手机笔记本均适用
热门文章
- 钉钉发送消息(非群机器人)
- 为方便大家,我分析导出了些高速下载器捆绑软件的反安装reg,需要的可自行选择
- 51单片机定时器的查询和进入中断处理
- Android手机,charles安装证书时提示“键入凭据存储的密码”问题
- 《乔布斯传》经典摘录(七)
- Tello talent无人机扩展模块库分析(default.ino)
- 图解最常用的 10 个机器学习算法
- Elasticsearch学习2 SpringBoot整合 测试复杂检索
- 忘记了word文件打开密码
- 学生上课睡觉班主任怎么处理_“佛系教师”语录:小孩是别人的,成绩是校长的,饭碗是自己的...