什么是JNI(Java Native Interface)呢?
Java Native Interface(JNI)标准是java平台的一部分,JNI是Java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用C/C++代码,C/C++的代码也可以调用Java代码。
JNI即为java的本地接口(C和C++开发的接口)由于JNI是JVM规范的一部分,因此我们可以将我们写的JNI程序在任何实现了JNI规范的Java虚拟机中运行.这个特性使我们可以复用以前大量的C和C++代码.
开发JNI程序会受到系统环境的限制.因为用C/C++写出来的代码和模块,编译过程当中要依赖当前操作系统环境所提供的一些函数库,并和本地库链接在一起.而且编译后生成的二进制代码只能在本地操作系统的环境下运行,因为不同的操作系统环境,有自己本地库和CPU指令集,而且各个平台堆标准C/C++的规范和标准库函数实现方式也有区别.这就造成了JNI接口的Java程序不再像以前那样自由的跨平台.如果要实现跨平台,就必须将本地代码在不同的操作平台编译出相应的动态库
JNI的作用:使得Java与本地其他类型语言交互(C/C++)。即在Java代码里调用c、c++等语言代码或者c、c++代码调用java代码.
JNI开发流程主要分为以下六步:
---> 1.编写声明了native方法的类
---> 2.将Java源代码编译成class字节码文件
---> 3.用javah-jni命令生成.h头文件
---> 4.用本地代码实现.h文件中的函数
---> 5.将本地代码编译成动态库
---> 6.拷贝动态库至java.library.path本地库搜素目录下,并允许Java程序
注意(Warring)
1.JNI是java调用的Native语言的一种特性
2.JNI是属于java的,与Android无直接关系
为什么要又JNI呢?
实际使用中,java需要与本地代码进行交互.因为java具备跨平台的特点,所有java与本地代码交互能力非常弱,所以采用JNI特性增强java与本地代码交互的能力
什么是NDK?
Native Development Kit(NDK)是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和java一起打包成apk。
定义:Native Development Kit,是Android的一个工具开发包
NDK是属于Android的,与java并无直接关系
作用:快速开发c、c++的动态库,并自动将so和应用一起打包成APK
即可通过NDK在android中,使用JNI与本地代码(如c、c++)交互
应用场景:在Android的场景下使用JNI即Android开发的功能需要本地代码(c\c++)实现
NDK开发具有以下有点:
1、项目需要调用底层的一些C/C++的一些东西(java无法直接访问到操作系统底层(系统硬件等)),或者已经在C/C++环境下实现了功能代码(大部分现存的开源库都是用C/C++代码编写的。)直接使用即可。
2、为了效率更加高效些。将要求高性能的应用逻辑使用C/C++开发,从而提高应用程序的执行效率。但是C/C++代码虽然是高效的,在java与C/C++相互调用时却增大了开销。
3、基于安全性考虑。防止代码被反编译,为了安全起见,使用C/C++语言来编写重要的部分以增大系统的安全性,最后生成so库(用过第三方库的应该都不陌生)便于给人提供方便。
4、便于移植。用C/C++写的库可以方便在其他的嵌入式平台上再次使用。
注意事项
JNI和NDK的关系
NDK可以为我们生成了C/C++的动态链接库,JNI是java和C/C++沟通过的接口,两者与android没有半毛钱关系,只因为安卓是java程序语言开发,然后通过JNI又能与C/C++沟通,所以我们可以使用NDK+JNI来实现Java+C的开发方式。
Studio实现步骤
1.首先将NDK导入进来
第二步骤与第三步骤都在Ctrl+Alt+S--->Tools--->Extermal Tools
2.第二步将.javah导入
Arguments:-classpath $ModuleFileDir$\src\main\java -jni -d $ModuleFileDir$\src\main\jni $FileClass$
Working directory:$ModuleFileDir$\src\main\java
3.配置ndk
Working directory:$ModuleFileDir$\src\main\
4.在build.gradle加入
sourceSets {
main.jniLibs.srcDirs = ['libs']
}
5.首先定义一个关于C/C++的代码
6.右击找到External Tools--->javah - jni --->生成com_baidu_cdemo4_MainActivity.h文件
7.将生成的.h文件复制一份改为.c
8.修改部分代码
.h:(JNIEnv *, jclass);
.c:(JNIEnv *env, jclass clazz){
char *a ="我是卫浩森的dad";
return (*env)->NewStringUTF(env,a);
};
9.写入两个mk文件加入.c和.h同级别目录下
Android.mk:(注意将Android.mk自动生成的jnittest.c切换成.c的类名)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myLib
LOCAL_SRC_FILES := 类名.c
include $(BUILD_SHARED_LIBRARY)
Application.mk:APP_ABI := all
10.将生成的libs包拷贝到与app同级别的libs包下
11.右击选择External Tools ---> ndk - build
12.回到主方法写一个代码块调用C/C++代码
调用
在Activity中测试调用,在TextView上显示我们通过C++代码实现的方法getStrFromC获取字符串。
如果缺省jniLibs.srcDirs=[] 会报如下错误
当调用so文件时必须在配置文件中配置如下图
否则调用可能会有问题。将编译生成的中间文件和源代码删除。
Android studio 下载NDK和构建工具
1、Android原生开发工具包(NDK):这套工具集允许您开发Android使用C和C++代码,并提供众多平台库,让您可以管理原生Activity和访问物理设备组件,例如传感器和触摸输入。
2、CMake:一款外部构建工具,可与Gradle搭配使用来构建原生库。如果您只计划使用ndk-build,则不需要此组件。
3、LLDB:一种调试程序,Android Studio使用它来调试原生代码。
您可以使用 SDK Manager安装这些组件:
1、在打开的项目中,从菜单选择Tools > Android >SDK Manager.
2、点击SDK Tools标签
3、选中LLDB、CMake和NDK旁的复选框 如下图所示:
创建支持 C/C++ 的新项目
创建支持 原生代码 的项目与创建任何其他 Android Studio 项目类似,不过支持原生代码的项目还需要额外几个步骤:
1. 在向导的 Configure your new project 部分,选中 Include C++ Support 复选框。
2. 点击 Next。
3. 正常填写所有其他字段并完成向导接下来的几个部分。
4. 在向导的 Customize C++ Support 部分,您可以使用下列选项自定义项目
5.C++ Standard:使用下拉列表选择您希望使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的CMake 设置,这个选项如果你现在还不确定该选哪个,最好选择 C++11 的标准。
6. Exceptions Support:如果您希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
7. Runtime Type Information Support:如果您希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。