现下很多同学甚至是公司有些过于崇尚NDK编程,觉得会使用NDK的人就更厉害。
经常发现一个做泛泛的大众化应用的公司,招聘要求第一行就是精通NDK编程。一个典型的码农型程序员开口闭口C++写安卓。
种种现象导致了我在相当一段长的时间里觉得NDK是一个很难的东西,其实同学们NDK对于我们来说就是一种工具,并没有什么大不了的。并且对于现阶段大多数应用的大多数情况中,你都不需要使用到NDK,在某些特殊情况下需要使用了,你会发现NDK其实也就是一种工具。
比如这次录制mp3音频,我就使用了NDK/JNI的技术,先去下载了一个关于mp3录制的C++工程,修改一些参数,接下来编译。(我是使用的eclipse,编译后so文件自动出现在lib文件夹下,但这里有个问题,编译生成的so文件会覆盖你的lib文件夹,也就是说lib文件夹里之前的文件可能会被清除,请注意),编译生成的so文件中的函数你就可以直接在java代码中引用了。所以说,NDK就是一个帮助你把C++/C编译成so库,并可以和你之前的工程打包成apk的工具。
好,接下来我们看我们需要做哪些准备工作。
1.下载NDK:https://developer.android.google.cn/ndk/downloads/index.html
此处注意,如果链接无法下载,你也可以去搜索其他资源,ndk工具的版本不一样提供的功能也有区别,比如我用r5版本时它提供的可编译平台就较少。后来改成r10版本,就可以编译出所有平台。所以建议您下载较新版本。
2.接着,我们需要实现linux环境 下载cygwin http://www.cygwin.com/ 。
因为NDK编译需要使用linux环境,cygwin是一个大家都推荐的windows平台上的虚拟环境,亲测确实挺好用的。
还有,需要注意的是,我搜索网上资源时,在选择需要安装的包时,网上众说纷纭,我选取了好几个版本尝试了几次,发现都有这样或那样的问题。像binutils,gcc,gcc-mingw,gdb等,因为本人并不能确认到底是哪个包需要又或者哪个包不需要,本人最终是选择了全部安装,这样下来才让接下来的工作没有发生问题。
所以,如果有同学因为不知道具体选择哪些包安装,而又不得其门而入时,可以尝试着全部安装,亲测公司网速一个下午安装完毕。
安装完毕后,可通过cygcheck -c cygwin,检测cygwin的运行状态。其他的还有gcc --version,g++ --version,make –version,gdb –version等命令,如果他们的信息都能显示出来,那么环境就安装成功了。
3.在下载下来的NDK包中就会有一些示例程序。
用cygwin进入制定目录后,就能使用ndk-build命令编译出so文件了,这里希望同学们稍微看一下这些示例程序中的c++代码,从里面就可以看到他定义的方法。好了,现在你就可以把so文件导入你的eclipse工程中去了。直接复制就行。
我是这样理解NDK的,NDK就是首先在Java文件中定义本地方法,这个方法将会在C++中实现,而你却可以在Java中调用。
public native static void XXXX();
然后你可以通过javah命令生成实现此方法的头文件。
在项目根目录下,进入java文件所在目录,javah xxx.xxxx.xxxx.xxxxx命令。注意,xxx.xxxx.xxxx.xxxxx是指你的java文件路径和名称。此处不带java文件后缀。执行完javah命令后,会生成一个.h文件。
在项目main目录下创建一个jni文件夹,并把上一步中的.h头文件转移到该文件夹下。
在jni目录下创建一个example.c的源文件,通过#include引入我们的头文件xxx.h,并把在头文件下的声明方法JNIEXPORT jstring JNICALL Java_com_sanhui_ndkdemo_Java2CJNI_java2C(JNIEnv *, jobject);复制到我们的example.c中,补全方法参数,并实现功能。
好了,至此我们的代码就已经编写完毕,接下来我们去项目的build.gradle中配置生成的so文件名和支持的平台,编译生成so库。
ndk{
moduleName "example" //so文件名
abiFilters "armeabi", "armeabi-v7a", "x86" //CPU类型
}
然后在你需要使用这个so库功能的java文件中,先载入这个库:System.loadLibrary("example"); example是指你的so文件名,不包含后缀。最后,你就可以在此Java调用你之前定义的本地方法了。