相信很多人对于NDK 开发都是懵逼的,比如都知道把加密的逻辑以及密钥放在so文件中,但是你知道怎么生成so文件吗?你知道开发jni吗?你熟悉jni语法吗?怎么配置android studio 中的NDK环境?此时你一定很懵逼,我也是从这过来的,我不能帮助你开发Ndk,但是我可以让你不懵逼。
Eclipse ndk开发这么古老的方法我就不说了,其实我也不会。有需要的可以去百度,这里讲一下android studio。顺便说一下百度上有很多很坑的文章,自己没动手做过不知道,文章晦涩难懂,而且有些地方一言蔽之,搞不清方向,必须仔细过滤,才能发现。所以我总结了这篇文章
一、NDK相关角色概述
1、NDK和SO
NDK 全称 Native Development Kit,是Google在Android开发中提供的一套用于快速创建native工程的一个工具。从上图这个Android系统框架来看,我们上层是通过JNI方式来调用NDK层的,使用这个工具可以很方便的编写和调试JNI的代码。因为C语言不跨平台,在Windows系统下使用NDK编译在Linux下能执行的函数库——SO文件,全称Shared Objects,其实质就是一堆c、c++的头文件和实现文件打包成一个库。目前Android系统目前支持以下七种不同的CPU架构,每一种对应着各自的应用程序二进制接口ABI:(Application Binary Interface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。
- ARMv5——armeabi
- ARMv7 ——armeabi-v7a
- ARMv8——arm64- v8a
- x86——x86
- MIPS ——mips
- MIPS64——mips64
- x86_64——x86_64
以本人ODM经验来说,你应该尽可能的提供专为每个ABI优化过的.so文件,(尽量不要混合着使用)。你应该为每个ABI目录提供对应的.so文件。当一个应用安装在设备上,只有该设备支持的CPU架构对应的.so文件会被安装。在x86设备上,libs/x86目录中如果存在.so文件的 话,会被安装,如果不存在,则会选择armeabi-v7a中的.so文件,如果也不存在,则选择armeabi目录中的.so文件(因为x86设备也支 持armeabi-v7a和armeabi)。ps: Native Libs Monitor 这个应用可以帮助我们理解手机上安装的APK用到了哪些.so文件,以及.so文件来源于哪些函数库或者框架。
二、JNI
JNI 全称Java Native Inteface,即Java本地接口,是Java中定义的一种用于连接Java和C/C++接口的一种实现方式。Java语言装载到虚拟机中,不能和硬件交互,不能驱动开发。JNI扩展了Java虚拟机的能力,驱动开发、无线热点共享,底层语言(C、C++)效率高,数学运算、实时渲染的游戏,音视频处理等等,简而言之,就是Java代码调用c、c++代码,JNI模式一共涉及到三个角色:C/C++ 代码、本地方法接口类、Java层中具体业务类
1、JNI简要流程
2、JNI的变量类型与Java类型对比表
Java中变量的类型 | JNI对应的类型名 | C/C++变量类型 |
---|---|---|
boolean | jboolean | unsigned char |
float | jfloat | float |
double | jdouble | double |
byte | jbyte | signed char |
char | jchar | unsigned short |
short | jshort | short |
int | jint/jsize | int |
long | jlong | long long |
Object | jobject | void * |
String | jstring | void * |
3、JNI的基本语法
JNIEXPORT jstring JNICALL
Java_xiao_mi_jni_JNITest_getJniStr(JNIEnv *env, jclass type) {
return (*env)->NewStringUTF(env, "Hello from JNI!");
}
-
命名规则
jstring
--------->返回值类型
xiao_mi_jni
--->包名
JNITest
--------->类名
getJniStr
------->方法名
-
Java加载so
static {
System.loadLibrary("jnitest");//加载so文件,不要带上前缀lib和后缀.so
}
ps:以前不明白上边注释的这句话,只有自己去看才能明白为什么,所以我用AS打开了apk,原来打包出来的都是前缀加lib后缀加.so的文件格式。
4、Gradle
Gradle 是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置。以往Android NDK开发需要在Eclipse或源码环境下,建立并配置Android.mk和Application.mk,且还要通过java命令生成.h头文件,才能编译生成so库。但在Android Studio中这些步骤都不需要,因为Gradle足够强大,只需配置Gradle即可编译生成so库。
三、开发JNI的步骤
JNI代码主要又分为Native代码和Java代码,所以我们得实现Native端和Java端
1、安装NDK配置环境变量和相关插件(NDK、CMake、LLDB)
下载完之后 会自动下载到sdk里面
2、新建一个Android标准工程,并在工程设置中配置NDK路径。
3、打开app下的 build.gradle,配置NDK和在gradle.properties里配置android.useDeprecatedNdk=true
defaultConfig {
applicationId "xiao.mi.jni"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
ndk{
moduleName "jnitest"//*生成的so文件名,必填
abiFilters "armeabi-v7a", "x86" //配置输出的abi体系结构下的so库,
}
}
配置gradle.properties
文件
android.useDeprecatedNdk=true
4.在类中定义jni本地接口方法。
public class JNITest {
public static native String getJniStr();
public static native String processBitmap(Bitmap bitmap);
}
5、生成对应的C文件默认实现
在我们定义了本地接口方法之后,我们在方法上按alt+Enter,然后生成对应的方法,可是不出意外的话生成的c文件只是有一个头文件的,并没有为我们生成对应的方法框架,
#include <jni.h>
如果你熟悉Jni的语法可以自己去实现,但是太麻烦了,幸好谷歌为我们提供了一个插件gradle-experimental,我们只需要在app下的gradle.build脚本里配置(仅仅在我们生成jni方法框架时添加,当我们全部添加完JNI方法框架之后,必须注释或者删除掉,否则run的时候就绝对报错)
- gradle-experimental插件
在2015年5月的Google I/O大会上, Google宣布Android Studio开始支持NDK开发,通过和JetBrains的合作,将Clion整合进了Android Studio 1.3,并免费支持NDC++开发。同年7月,在Android Studio 1.3版本上添加了 gradle-experimental插件,该插件支持NDK开发和调试,且带有代码不全和重构等高级功能。
2.3版本的studio 已经整合了这个插件不用开发者自己手动去添加依赖。(必须配置好ndk开发的环境才能这样去做,不然会没反应的)
所以定义好本地方法之后,按alt+enter就会出现下边的页面。
点击左边的两个箭头,点击就可以跳转到本地方法去,也很方便。