3.NDK
配置
这个版本NDK的配置比较简单,前面的老版本还须要设置许多环境变量,这个版本不须要设置,直接解压缩就能够了。主目录android-ndk-r8下有一个脚本文件ndk-build,这个就是进行编译用的脚本程序。固然,若是运行脚本时不想输入ndk-build的路径的话能够将其所在路径加入到PATH环境变量中,具体的加入方式咱们在前面的“Linux平台JDK安装”一文中已经讲过,在此就不重复了。要编译的文件放在一个目录下,通常就叫jni(也能够叫别的名字),把这个目录放在Android工程下,编译后的库文件缺省会自动放到Android工程的库文件目录libs中。咱们以NDK自带的例子程序hello-jni为例,以下图所示:
在jni的目录中,包括编译配置用的脚本文件和C/C++两种文件,C/C++除了少许遵循JNI规范外,主要实际上都是Linux环境中C/C++编程而已。配置文件主要有两个:Android.mk和Application.mk。咱们简单说一下这两个文件,通常的NDK开发就足够了,想详细了解的话能够阅读NDK中的相关文档。
以hello-jni例子中Android.mk文件为例,以下图所示:
上面两条是相关的参数和环境变量设置,咱们不用管它。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文件为例,以下图所示:
和前面的相比,这里上边多了LOCAL_CFLAGS,它的右边就是编译选项,这个例子中包括两个ANDROID_NDK和DISABLE_IMPORTGL,每一个选项前加上-D做为标识符。下边多了LOCAL_LDLIBS,它的右边是编译中用到的库,每一个库名前加上-l做为标识符。 java
本版本的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库 android
4.C
语言代码实现:
咱们以NDK开发包中自带的例子hello-jni来进行演示和说明。进入jni目录下,运行ndk-build就能够进行编译了,以下图所示:
编译后获得库libhello-jni.so
,以lib
字符做为前缀,so
做为后缀。实际在程序加载时要去掉这两部分,即文件名称在lib
和.so
中间的部分为真正的库名称。须要说明的是和libhello-jni.so
文件在一块儿的还有两个文件gdb.setup
和gdbserver
,这两个是用于NDK
调试的,在最后正式发布apk
文件时这两个文件时不须要的。具体NDK
的调试方法,咱们在后面会将,如今在这里暂时不讲。
在Eclipse中加载该例子,因为该例子最开始不是Eclipse项目,须要建立新项目,选择从源代码方式建立,以下图所示:
建立后,以下图所示:
Jni
目录下文件hello-jni.c
以下图所示:
从上面两幅图能够看到,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 !,以下图所示: |