java ant打包工具_Android打包—Ant

最近在项目中遇到了一些打包的问题,顺便去了解了下打包的一些知识点。这里主要介绍和总结了一下ant、build.xml的知识点以及构建apk和jar包的一些注意事项。

Android打包

对工程代码和资源文件使用打包工具进行编译、混淆、签名、优化对齐等一系列步骤之后生成可发布到应用市场的apk的构建过程。

打包流程

2a5b1aa91c52

build.png

大概分为以下几个步骤

1、使用aapt工具将res资源文件生成R.java文件

2、使用aidl工具将aidl文件生成对应java文件

3、使用javac命令编译工程源代码和上面两步生成的文件,生成class文件

4、通过dex工具将class文件和第三方jar包打成dex文件

5、用aapt工具将res下的资源文件编译成二进制文件,然后将其和上一步中的dex文件以及assets中的文件通过apkbuilder工具打包成apk文件

6、通过jarsigner对apk进行签名

7、利用zipalign工具对apk进行字节对齐优化操作

打包方式 — Ant

Ant是将软件编译、测试、部署等步骤联系在一起自动化构建工具,主要用在java工程的构建中,所以也可以用来进行android打包。

现在android开发工具基本上都用的AS,构建用gradle,由于某些原因,项目组中用的还是eclipse+ant方式,所以暂时只介绍ant的构建方式。虽然工具不一样,但是整个构建原理和流程还是一样的。

Ant的默认构建文件为build.xml,输入ant命令后,ant会在当前目录下搜索是否有build.xml,如果有,则执行该文件,也可以自定义构建文件,通过ant -f test.xml即可指定test.xml为构建文件。

build.xml脚本

先看一个简单的build.xml

//ant默认构建文件即build.xml文件中需定义一个唯一的项目(Project标签),Project下可以定义若干个目标(target标签)

//project名称为MyApp, default表示默认的运行target,为必须属性,如果ant命令没有指定target时,则运行default属性中的target

//如MyApp工程目录下直接输入ant命令,则会直接打debug包。 basedir表示项目的基准目录

//property标签用来设置属性值,可以通过file标签来指定要加载的属性文件的路径,加载后属性文件中的指定的属性可以直接引用。

//为了方便配置,可以将环境变量声明在build.properties中,并通过file引入到build.xml中

//property中的name表示属性的名称 value表示属性值 在其他地方可以通过${属性名}进行引用, 类似于定义一个变量

//tartget,表示一个构建目标,也可以看成一个构建步骤, 一次构建过程中会执行一个或者多个构建步骤。

//target中的depends属性表示target之间的依赖关系,一个target可以依赖其他的target标签,depends属性也指定了target的执行顺序。

//ant会按照depends属性中target的顺序来依次执行每个target。所以本文中target的执行顺序为 targetone -> targettwo -> debug

//创建目录

//task是target中的子元素,一个target中可以有多个task,类似于target的子任务,常用的task有echo、mkdir、delete、javac、java等等

//删除目录

//输出日志信息

debug target perform...

打包成apk

build脚本中,一般android源工程打包成apk的执行步骤大体如下:

gen-R->aidl->compile->obfuscate->dex->package-res-and-assets->package->jarsigner->zipalign->release

gen-R之前还有一些clean清除上次打包产生的文件的操作,这里不再赘述

1、gen-R

gen-R 执行aapt命令来编译资源文件生成R.java文件 arg中的参数就是aapt中的命令行参数,该target其实执行的就是如下命令

aapt package -m -J gen -M AndroidManifest.xml -S res -I android.jar

具体参数命令含义如下:

-m 使生成的包的目录放在-J参数指定的目录。

-J 指定生成的R.java的输出目录

-M AndroidManifest.xml的路径

-S res文件夹路径

-I 某个版本平台的android.jar的路径

2、aidl

此步骤主要是生成aidl文件对应的java文件

使用apply标签可以进行批量运行task,此步骤即用build-tools下的aidl工具对src文件夹下的所有aidl文件进行批量转换成java文件。

是作为的一个子类而被实现,所以任务的所有属性,都可以用于

3、compile

//javac标签用于编译java文件生成class文件 destdir表示生成class文件的目录

bootclasspath="${android-jar}" fork="true" memoryMaximumSize="512m" >

//表示依赖库的路径 内嵌在、中

compile执行的是javac命令,编码格式指定为utf-8,target指定生成的class文件与该版本的虚拟机兼容,保证在该版本的虚拟机上正常运行。

debug表示是否产生调试信息,默认为false。extdirs为扩展文件的路径,destdir指定了存放编译后的class文件的文件夹路径。bootclasspath指定了编译过程中需要导入的class文件。fork指定是否再外部启用一个新的JDK编译器来执行编译,如果为false,则javac命令和ant将在同一个进程中执行,并且javac命令被分配的内存只有64MB,可能会导致java.lang.OutOfMemoryError(OOM)错误,如果fork为true,则另起一个进程来执行javac命令,分配的内存大小将由memoryMaximumSize来指定。src指定了java源文件的路径,classpath指定了依赖的第三方jar包路径。

4、obfuscate

//jar标签用来生成jar文件,basedir表示需要打包城jar文件的原文件目录, destfile表示生成的jar文件

//java标签用来执行编译生成的class文件 fork表示再一个新的虚拟机中运行该类 failonerror表示当出现错误时是否自动停止

//arg标签用来指定参数 value是命令行参数

obfuscate混淆先是执行了jar命令,将bin目录下的class文件打包成temp.jar。然后执行了proguard命令来压缩、优化和混淆操作。

-injars {class_path}指定要处理的应用程序jar和目录,即temp.jar

-outjars {class_path}指定处理完后要输出的jar和目录,即obfuscate.jar

-libraryjars {classpath}指定要处理的应用程序jar和目录所需要的程序库文件,即其他依赖的第三方jar包

混淆配置文件为proguard.config。混淆之后删除生成的临时文件,并解压obfuscate.jar到bin目录下

5、dex

dex就是用dx.bat工具将class文件转换成classes.dex文件,即对上一步在bin/classes目录中生成的优化过的class文件以及依赖的第三方jar包进行dex操作,最后在bin目录下生成classes.dex文件。Parallel用于指定将多个task并行执行。

6、package-res-and-assets

package-res-and-assets中执行了aapt命令,来将res、assets目录下的资源文件打包到resources.ap_

aapt package -f -M -S -A -I -F

7、package

通过apkbuilder.bat工具根据classes.dex文件和resources.ap_生成未混淆的apk包

apkbuilder -z -f -rf -rj -nf

8、jarsigner

jarsigner是对上面生成的apk文件进行签名操作

-verbose 签名时输出详细信息

-storepass 密钥库密码

-keystore 密钥库位置

-signedjar 后面接的参数依次是 签名后的apk、待签名的apk、密钥库别名

9、zipalign

zipalign target通过zipalign工具对签名后的apk包进行字节对齐,好处是能够减少应用程序的RAM内存资源消耗

-v 表示输出详细信息

-f 表示如果输出文件已存在 则直接覆盖

4 表示对齐为4个字节

10、release

......

至此打一个完整的带签名的可发布的包的流程就结束了。执行ant release命令即可完成打包。

打包成jar

由于jar包中不能包含资源文件,所以要通过jar包提供UI视图供第三方使用,可以通过如下方式实现:

1、使用硬编码来实现布局文件

2、布局中的资源文件需放在assets文件夹中,然后打包到jar中,通过流的方式读取。这种方式将资源文件放在assets目录下和java代码一起打包为jar,其他工程依赖该jar包时,可以只引用jar包,不需要再额外导入资源文件,在该工程编译应用时会将jar包assets目录中的文件与该工程中的assets目录中的文件合并。注意assets目录中的文件名与所导入工程中的文件名称不能重复,否则在编译的时候会报错“Error generating final archive: Found duplicate file for APK”提示有重名文件。

另外,打包到jar中的资源文件必须是编译之后的资源文件,即编译成二进制文件,因为读取资源时是通过流的方式读取的,所以相关的资源文件必须在编译成二进制文件之后再放入assets打包。

读取方式如下

//读取图片

InputStream inputStream = context.getAssets().open(path);

Drawable drawable = Drawable.createFromResourceStream(

context.getResources(), value, inputStream, name);

//读取xml图片资源

XmlResourceParser parser = context.getAssets().openXmlResourceParser(path);

Drawable draw = Drawable.createFromXml(context.getResources(), parser);

jar包的构建方式与apk的类似,执行步骤大概为

aidl->compile->copy_asset->obfuscate->jarsigner

与打包成apk流程相比少了gen-R、aapt、dex、package-res-and-assets、package、zipalign等操作,需要注意就是obfuscate混淆这一步,

打成jar包时obfuscate如下:

Obscure the class files....

...

obfuscate混淆先是执行了jar命令,将bin目录下的class文件以及资源文件打包成jar包,然后执行proguard命令来压缩、优化和混淆操作。这里需要注意的是如果该工程还依赖了其他jar包(未混淆),则打成jar的同时需要将其他jar包也引入进来,因为最后对外提供的是该工程的jar包。

另外需要注意的是proguard.cfg混淆文件中需要为其他jar包的类文件指明重命名类的包路径

# Specifies to repackage all class files that are renamed, by moving them into the single given package

-repackageclasses 'com.example.otherjar'

一定要为一些重命名的class文件指明打到jar包中的包路径,jar包中所有的class文件需要有明确的包路径,以防被第三方apk集成编译时,这些class文件无法-keep,被编译混淆之后找不到这些类,导致jar包功能异常。

2a5b1aa91c52

rename1.png

而增加了路径指定后,重命名的类就会被打到指定的包路径下,其他地方对这些类的调用也能正常进行。

2a5b1aa91c52

rename2.png

基本上要介绍的就这么多,可能会有理解错误的地方,欢迎一起讨论!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值