Android 中的 NDK 到底是什么?(详细解析+案例实战)

NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk;这些工具对开发者的帮助是巨大的


什么是NDK?

Android原生开发包NDK(NativeDelopmentkits)将用于Android平台上的C++开发

AndroidNDK是Android软件开发包(SDK)的相关工具集,用来扩展AndroidSDK的功能,从而是开发人员能够使用机器代码生成的编程语言(如C、C++和汇编语言)实现一些对代码行要求较高的模块并将这些模块嵌入到Android应用程序中

众所周知,Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C/C++之类的原生代码语言执行部分程序

NDK的定义

AndroidNDK不是一个单独的工具:它是一个包含API、交叉编译器、链接程序、调试器、构建工具、文档和实例应用程序的综合工具集

在Android的官方文档上是这么解释NDK的:“原生开发套件(NDK)是一套工具,使您能够在Android应用中使用C和C++代码,并提供众多平台库,您可使用这些平台库管理原生Activity和访问物理设备组件;例如传感器和轻触输入”

NDK是一个Android官方提供的一个开发套件与AndroidSDK相对应,NDK是原生开发套件,而SDK是JAVA开发套件。NDK使得Android应用可以利用C++语言高效的计算性能,进一步提升App的性能,降低延迟。

说道这里,大家肯定要问NDK有那些应用场景,我为什么要用NDK呢,用JAV不行吗?

下面列举一些NDK的应用场景

重用一些现成的库,例如已经用C/C++编写好的openCV库前面提到的高性能计算,例如很多Bitmap的处理到放在NDK进行处理一些敏感信息的保护,例如密钥等信息(密钥等信息还是要经过加盐才能放到NDK中,不然还是会有别反编译的风险)知道了应用场景,大家肯定已经摩拳擦掌准备试一试了,先别着急。欲善其事,先利其器;以下给出了开发NDK的三大利器;

NDK的三大开发组件

NDKAndroid原生开发套件

CMAKE外部编译工具

LLDB原生代码调试工具

NDK开发优点

利用NDK开发的库,不容易被反编译,保密性,安全性都提高了

很多开源工程和大工程都是C/C++代码写的

C/C++的代码运行速度和效率都比Java快很多

AndroidNDK开发步骤

(1)JNI接口设计;(2)使用C/C++本地实现方法;(3)生成动态链接库;(4)将动态链接库复制到Java工程,运行Java程序

NDK基础实践CMake

推荐使用CMake而不是传统NDK-build的方式,既然都用新的,自然有它的道理,简单方便有很多人在配置时编译不通过,是自己的问题吗?当然,难不成还是它的问题吗?

首先我们想要打出一个.so文件来,我们肯定是要先写Java代码

第一步:

解释一下这里代码的意思:native这个就是我们提供出去的方法,这个方法到时候要和.c文件里面或者.cc文件里面的方法名一致,我们再静态中去加载我们打出来的.so文件,这里的参数名字不是.so文件的名字,而是我们在打包的时候配置的名字,这个配置下面介绍

publicclassJniKit{//这里的方法名如果报错那是正常的,不影响publicstaticnativeintcalculate(intnum);static{("JniDemo");}}
第二步:

我们需要根据这个写好的Java文件来生成一个.h文件,生成.h文件是通过javah来执行的,这里我之前尝试了各种办法,但是网上说的办法都没办法成功,都是报错说找不到类文件,我觉得这里可能和我的文件的方法有点问题,等会我把我现在成功的文件目录贴出来,执行的代码

javah-classpathD:\360PhoneInfo\small-video-record-master\SmallVideoRecord2\testndk\build\intermediates\classes\}

根据这个代码我得到了.h文件,包括这个jni文件夹也是通过-djni这个生成出来的,不是自己创建的

第三步:
这句是设置生成的cpu指令类型,提示,目前绝大部分安卓手机支持armeabi,libs下太多类型,编译进去apk包会过大APP_PLATFORM:=android-8#这句是设置最低安卓平台,可以不弄

3、因为我的这两个文件是和.放在同一个文件夹中-jni,所以我们要执行ndk-build命令需要进入到jni文件夹下再去执行

这里给一个范例,传入字符串调用so库中的方法

publicclassJniUtil{static{("JniUtil");}publicstaticnativevoidinitialize(Stringstring,StringlogPath);}
extern"C"JNIEXPORTvoidJNICALLJava_com_kxqin_livingrecognitiondemo_JniUtil_initialize(JNIEnv*env,jclassjclazz,jstringjstring1,jstringlogPath){//获取字符串指针,必须使用指针,不能使用charstrContent[],因为GetStringUTFChars()返回值为constchar*;constchar*str=env-GetStringUTFChars(jstring1,JNI_FALSE);constchar*path=env-GetStringUTFChars(logPath,JNI_FALSE);std::stringlog=path;std::stringstring=str;//头文件中的方法defence_native_initialize(string,log);//LOGD("initializeissuccess");}

然后直接(String1,String2)就可以调用到cpp中的方法了

试试在Terminal中输入

将${ABI}换为你的ABI,正常情况下在模拟器上使用就是x86,真机就是armabi-v7a或arm64-v8a,或许能帮你解决不少麻烦

总结

通过前面详细的讲解,我想各位读者应该对NDK有一个清晰的认识了下面让我在最后用一句话总结那就是NDK则是Android妈咪谷歌提供的一种开发工具套件



免责声明:本文章如果文章侵权,请联系我们处理,本站仅提供信息存储空间服务如因作品内容、版权和其他问题请于本站联系