700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > ant build.xml 配置详解

ant build.xml 配置详解

时间:2022-02-27 21:55:10

相关推荐

ant build.xml 配置详解

随着工程越来越复杂,项目越来越多,以及平台的迁移(我最近就迁了2回),还有各大市场的发布,自动化编译android项目的需求越来越强烈,后面如果考虑做持续集成的话,会更加强烈。

经过不断的尝试,在ubuntu环境下,以花界为例,我将一步一步演示如何使用命令行,使用ant编译android项目,打包多渠道APK。

要点:

(1). 编译android的命令使用

(2). ant基本应用

(3). 多项目如何编译(包含android library)

(4). 如何多渠道打包

ps:我将以最原始的方式来实现,而不是使用android自带的ant编译方式,并尽量详细解释,这样有益于我们彻底搞懂android打包的基本原理。

1. Android编译打包的整体过程

使用ant,ant的参考文档:/manual/index.html

首先,假设现在已经有这样的一个项目(多工程的,简单的单工程就更简单了):

world

├── baseworld //android library,基础类库,共享于其他主应用

├── floworld//android project,花界应用

├── healthworld //android project,健康视线应用

├── speciality //android project,其它应用

├── starworld //android project,其它应用

├── build.xml//ant编译脚本,可用于整个项目的编译,也可只编译某个工程

├── code_checks.xml

├── kaiyuanxiangmu_world.keystore //密钥

└── README.md

一个大的项目world,下面有1个基础Android Library和4个Android Project。我们要做的就是编译这4个人project成对应的一系列各市场APK。

那么我们在来看看baseworld和floworld的工程结构:

Android Library,baseworld:

baseworld

├── assets //assets目录,其中文件可能会被主应用覆盖

├── libs//存放第三方jar库

├── res//类库资源,其中文件可能会被主应用覆盖

├── src//源码,可直接供主应用使用

├── AndroidManifest.xml

├── lint.xml

├── proguard.cfg

├── project.properties

└── README.md

和Android Project,floworld:

floworld/

├── assets //assets目录,主应用优先级高

├── build

├── data

├── libs//存放第三方jar库

├── res//主应用资源,主应用优先级高

├── src//源码,可直接供主应用使用

├── AndroidManifest.xml

├── build.xml//ant编译脚本,可用于整个项目的编译,也可只编译某个工程

├── default.properties

├── lint.xml

├── proguard.cfg

├── project.properties

└── README.md

结构已经出来了,那么android打包主要是在做什么?

说白了,先编译java成class,再把class和jar转化成dex,接着打包aaset和res等资源文件为res.zip(以res.zip示例),再把dex和res.zip合并为一个未签名apk,再对它签名,最终是一个带签名的apk文件。

当然这么说忽略了很多细节。

下面我把这些步骤用一句话分别列举如下,脑子里先有一个整体的流程,后续再结合ant详细展开:

(1). 生成用于主应用的R.java;

(2). 生成用于库应用的R.java(如果有库应用);

(3). 编译所有java文件为class文件;

(4). 打包class文件和jar包为classes.dex;

(5). 打包assets和res资源为资源压缩包(如res.zip,名字可以自己定义);

(6). 组合classes.dex和res.zip生成未签名的APK;

(7). 生成有签名的APK;

针对多项目同步发布和多渠道打包问题,我们需要额外增加三个处理:

(1). 各个工程下建立一个build.xml,然后在整个项目的根目录下建立一个build.xml,用于统一编译各个工程的;

(2). 各个工程的build.xml,通过传入市场ID和应用Version参数生成对应的版本

(3). 针对(1),(2)问题,建立一个批处理支持一键生成所有版本

大概流程即是如此。

2. 建立各个工程的ant脚本文件build.xml(位置:floworld/build.xml)

因为需要创建一些基本的文件目录和清理上次生成的文件,所以我们简单的定义一下几个目标吧:init,main,clean。

代码模板如下:

3. 初始化

在正式打包之前,有必要说明一下可能需要用到的初始化变量和操作。

前面已经讲述了打包的大概流程,现在,第一, 打包需要你使用哪个版本android.jar; 第二, 生成的R文件放到gen目录下; 第三, 生成的classes文件放到bin目录下; 第四, 生成的打包文件放到out目录下; 第五, 生成的各市场版本放到build目录下。目录完全可以自定义。

所以,如下的初始化必须先要做好,不然后面会提示找不到目录:

4. 生成R.java

Android Library和Android Project应用的R.java是来自不同的package的。比如:

(1). baseworld中导入的包是import com.tianxia.lib.baseworld.R;

(2). floworld中导入的包是import com.tianxia.lib.baseworld.R;

但是他们最终是调用统一的资源,所以这两个R.java文件必须一致。

下面是主应用的R.java的生成脚本:

注意res和../baseworld/res两个顺序不能搞反,写在前面具有高优先级,我们当然优先使用主应用的资源了,这样就能正确覆盖库应用的资源,实现重写。

库应用的R.java的生成脚本差不多,区别是指定库应用的AndroidManifest.xml,以用于生成的是不同的包和目录。

另外,aapt的使用中特别说明了,为了库应用的资源更好的可重用,库应用生成的R.java字段不需要修饰为final,加上参数--non-constant-id即可。

这样的话就可以生成2个正确的R.java文件了(如果你引用了两个库,则需要生成3个R.java,以此类推)。

结果如下:

5. 编译java文件为class文件

使用javac命令把src目录,baseworld/src目录,gen/*/R.java这些java编译成class文件:

命令原型是:

转化成ant脚本为:

6. 打包class文件为classes.dex

这步简单,用dx命令把上步生成的classes和第三方jar包打包成一个classes.dex。

命令原型是:

转化成ant脚本为:

7. 打包res,assets为资源压缩包(暂且命名为res.zip)

还是使用aapt命令,如生成R.java最大的不同是参数-F,意思是生成res.zip文件。

命令原型和ant脚本差不多:

8. 使用apkbuilder命令组合classes.dex,res.zip和AndroidManifest.xml为未签名的apk

apkbuilder命令能把class类,资源等文件打包成一个未签名的apk,原型命令和ant脚本类似:

这个命令比较简单。

9. 签名未签名的apk

使用jarsigner命令对上步中产生的apk签名。这是个传统的java命令,非android专用。

原型命令和ant脚本差不多:

至此,完整具有打包功能了,最后的build.xml为:

在工程目录下运行ant:

成功的在build/latest目录下生成一个product_latest_dev.apk,这就是默认的生成的最终的APK,可以导入到手机上运行。

10. 多渠道打包

目前主流的多渠道打包方法是在AndroidManifest.xml中的Application下添加一个渠道元数据节点。

比如,我使用的是友盟统计,它配置AndroidManifest.XML添加下面代码:

通过修改不同的Channel ID值,标识不同的渠道,有米广告提供了一个不错的渠道列表:/PromotionChannelIDs.

实现多渠道自动打包,就是实现自动化过程中替换Channel ID,然后编译打包。

这个替换需要用到正则表达式实现。

ant中提供的replace方法,功能太简单了,replaceregrex又需要添加另外的jar包,而且我们后面我们实现ant传参需要写另外的linux shell脚本,所以我干脆使用我熟悉的sed-i命令来实现替换。

替换命令:

渠道修改的问题解决了。

还记得前面定义的${apk-version},${apk-name},${apk-market}吗?

ant提供了额外的参数形式可以修改build.xml中定义的属性的值:ant -Dapk-version=1.0,则会修改${apk-version}值为1.0,而不是latest了,其他属性类似。

所以,在工程下面这条命令会生成:

命令问题通过ant的参数传值也解决了。

现在需要的是批量生产N个市场的版本,既替换AndroidManifest.xml,又生成对应的apk文件,我结合上面说的亮点,写了一个shell脚本(位置:world/floworld/build.sh):

好的,在工程目录下执行build.sh:

在build下生成了对应的apk文件:

成功生成!

11. 工程脚本的执行目录问题

上面的脚本执行之后的确很cool,但是有一个问题,我必须在build.sh目录下执行,才能正确编译,这个和build.xml中定义的相对路径有关。

我们必须在任何目录执行工程目录下的build.sh都不能出错,改进build.sh为如下:

现在你在项目根目录下执行也没有问题:./floworld/build.sh,不会出现路径不对,找不到文件的错误了。

12. 建立整个项目的自动化编译脚本(位置:world/build.sh)

单个工程的自动化打包没有问题了,但是一个项目下有N个工程,他们往往需要同步发布(或者daily build也需要同步编译),所以有必要建立一个项目级别的编译脚本:

build.sh(项目根目录下,位置:/world/build.sh)

最简单的傻瓜式的做法就是,遍历项目下的工程目录,如果包含工程编译的build.sh,则编译该工程.

shell脚本如下:

执行该脚本:

成功自动寻找,并编译打包。

13. 其他细节

为了尽量详细,我一再解说,但是还有一些细节未包括其中,如编译后清理clean目标,apk对齐优化,java代码混淆等,请参考其他资料,在此省略。

另外,我反编译生成的apk,查看Androidmanifest.xml均正确对应,验证通过。

14. 小结

自动化编译多渠道打包这个功能是Android产品发布的重要环节,能大大节省人力和出错的概率。

最近写博客的步伐慢了下来了,我决定加大力度,多写几篇。

其实早就想做这一块的内容了,一直不得空,或者说心里不得空,前几天刚完全格式化硬盘迁移到ubuntu(抛弃了双系统), 最近又开始着手准备一套《使用vim开发android》视频教程,人又不能太过于沉溺于舒适区域,我决定逼迫一下自己,终于逼出了这篇文章。

真是不容易,今天好热啊,火,你就是火,到处都是火 ... ...

本人项目中的具体应用示例:/openproject/world

转载:/qianxudetianxia/archive//07/04/2573687.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。