在Windows上用ant打包安卓apk
最近在研究多渠道自动打包,需要用到ant,做个笔记,方便以后看。
粗略整理一下看过的一些实用的贴:
1.自动生成build.xml,并实现工程依赖(已实践):
http://www.lephones.net/2014/10/13/ant-apk-with-lib/
这个是博主关于ant打包的集合帖:
http://www.lephones.net/2014/12/02/android-ant-all/
2.工程引用第三方jar包,ant中添加classpath(已实践):
https://my.oschina.net/yunfound/blog/169288
2.1第三方jar包只用作编译,但是不添加到classes.dex
http://www.lai18.com/content/6776196.html
3.自动批量根据渠道信息生成后缀名不同的jar包,并且manifest中的渠道名也不同(已实践):
http://frank-zhu.github.io/android/2014/05/23/android-ant/
4.美团实现一个apk对应所有渠道统计信息的解决方案:
http://tech.meituan.com/mt-apk-packaging.html(美团原贴,思路)
http://www.cnblogs.com/ct2011/p/4152323.html(参照美团思路的具体实现)
5.一个关于ant自动打包过程分析的神贴,不过要在ubantu环境
http://www.cnblogs.com/qianxudetianxia/archive/2012/07/04/2573687.html
6.如何捕获ant构建过程中的异常
http://blog.csdn.net/sxyandapp/article/details/50600910
http://blog.sina.com.cn/s/blog_670bfea20101a81s.html
☆☆☆任务一:ant打包应用apk,并且要依赖一些库工程
参考贴:(该贴已实际验证)
http://www.lephones.net/2014/10/13/ant-apk-with-lib/
主要步骤如下:
1.用ant工具为project生成build.xml文件用sdk/tools目录下自带的工具,将目录换成我们应用的工程目录,执行下面的命令:
android update project -p /dir/to/ur/project
就会在目录下生成2个文件,build.xml
和local.properties。
在工程目录新建ant.properties
,将下面的配置信息添加到该文件中,记得要修改keystore的路径
key.store=E:/MyDemo/AndroidDemo/SGSDK_Demo_2/key/sgsdk_key.keystore key.alias=SGSDK key.store.password=123456 key.alias.password=123456
这么依赖,在project下执行ant release就可以生成project对应的apk了。
可是如果我们的应用依赖了其他的project怎么办?直接执行ant release会报错,库工程下没有build.xml文件,这种情况,怎么办?
2.为库工程生成build.xml文件
很简单,为每个库工程都自动生成一个build.xml即可,在eclipse中配置好依赖关系,程序可以运行即可,然后在每个库工程下都执行
android update project -p /dir/to/ur/project
这样一来,用ant为依赖了库工程的目标工程自动生成apk就实现了。
3.为classpath添加第三方的jar包。
在集成的过程中,发现一个问题,我们目标工程有些jar包是放在runtime目录下的,即不是libs目录下,在eclipse运行的时候,可以通过add to buildpath将这些目录下的jar包添加到编译目录下来避免编译时找不到包,但是用ant编译的时候,却还是报错,import找不到对应的包,什么原因呢?
虽然不知道原因,但是build.xml毕竟是用工具生成的,我也不是特别懂,不晓得到底引用了哪些jar包。
后来搜了下eclipse的add build path,看到http://blog.csdn.net/waeceo/article/details/50484001上说eclipse的add build path只能在eclipse中生效
后来看到这个帖子https://my.oschina.net/yunfound/blog/169288,结合上一个帖子,我的理解如下:
默认的classpath只包括libs目录下,在eclipse中对一些libs目录下的jar包使用add to buildpath,这个配置只在eclipse中生效,用工具对project生成的build.xml文件中并不会自动生成这部分内容。所以我们要自己修改build.xml文件,将libs目录外的jar包也包含进去(google搜索关键字:安卓 ant 第三方jar)。
解决办法:
https://my.oschina.net/yunfound/blog/169288这个帖子说的很清楚了,直接进去看,so easy
4.给classpath增加了第三方库的路径之后,还是在编译的时候报找不到包的错误??
检查了一下classpath的路径,发现问题了,首先是发现我添加的jar路径错误了,定位到sdk路径下,而不是工程目录下。
终于发现问题了
在custom_rules.xml文件中,工程目录下第三方jar包的路径名定义成了 sdk.dir ,而sdk.dir这个值是对应安卓sdk的路径。产生冲突,好吧,把这个sdk.dir sdk.lib改掉去就好。
所以,以后自己的custom_rules.xml文件中定义的变量,一定要避免和系统变量名冲突。否则就会这样张冠李戴。
5.运行非当前目录下的build.xml
ant在dos下默认运行当前目录下的build.xml文件,如果要指定xml文件,使用-buildfile选项,例如:
"ant -buildfile E:\ant\build.xml deploy"
6.eclipse直接run一切正常,但是自动打包的程序就会闪退,而且没有任何提示
如题,就遇到了这种问题,而且没有任何提示。怎么办呢?首先,我想到是不是证书问题,于是我用eclipse导出了正式的apk,也能正常工作,这样一来基本判断是我自动打包工具的问题了。
我对比了一下自动打包生成的apk和eclipse导出的apk里面的结构,发现classes.dex文件大小不同,现在有两个工作需要做:
1.尝试替换classes.dex重新生成apk,看看是否可以正常工作
2.找到出错的那个apk的classes.dex和正常的有哪些区别,找到自动打包出错的地方。
[1]尝试替换chasses.dex并重新打包
[2]对比classes.dex
于是进去查原因,可是文件是二进制的,怎么办?
找到反编译工具,使用 d2j-dex2jar.bat classes.dex 就可以将dex文件反编译出jar包啦,这样就可以逐个对比到底有什么区别啦
7.上面那个问题,发现我用ant生成的apk中的classes.dex,比eclipse导出的要多了两个文件夹,而这两个文件夹正好是runtime目录下两个jar包的内容。明白了,runtime目录下的两个jar包只用于编译,但是并不打包进classes.dex,这该怎么做到呢?
原来是这样的,问题4的时候,我把runtime目录下的两个jar包加入到了project.all.jars.path中,但是这个目录里的jar即参加compile,也参加dex(功能相当于放到libs目录下);而如果有些jar包,只参与编译,不参与打包,加到tested.project.classpath即可(相当于加到了安卓Library)
参考贴:
http://www.lai18.com/content/6776196.html (里面搜索:不参与项目打包)
http://stackoverflow.com/questions/10829815/android-ant-build-how-to-compile-against-a-jar-but-exclude-it-from-classes-de(我是通过搜索project.all.jars.path和tested.project.classpath找到的帖子)
8.同一份代码,在eclipse里没有编译错误,但是ant release却报编译错误,类型转换失败?
后来找到原因了,是JDK版本不一致导致的,我在eclipse工程里JDK版本是1.7,就不会有这个报错,而如果改成1.6在eclipse中也会有这个报错。
怎么修改ant时候的jdk版本呢?
修改local.properties文件,加上这两行即可
java.target=1.7
java.source=1.7
!!!解决
!!!!!尚未解决的问题
现在有个问题,加入依赖库里有个jar包叫umeng.jar,我的工程引用了依赖库,但是本目录下没有umeng.jar
用eclipse运行就么有错误,但是用ant就会报编译错误
是不是一样的原理???
☆☆☆目标二:批量自动多渠道打包
参考贴:(已验证,可以生成带渠道名后缀的apk文件)
http://frank-zhu.github.io/android/2014/05/23/android-ant/
按照文章中描述的,已经可以在本地运行,但是中间出现过一些bug,列举如下:
1.报一个编码的错误,后面没能重现
解决方法在网上找一下就有,挺容易解决的
把自己的的build.xml中的encoding全部改成encoding="UTF8"即可
2.报错 <javac 不支持的编码 utf-8
我看上说是编译文件时默认为的事java.encoding的编码方式,一般是GBK,所以会报错
倒腾了好久,改了下android-sdk/tools/ant/build.xml
<javac encoding="${java.encoding}" 改成 <javac encoding="utf-8"
虽然在自己的ant.properties文件里配了java.encoding="utf-8"可不知道为什么没生效,改了之后就好了
!!!不过现在居然又不能重现了!!!
3.报错: key 加载失败之类的错误
注意ant.properties里跟key、密码相关的配置项后面不可以有空格
4.下面这种情况需要clean一下工程
5.引用了库工程,但是在工程目录下找不到build.xml,报错
就是因为这个问题,所以才会找到帖子一。
目标三:如何捕获ant构建过程中的异常呢
参考贴:
http://blog.csdn.net/sxyandapp/article/details/50600910
http://blog.sina.com.cn/s/blog_670bfea20101a81s.html
结合参考的帖子,自己的demo
<?xml version="1.0" encoding="UTF-8"?> <project default="release" name="custom_rules"> <taskdef resource="net/sf/antcontrib/antcontrib.properties"> <classpath> <pathelement location="D:/software/ant/apache-ant-1.9.7/lib/ant-contrib-1.0b3.jar"/> </classpath> </taskdef> <target name="deploy"> <trycatch> <try> <antcall target="clean"/> <antcall target="release"/> <copy tofile="./output/${output.apk.name}.apk"> <fileset dir="${out.absolute.dir}/" includes="${ant.project.name}-release.apk"/> </copy> <delete includeEmptyDirs="true"> <fileset dir="${out.absolute.dir}" includes="**/*"/> </delete> </try> <catch> <echo message="result" file="E:/ant_result.txt" /> <echo level="error">构建错误,按Enter结束</echo> <input /> </catch> </trycatch> </target> </project>
还会继续完善