《AndroidNDK开发——教程.ppt》由会员分享,可在线阅读,更多相关《AndroidNDK开发——教程.ppt(37页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第10章章 Android NDK开开发发本章学习目标:n了解Android NDK的用途n掌握Android NDK编译环境的安装与配置方法n掌握Android NDK的开发方法10.1 NDK简介 nAndroid NDKq(Android Native Development Kit)是一系列的开发工具,允许程序开发人员在Android应用程序中嵌入C/C+语言编写的非托管代码qAndroid NDK优势n解决了核心模块使用托管语言开发执行效率低下的问题n允许程序开发人员直接使用C/C+源代码,极大的提高了Android应用程序开发的灵活性qAndroid NDK不足n增加程序的例如信
2、号处理或物理仿真)使用非托管代码运行效率最高,复杂性,增加了程序调试的难度nCPU运算量大和内存消耗较少的部分(因此并不是所有的核心部分都适合使用C/C+语言编写10.1 NDK简介 nAndroid NDKqAndroid NDK的版本是1.5,集成了交叉编译器,支持ARMv5TE处理器指令集、JNI接口和一些稳定的库文件qAndroid NDK仅支持Android SDK 1.5版本,因此1.0和1.1版本的应用程序不能够使用Android NDKqAndroid NDK提供一系列的说明文档、示例代码和开发工具,指导程序开发人员使用C/C+语言进行库文件开发,并提供便捷工具将库文件打包到a
3、pk文件中10.2 NDK编译环境nAndroid NDK编译环境支持Windows XP、Linux和MacOS,本书仅介绍Windows系统的编译环境配置方法nWindows系统的编译环境配置方法q下载Android NDK的安装包q下载并安装Cygwinq配置Cygwin的NDK开发环境q测试开发环境是否可以正常工作10.2 NDK编译环境n下载Android NDK的安装包q在Google的官方网站下载Android NDK的安装包,下载地址是http:/ NDK编译环境n下载Android NDK的安装包q将下载的ZIP文件解压缩到用户的Android开发目录中,作者将Android
4、 NDK解压到E:Android目录中,ZIP文件中包含一层目录,因此Android NDK的最终路径为E:Androidandroid-ndk-1.5_r110.2 NDK编译环境n下载并安装CygwinqAndroid NDK目前还不支持在Windows系统下直接进行交叉编译,因此需要在Windows系统下安装一个Linux的模拟器环境Cygwin,完成C/C+代码的交叉编译工作qAndroid NDK要求GNU Make的版本高于或等于3.18,之前的版本并没有经过测试,因此需要安装较新版本的CygwinqCygwin的最新版本可以到官方网站http:/下载,也可以到中文的映像网站htt
5、p:/下载10.2 NDK编译环境n下载并安装Cygwinq在Cygwin的安装过程中,需要将Devel下的gcc和make的相关选项选上,否则Cygwin将无法编译C/C+代码文件10.2 NDK编译环境n配置Cygwin的NDK开发环境q在缺省情况下,Cygwin安装在C盘的根目录下,修改C:cygwinhomeusername.bash_profile文件,username会根据用户使用的用户名称而变化q在.bash_profile文件的结尾处添加如下代码n上面的代码说明了Android NDK所在的目录,目录是e盘android/android-ndk-1.5_r1n如果Android
6、 NDK安装在c盘的TestAndroid/android-ndk-1.5_r1中,则上面的代码则应该为ANDROID_NDK_ROOT=/cygdrive/e/android/android-ndk-1.5_r1export ANDROID_NDK_ROOTANDROID_NDK_ROOT=/cygdrive/c/TestAndroid/android-ndk-1.5_r1export ANDROID_NDK_ROOT10.2 NDK编译环境n测试开发环境是否可以正常工作q首先启动Cygwin,然后切换到/build目录中,运行host-setup.sh文件q如果运行结果如下图,说明Andr
7、oid NDK的开发环境已经可以正常工作了nAndroid NDK的编译环境已经安装配置完毕10.2 NDK编译环境nAndroid NDK的目录结构q在android-ndk-1.5_r1目录中,包含5个子目录和2个文件napps目录是Android工程的保存目录,子目录hello-jni和tow-libs是NDK自带的两个示例目录nbuild目录保存了交叉编译工具、编译脚本和配置文件ndocs目录是帮助文档的保存目录nout目录是交叉编译的输出目录,保存输出的so文件(+)apps (+)hello-jni (+)tow-libs(+)build(+)docs(+)out (-).giti
8、gnore(+)sources (+)samples (+)hello-jni (+)tow-libs (-)Android.mk(-)GNUmakefile(-)README.TXT10.2 NDK编译环境nAndroid NDK的目录结构nsources目录是C/C+源代码文件的保存目录,其下的hello-jni和tow-libs子目录,分别保存了NDK自带示例所需要的C/C+源代码文件nGNUmakfile文件和README.TXT文件分别是make工具的配置文件和NDK的说明文件(+)apps (+)hello-jni (+)tow-libs(+)build(+)docs(+)out
9、(-).gitignore(+)sources (+)samples (+)hello-jni (+)tow-libs (-)Android.mk(-)GNUmakefile(-)README.TXT10.2 NDK编译环境nAndroid NDK的目录结构qdocs目录中的帮助文件说明文件名文件名说明说明INSTALL.TXTNDK的安装与配置说明文档OVERVIEW.TXTNDK的用途和使用范围的说明文档ANDROID-MK.TXTAndroid.mk文件的说明文档,Android.mk文件定义了需要编译的C/C+源代码APPLICATION-MK.TXTApplication.mk文件的
10、说明文档,Application.mk文件定义了Android工程需要调用的C/C+源代码HOWTO.TXT关于NDK开发的一般性信息SYSTEM-ISSUES.TXT使用NDK开发时所需要注意的问题STABLE-APIS.TXT NDK头文件所支持的稳定的API类表10.2 NDK编译环境nAndroid NDK自带两个示例hello-jni和tow-libsqhello-jni是一个非常简单的例子,非托管代码实现了一个可以返回字符串的共享库,Android工程调用这个共享库获取字符串,然后显示在用户界面上qtow-libs是稍微复杂一些的例子,使用非托管代码实现了一个数学运算的共享库,An
11、droid工程动态加载这个共享库,并调用其中的函数,函数功能是通过使用静态库实现的10.3 NDK开发示例n在进行NDK开发时,一般需要同时建立Android工程和C/C+工程,然后使用NDK编译C/C+工程,形成可以被调用的共享库,最后共享库文件会被拷贝到Android工程中,并被直接打包到apk文件中n后面的内容将AndroidNdkDemo示例说明如何进行Android NDK开发qAndroidNdkDemo是一个进行加法运算的示例,程序会随机产生两个整数,然后调用C语言开发的共享库对这两个整数进行加法运算,最后将运算结果显示在用户界面上10.3 NDK开发示例nAndroidNdkD
12、emo示例的界面q进行Android NDK开发一般要经过如下的步骤n建立Application.mk文件n建立Android工程n建立Android.mk文件n建立C源代码文件n编译共享库模块10.3 NDK开发示例n建立Application.mk文件q建立步骤n在apps目录中建立应用程序目录,AndroidNdkDemo示例的应用程序目录为ndk-demon在ndk-demo目录中建立一个空目录project,这个目录以后会用来存放Android工程n在ndk-demo目录中建立一个名为Application.mk的文件,用来描述Android工程将调用的共享库qAndroidNdkD
13、emo示例的目录结构(+)apps (+)ndk-demo (+)project (-)Application.mk10.3 NDK开发示例n建立Application.mk文件q在进行NDK开发时,在应用程序目录中一定要有Application.mk文件,用来声明Android工程需要调用的非托管模块(如静态库或共享库)qAndroidNdkDemo示例的Application.mk的代码如下n第1行的变量APP_PROJECT_PATH表示Android工程所在的目录,在生产共享库文件后,APK将自动将共享库文件拷贝到libsarmeabi目录中,本示例将共享库文件拷贝到appsndk-d
14、emoprojectlibsarmeabi目录中1.APP_PROJECT_PATH:=$(call my-dir)/project2.APP_MODULES :=add-module10.3 NDK开发示例n建立Application.mk文件n第2行代码中的变量APP_MODULES表示Android工程需要调用的非托管模块,如果存在多个非托管模块,使用空格进行分隔。本示例调用的非托管模块为add-module,对应在后面涉及的Android.mk文件qApplication.mk的变量说明变量变量强制使用强制使用说明说明APP_PROJECT_PATH是Android工程所在的目录APP
15、_MODULES是Android工程需要调用的非托管模块APP_OPTIM否指定优化等级,包含两个等级debug和release,release是缺省设置。debug生产非优化代码,更加易于调试APP_CFLAGS否编译C代码时所传递的编译器标志APP_CXXFLAGS否编译C+代码时所传递的编译器标志APP_CPPFLAGS否编译C/C+代码时所传递的编译器标志10.3 NDK开发示例n建立Android工程q在project目录中建立Android工程时,需要取消复选框“Use default location”,并指定预先建立的project文件夹作为工程文件夹q在建立AndroidNd
16、kDemo工程后,修改main.xml文件,添加一个id为display的TextView和一个id为add_btn的Button按钮10.3 NDK开发示例n建立Android工程q程序中的生产随机数和调用的代码在AndroidNdkDemo.java文件中,下面是AndroidNdkDemo.java文件的核心代码1.public class AndroidNdkDemo extends Activity 2.Override3.public void onCreate(Bundle savedInstanceState)4.super.onCreate(savedInstanceStat
17、e);5.setContentView(R.layout.main);6.final TextView displayLable=(TextView)findViewById(R.id.display);7.Button btn=(Button)findViewById(R.id.add_btn);8.btn.setOnClickListener(new View.OnClickListener()9.Override10.public void onClick(View v)11.double randomDouble=Math.random();10.3 NDK开发示例n建立Android
18、工程12.long x=Math.round(randomDouble*100);13.randomDouble=Math.random();14.long y=Math.round(randomDouble*100);15.16./System.loadLibrary(add-module);17.long z=add(x,y);18.String msg=x+y+=+z;19.displayLable.setText(msg);20.21.);22.23./public native long add(long x,long y);24.25.public long add(long x,
19、long y)26.return x+y;27.28.10.3 NDK开发示例n建立Android工程n上面的代码有一个NDK开发的小技巧,在开发C/C+的共享库前,可以使用具有相同和相近功能的Java函数进行替代。在代码第17行本应该调用共享库的add()函数,但为了便于开发和调试,在代码第25行到第27行,使用Java代码开发了一个功能相同的add()函数,这样即使在没有完成C/C+的共享库开发前,也可以对这个Android工程进行界面部分的调试n第16行和第23行注释掉的代码,就是在C/C+的共享库开发完毕后需要使用的代码,其中第16行是动态加载共享库的代码,加载的共享库名称为add-m
20、odule;第23行用来声明共享库的函数,使用C/C+开发的共享库必须有同名的函数。在共享库开发完毕后,取消第16行和第23行代码的注释,并注释掉第25行到第27行代码,这样程序就可以正常调用共享库内的函数进行加法运算10.3 NDK开发示例n建立Android.mk文件q建立C/C+源代码文件前,首先需要在sources目录中建立模块目录,AndroidNdkDemo示例的模块目录为add-module,这个模块目录的名称与Application.mk文件中声明的模块名称相同qadd-module目录中包含两个文件,Android.mk和add-module.c,目录结构如下(+)sourc
21、es(+)add-module(-)Android.mk(-)add-module.c10.3 NDK开发示例n建立Android.mk文件qAndroid.mk是为NKD编译系统准备的脚本文件,用来描述模块需要编译C/C+文件的信息q通常NKD编译系统会搜寻$NDK/sources/*/目录中的所有Android.mk文件,但如果程序开发人员将Android.mk文件放置在下一级目录中,则需要在上一级目录中的Android.mk文件添加如下代码include$(call all-subdir-makefiles)10.3 NDK开发示例n建立Android.mk文件q下面来分析Android
22、NdkDemo示例的add-module模块的Android.mk文件qAndroid.mk文件的代码如下1.LOCAL_PATH:=$(call my-dir)2.3.include$(CLEAR_VARS)4.5.LOCAL_MODULE :=add-module6.LOCAL_SRC_FILES:=add-module.c7.8.include$(BUILD_SHARED_LIBRARY)10.3 NDK开发示例n建立Android.mk文件n每个Android.mk文件都必须以第1行代码开始,变量LOCAL_PATH用来定义需要编译的C/C+源代码的位置,my-dir由NKD编译系统提
23、供,表示当前目录的位置。代码第3行的include$(CLEAR_VARS)表示清空所有以LOCAL_开始的变量,例如LOCAL_MODULE、LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIES等,但第1行定义的LOCAL_PATH不在清空的范围内。因为所有的脚本都将粘贴到同一个GNU Make的执行上下文中,而且所有变量都是全局变量,因此必须在每次使用前清空所有以前用过的变量10.3 NDK开发示例n建立Android.mk文件n第5行代码变量LOCAL_MODULE用来声明模块名称,模块名称必须唯一,而且中间不能够存在空格。NKD编译系统将会在模块名称前自动添加l
24、ib前缀,然后生产so文件。这里的模块名称为add-module,生产的共享库文件名为libadd-module.so。但需要注意的是,如果程序开发人员使用具有lib前缀的模块名称,NKD编译系统将不再添加前缀,例如模块名称为libsub,生产的共享库文件名为libsub.so10.3 NDK开发示例n建立Android.mk文件n第6行代码中的变量LOCAL_SRC_FILES表示编译模块所需要使用的C/C+文件列表,但不需要给出头文件的列表,因为NKD编译系统会自动计算依赖关系。add-module模块仅需要一个C文件,文件名为add-module.c。缺省情况下,结尾名为.c的文件是C语
25、言源文件,结尾名为.cpp的文件是C+语言源文件n第8行代码include$(BUILD_SHARED_LIBRARY)表示NKD编译系统构建共享库,如果变量BUILD_SHARED_LIBRARY更改为BUILD_STATIC_LIBRARY,则表示需要NKD编译系统构建静态库10.3 NDK开发示例n建立C源代码文件q根据Android.mk文件的声明,add-module模块仅包含一个C源代码文件add-module.c。add-module.c文件的作用是实现两个整数加法运算功能,全部代码如下1.#include 2.3.jlong Java_edu_hrbeu_AndroidNdkD
26、emo_AndroidNdkDemo_add(JNIEnv*env,jobject this,jlong x,jlong y)4.5.return x+y;6.10.3 NDK开发示例n建立C源代码文件n第1行代码引入的是JNI(Java Native Interface)的头文件n第3行代码是函数名称,jlong表示Java长型整数,Java_edu_hrbeu_AndroidNdkDemo_AndroidNdkDemo_add的构成为Java_,其中的名称和参数要与AndroidNdkDemo.java文件定义的函数一致,AndroidNdkDemo.java文件定义的函数为public
27、native long add(long x,long y)n第5行代码用来返回加法运算结果10.3 NDK开发示例n编译共享库模块q首先启动cygwin,然后切换到Androd NDK的主目录下,键入如下的编译命令nndk-demo是apps目录下的应用程序目录名称。在指定应用程序(目录)名称后,NKD编译系统会首先找到目录中的Application.mk文件,根据Application.mk文件的信息,确定该Android共享需要使用add-module模块;然后在sources目录中搜索所有Android.mk文件,在找到与add-module模块匹配的Android.mk文件后,根据A
28、ndroid.mk文件提供的信息编译指定的C/C+源代码文件,形成共享库文件;最后将生产的共享库文件拷贝到Android工程的指定目录中make APP=ndk-demo10.3 NDK开发示例n编译共享库模块q目前Android NDK 1.5版本存在一个小错误,如果用户直接运行make APP=ndk-demo命令编译程序,NDK编译系统将提示out/host/config.mk文件不存在,让用户重新运行build/host-setup.sh脚本q解决这问题的方法非常简单,只需要将/build/out/host文件夹和其中的config.mk文件拷贝到/out目录中即可10.3 NDK开发
29、示例n编译共享库模块q下图是编译成功的提示信息q提示信息包括编译add-module模块所使用到的文件,生产so文件的文件名和so文件的安装位置。为了确认是否成功编译了模块,用户可以打开apps/ndk-demo/project/libs/armeabi目录,如果目录中存在libadd-module.so文件,则表示编译成功10.3 NDK开发示例n运行Android程序q在运行AndroidNdkDemo示例程序前,务必将AndroidNdkDemo.java文件中第16行和第23行的注释取消,并注释掉第25行到第27行代码习题:n1.简述Android NDK开发的优势和不足。n2.说明Android NDK应用程序开发的一般步骤。n3.参考NDK的tow-libs示例,使用静态库实现AndroidNdkDemo示例中加法运算的函数功能。n4.使用NDK能够提高复杂函数的运算速度,但程序运行效率的提升并不容易度量。分别使用C/C+和Java语言设计一个具有复杂运算的函数,通过对比函数的调用和返回时间,分析NDK对提高程序运行效率的能力。
限制150内