上一篇我们讲了如何利用ant来代替eclipse实现安卓工程的编译签名打包,这一篇重点来研究一下多渠道问题。
搞过移动开发的应该都知道,国内的安卓市场有成百上千个,我们的apk发布之前,通常要为每一个渠道打包出来一个独一无二的安装包,如果仍然安装老方法来,在每一个渠道下都执行一次ant release,肯定能实现,但试想一下,每一个apk打包出来需要几分钟,要这样执行下去的话,容易重复不说,打包的人估计也得疯掉。
有没有一种更优雅更高效的方式来实现?比如建立一个循环,让它自动执行呢?
答案肯定是有的。
ant脚本本身并不支持for循环功能,我们需要借助第三方扩展包来实现。所以在打包之前,需要下下载一个开源的Ant-contrib包,下载地址为http://download.csdn.net/detail/luochoudan/9474447, 解压之后,请将jar文件放到ant的lib目录,然后就OK了。
开始打包之前,我们先来看三个知识点,它们与你的工程构建息息相关,很有利于排错。
utf-8有无BOM的区别。BOM,就是字节序标记,用来标识后面的字节是通过utf-8编码产生的,对应的编码是EFBBBF,遗憾的是很多软件并不支持BOM,反而会导致出错。Windows自带的记事本对文本文件的处理就是加了BOM符,实在是脑残设计。推荐使用Notepad++来代替记事本,注意Notepad++本身支持带BOM符和不带BOM符的utf-8编码,建议设置成默认不带BOM符的。
.class文件和class.dex文件。.class文件比较常见,一般的.java文件执行javac之后生成的便是.class文件,JVM可对其进行解释。class.dex是Android中的特殊产物,由.class文件经过dex工具转译而成,专门供DVM解释执行的。具体的比较可参看这篇文章http://www.w2bc.com/Article/14646
ant打包的过程,一般可分为7步。再次唠叨一下,这7步环环相扣,其中的逻辑处理、调度顺序已经有eclipse自带的build.xml帮你规范好了。这里只略提一下,有兴趣的可参考http://blog.csdn.net/l_serein/article/details/7635816 这篇博文,对应原生的build.xml文件,了解具体实现。
接下来我们一步一步来实现所谓的多渠道。
market_channels=91,360
version=1.0.5
加入的代码如上所示,各渠道之间用”,”分割,version代表apk的版本号。后面我会给出完整的ant.properties文件,供大家参考。
然后编写循环打包的脚本。
这个地方,真的是忍不住要吐槽一下网上的十八路文章东拼西凑,基本大同小异,基本不能运行,基本就是在坑人。
上一篇我们已经说过,eclipse自带的build.xml脚本及其完善,它已经帮你规划好了整个打包流程,我们所要做的就是在这个基础上稍微修改一下。就好比一个完善的产品,到我们手里只需要加上一些个性化的定制,完全就可以实现我们想要的功能。所以当你在csdn或者博客园或者ITeye上看到那些密密麻麻甚至好几页的build脚本时,请自动忽略它,难懂晦涩不说,关键是不好用呃,浪费时间呃!!!!!笔者写到此处,心里还在滴血…
假设你已经看过上一篇文章,此刻你的工程有了如下的目录结构,
如果有请继续往下读,否则请先阅读上一篇文章《史上最全:ant多渠道打包安卓工程(一)》
我们工程根目录下的这个build.xml文件,就是最终要执行打包的终极文件,它里面有这样两句话,请认真注意一下,
<import
file="custom_rules.xml"
optional="true" />
<import file="${sdk.dir}/tools/ant/build.xml" />
很明显,import了两个文件,一个是eclipse的\sdk\tools\ant\build.xml,一个是custom_rules.xml文件。前一个好说,是系统自带的,每一个adt都一样的;后一个是什么呢?
其实就是留给你实现的个性化定制。一般情况下,工程并没有这个custom_rules.xml,所以构建的时候会自动忽略它。而我们要实现多渠道的自动打包,很显然,在它里面定义一下就可以了。
工程根目录下创建custom_rules.xm,注意名字不要出错。它的内容我就直接贴代码了,笔者也是参考这篇文章http://www.cnblogs.com/yaozhongxiao/p/3523061.html ,这里稍加注释。不用粘贴复制,后面会给出完整的文件下载。
<project name="custom_rules" >
<taskdef resource="net/sf/antcontrib/antcontrib.properties" >
<classpath>
<pathelement location="lib/ant-contrib-1.0b3.jar" />
classpath>
taskdef>
<target name="deploy" >
<foreach
-- 分隔符 -->
delimiter=","
list="${market_channels}"
param="channel"
target="modify_manifest" >
foreach>
target>
<target name="modify_manifest" >
<replaceregexp
byline="false"
flags="g" >
<regexp pattern="android:name="UMENG_CHANNEL" android:value="(.*)"" />
<substitution expression="android:name="UMENG_CHANNEL" android:value="${channel}"" />
<fileset
dir=""
includes="AndroidManifest.xml" />
replaceregexp>
<property name="out.release.file" location="${out.absolute.dir}/${ant.project.name}_${channel}.apk" />
<antcall target="release" />
<copy
file="bin/${ant.project.name}-release.apk"
tofile="${out.absolute.dir}/out/${ant.project.name}v${version}-${channel}.apk" />
target>
project>
添加完这个文件,基本的工作已经完成。
cmd下同样切换到工程根目录,运行ant deploy指令。
虽然如此,打包的路还有很长要走,因为在编译、文件转换的过程会出现各种各样的奇葩错误,但总的来说都是跟个人的配置有关,笔者在打包的过程中涕泪交零,总结一些常见的错误,需要的话可继续阅读后面的问题汇总。
如果运行ant -v deploy,一阵输出后,出现了如下画面,那就恭喜你;如果没有,也不要灰心,不要气馁,芝麻总会开花,问题总有解决的办法,多google找找原因吧。
<property name="java.target" value="1.7" />
<property name="java.source" value="1.7" />
<property name="java.compilerargs" value="-encoding UTF-8" />
<do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
这个问题真心困惑了好久,google了好久,最后找到了一个解决方法,在工程的project.properties里面加上这样一句话。
dex.disable.merger=true
具体原理不了解,回答者给出的解释是sdk的一个bug。
仍然是文件格式,只不过这个比较隐蔽。
错误描述:”X字节的utf-8序列的字节X无效“。
解决方案:将notepad++编码格式设置为”utf-8 无BOM格式编码”(一般默认都是这个选项),然后用打开报错的文件,一定会发现不和谐的乱码字符,将其清理即可。值得注意的是xml文件虽然已经指定了编码格式,依然有编码问题。尤其是从别的地方粘贴过来的字符,虽然IDE中打开不会乱码,但有无BOM的区别同样会导致编译失败。
同时建议将IDE的拼写设置一下Preference->General->Editors->Text Editors->Spelling->Encoding utf-8
另一个常见的错误就是jar包重复,这个我打包过程没遇到过,不敢妄言。
每一个列出来的问题都是血泪,如果对其不熟悉,足够你头疼半天,而且网上的东西大多语焉不详,实践中很难奏效。笔者把亲身经历略作整理,每一个错误都相当经典,希望能够帮助同道中人少走弯路。
最后割肉给出ant脚本,需要的话自行下载参考,http://download.csdn.net/detail/luochoudan/9487822
欢迎留言拍砖,转载请注明出处。