文章目录

  • 一、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开发流程

  1. 编写 Java 类,声明了Native方法。
  2. 编写 Native 代码。
  3. 将 Native 代码编译成so文件。
  4. 在 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件事。

  1. 加载动态链接库 jnitestdemo,这个库的名字在 CMakeLists.txt 文件中的 add_library() 中声明指定。
  2. 通过 JNI 从 Native 层获取 String 类型的数据。
  3. 定义一个返回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());
}

小结:

  1. JNIEXPORT 和 JNICALL 是JNI中所定义的宏,所以需要引入 <jni.h> 这个头文件。
  2. 因为方法返回了一个 String 类型的数据,所以引入 C++ 的 <sting> 库。
  3. extern “C” 的作用:指示编译器按C语言(而不是C++)的方式进行编译。
    • C编译:C语言的方法签名只包含方法名,不包含参数,所以C语言中不存在方法重载。
    • C++编译: C++的方法签名包含方法名和含参数,所以存在方法重载。
  4. jobect对象:jobject 表示Java对象中的this,如果是静态方法则表示jclass。
  5. JNIEnv对象:代表Java调用Native层的环境,一个封装了几乎所有的JNI方法的指针。其只在创建它的线程有效,不能跨线程传递,不同的线程的JNIEnv彼此独立。

到这里,一个简单的 Native 工程就已经构建完成了,也完成了 Java 对 Native 方法的调用。

NDK(一):NDK 的集成相关推荐

  1. 【Android NDK 开发】NDK 交叉编译 ( NDK 函数库目录 | Linux 交叉编译环境搭建 | 指定头文件目录 | 指定函数库目录 | 编译 Android 命令行可执行文件 )

    文章目录 I . NDK platforms 目录下的 函数库 II . Ubuntu 配置 NDK 交叉编译环境 III . 同时指定编译的头文件和库文件 IV . 指定编译的头文件 V . 指定编 ...

  2. 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 ...

  3. NDK R20编译Ffmpeg集成Android命令

    本次编译环境为windows,linux和mac大同小异(windows都异类了,其他环境编译没啥问题) 下载好MINGW,咋个配置的,百度吧,忘了. 下载好NDK文件,我是R20版本的:在从ffmp ...

  4. android studio ndk 书籍,NDK 在AndroidStudio3.2.1版本集成方法(ndk-build方式)

    在 java 类里写个native方法 public class Java2CJNI { public native String java2C(); } 复制代码 javah 生成jni样式的标准头 ...

  5. 【Android NDK 开发】Android NDK 下载 ( 下载指定历史版本 NDK | Android NDK r10e - 2015 年 5 月 )

    文章目录 一.下载指定历史版本 NDK 一.下载指定历史版本 NDK 进入到 ndk 下载的 " 修订历史记录 " 页面 https://developer.android.goo ...

  6. linux下配置ndk路径,NDK调试arm-linux-androideabi-addr2line工具的使用

    作用 arm-linux-androideabi-addr2line看工具名称就知道是将内存地址转换成行号,具体点就是根据so库抛出的Error日志的中内存地址,找到具体是在那个文件的哪一行出现的该错 ...

  7. eclipse adt开发android ndk没有NDK选项问题的解决方案

    原创 2015年01月28日 09:38:40 标签: android ndk / eclipse / adt 15989 今天是2015年1月28号,整理一下昨天使用eclipse adt搭建的an ...

  8. android ndk 10d,NDK r10d 升级 NDK r16b

    NDK 升级变化 一. r10c 添加clang 3.5 的支持,NDK_TOOLCHAIN_VERSION=clang 会使用3.5版本的clang 弃用gcc 4.6 ,并且会在后续版本中移除gc ...

  9. android jni不适用ndk,Android NDK编译之undefined reference to 'JNI_CreateJavaVM'

    利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...

  10. android 不会ndk,Android ndk找不到atof功能

    我试图在我的 Android项目中使用开源C库.该库使用atof()函数.我知道atof()是标准C库(stdlib.h)中定义的函数.因此,它应该在Android NDK(仿生库)上的标准C库中实现 ...

最新文章

  1. C++:MFC SetTimer定时执行某一函数;
  2. 自然语言处理笔记2-哈工大 关毅
  3. zigbee 万能遥控器 裸机发送和协议栈发送
  4. 图论 —— 环与块 —— 连通块的计数
  5. JSP页面是否需要重新编译--checkInterval
  6. 80 后技术人的中年危机
  7. Mybatis-plus的两种分页插件的配置方式
  8. 【LeetCode 剑指offer刷题】发散思维题2:43 n个骰子的点数
  9. UVA-10859 - Placing Lampposts(树形DP)
  10. instanceof constructor Object.prototype.tostring.call ( [] )区别 数组和 对象的3中方法
  11. Java设计模式-工厂模式
  12. PHPExcel 插件使用详解
  13. 用友畅捷通T+漏洞学习——DownloadProxy.aspx 任意文件读取漏洞
  14. CMMI 4高级别过程改进案例介绍
  15. 参考文献引用详细教程
  16. excel如何把多张表合并成一个表_如何将多个 Excel 工作簿的工作表合并成一个工作表?...
  17. 慕课软件工程(第五章.初始模块结构图的设计)
  18. pthread_cond_wait pthread_cond_broadcast
  19. 陶朗食品业务调整为两个业务版块,专注新鲜食品和加工食品
  20. 易拉罐被证实能增强WiFi信号 手机笔记本均适用

热门文章

  1. 钉钉发送消息(非群机器人)
  2. 为方便大家,我分析导出了些高速下载器捆绑软件的反安装reg,需要的可自行选择
  3. 51单片机定时器的查询和进入中断处理
  4. Android手机,charles安装证书时提示“键入凭据存储的密码”问题
  5. 《乔布斯传》经典摘录(七)
  6. Tello talent无人机扩展模块库分析(default.ino)
  7. 图解最常用的 10 个机器学习算法
  8. Elasticsearch学习2 SpringBoot整合 测试复杂检索
  9. 忘记了word文件打开密码
  10. 学生上课睡觉班主任怎么处理_“佛系教师”语录:小孩是别人的,成绩是校长的,饭碗是自己的...