实例的工程下载地址:http://download.csdn.net/detail/keanbin/6912591
完整的Ant,包含扩展包Ant-contrib的下载地址:http://download.csdn.net/detail/keanbin/6912595
apkbuilder.bat 下载地址:http://download.csdn.net/detail/keanbin/6912619
今天花费了几个小时,参考网上的资料,期间遇到了好几个问题, 终于实现了使用Ant批量多渠道打包,现在,梳理一下思路,总结使用Ant批量多渠道打包的方法:
1. 下载安装Ant,不是使用Androis sdk 或者 Eclipse中的Ant,而是去官网下载完整的Ant。官网:http://ant.apache.org/
1) 解压Ant,比如解压到D:\Android\Ant
2) 我的电脑->属性->高级->环境变量
3) 系统变量新建ANT_HOME,变量值为D:\Android\Ant
4) 系统变量新建或修改path,变量值为%ANT_HOME%\bin
测试ant是否成功,你可以在控制台输入Cmd 回车, ant 回车。如果出现
Buildfile: build.xml does not exist!
Build failed
恭喜你已经ant安装完毕了!!
2. 安装扩展包 Ant-contrib,支持循环打包。
2) 从下载的压缩包中复制ant-contrib-1.0b3.jar,到放到Ant的lib文件夹中。
3. 复制签名key文件“gaoxin.key”到工程的更目录下。
4. 在工程的根目录下创建文件build.xml。
<span style="font-size:18px;"><project
name="TestMutilChannelApk"
default="release" >
<!-- ANT环境变量 -->
<property environment="env" />
<!-- 使用第三方的ant包,使ant支持for循环 -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" >
<classpath>
<pathelement location="D:/Android/Ant/lib/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
<!-- 应用名称 -->
<property
name="appName"
value="${ant.project.name}" />
<!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->
<property
name="sdk-folder"
value="D:/Android/adt-bundle-windows-x86_64-20131030/sdk" />
<!-- SDK指定平台目录 -->
<property
name="sdk-platform-folder"
value="${sdk-folder}/platforms/android-8" />
<!-- SDK中tools目录 -->
<property
name="sdk-tools"
value="${sdk-folder}/tools" />
<!-- SDK指定平台中tools目录 -->
<property
name="sdk-platform-tools"
value="${sdk-folder}/platform-tools" />
<!-- 使用到的命令(当前系统为windows,如果系统为linux,可将.bat文件替换成相对应的命令) -->
<property
name="aapt"
value="${sdk-platform-tools}/aapt" />
<property
name="aidl"
value="${sdk-platform-tools}/aidl" />
<property
name="dx"
value="${sdk-platform-tools}/dx.bat" />
<property
name="apkbuilder"
value="${sdk-tools}/apkbuilder.bat" />
<property
name="jarsigner"
value="${env.JAVA_HOME}/bin/jarsigner" />
<property
name="zipalign"
value="${sdk-tools}/zipalign.exe" />
<!-- 编译需要的jar; 如果项目使用到地图服务则需要maps.jar -->
<property
name="android-jar"
value="${sdk-platform-folder}/android.jar" />
<property
name="android-maps-jar"
value="${sdk-folder}/add-ons/addon_google_apis_google_inc_8/libs/maps.jar" />
<!-- -->
<property
name="channelname"
value="" />
<property
name="channelkey"
value="" />
<!-- 渠道名:渠道号 -->
<property
name="key"
value="UM:umumum,BAI:baidu" />
<!-- 编译aidl文件所需的预处理框架文件framework.aidl -->
<property
name="framework-aidl"
value="${sdk-platform-folder}/framework.aidl" />
<!-- 清单文件 -->
<property
name="manifest-xml"
value="AndroidManifest.xml" />
<!-- 源文件目录 -->
<property
name="resource-dir"
value="res" />
<property
name="asset-dir"
value="assets" />
<!-- java源文件目录 -->
<property
name="srcdir"
value="src" />
<property
name="srcdir-ospath"
value="${basedir}/${srcdir}" />
<!-- 外部类库所在目录 -->
<property
name="external-lib"
value="libs" />
<property
name="external-lib-ospath"
value="${basedir}/${external-lib}" />
<!-- 版本 -->
<property
name="version"
value="3.0" />
<!-- 循环打包 -->
<target name="deploy" >
<foreach
delimiter=","
list="${key}"
param="nameandchannel"
target="modify_manifest" >
</foreach>
</target>
<target name="modify_manifest" >
<!-- 获取渠道名字 -->
<propertyregex
input="${nameandchannel}"
override="true"
property="channelname"
regexp="(.*):"
select="\1" />
<!-- 获取渠道号码 -->
<propertyregex
input="${nameandchannel}"
override="true"
property="channelkey"
regexp=":(.*)"
select="\1" />
<!-- 正则匹配替换渠道号 -->
<replaceregexp
byline="false"
encoding="UTF-8"
flags="g" >
<regexp pattern="meta-data android:value="(.*)" android:name="app_key"" />
<substitution expression="meta-data android:value="${channelkey}" android:name="app_key"" />
<fileset
dir=""
includes="AndroidManifest.xml" />
</replaceregexp>
<antcall target="zipalign" />
</target>
<!-- 初始化工作 -->
<target name="init" >
<echo>
目录初始化....
</echo>
<!-- 生成R文件的相对目录 -->
<var
name="outdir-gen"
value="gen" />
<!-- 编译后的文件放置目录 -->
<var
name="outdir-bin"
value="bin-${channelname}" />
<!-- 生成class目录 -->
<var
name="outdir-classes"
value="${outdir-bin}" />
<var
name="outdir-classes-ospath"
value="${basedir}/${outdir-classes}" />
<!-- classes.dex相关变量 -->
<var
name="dex-file"
value="classes.dex" />
<var
name="dex-path"
value="${outdir-bin}/${dex-file}" />
<var
name="dex-ospath"
value="${basedir}/${dex-path}" />
<!-- 经过aapt生成的资源包文件 -->
<var
name="resources-package"
value="${outdir-bin}/resources.ap_" />
<var
name="resources-package-ospath"
value="${basedir}/${resources-package}" />
<!-- 未认证apk包 -->
<var
name="out-unsigned-package"
value="${outdir-bin}/${appName}-unsigned.apk" />
<var
name="out-unsigned-package-ospath"
value="${basedir}/${out-unsigned-package}" />
<!-- 证书文件 -->
<var
name="keystore-file"
value="${basedir}/gaoxin.key" />
<!-- 已认证apk包 -->
<var
name="out-signed-package"
value="${outdir-bin}/${appName}-${channelname}-${version}.apk" />
<var
name="out-signed-package-ospath"
value="${basedir}/${out-signed-package}" />
<delete dir="${outdir-bin}" />
<mkdir dir="${outdir-bin}" />
<mkdir dir="${outdir-classes}" />
</target>
<!-- 根据工程中的资源文件生成R.java文件 -->
<target
name="gen-R"
depends="init" >
<echo>
生成R.java文件....
</echo>
<exec
executable="${aapt}"
failοnerrοr="true" >
<arg value="package" />
<arg value="-f" />
<arg value="-m" />
<arg value="-J" />
<arg value="${outdir-gen}" />
<arg value="-S" />
<arg value="${resource-dir}" />
<arg value="-M" />
<arg value="${manifest-xml}" />
<arg value="-I" />
<arg value="${android-jar}" />
</exec>
</target>
<!-- 编译aidl文件 -->
<target
name="aidl"
depends="gen-R" >
<echo>
编译aidl文件....
</echo>
<apply
executable="${aidl}"
failοnerrοr="true" >
<!-- 指定预处理文件 -->
<arg value="-p${framework-aidl}" />
<!-- aidl声明的目录 -->
<arg value="-I${srcdir}" />
<!-- 目标文件目录 -->
<arg value="-o${outdir-gen}" />
<!-- 指定哪些文件需要编译 -->
<fileset dir="${srcdir}" >
<include name="**/*.aidl" />
</fileset>
</apply>
</target>
<!-- 将工程中的java源文件编译成class文件 -->
<target
name="compile"
depends="aidl" >
<echo>
java源文件编译成class文件....
</echo>
<javac
bootclasspath="${android-jar}"
destdir="${outdir-classes}"
encoding="utf-8"
srcdir="."
target="1.5"
verbose="false" >
<compilerarg line="-encoding GBK " />
<classpath>
<fileset
dir="${external-lib}"
includes="*.jar" />
</classpath>
</javac>
</target>
<!-- 将.class文件转化成.dex文件 -->
<target
name="dex"
depends="compile" >
<echo>
将.class文件转化成.dex文件....
</echo>
<exec
executable="${dx}"
failοnerrοr="true" >
<arg value="--dex" />
<!-- 输出文件 -->
<arg value="--output=${dex-ospath}" />
<!-- 要生成.dex文件的源classes和libraries -->
<arg value="${outdir-classes-ospath}" />
<arg value="${external-lib-ospath}" />
</exec>
</target>
<!-- 将资源文件放进输出目录 -->
<target name="package-res-and-assets" >
<echo>
将资源文件放进输出目录....
</echo>
<exec
executable="${aapt}"
failοnerrοr="true" >
<arg value="package" />
<arg value="-f" />
<arg value="-M" />
<arg value="${manifest-xml}" />
<arg value="-S" />
<arg value="${resource-dir}" />
<arg value="-A" />
<arg value="${asset-dir}" />
<arg value="-I" />
<arg value="${android-jar}" />
<arg value="-F" />
<arg value="${resources-package}" />
</exec>
</target>
<!-- 打包成未签证的apk -->
<target
name="package"
depends="dex, package-res-and-assets" >
<echo>
打包成未签证的apk....
</echo>
<exec
executable="${apkbuilder}"
failοnerrοr="true" >
<arg value="${out-unsigned-package-ospath}" />
<arg value="-u" />
<arg value="-z" />
<arg value="${resources-package-ospath}" />
<arg value="-f" />
<arg value="${dex-ospath}" />
<arg value="-rf" />
<arg value="${srcdir-ospath}" />
</exec>
</target>
<!-- 对apk进行签证 ,因为JDK7会修改签名的默认算法,所以需要指定SHA1 -->
<target
name="jarsigner"
depends="package" >
<echo>
Packaging signed apk for release...
</echo>
<exec
executable="${jarsigner}"
failοnerrοr="true" >
<arg value="-verbose" />
<arg value="-digestalg" />
<arg value="SHA1" />
<arg value="-sigalg" />
<arg value="MD5withRSA" />
<arg value="-keystore" />
<arg value="${keystore-file}" />
<arg value="-storepass" />
<arg value="123456" />
<arg value="-keypass" />
<arg value="123456" />
<arg value="-signedjar" />
<arg value="${out-signed-package-ospath}" />
<arg value="${out-unsigned-package-ospath}" />
<!-- 不要忘了证书的别名 -->
<arg value="gaoxin" />
</exec>
</target>
<!-- 发布 -->
<target
name="release"
depends="jarsigner" >
<!-- 删除未签证apk -->
<delete file="${out-unsigned-package-ospath}" />
<echo>
APK is released. path:${out-signed-package-ospath}
</echo>
</target>
<!-- 打包的应用程序进行优化 -->
<target
name="zipalign"
depends="release" >
<exec
executable="${zipalign}"
failοnerrοr="true" >
<arg value="-v" />
<arg value="4" />
<arg value="${out-signed-package-ospath}" />
<arg value="${out-signed-package-ospath}-zipaligned.apk" />
</exec>
</target>
</project></span>
该文件需要改动地方:
1) TestMutilChannelApk 的值替换成你的工程名。
2)
“D:/Android/Ant/lib/ant-contrib-1.0b3.jar” 替换成你存放ant-contrib-1.0b3.jar的地方。
本来这边可以使用环境变量ANT_HOME,但是一直不行,所以改成了绝对路径。
3) 替换你的SDK目录:
name="sdk-folder"
value="D:/Android/adt-bundle-windows-x86_64-20131030/sdk" />
"D:/Android/adt-bundle-windows-x86_64-20131030/sdk" 替换成你的SDK目录
本来这边可以使用环境变量ANDROID_SDK_HOME,但是一直不行,所以改成了绝对路径。
4)配置渠道名和渠道号:
name="key"
value="UM:umumum,BAI:baidu" />
"UM:umumum,BAI:baidu"替换成你要配置渠道名和渠道号。格式:渠道名1:渠道号1,渠道名2:渠道号2,......
5)修改版本号:
name="version"
value="3.0" />
"3.0" 替换成你的版本号。
6)设置签名部分:
name="keystore-file"
value="${basedir}/gaoxin.key" />
"${basedir}/gaoxin.key" 替换成的你签名文件的路径
name="jarsigner"
depends="package" >
Packaging signed apk for release...
executable="${jarsigner}"
failοnerrοr="true" >
如果你的JDK是7,需要添加红色部分的代码,如果是6,就可以不需要,否则,最终的APK安装会出现“该文件签名有问题,无法安装”。
第一个 替换成你的密钥的密码
第二个 替换成你别名的密码
"gaoxin" 替换成你密钥中的别名
5. 在AndroidManifest.xml中设置保存渠道号的meta-data:
注意,build.xml文件中的:
input="${nameandchannel}"
override="true"
property="channelname"
regexp="(.*):"
select="\1" />
input="${nameandchannel}"
override="true"
property="channelkey"
regexp=":(.*)"
select="\1" />
byline="false"
encoding="UTF-8"
flags="g" >
dir=""
includes="AndroidManifest.xml" />
中的要和你的AndroidManifest.xml的中meta-data字符串格式对应,如果不对应,正则替换就替换不了。
6. 最新的Android SDK 没有文件"apkbuilder.bat",我在网上下载了一个以前版本的,发现用不了,后来找到一个别人根据最新SDK修改过的。
把下载的"apkbuilder.bat"放到“D:\Android\adt-bundle-windows-x86_64-20131030\sdk\tools”中。
7. 运行build.xml:
选中deploy,去掉选中release[default],点击运行。
控制台输出的LOG:
Buildfile: D:\WorkSpace\TestMutilChannelApk\build.xml
deploy:
modify_manifest:
init:
[echo] 目录初始化....
[echo]
[mkdir] Created dir: D:\WorkSpace\TestMutilChannelApk\bin-UM
gen-R:
[echo] 生成R.java文件....
[echo]
aidl:
[echo] 编译aidl文件....
[echo]
compile:
[echo] java源文件编译成class文件....
[echo]
[javac] D:\WorkSpace\TestMutilChannelApk\build.xml:365: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 3 source files to D:\WorkSpace\TestMutilChannelApk\bin-UM
[javac] WARNING
[javac] The -source switch defaults to 1.7 in JDK 1.7.
[javac] If you specify -target 1.5 you now must also specify -source 1.5.
[javac] Ant will implicitly add -source 1.5 for you. Please change your build file.
dex:
[echo] 将.class文件转化成.dex文件....
[echo]
package-res-and-assets:
[echo] 将资源文件放进输出目录....
[echo]
package:
[echo] 打包成未签证的apk....
[echo]
[exec] THIS TOOL IS DEPRECATED. See --help for more information.
jarsigner:
[echo] Packaging signed apk for release...
[echo]
[exec] ???????: META-INF/MANIFEST.MF
[exec] ???????: META-INF/GAOXIN.SF
[exec] ???????: META-INF/GAOXIN.RSA
[exec] ???????: res/layout/activity_main.xml
[exec] ???????: res/menu/main.xml
[exec] ???????: AndroidManifest.xml
[exec] ???????: resources.arsc
[exec] ???????: res/drawable-hdpi/ic_launcher.png
[exec] ???????: res/drawable-mdpi/ic_launcher.png
[exec] ???????: res/drawable-xhdpi/ic_launcher.png
[exec] ???????: res/drawable-xxhdpi/ic_launcher.png
[exec] ???????: classes.dex
release:
[delete] Deleting: D:\WorkSpace\TestMutilChannelApk\bin-UM\TestMutilChannelApk-unsigned.apk
[echo] APK is released. path:D:\WorkSpace\TestMutilChannelApk/bin-UM/TestMutilChannelApk-UM-3.0.apk
[echo]
zipalign:
[exec] Verifying alignment of D:\WorkSpace\TestMutilChannelApk/bin-UM/TestMutilChannelApk-UM-3.0.apk-zipaligned.apk (4)...
[exec] 50 META-INF/MANIFEST.MF (OK - compressed)
[exec] 531 META-INF/GAOXIN.SF (OK - compressed)
[exec] 1074 META-INF/GAOXIN.RSA (OK - compressed)
[exec] 2220 res/layout/activity_main.xml (OK - compressed)
[exec] 2612 res/menu/main.xml (OK - compressed)
[exec] 2904 AndroidManifest.xml (OK - compressed)
[exec] 3660 resources.arsc (OK)
[exec] 5840 res/drawable-hdpi/ic_launcher.png (OK)
[exec] 11868 res/drawable-mdpi/ic_launcher.png (OK)
[exec] 15044 res/drawable-xhdpi/ic_launcher.png (OK)
[exec] 24464 res/drawable-xxhdpi/ic_launcher.png (OK)
[exec] 42394 classes.dex (OK - compressed)
[exec] Verification succesful
modify_manifest:
init:
[echo] 目录初始化....
[echo]
[mkdir] Created dir: D:\WorkSpace\TestMutilChannelApk\bin-BAI
gen-R:
[echo] 生成R.java文件....
[echo]
aidl:
[echo] 编译aidl文件....
[echo]
compile:
[echo] java源文件编译成class文件....
[echo]
[javac] D:\WorkSpace\TestMutilChannelApk\build.xml:365: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 3 source files to D:\WorkSpace\TestMutilChannelApk\bin-BAI
[javac] WARNING
[javac] The -source switch defaults to 1.7 in JDK 1.7.
[javac] If you specify -target 1.5 you now must also specify -source 1.5.
[javac] Ant will implicitly add -source 1.5 for you. Please change your build file.
dex:
[echo] 将.class文件转化成.dex文件....
[echo]
package-res-and-assets:
[echo] 将资源文件放进输出目录....
[echo]
package:
[echo] 打包成未签证的apk....
[echo]
[exec] THIS TOOL IS DEPRECATED. See --help for more information.
jarsigner:
[echo] Packaging signed apk for release...
[echo]
[exec] ???????: META-INF/MANIFEST.MF
[exec] ???????: META-INF/GAOXIN.SF
[exec] ???????: META-INF/GAOXIN.RSA
[exec] ???????: res/layout/activity_main.xml
[exec] ???????: res/menu/main.xml
[exec] ???????: AndroidManifest.xml
[exec] ???????: resources.arsc
[exec] ???????: res/drawable-hdpi/ic_launcher.png
[exec] ???????: res/drawable-mdpi/ic_launcher.png
[exec] ???????: res/drawable-xhdpi/ic_launcher.png
[exec] ???????: res/drawable-xxhdpi/ic_launcher.png
[exec] ???????: classes.dex
release:
[delete] Deleting: D:\WorkSpace\TestMutilChannelApk\bin-BAI\TestMutilChannelApk-unsigned.apk
[echo] APK is released. path:D:\WorkSpace\TestMutilChannelApk/bin-BAI/TestMutilChannelApk-BAI-3.0.apk
[echo]
zipalign:
[exec] Verifying alignment of D:\WorkSpace\TestMutilChannelApk/bin-BAI/TestMutilChannelApk-BAI-3.0.apk-zipaligned.apk (4)...
[exec] 50 META-INF/MANIFEST.MF (OK - compressed)
[exec] 530 META-INF/GAOXIN.SF (OK - compressed)
[exec] 1073 META-INF/GAOXIN.RSA (OK - compressed)
[exec] 2220 res/layout/activity_main.xml (OK - compressed)
[exec] 2612 res/menu/main.xml (OK - compressed)
[exec] 2904 AndroidManifest.xml (OK - compressed)
[exec] 3660 resources.arsc (OK)
[exec] 5840 res/drawable-hdpi/ic_launcher.png (OK)
[exec] 11868 res/drawable-mdpi/ic_launcher.png (OK)
[exec] 15044 res/drawable-xhdpi/ic_launcher.png (OK)
[exec] 24464 res/drawable-xxhdpi/ic_launcher.png (OK)
[exec] 42394 classes.dex (OK - compressed)
[exec] Verification succesful
BUILD SUCCESSFUL
Total time: 16 seconds
工程目录下多出了两个文件夹:
文件夹里面: