NDK之配置环境,Hello-JNI,批量处理,多编译文件,面向多CPU架构
写在前面
作为一个android开发新人,NDK成了一项必要掌握的技能,于是我挤了些时间总结一下最近对NDK的学习。
目录
第一章:
一、NDK简介
二、NDK使用场景/优缺点
第二章:
三、NDK环境配置
四、第一个NDK程序-Hello-JNI
五、ANT脚本-自动运行javah命令,批量处理
六、如何同时编译多个源文件
七、面向多种CPU架构编译
第三章
八、NDK中C与C++的区别
..........
开始
一、NDK简介
对NDK进行了粗略的研究后,我对“NDK是什么”的理解如下:
1、NDK是一系列工具的集合。
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。
NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。
NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。
2、NDK提供了一份稳定、功能有限的API头文件声明。
Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。
二、NDK使用场景/优缺点
三、NDK环境配置
1.配置eclipse的安卓环境
2.下载最新版本的NDK-r10,并解压,如图:
3.打开eclipse,配置NDK路径:
Window->preferences->Android->NDK
四、第一个NDK程序-Hello-JNI
1.新建一个android工程
2.新建一个Activity展示结果,新建两个要调用本地jni的类,如图:
(1)
(2)
3.执行javah -jni com.elvis.android_elvis_note.GetString命令:如图:
就会生成相应的.h文件:
(1)
(2)
4.右键项目工程->Android Tools->Add Native Support
此时,填入一个Library Name--例如填写“elvis”:
然后你就会发现项目工程多了一个jni文件夹:
5.接下来对HelloNDK.cpp进行更改:
5.对MainActivity文件进行更改,别忘记这里要加载动态链接库:
6.可能遇到的问题:
1)如果出现问题Unresolved inclusion: <jni.h>
解决方案:
选中工程,右键->Properties,点击C/C++ General展开,点击 Path and Symbols,在右边Includes下,点击Add,把NDK文件夹下的jni头文件和相应的C++头文件添加进来。一定要填写完整的路径,比如我添加的两个路径分别是: E:\AndroidNDK\android-ndk-r10c\toolchains\mipsel-linux-android-4.8\prebuilt\windows-x86_64\lib\gcc\mipsel-linux-android\4.8\include
E:\AndroidNDK\android-ndk-r10c\platforms\android-19\arch-arm\usr\include
如下图所示:
大家在自己的NDK文件安装目录下参照我的路径找到相应的include文件夹,添加包含路径,再重新编译,就不会报错了。
五、ANT脚本-自动运行javah命令,批量处理:
1.新建ant文件:
2.更改xml文件
3.将脚本添加到ant空间,双击运行
六、如何同时编译多个源文件:
1.新建SecondClass类c++类:
(1)
(2)
2.更改Android.mk文件:
3.源文件的方法就可以在源文件之间调用了:
七、面向多种CPU架构编译
1.你会发现你的程序只能够在arm架构的处理器上运行,这是为啥呢?看下图:
原因很简单,程序编译的时候只生成了对arm处理器的处理文件。那么我进行如下配置就可以面向多种cpu架构编译了。
2.新建Application.mk文件,并进行设置:
(1)
(2)
3.重新编译,就生成了两种cpu架构的文件:
八、NDK中C与C++的区别
由于Android官方NDK例子大多使用C语言编写,所以当我们想用C++进行开发时,会出现种种错误。下面简单说说几点不同之处:
1.先来一个用C写的例子:
(1)hello.c文件。在C中没有引用,传递的env是个两级指针,用(*env)->调用方法且方法中要传入env.
(2)Android.mk文件,更改后缀名为.c
2.再来一个用C++写的例子:
(1)hello.cpp文件。C++中env为一级指针,用env->调用方法,无需传入env;C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern "C"进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名;exter "C"{jni代码}。
(2)Android.mk文件,更改后缀名为.cpp
..........
// 如果觉得不错,记得顶我哦! 顶我!顶我!顶我!