Eclipse下使用Ant多渠道批量打包

来源:互联网 发布:淘宝首发认证 编辑:程序博客网 时间:2024/05/21 14:00
]

在上一篇文章《eclipse下Ant自动打包,混淆和签名》中,我们已经可以使用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节点如下:

 

[html] view plaincopy
  1. <meta-data  
  2.            android:name="channelname"  
  3.            android:value="channelkey" >  
  4.        </meta-data>  

待会儿我们在打包的时候就会把channelname替换成渠道名,把channelkey替换成渠道号。

上一篇文章讲到local.properties,我们把参数都写在这里

如下local.properties:

[html] view plaincopy
  1. #下面这句是自动生成的  
  2. sdk.dir=D:\\Program Files\\Android\\android-sdk  
  3. #数字签名文件  
  4. key.store=jingchen.keystore  
  5. #别名alias  
  6. key.alias=jingchen  
  7. #数字签名的密码  
  8. key.store.password=111111  
  9. #alias的密码  
  10. key.alias.password=111111  
  11. #这里设置混淆代码  
  12. proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt  
  13. #写上所有的渠道,格式 渠道名:渠道号  
  14. market_channels=UMENG_CHANNEL:UMENG,JPUSH_CHANNEL:AAA,BAIDU_CHANNEL:BAIDU  
  15. #版本  
  16. version=1.0.0  

上面的两个参数market_channels和version我们在custom_rules.xml会获取,无论有多少渠道都可以写上,用","分隔。下面看一下我们的custom_rules.xml的内容

新建一个custom_rules.xml

         在这里来看一下build.xml:

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project  
  3.     name="MainActivity"  
  4.     default="help" >  
  5.   
  6.     <property file="local.properties" />  
  7.   
  8.     <property file="ant.properties" />  
  9.   
  10.     <property environment="env" />  
  11.   
  12.     <condition  
  13.         property="sdk.dir"  
  14.         value="${env.ANDROID_HOME}" >  
  15.   
  16.         <isset property="env.ANDROID_HOME" />  
  17.     </condition>  
  18.   
  19.     <loadproperties srcFile="project.properties" />  
  20.   
  21.     <fail  
  22.         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."  
  23.         unless="sdk.dir" />  
  24.   
  25.     <import  
  26.         file="custom_rules.xml"  
  27.         optional="true" />  
  28.   
  29.     <import file="${sdk.dir}/tools/ant/build.xml" />  
  30.   
  31. </project>  


它会导入当前目录下的custom_rules.xml,所以我们在当前工程目录下新建一个custom_rules.xml,里面写上我们的打包规则。所有的替换,打包和输出操作都写在custom_rules.xml中。这里面,替换渠道号的写法有两种:

注意:双引号用“&quot;”,由于贴代码的时候网页自动把“&quot;”替换成“"”了。。

写法1

 custom_rules.xml:

 

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!-- 渠道包打包脚本  ant deploy -->  
  3. <project name="custom_rules" >  
  4.   
  5.     <!-- 引用支持循环的jar包ant-contrib-1.0b3.jar -->  
  6.   
  7.     <taskdef resource="net/sf/antcontrib/antcontrib.properties" >  
  8.   
  9.         <classpath>  
  10.   
  11.             <pathelement location="lib/ant-contrib-1.0b3.jar" />  
  12.         </classpath>  
  13.     </taskdef>  
  14.   
  15.     <!-- 循环打包,target名为deploy,构建的时候必须选择deploy -->  
  16.   
  17.     <target name="deploy" >  
  18.   
  19.         <!-- 进来的时候先clean一下项目 -->  
  20.   
  21.         <antcall target="clean" />  
  22.         <!-- for循环内容传进来的参数为market_channels,以","为分隔构建list,循环读取list,并将读取到的字符串以参数channel传进modify_manifest中 -->  
  23.   
  24.         <foreach  
  25.             delimiter=","  
  26.             list="${market_channels}"  
  27.             param="channel"  
  28.             target="modify_manifest" >  
  29.         </foreach>  
  30.     </target>  
  31.   
  32.     <target name="modify_manifest" >  
  33.   
  34.         <!-- 按正则匹配获取渠道名字,赋给channelname -->  
  35.   
  36.         <propertyregex  
  37.             input="${channel}"  
  38.             override="true"  
  39.             property="channelname"  
  40.             regexp="(.*):"  
  41.             select="\1" />  
  42.         <!-- 按正则匹配获取渠道号码,赋给channelkey -->  
  43.   
  44.         <propertyregex  
  45.             input="${channel}"  
  46.             override="true"  
  47.             property="channelkey"  
  48.             regexp=":(.*)"  
  49.             select="\1" />  
  50.         <!-- 将AndroidManifest.xml中的android:name="channelname"替换成为android:name="${channelname}",这里的${channelname}是我们上面正则匹配出来的内容 -->  
  51.   
  52.         <replaceregexp  
  53.             byline="true"  
  54.             encoding="utf-8"  
  55.             file="AndroidManifest.xml"  
  56.             match="android:name="channelname""  
  57.             replace="android:name="${channelname}"" />  
  58.         <!-- 将AndroidManifest.xml中的android:value="channelkey"替换成为android:value="${channelkey}" -->  
  59.   
  60.         <replaceregexp  
  61.             byline="true"  
  62.             encoding="utf-8"  
  63.             file="AndroidManifest.xml"  
  64.             match="android:value="channelkey""  
  65.             replace="android:value="${channelkey}"" />  
  66.   
  67.         <!-- 用release打包 -->  
  68.   
  69.         <antcall target="release" />  
  70.         <!-- 拷贝渠道包到指定目录下,out.absolute.dir在自带的build.xml中定义了,为bin目录,如果要修改,可以在local.properties中添加一行out.absolute.dir=指定目录 -->  
  71.   
  72.         <copy  
  73.             file="${out.absolute.dir}/${ant.project.name}-release.apk"  
  74.             tofile="${out.absolute.dir}/out/${ant.project.name}-v${version}-${channelkey}.apk" />  
  75.   
  76.         <!-- 打包完一个渠道包后把渠道名和渠道号替换回原来格式,这样可以进行下一次替换,AndroidManifest.xml里所有匹配的东西都会被替换 -->  
  77.   
  78.         <replaceregexp  
  79.             byline="true"  
  80.             encoding="utf-8"  
  81.             file="AndroidManifest.xml"  
  82.             match="android:name="${channelname}""  
  83.             replace="android:name="channelname"" />  
  84.   
  85.         <replaceregexp  
  86.             byline="true"  
  87.             encoding="utf-8"  
  88.             file="AndroidManifest.xml"  
  89.             match="android:value="${channelkey}""  
  90.             replace="android:value="channelkey"" />  
  91.     </target>  
  92.   
  93. </project>  
以上是其中一种写法,在替换AndroidManifest.xml中的内容的时候比较灵活,不用在乎AndroidManifest.xml的格式问题,比如android:name和android:value间多一个空格或者换行啥的,都不会影响到结果(下面的写法2就必须要求android:name和android:value间必须有且只有一个空格符)。但是也有一个缺点:AndroidManifest.xml中如果出现其他内容与替换内容一样的话也会被替换掉,不过这个概率是微乎其微的。重新选择运行选项,如下:


写法2

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!-- 渠道包打包脚本  ant deploy -->  
  3. <project name="custom_rules" >  
  4.   
  5.     <taskdef resource="net/sf/antcontrib/antcontrib.properties" >  
  6.   
  7.         <classpath>  
  8.   
  9.             <pathelement location="lib/ant-contrib-1.0b3.jar" />  
  10.         </classpath>  
  11.     </taskdef>  
  12.   
  13.     <!-- 循环打包 -->  
  14.   
  15.     <target name="deploy" >  
  16.   
  17.         <antcall target="clean" />  
  18.   
  19.         <foreach  
  20.             delimiter=","  
  21.             list="${market_channels}"  
  22.             param="channel"  
  23.             target="modify_manifest" >  
  24.         </foreach>  
  25.     </target>  
  26.   
  27.     <target name="modify_manifest" >  
  28.   
  29.         <!-- 获取渠道名字 -->  
  30.   
  31.         <propertyregex  
  32.             input="${channel}"  
  33.             override="true"  
  34.             property="channelname"  
  35.             regexp="(.*):"  
  36.             select="\1" />  
  37.         <!-- 获取渠道号码 -->  
  38.   
  39.         <propertyregex  
  40.             input="${channel}"  
  41.             override="true"  
  42.             property="channelkey"  
  43.             regexp=":(.*)"  
  44.             select="\1" />  
  45.           
  46.         <replaceregexp  
  47.             byline="false"  
  48.             flags="g" >  
  49.   
  50.             <!-- 匹配的内容是 android:name="channelname" android:value="(.*)" -->  
  51.   
  52.             <regexp pattern="android:name="channelname" android:value="(.*)"" />  
  53.             <!-- 匹配之后将其替换为 android:name="${channelname}" android:value="channelkey" -->  
  54.   
  55.             <substitution expression="android:name="${channelname}" android:value="${channelkey}"/>  
  56.             <!-- 正则表达式需要匹配的文件为AndroidManifest.xml -->  
  57.   
  58.             <fileset  
  59.                 dir=""  
  60.                 includes="AndroidManifest.xml" />  
  61.         </replaceregexp>  
  62.   
  63.         <!-- 打包 -->  
  64.   
  65.         <antcall target="release" />  
  66.         <!-- 拷贝渠道包到指定目录下 -->  
  67.   
  68.         <copy  
  69.             file="${out.absolute.dir}/${ant.project.name}-release.apk"  
  70.             tofile="${out.absolute.dir}/out/${ant.project.name}-v${version}-${channelkey}.apk" />  
  71.   
  72.         <!-- 打包完一个渠道包后把渠道名和渠道号替换回原来格式,这样可以进行下一次替换 -->  
  73.   
  74.         <replaceregexp  
  75.             byline="false"  
  76.             flags="g" >  
  77.   
  78.             <regexp pattern="android:name="${channelname}" android:value="(.*)"/>  
  79.   
  80.             <substitution expression="android:name="channelname" android:value="channelkey"" />  
  81.             <!-- 正则表达式需要匹配的文件为AndroidManifest.xml -->  
  82.   
  83.             <fileset  
  84.                 dir=""  
  85.                 includes="AndroidManifest.xml" />  
  86.         </replaceregexp>  
  87.   
  88.     </target>  
  89.   
  90. </project>  
这时候AndroidManifest.xml中的渠道meta节点就要改为下面这样了:
[html] view plaincopy
  1. <meta-data  
  2.             android:name="channelname" android:value="channelkey" >  
  3.         </meta-data>  
android:name="channelname"和android:value="channelkey"之间的那个空格符不能多也不能少!
其他的和写法1差不多,可以看上面的注释。

打包结果

经过上面执行ant构建完成之后,刷新输出目录bin,可以看到有带有渠道号的apk包啦!

下面,我们将三个包反编译看看AndroidManifest.xml中的渠道信息到底有没有被替换呢?可以看到,三个apk中的渠道信息都成功被替换了!


好啦,Ant批量打包就讲完啦!大家动手试试吧~


 

0 0