在上一篇文章中,我们已经可以使用ant进行打包了,但是很多情况下我们需要批量打包,比如发布到平台上时需要上传每个市场的渠道包,每个apk都包含了不同的渠道号,具体数值写在AndroidManifest.xml的meta元素中,比如在AndroidManifest.xml中添加一个渠道名和渠道号可以加入<meta android:name="UMENG_CHANNEL" android:value="UMENG"></meta>。然后再打包。所以,如果渠道号有很多,在版本更新之后又要重新打包的时候,谁都不想手动将一个个不同渠道的apk导出。这时,ant批量打包就能节省好多时间了。
首先,我们在配置文件中写好需要用到的渠道名和渠道号,用ant构建时将会读取我们写好的渠道,动态替换AndroidManifest.xml中的meta节点的name和value,每替换完一个就打出一个apk包,用一个for循环不断地重复打包直到导出所有的渠道包为止。
为了方便替换,在AndroidManifest.xml中添加一个meta节点如下:
- <meta-data
- android:name="channelname"
- android:value="channelkey" >
- </meta-data>
待会儿我们在打包的时候就会把channelname替换成渠道名,把channelkey替换成渠道号。
上一篇文章讲到local.properties,我们把参数都写在这里
如下local.properties:
- #下面这句是自动生成的
- sdk.dir=D:\\Program Files\\Android\\android-sdk
- #数字签名文件
- key.store=jingchen.keystore
- #别名alias
- key.alias=jingchen
- #数字签名的密码
- key.store.password=111111
- #alias的密码
- key.alias.password=111111
- #这里设置混淆代码
- proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
- #写上所有的渠道,格式 渠道名:渠道号
- market_channels=UMENG_CHANNEL:UMENG,JPUSH_CHANNEL:AAA,BAIDU_CHANNEL:BAIDU
- #版本
- version=1.0.0
上面的两个参数market_channels和version我们在custom_rules.xml会获取,无论有多少渠道都可以写上,用","分隔。下面看一下我们的custom_rules.xml的内容
新建一个custom_rules.xml
在这里来看一下build.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <project
- name="MainActivity"
- default="help" >
-
- <property file="local.properties" />
-
- <property file="ant.properties" />
-
- <property environment="env" />
-
- <condition
- property="sdk.dir"
- value="${env.ANDROID_HOME}" >
-
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <loadproperties srcFile="project.properties" />
-
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir" />
-
- <import
- file="custom_rules.xml"
- optional="true" />
-
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
- </project>
它会导入当前目录下的custom_rules.xml,所以我们在当前工程目录下新建一个custom_rules.xml,里面写上我们的打包规则。所有的替换,打包和输出操作都写在custom_rules.xml中。这里面,替换渠道号的写法有两种: 注意:双引号用“"”,由于贴代码的时候网页自动把“"”替换成“"”了。。
写法1
custom_rules.xml:
- <?xml version="1.0" encoding="UTF-8"?>
-
- <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" >
-
-
-
- <antcall target="clean" />
-
-
- <foreach
- delimiter=","
- list="${market_channels}"
- param="channel"
- target="modify_manifest" >
- </foreach>
- </target>
-
- <target name="modify_manifest" >
-
-
-
- <propertyregex
- input="${channel}"
- override="true"
- property="channelname"
- regexp="(.*):"
- select="\1" />
-
-
- <propertyregex
- input="${channel}"
- override="true"
- property="channelkey"
- regexp=":(.*)"
- select="\1" />
-
-
- <replaceregexp
- byline="true"
- encoding="utf-8"
- file="AndroidManifest.xml"
- match="android:name="channelname""
- replace="android:name="${channelname}"" />
-
-
- <replaceregexp
- byline="true"
- encoding="utf-8"
- file="AndroidManifest.xml"
- match="android:value="channelkey""
- replace="android:value="${channelkey}"" />
-
-
-
- <antcall target="release" />
-
-
- <copy
- file="${out.absolute.dir}/${ant.project.name}-release.apk"
- tofile="${out.absolute.dir}/out/${ant.project.name}-v${version}-${channelkey}.apk" />
-
-
-
- <replaceregexp
- byline="true"
- encoding="utf-8"
- file="AndroidManifest.xml"
- match="android:name="${channelname}""
- replace="android:name="channelname"" />
-
- <replaceregexp
- byline="true"
- encoding="utf-8"
- file="AndroidManifest.xml"
- match="android:value="${channelkey}""
- replace="android:value="channelkey"" />
- </target>
-
- </project>
以上是其中一种写法,在替换AndroidManifest.xml中的内容的时候比较灵活,不用在乎AndroidManifest.xml的格式问题,比如android:name和android:value间多一个空格或者换行啥的,都不会影响到结果(下面的写法2就必须要求android:name和android:value间必须有且只有一个空格符)。但是也有一个缺点:AndroidManifest.xml中如果出现其他内容与替换内容一样的话也会被替换掉,不过这个概率是微乎其微的。重新选择运行选项,如下:
写法2
- <?xml version="1.0" encoding="UTF-8"?>
-
- <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" >
-
- <antcall target="clean" />
-
- <foreach
- delimiter=","
- list="${market_channels}"
- param="channel"
- target="modify_manifest" >
- </foreach>
- </target>
-
- <target name="modify_manifest" >
-
-
-
- <propertyregex
- input="${channel}"
- override="true"
- property="channelname"
- regexp="(.*):"
- select="\1" />
-
-
- <propertyregex
- input="${channel}"
- override="true"
- property="channelkey"
- regexp=":(.*)"
- select="\1" />
-
- <replaceregexp
- byline="false"
- flags="g" >
-
-
-
- <regexp pattern="android:name="channelname" android:value="(.*)"" />
-
-
- <substitution expression="android:name="${channelname}" android:value="${channelkey}"" />
-
-
- <fileset
- dir=""
- includes="AndroidManifest.xml" />
- </replaceregexp>
-
-
-
- <antcall target="release" />
-
-
- <copy
- file="${out.absolute.dir}/${ant.project.name}-release.apk"
- tofile="${out.absolute.dir}/out/${ant.project.name}-v${version}-${channelkey}.apk" />
-
-
-
- <replaceregexp
- byline="false"
- flags="g" >
-
- <regexp pattern="android:name="${channelname}" android:value="(.*)"" />
-
- <substitution expression="android:name="channelname" android:value="channelkey"" />
-
-
- <fileset
- dir=""
- includes="AndroidManifest.xml" />
- </replaceregexp>
-
- </target>
-
- </project>
这时候AndroidManifest.xml中的渠道meta节点就要改为下面这样了:
- <meta-data
- android:name="channelname" android:value="channelkey" >
- </meta-data>
android:name="channelname"和android:value="channelkey"之间的那个空格符不能多也不能少!
打包结果
经过上面执行ant构建完成之后,刷新输出目录bin,可以看到有带有渠道号的apk包啦! 下面,我们将三个包反编译看看AndroidManifest.xml中的渠道信息到底有没有被替换呢?可以看到,三个apk中的渠道信息都成功被替换了! 好啦,Ant批量打包就讲完啦!大家动手试试吧~