一,运行环境
win7+ant+eclipse+jdk1.6
ant打包可以直接在eclipse中直接右键build.xml文件运行,也可以在控制台切换到项目所在目录,执行命令ant。两个的效果是一样的。
但是在调试时,推荐使用eclipse右键运行。因为可以查看到完整日志,控制台下看不到完成日志,不利于错误的查找。稳定后可以使用控制台方式。
如果eclipse看不到完整日志的时候,可以调整输出日志大小。window-preferences-Run/Debug/Console,将Console buffer size调大,如800000;
1.下载ant
http://archive.apache.org/dist/ant/binaries/apache-ant-1.9.1-bin.zip
2.下载ANT Contrib(多渠道循环时需要用到)
http://nchc.dl.sourceforge.net/project/ant-contrib/ant-contrib/1.0b3/ant-contrib-1.0b3-bin.zip
下载完上面两个包后解压。将ANT Contrib解压包中的ant-contrib-1.0b3.jar文件拷贝到ant解压包下的lib目录里。并且将其也拷贝一份到eclipse安装目录下的plugins/org.apache.ant***/lib目录下.
3.配置ant环境变量
在系统变量里增加一个变量名为:ANT_HOME,值为ant解压根目录。如:E:\开发工具\ant\apache-ant-1.9.1
修改path环境变量,在最后增加:%ANT_HOME%\bin;
在控制台下,输入ant,出现下面的文字说明安装成功
Buildfile: build.xml does not exist!
Build failed
二,build.xml文件编写
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.test.myproject" default="deploy" >
<!-- 版本 -->
<property name="version" value="v1.8.5" />
<!-- ANT环境变量 -->
<property environment="env" />
<!-- 使用第三方的ant包,使ant支持for循环-->
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${env.ANT_HOME}/lib/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
<!-- 应用名称 -->
<property name="appName" value="${ant.project.name}" />
<!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->
<property name="sdk-folder" value="${env.Android_Home}" />
<!-- SDK指定平台目录 -->
<property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-7" />
<!-- 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" />
<!-- 编译需要的jar; 如果项目使用到地图服务则需要maps.jar -->
<property name="android-jar" value="${sdk-platform-folder}/android.jar" />
<property name="proguard-home" value="${sdk-tools}/proguard/lib" />
<!-- <property name="android-maps-jar" value="${sdk-folder}/add-ons/addon_google_apis_google_inc_8/libs/maps.jar" /> -->
<!-- 编译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="channelname" value="" />
<property name="channelkey" value="" />
<!-- 渠道名:渠道号 -->
<!-- <property name="key" value="UMENG_CHANNEL:goapk,UMENG_CHANNEL:QQ" /> -->
<property name="key" value="goapk,QQ" />
<!--循环打包 -->
<target name="deploy">
<foreach target="modify_manifest" list="${key}" param="nameandchannel" delimiter=",">
</foreach>
</target>
<target name="modify_manifest">
<!-- 获取渠道名字 -->
<!-- <propertyregex override="true" property="channelname" input="${nameandchannel}" regexp="(.*):" select="\1" /> -->
<!-- 获取渠道号码 -->
<propertyregex override="true" property="channelkey" input="${nameandchannel}" regexp="(.*)" select="\1" />
<!-- 正则匹配替换渠道号(这里pattern里的内容要与mainfest文件的内容一致,包括顺序,空格) -->
<replaceregexp flags="g" byline="false" encoding="UTF-8">
<regexp pattern='meta-data android:name="UMENG_CHANNEL" android:value="(.*)"' />
<substitution expression='meta-data android:name="UMENG_CHANNEL" android:value="${channelkey}"' />
<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="publish/${channelkey}" />
<!-- 生成class目录 -->
<var name="outdir-classes" value="${outdir-bin}/otherfile" />
<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}/***.keystore" />
<!-- 当前时间 -->
<tstamp>
<format property="nowtime" pattern="yyyyMMdd"></format>
</tstamp>
<!-- 已认证apk包 -->
<var name="out-signed-package" value="${outdir-bin}/${appName}_${channelkey}_${version}_${nowtime}.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}" failonerror="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}" failonerror="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 encoding="utf-8" target="1.6" srcdir="." destdir="${outdir-classes}" bootclasspath="${android-jar}" verbose="false">
<compilerarg line="-encoding GBK " />
<!-- <compilerarg line="-encoding UTF-8 "/> -->
<classpath>
<fileset dir="${external-lib}" includes="*.jar" />
</classpath>
</javac>
</target>
<!--执行代码混淆-->
<target name="optimize" depends="compile">
<jar basedir="${outdir-classes}" destfile="temp.jar"/>
<java jar="${proguard-home}/proguard.jar" fork="true" failonerror="true">
<jvmarg value="-Dmaximum.inlined.code.length=32"/>
<arg value="-injars temp.jar"/>
<arg value="-outjars optimized.jar"/>
<arg value="-libraryjars ${android-jar}"/>
<arg value="-libraryjars ${external-lib}/"/>
<arg value="-dontpreverify"/>
<arg value="-dontoptimize"/>
<arg value="-dontusemixedcaseclassnames"/>
<arg value="-repackageclasses ''"/>
<arg value="-allowaccessmodification"/>
<!--<arg value="-keep public class ${exclude-activity}"/>-->
<!--<arg value="-keep public class ${exclude-provider}"/>-->
<arg value="@proguard.cfg"/>
<arg value="-optimizationpasses 7"/>
<arg value="-verbose"/>
<arg value="-dontskipnonpubliclibraryclasses"/>
<arg value="-dontskipnonpubliclibraryclassmembers"/>
</java>
<delete file="temp.jar"/>
<delete dir="${outdir-classes}"/>
<mkdir dir="${outdir-classes}"/>
<unzip src="optimized.jar" dest="${outdir-classes}"/>
<delete file="optimized.jar"/>
</target>
<!-- 将.class文件转化成.dex文件 -->
<target name="dex" depends="compile,optimize" unless="do.not.compile">
<echo>将.class文件转化成.dex文件....</echo>
<exec executable="${dx}" failonerror="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}" failonerror="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}" failonerror="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进行签证 -->
<target name="jarsigner" depends="package">
<echo>Packaging signed apk for release...</echo>
<exec executable="${jarsigner}" failonerror="true">
<arg value="-keystore" />
<arg value="${keystore-file}" />
<arg value="-storepass" />
<arg value="123***" />
<arg value="-keypass" />
<arg value="123***" />
<arg value="-signedjar" />
<arg value="${out-signed-package-ospath}" />
<arg value="${out-unsigned-package-ospath}" />
<!-- 不要忘了证书的别名 -->
<arg value="Aliases" />
</exec>
</target>
<!-- 发布 -->
<target name="release" depends="jarsigner">
<!-- 删除未签证apk -->
<delete file="${out-unsigned-package-ospath}" />
<echo>APK is released. path:${out-signed-package-ospath}</echo>
<echo>删除其他文件,最后只保留apk</echo>
<delete dir="${outdir-classes}"/>
<delete file="${dex-ospath}" />
<delete file="${resources-package-ospath}" />
<echo>生成apk完成</echo>
</target>
<!-- 打包的应用程序进行优化 -->
<target name="zipalign" depends="release">
<exec executable="${zipalign}" failonerror="true">
<arg value="-v" />
<arg value="4" />
<arg value="${out-signed-package-ospath}" />
<arg value="${out-signed-package-ospath}-zipaligned.apk" />
</exec>
</target>
</project>
参考:
http://blog.csdn.net/tenggangren/article/details/8051937
可能运到的错误:
1.ant打包时,提示资源文件找不到,都是res drawable目录下的资源。这个用eclipse的ant打包可以发现原来是.9格式的图片有问题。解决办法,参考:http://blog.csdn.net/yueliangniao1/article/details/7077352
2.当提示找不到antContrib下的某个文件时,看是否配置正确,ant-contrib-1.0b3.jar文件是否拷贝到ant lib目录下。
分享到:
相关推荐
demo所需的所有 jar 与demo。 直接下载后 按照csdn描述即可,此项目不包括 ant 混淆打包 混淆打包具体看我的csdn
Android ant 多渠道批量打包解决方案
android ant 多渠道批量打包,利用ant 可实现多渠道,批量打包。
android ant 多渠道批量打包,利用ant 可实现多渠道,批量打包。
整了三天,终于弄通了,共享一下。 android ant多市场,打包混淆签名 里面两个工程,一个是打包的,一人是被打包的
Android中使用Ant方式打包,一次打出N个渠道的包。
关于最新的Android Sdk 使用Ant多渠道批量打包的实现的文章可以看我的博客。
Ant多渠道 多项目引用 打包Android项目
本资源详细的描述了如何使用Ant批量多渠道导报Android应用。运营是需要上传应用到20几个市场上去,这个时候需要批量打不通tag的包,以便友盟能够统计得到各通道下载量
ant 多渠道自动打包 ,出现appt 没找到 ,去sdk里拷贝到指定目录
ant 多渠道包混淆 签名 build xml android4 0 打多个包
mac下是用ant对android App的多渠道打包工具。
Android Ant 打包
Android多渠道全自动打包发布工具,ant实现
使用ant打包android,使用ant打包android
ant混淆打包
打包原理: 反编译基础Apk -> 循环渠道号 -> 替换assets目录下的渠道文件 -> 修改渠道号 -> 重新生成Apk -> 进行签名 -> zipalign优化
ant配置、实现自己的多渠道打包,对于需要者相当有参考意义。
build_mulity_channel是多渠道打包脚本。该脚本需要ant-contrib-1.0b3.jar的支持。包中已包含,需要将其放到ant的lib文件夹下。">build_with_bat是基于bat脚本实现的。 build是在build_with_bat的基础上实现的,...
因为项目的需要必须写一个ANDROID_ANT自动编译打包签名的脚本,终于奋斗了几天写完了,和大家分享一下