AndroidNDK ( Native Development Kit )实际上属于 JNI ( Java Native Interface )的一部分, JNI 就是允许 Java 代码和其他语言写的代码进行交互。 Android 基于 Java 平台,自然也是支持这个特征了,因此 Android NDK 就是支持在 Android 平台上使用 Java 语言调用采用 C/C++ 编译的库文件的一系列工具。 1. 下载: NDK
的下载页面为:http://developer.android.com/sdk/ndk/index.html
,当前最新版本为r8
,如下图所示: 2012-6-20 18:17 上传
下载附件 (21.93 KB) 前面我们说过Android SDK支持三种平台,这里相应的Android NDK也是分为三种平台Windows、Linux和 Mac OS X。其中Mac OS X 后面的括号中给出Intel。说明仅支持英特尔的硬件平台,即在英特尔的电脑上安装的Mac OS X系统才能使用该NDK,早期的苹果电脑使用的是非英特尔的硬件平台,所以这个对于苹果电脑用户而言需要是注意的。Linux平台后面的括号中给出x86,说明只支持运行在x86体系上的Linux平台。当然Windows平台早期还支持Alpha处理器,后来的版本就只支持x86体系了。鼠标点击链接后就开始下载相应的版本了。对Windows平台有特殊情结的可以使用Windows版本的NDK,当然需要Linux系统的模拟环境,最常用的就是Cygwin。苹果迷就直接用Mac OS X版本的NDK就行了。大多数用户,我们还是推荐使用Linux平台的NDK,下面我们就以Linux平台的NDK来配置NDK的开发环境。对于Linux环境,Google官方推荐平台是Ubuntu,我们这里用的是CentOS6.2版本,Linux不同版本对于开发来说大同小异,下面我们就以CentOS6.2来进行配置NDK。
2.NDK 的目录结构说明 : 下载Linux 平台的NDK 文件解压缩后看到的目录结构如下所示: 2012-6-20 18:25 上传 下载附件 (11.63 KB) build :进行编译时用到的脚本和一些补丁 docs :有关NDK 的相关文档 platforms :针对不同Android 发行版本进行编译用到的头文件和库文件 prebuilt :一些小工具,用于真正编译前的预处理阶段 samples :给出了一些NDK 的例子 sources :一些在编译过程中被脚本或其它工具用到的头文件和库文件 tests :执行NDK 的自动化测试,确保NDK 正式发布后能够正常运行 toolchains:具体进行编译时的工具,包括对三种架构arm、mips和x86的支持
3.NDK 配置 这个版本NDK的配置比较简单,前面的老版本还需要设置许多环境变量,这个版本不需要设置,直接解压缩就可以了。主目录android-ndk-r8下有一个脚本文件ndk-build,这个就是进行编译用的脚本程序。当然,如果运行脚本时不想输入ndk-build的路径的话可以将其所在路径加入到PATH环境变量中,具体的加入方式我们在前面的“Linux平台JDK安装”一文中已经讲过,在此就不重复了。要编译的文件放在一个目录下,一般就叫jni(也可以叫别的名字),把这个目录放在Android工程下,编译后的库文件缺省会自动放到Android工程的库文件目录libs中。我们以NDK自带的例子程序hello-jni为例,如下图所示: 2012-6-20 18:34 上传 下载附件 (11.5 KB) 在jni的目录中,包括编译配置用的脚本文件和C/C++两种文件,C/C++除了少量遵循JNI规范外,主要实际上都是Linux环境中C/C++编程而已。配置文件主要有两个:Android.mk和Application.mk。我们简单说一下这两个文件,一般的NDK开发就足够了,想详细了解的话可以阅读NDK中的相关文档。 以hello-jni例子中Android.mk文件为例,如下图所示: 2012-6-20 18:36 上传 下载附件 (4.34 KB) 上面两条是相关的参数和环境变量设置,我们不用管它。LOCAL_MODULE 右边的hello-jni 是编译后库的名字,LOCAL_SRC_FILES 右边的hello-jni.c 是C/C++ 源文件的名字,如果有多个源文件,只需要放在后面用空格隔开就行了,不需要把头文件放进来。最下面的BUILD_SHARED_LIBRARY 表示编译为动态库,如果要编译为静态库的话就应该是BUILD_STATIC_LIBRARY 。 文件Application.mk主要是对编译的补充,以native-plasma例子中的Application.mk为例,如下图所示: “APP_ABI ”的右边指定了所支持的处理器架构,本次版本的NDK 支持arm 、x86 和mips 三种。缺省是按arm 架构编译。APP_PLATFORM 的右边指定的是Android 平台的版本。缺省是按Android SDK 1.5 版本编译,版本越高所提供的特性也越多,不过能适配的Android SDK 版本也就越少,意味着能够使用该应用的用户也越少。 当然,NDK既支持C语言环境,也支持C++语言环境,不过对C++的特性支持要少一些,具体可以看文档中对C++支持的相关说明。另外在Android.mk和Application.mk中都可以加入对C/C++进行编译的一些编译选项,以例子san-angeles中的Android.mk文件为例,如下图所示: 2012-6-20 18:44 上传 下载附件 (6.94 KB) 和前面的相比,这里上边多了LOCAL_CFLAGS,它的右边就是编译选项,这个例子中包括两个ANDROID_NDK和DISABLE_IMPORTGL,每个选项前加上-D作为标识符。下边多了LOCAL_LDLIBS,它的右边是编译中用到的库,每个库名前加上-l作为标识符。 本版本的NDK 中有多个例子,我们简要说明一下这些的例子的具体作用,便于大家对这些例子有一个初步认识,至少知道每个例子引入的目的。 bitmap-plasma : 如何在NDK 中使用bitmap 的例子,早期的NDK 版本不能直接使用bitmap ,后来的版本中增加了对bitmap 的支持。 hello-gl2 : 在NDK 中如何使用OpenGLES 的运用 hello-jni : 最基本的NDK 使用方式,通过NDK 获取字符串然后在Android 应用中显示出来 hello-neon : 在NDK 中有关neon 的优化 module-exports : 多个库的调用方式。foo 被编译为静态库,bar 被编译为动态库并调用了库foo ,zoo 被编译为动态库并调用了库bar 。 native-activity : 完全用NDK 实现整个Android 程序 native-audio : 在NDK 中有关音频的操作 native-media : 在NDK 中对视频的操作 native-plasma : 完全用NDK 实现整个Android 程序并且提供了涉及plasma 的优化 san-angeles : 移植到Android 平台的OpenGL ES 的例子 test-libstdc++ : 对C++ 的支持,但并非支持C++ 的全部特征 two-libs:两个库的使用,first为静态库,second为动态库,并且second库调用first库 4.C 语言代码实现: 我们以NDK开发包中自带的例子hello-jni来进行演示和说明。进入jni目录下,运行ndk-build就可以进行编译了,如下图所示: 2012-6-20 18:55 上传 下载附件 (73.71 KB) 编译后得到库libhello-jni.so ,以lib 字符作为前缀,so 作为后缀。实际在程序加载时要去掉这两部分,即文件名称在lib 和.so 中间的部分为真正的库名称。需要说明的是和libhello-jni.so 文件在一起的还有两个文件gdb.setup 和gdbserver ,这两个是用于NDK 调试的,在最后正式发布apk 文件时这两个文件时不需要的。具体NDK 的调试方法,我们在后面会将,现在在这里暂时不讲。 在Eclipse中加载该例子,由于该例子最开始不是Eclipse项目,需要创建新项目,选择从源代码方式创建,如下图所示: 2012-6-20 19:02 上传 下载附件 (54.01 KB) 创建后,如下图所示: 2012-6-20 19:03 上传 下载附件 (122.06 KB) Jni 目录下文件hello-jni.c 如下图所示: 2012-6-20 19:03 上传 下载附件 (9.13 KB) 从上面两幅图可以看到,hello-jni在Java环境中的类HelloJni中声明的函数名为stringFromJNI,前面要用到修饰符native,类HelloJni所在的包名为com.example.hellojni,需要用函数System.loadLibrary加载lib库libhello-jni.so,采用static修饰符确保只加载一次。然后按正常函数使用就行了。而在NDK这边,即C语言这层,函数命名要遵循Java_包_类_函数的命名方式,中间用下划线_进行连接,如上面所示,在包com.example.hellojni中的类HelloJni声明为stringFromJNI,则在C/C++文件中定义的函数名为Java_com_example_hellojni_HelloJni_stringFromJNI,注意区分大小写。函数可以传参数,本例子中没有传入参数,只是有返回参数,返回参数的数据类型为jstring,即Java中的String类型。对于C/C++中与上面的Java环境打交道的数据类型可以参照JNI,具体可访问官方网站http:// java.sun.com/docs/books/jni/。对于函数Java_com_example_hellojni_HelloJni_stringFromJNI中的两个参数env和thiz是系统必须的,如果需要输入参数,必须再增加参数。这个例子运行的结果就是在文本控件(TextView)上面显示Hello from JNI by C !,如下图所示: | |
5.C++ 语言代码实现: 我们对上面的例子 hello-jni 稍微改动,改名为 hello-jni-ex ,为了以示区别把类名和包名也稍微修改了一下。 C++ 语言这种方法灵活性更好,当然,具体采用哪一种根据自己的喜好选择。 Hello-jni-ex 如下图所示: 2012-6-20 19:08 上传
下载附件 (184.74 KB) 程序运行结果如下图所示: 2012-6-20 19:09 上传
下载附件 (25.33 KB) 有关NDK
的实现部分如下图所示: 2012-6-20 19:10 上传
下载附件 (205.04 KB) 函数registerNativeMethods
和registerNatives
,以及JNI_OnLoad
里边的东西,我们这边暂时不讲述,后面进一步讲述NDK
开发时再详细讲述。我们真正自己定义的NDK
函数是testStringFromJNI
,这个函数名称不需要和上层Java
类中的native
声明函数保持一致。需要保持一致的是对应的包名和类名,这个在变量classPathName
中定义了,定义为:com/example/hellojniex/HelloJniEx
。在JNINativeMethod
类型的数组filterMethods
中建立上层Java
层面函数调用和NDK
层函数之间的映射关系。第一个变量stringFromJNI
为在Java
层进行调用的函数名称,第二个变量()Ljava/lang/String;
为函数的参数和返回值,第三个变量(void*)testStringFromJNI
为NDK
层函数名称(实际就是函数指针)。第一个变量和第三个变量都很容易理解,第二个变量理解起来麻烦一些。()中表示的是函数的参数类型,()后面表示的是函数的返回参数类型。例如本例中的()Ljava/lang/String;
就表示没有参数,返回String
类型。类型说明如下: 字符 Java类型 C类型 V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
数组则以"["开始,用两个字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本类型。如果Java
函数的参数是class
,则以"L"
开头,以";"
结尾中间是用"/"
隔开的包及类名。而其对应的C
函数名的参数则为jobject.
一个例外是String
类,其对应的类为jstring
。 Ljava/lang/String;String jstring
Ljava/net/Socket; Socket jobject
如果JAVA
函数位于一个嵌入类,则用$
作为类名间的分隔符。 例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"
6 .总结: 本次有关 NDK 的配置到此就讲完了,看完本文后,用户应该能够基本掌握 NDK 的配置和开发。对于进一步有关 NDK 的开发,我们将在后面的高级开发中详细讲解。
- 完美Android Cursor使用例子(Android数据库操作)
- 修改Android中的文件权限
- Android录音文件在IOS上播放不出来的问题
- 几行代码看程序员的水平——Android文件命名规范
- Android — 创建文件及文件夹
- Android文件选择器的实例分享
- Android的程序解码与XML文件解码
- 在Android上调用OpenCV 2.4.10库函数
随机推荐
-
基于android平台开发的计算器
-
Creating Release Keys and Signing Buil
-
按返回键返回到主界面
-
编译android源码前的准备
-
android项目中单实例数据库类
-
IOS 实现android Toast效果
-
自定义view之自定义圆角矩形imageview
-
android 获取本机IP地址
-
Android实现图片上传
-
PhoneWindow源码