一 JNI和NDK 相关介绍
1 什么是JNI
jni 全称 java native interface 即java 本地接口 ,是java 平台的特性,主要定义了native方法,目的实现java 和 c/c++代码互相调用
,能够使java文件代码使用到C/C++语言. JNI不局限于android平台,(window的dll文件,linux 的so库)
2 使用JNI的作用
1)加密:产品核心或重要功能代码的保护,由于APK的Java层代码很容易被反编译,而C/C++库反汇难度较大。对代码加密这一块有比较大的保护作用;
2)执行效率:因为c/c++比Java效率高,所以应用运行起来速度比较快,特别是一些游戏中的算法;
2)使用成熟的C/C++库:在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。所以可以有更多的可用库,方便一些特殊的实现方式;
3)便于移植:用C/C++写的库可以方便在其他的嵌入式平台上再次使用,比如图片视频处理算法:FFmpeg;
4)底层实现:因为Android应用程序是跑在虚拟机上面,所以有些底层的硬件调用需要使用更底层的语言去调用,比如一些驱动拓展之类的。
4 使用NDK 作用
1, 运行效率高,在开发中采用c++更加有效,如果使用本地方法执行算法,算法执行效率更高
2,代码安全性高,因为java 是半解释性语言,使用java语言开发容易反编译得到java源代码,例如jar包反编译,但是如果使用so反编译则不会,提高了代码的安全性
5 JNI 和 NDK 的关系
jni 是java 和c/c++互调的目的 ,ndk 是 android 中实现的过程方法,另外 NDK 提供了把.so和apk一起打包的工具.NDK提供的库有限,仅用于处理算法效率和敏感的问题,提供了交叉编译器,用户生成特定CPU平台的动态库
二 使用步骤(注意这里是用as2.2.2开发)
流程大致 :
下载ndk->as配置ndk环境->写java需要用到c++的类->生成.h头文件->写c++代码->生成so库->引用so库实现调用(注意我们这里使用as开发不需要创建android.mk文件,因为as自己会创建,如果使用eclipse则需要在编写c++代码下一步创建android.mk文件)
1,下载ndk, 这里去下载,下载完成之后解压,我这里是放到sdk目录里面了
2 在as里面讲as与ndk关联
3,配置local.properties
进入local.properties添加,目的是指明sdk 和 ndk路径
ndk.dir=I\:\\android_studio_sdk\\ndk-bundle sdk.dir=I\:\\android_studio_sdk
4,配置gradle.properties,目的是旧版本ndk也有效
android.useDeprecatedNdk=true
5, 开始编写java 文件,新建ndkone应用,并新建JNIUtils类,声明sayHelloFromJNI()接口
6, 在终端terminal用指令生成JNIUtils对应的.h头文件
在as terminal窗口,使用命令:
cd app/src/main/java
javah -d ../jni com.jn.ndkone.JNIUtils
刷新项目,会在main目录下也就是与java同级目录生成jni文件夹,在文件里面会有.h头文件,文件名称com_jn_ndkone_JNIUtils.h
7,选中jni文件夹右键,创建c++资源文件,即c/c++ source file 文件名选择.cpp,因为是编写c++,如果编写c,则文件类型是.c
我这里新建JNIHello.cpp
8 开始编写c++代码,如上图所示,首先是导入
#include "com_jn_ndkone_JNIUtils.h"
然后实现声明接口里面的方法
JNIEXPORT jstring JNICALL Java_com_jn_ndkone_JNIUtils_sayHelloFromJNI (JNIEnv *env, jclass) { return env->NewStringUTF("Hello World From JNI!!!!!"); }9 在 app的build.gradle里的在defaultConfig括号里面添加
ndk { moduleName"JNIHello" //对应c文件名 }
注意我这里没有加abiFilter 架构适配,默认处理器都适配,都生成.so文件
10,然后再java本地接口的那个类添加静态代码块
static { System.loadLibrary("JNIHello"); }
11,然后可以在mainActivity里面调用这个类的这个方法
期间我出现了
就是因为我在build.gradle下面添加了
//生成对应 平台so库,去掉则默认生成全部so库 abiFilters "armeabi", "armeabi-v7a","x86"
最后我点击报错第一行,读了代码
应该是abi过滤相关的,于是我去掉然后就ok了