通过ant脚本,编译打包android工程
1.Android程序编译、打包、签名、发布的三种方式:
方式一:命令行手动编译打包
方式二:使用ant自动编译打包
方式三:使用eclipse+ADT编译打包
2.Android编译、打包的步骤:
2.1第一步 生成R.java类文件:
Eclipse中会自动生成R.java,ant和命令行使用android SDK提供的aapt.ext程序生成R.java。
2.2第二步 将.aidl文件生成.java类文件:
Eclipse中自动生成,ant和命令行使用android SDK提供的aidl.exe生成.java文件。
2.3第三步 编译.java类文件生成class文件:
Eclipse中自动生成,ant和命令行使用jdk的javac编译java类文件生成class文件。
2.4第四步 将class文件打包生成classes.dex文件:
Eclipse中自动生成,ant和命令行使用android SDK提供的dx.bat命令行脚本生成classes.dex文件。
2.5第五步 打包资源文件(包括res、assets、androidmanifest.xml等):
Eclipse中自动生成,ant和命令行使用Android SDK提供的aapt.exe生成资源包文件。
2.6第六步 生成未签名的apk安装文件:
Eclipse中自动生成debug签名文件存放在bin目录中,ant和命令行使用android SDK提供的apkbuilder.bat命令脚本生成未签名的apk安装文件。
2.7第七步 对未签名的apk进行签名生成签名后的android文件:
Eclipse中使用Android Tools进行签名,ant和命令行使用jdk的jarsigner对未签名的包进行apk签名。
这个ant脚本只能编译打包一个单独的android工程或依赖一个library 的android工程
首先配置ant的环境变量,这个我就不多少了,自己查。
ant脚本,生成build.xml
- <span style="font-size:18px">H:\install\eclipse-SDK-3.7.2-win32\eclipse\android_sdk\tools\android.bat update project -n BuiltDemo -t android-8 -p H:\workspace\prac_a3\BuiltDemo</span>
- <span style="font-size:18px">sdk.dir=H:/install/eclipse-SDK-3.7.2-win32/eclipse/android_sdk
- ANDROID_HOME=H:/install/eclipse-SDK-3.7.2-win32/eclipse/android_sdk
- ANT_HOME=F:/Soft/ant/apache-ant-1.9.2
- JAVA_HOME=C:/Program Files/Java/jdk1.6.0_10</span>
- <span style="font-size:18px">H:\install\eclipse-SDK-3.7.2-win32\eclipse\android_sdk\tools\android.bat debug
- H:\install\eclipse-SDK-3.7.2-win32\eclipse\android_sdk\tools\android.bat release</span>
- <span style="font-size:18px"><?xml version="1.0" encoding="UTF-8"?>
- <project name="BuiltDemo" default="release">
- <property file="local.properties" />
- <!-- ANT环境变量 -->
- <property environment="env" />
- <!-- 应用名称 -->
- <property name="appName" value="BuiltDemo" />
- <property name="basedir" value="H:/workspace/prac_a3/BuiltDemo" />
- <property name="library-dir" value="H:/workspace/prac_a3/BuiltDemo">
- </property>
- <!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->
- <!-- <property name="sdk-folder" value="${env.ANDROID_SDK_HOME}" /> -->
- <property name="sdk-folder" value="${env.ANDROID_HOME}" />
- <!-- 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.exe" />
- <property name="aidl" value="${sdk-platform-tools}/aidl.exe" />
- <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" />
- <!-- 编译需要的jar; 如果项目使用到地图服务则需要maps.jar -->
- <property name="android-jar" value="${sdk-platform-folder}/android.jar" />
- <!-- 编译aidl文件所需的预处理框架文件framework.aidl -->
- <property name="framework-aidl" value="${sdk-platform-folder}/framework.aidl" />
- <!-- 生成R文件的相对目录 -->
- <property name="outdir-gen" value="gen" />
- <!-- 编译后的文件放置目录 -->
- <property name="outdir-bin" value="out" />
- <!-- 清单文件 -->
- <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}" />
- <!-- 生成class目录 -->
- <property name="outdir-classes" value="${outdir-bin}" />
- <property name="outdir-classes-ospath" value="${basedir}/${outdir-classes}" />
- <!-- classes.dex相关变量 -->
- <property name="dex-file" value="classes.dex" />
- <property name="dex-path" value="${outdir-bin}/${dex-file}" />
- <property name="dex-ospath" value="${basedir}/${dex-path}" />
- <!-- 经过aapt生成的资源包文件 -->
- <property name="resources-package" value="${outdir-bin}/resources.ap_" />
- <property name="resources-package-ospath" value="${basedir}/${resources-package}" />
- <!-- 未认证apk包 -->
- <property name="out-unsigned-package" value="${outdir-bin}/${appName}-unsigned.apk" />
- <property name="out-unsigned-package-ospath" value="${basedir}/${out-unsigned-package}" />
- <!-- 证书文件 -->
- <property name="keystore-file" value="${basedir}/sbx" />
- <!-- 已认证apk包 -->
- <property name="out-signed-package" value="${outdir-bin}/${appName}.apk" />
- <property name="out-signed-package-ospath" value="${basedir}/${out-signed-package}" />
- <!-- 初始化工作 -->
- <target name="init">
- <echo>Initializing all output directories...</echo>
- <delete dir="${outdir-bin}" />
- <mkdir dir="${outdir-bin}" />
- <mkdir dir="${outdir-classes}" />
- </target>
- <!-- 根据工程中的资源文件生成R.java文件 -->
- <target name="gen-R" depends="init">
- <echo>Generating R.java from the resources...</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>-->
- <exec executable="${aapt}" failonerror="true">
- <arg value="package" />
- <arg value="-m" />
- <arg value="--auto-add-overlay" />
- <arg value="-J" />
- <arg value="${outdir-gen}" />
- <arg value="-M" />
- <arg value="${manifest-xml}" />
- <arg value="-S" />
- <arg value="${resource-dir}" />
- <arg value="-S" />
- <arg value="${library-dir}/${resource-dir}" />
- <arg value="--extra-packages" />
- <arg value="com.mobcent.share.android" />
- <arg value="-A" />
- <arg value="${asset-dir}" />
- <arg value="-I" />
- <arg value="${android-jar}" />
- </exec>
- </target>
- <!-- 编译aidl文件 -->
- <target name="aidl" depends="gen-R">
- <echo>Compiling .aidl into java files...</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>Compiling java source code...</echo>
- <javac encoding="utf-8" target="1.6" destdir="${outdir-classes}" bootclasspath="${android-jar}">
- <src path="src" />
- <src path="gen" />
- <src path="${library-dir}/src" />
- <classpath>
- <fileset dir="${external-lib}" includes="*.jar" />
- <fileset dir="${library-dir}/libs" includes="*.jar" />
- <filelist>
- <file name="${android-maps-jar}" />
- </filelist>
- </classpath>
- </javac>
- </target>
- <!-- 将.class文件转化成.dex文件 -->
- <target name="dex" depends="compile">
- <echo>Converting compiled files and external libraries into a .dex
- file...
- </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}" />
- <!-- <arg value="${library-dir}/libs" /> -->
- </exec>
- </target>
- <!-- 将资源文件放进输出目录 -->
- <!--在这截断-->
- <target name="package-res-and-assets" depends="dex">
- <echo>Packaging resources and assets...</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="-S" />
- <arg value="${library-dir}/${resource-dir}" />
- <arg value="-A" />
- <arg value="${library-dir}/${asset-dir}" />
- <arg value="-I" />
- <arg value="${android-jar}" />
- <arg value="-F" />
- <arg value="${resources-package}" />
- <arg value="--auto-add-overlay" />
- </exec>
- </target>
- <!-- 打包成未签证的apk -->
- <target name="package" depends="dex, package-res-and-assets">
- <echo>Packaging unsigned apk for release...</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}" />
- <arg value="-nf"/>
- <arg value="${library-dir}/libs"/>
- </exec>
- <echo>It will need to be signed with jarsigner before being published.
- </echo>
- </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="111111" />
- <arg value="-keypass" />
- <arg value="111111" />
- <arg value="-signedjar" />
- <arg value="${out-signed-package-ospath}" />
- <arg value="${out-unsigned-package-ospath}" />
- <!-- 不要忘了证书的别名 -->
- <arg value="sbx" />
- </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>
- </project>
- </span>
Android官方提供的打包脚本: 1400多行,我加了中文注释,希望能看懂。
- <?xml version="1.0" encoding="UTF-8"?>
- <project name="pet_dog_base_forum" default="release">
- <!--自己需要添加的属性 -->
- <property name="sdk.dir" value="C:/Program Files/android-sdk_r15-windows/android-sdk-windows" />
- <!--导入project.properties 文件,设置了编译的target 和相关的library工程-->
- <property file="project.properties" />
- <!--导入build.properties文件,设置了android的目录和key-->
- <property file="ant.properties" />
- <!--
- This build file is imported by the project build file. It contains
- all the targets and tasks necessary to build Android projects, be they
- regular projects, library projects, or test projects.
- At the beginning of the file is a list of properties that can be overridden
- by adding them to your build.properties (properties are immutable, so their
- first definition sticks and is never changed).
- Follows:
- - custom task definitions,
- - more properties (do not override those unless the whole build system is modified).
- - macros used throughout the build,
- - base build targets,
- - debug-specific build targets,
- - release-specific build targets,
- - instrument-specific build targets,
- - test project-specific build targets,
- - install targets,
- - help target
- 步骤如下:
- —— 自定义task
- —— 设置相关属性
- —— 全局的使用整个构建
- —— 基本bulid的targets
- —— debug使用的targets
- —— release使用的targets
- —— 特定仪器使用的targets
- —— 测试使用的targets
- —— 安装的targets
- —— 帮助的targets
- -->
- <!-- ********** Overrideable Properties ********** -->
- <!-- ********** 可重写的属性 ********** -->
- <!-- You can override these values in your build.xml or build.properties.
- Overriding any other properties may result in broken build. -->
- <!-- 你可以覆盖build.xml 或者 build.properties 文件中的任何属性,覆盖任何一个属性,都可能导致build出错,慎用 -->
- <!-- Tells adb which device to target. You can change this from the command line
- by invoking "ant -Dadb.device.arg=-d" for device "ant -Dadb.device.arg=-e" for
- the emulator. -->
- <!-- 设置链接的机器,
- ant -Dadb.device.arg=-d 使用链接当前的设备
- ant -Dadb.device.arg=-e 使用模拟器
- -->
- <property name="adb.device.arg" value="" />
- <!-- fileset exclude patterns (space separated) to prevent
- files inside src/ from being packaged. -->
- <!-- 设置改属性可以排除编译一部分代码
- -->
- <property name="android.package.excludes" value="" />
- <!-- set some properties used for filtering/override. If those weren't defined
- before, then this will create them with empty values, which are then ignored
- by the custom tasks receiving them. -->
- <!--
- version.code,version.name可以替換AndroidManifest.xml中的android:versionCode和android:versionName
- -->
- <property name="version.code" value="11" />
- <property name="version.name" value="111" />
- <property name="aapt.resource.filter" value="" />
- <!-- compilation options -->
- <property name="java.encoding" value="UTF-8" />
- <property name="java.target" value="1.6" />
- <property name="java.source" value="1.6" />
- <!-- Verbosity -->
- <property name="verbose" value="false" />
- <!-- ********** Custom Tasks ********** -->
- <!-- ********** 自定义Tasks ********** -->
- <!-- 导入自定义Task是需要的文件 -->
- <path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
- </path>
- <!-- Custom tasks -->
- <taskdef name="setup" classname="com.android.ant.NewSetupTask" classpathref="android.antlibs" />
- <taskdef name="aapt" classname="com.android.ant.AaptExecTask" classpathref="android.antlibs" />
- <taskdef name="aidl" classname="com.android.ant.AidlExecTask" classpathref="android.antlibs" />
- <taskdef name="renderscript" classname="com.android.ant.RenderScriptTask" classpathref="android.antlibs" />
- <taskdef name="dex" classname="com.android.ant.DexExecTask" classpathref="android.antlibs" />
- <taskdef name="apkbuilder" classname="com.android.ant.ApkBuilderTask" classpathref="android.antlibs" />
- <taskdef name="zipalign" classname="com.android.ant.ZipAlignTask" classpathref="android.antlibs" />
- <taskdef name="xpath" classname="com.android.ant.XPathTask" classpathref="android.antlibs" />
- <taskdef name="if" classname="com.android.ant.IfElseTask" classpathref="android.antlibs" />
- <!-- Emma configuration
- EMMA 是一种快速的,基于字节码指令的Java 代码覆盖工具。
- -->
- <property name="emma.dir" value="${sdk.dir}/tools/lib" />
- <path id="emma.lib">
- <pathelement location="${emma.dir}/emma.jar" />
- <pathelement location="${emma.dir}/emma_ant.jar" />
- </path>
- <taskdef resource="emma_ant.properties" classpathref="emma.lib" />
- <!-- End of emma configuration -->
- <!-- ********** Other Properties ********** -->
- <!-- overriding these properties may break the build
- unless the whole file is updated -->
- <!-- 输入文件 -->
- <property name="source.dir" value="src" />
- <property name="source.absolute.dir" location="${source.dir}" />
- <property name="gen.absolute.dir" location="gen" />
- <property name="resource.absolute.dir" location="res" />
- <property name="asset.absolute.dir" location="assets" />
- <property name="jar.libs.dir" value="libs" />
- <property name="jar.libs.absolute.dir" location="${jar.libs.dir}" />
- <property name="native.libs.absolute.dir" location="libs" />
- <!-- 输出文件 -->
- <property name="out.dir" value="bin" />
- <property name="out.absolute.dir" location="${out.dir}" />
- <property name="out.classes.absolute.dir" location="${out.dir}/classes" />
- <property name="out.res.absolute.dir" location="${out.dir}/res" />
- <!-- tools location 编译所需要用到的工具 -->
- <property name="android.tools.dir" location="${sdk.dir}/tools" />
- <property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
- <condition property="exe" value=".exe" else="">
- <os family="windows" />
- </condition>
- <condition property="bat" value=".bat" else="">
- <os family="windows" />
- </condition>
- <property name="adb" location="${android.platform.tools.dir}/adb${exe}" />
- <property name="zipalign" location="${android.tools.dir}/zipalign${exe}" />
- <property name="aidl" location="${android.platform.tools.dir}/aidl${exe}" />
- <property name="aapt" location="${android.platform.tools.dir}/aapt${exe}" />
- <property name="dx" location="${android.platform.tools.dir}/dx${bat}" />
- <!-- renderscript location is set by NewSetupTask since we have a choice of
- several executables based on minSdkVersion -->
- <!-- Intermediate files 中间文件 -->
- <property name="dex.file.name" value="classes.dex" />
- <property name="intermediate.dex.file" location="${out.absolute.dir}/${dex.file.name}" />
- <property name="resource.package.file.name" value="${ant.project.name}.ap_" />
- <!-- Build property file build的属性文件 -->
- <property name="out.build.prop.file" location="${out.absolute.dir}/build.prop" />
- <!-- This is needed by emma as it uses multilevel verbosity instead of simple 'true' or 'false'
- The property 'verbosity' is not user configurable and depends exclusively on 'verbose'
- value.
- 这是需要通过艾玛,因为它使用多级verbosity不是简单的“true”或“false”。属性“冗长”不是用户可配置的,只取决于verbose”值。
- -->
- <condition property="verbosity" value="verbose" else="quiet">
- <istrue value="${verbose}" />
- </condition>
- <!-- properties for signing in release mode -->
- <!-- 签名所需要的文件 -->
- <condition property="has.keystore">
- <and>
- <isset property="key.store" />
- <length string="${key.store}" when="greater" length="0" />
- <isset property="key.alias" />
- </and>
- </condition>
- <condition property="has.password">
- <and>
- <isset property="has.keystore" />
- <isset property="key.store.password" />
- <isset property="key.alias.password" />
- </and>
- </condition>
- <!-- properties for packaging -->
- <property name="build.packaging.nocrunch" value="true" />
- <!-- ********** Macros ********** -->
- <!-- ********** 宏定义 ********** -->
- <!-- macro to do a task on if project.is.library is false.
- elseText attribute is displayed otherwise -->
- <!-- 定义了没有关联library工程时,将会打印elseText -->
- <macrodef name="do-only-if-not-library">
- <attribute name="elseText" />
- <element name="task-to-do" implicit="yes" />
- <sequential>
- <if condition="${project.is.library}">
- <else>
- <task-to-do />
- </else>
- <then>
- <echo>@{elseText}</echo>
- </then>
- </if>
- </sequential>
- </macrodef>
- <!-- macro to do a task on if manifest.hasCode is true.
- elseText attribute is displayed otherwise -->
- <macrodef name="do-only-if-manifest-hasCode">
- <attribute name="elseText" default="" />
- <element name="task-to-do" implicit="yes" />
- <sequential>
- <if condition="${manifest.hasCode}">
- <then>
- <task-to-do />
- </then>
- <else>
- <if>
- <condition>
- <length string="@{elseText}" trim="true" when="greater" length="0" />
- </condition>
- <then>
- <echo>@{elseText}</echo>
- </then>
- </if>
- </else>
- </if>
- </sequential>
- </macrodef>
- <!-- Configurable macro, which allows to pass as parameters output directory,
- output dex filename and external libraries to dex (optional)
- 配置宏,允许通过参数设置输出的目录,dex文件和dex额外的libraries
- -->
- <macrodef name="dex-helper">
- <element name="external-libs" optional="yes" />
- <attribute name="nolocals" default="false" />
- <sequential>
- <!-- sets the primary input for dex. If a pre-dex task sets it to
- something else this has no effect -->
- <property name="out.dex.input.absolute.dir" value="${out.classes.absolute.dir}" />
- <!-- set the secondary dx input: the project (and library) jar files
- If a pre-dex task sets it to something else this has no effect -->
- <if>
- <condition>
- <isreference refid="out.dex.jar.input.ref" />
- </condition>
- <else>
- <path id="out.dex.jar.input.ref">
- <path refid="jar.libs.ref" />
- </path>
- </else>
- </if>
- <dex executable="${dx}" output="${intermediate.dex.file}" nolocals="@{nolocals}" verbose="${verbose}" previousBuildType="${build.last.target}" buildType="${build.target}">
- <path path="${out.dex.input.absolute.dir}" />
- <path refid="out.dex.jar.input.ref" />
- <external-libs />
- </dex>
- </sequential>
- </macrodef>
- <!-- This is macro that enable passing variable list of external jar files to ApkBuilder
- 设置ApkBuilder 是额外的jar文件
- 默认把工程下libs中的jar文件打到APK里
- Example of use:
- <package-helper>
- <extra-jars>
- <jarfolder path="my_jars" />
- <jarfile path="foo/bar.jar" />
- <jarfolder path="your_jars" />
- </extra-jars>
- </package-helper> -->
- <macrodef name="package-helper">
- <element name="extra-jars" optional="yes" />
- <sequential>
- <apkbuilder outfolder="${out.absolute.dir}" resourcefile="${resource.package.file.name}" apkfilepath="${out.packaged.file}" debugpackaging="${build.is.packaging.debug}" debugsigning="${build.is.signing.debug}" verbose="${verbose}" hascode="${manifest.hasCode}" previousBuildType="${build.last.is.packaging.debug}/${build.last.is.signing.debug}" buildType="${build.is.packaging.debug}/${build.is.signing.debug}">
- <dex path="${intermediate.dex.file}" />
- <sourcefolder path="${source.absolute.dir}" />
- <jarfile refid="jar.libs.ref" />
- <nativefolder path="${native.libs.absolute.dir}" />
- <nativefolder refid="project.libraries.libs" />
- <extra-jars />
- </apkbuilder>
- </sequential>
- </macrodef>
- <!-- This is macro which zipaligns in.package and outputs it to out.package. Used by targets
- debug, -debug-with-emma and release.
- 通过zipaligns 对APK进行优化
- -->
- <macrodef name="zipalign-helper">
- <attribute name="in.package" />
- <attribute name="out.package" />
- <sequential>
- <zipalign executable="${zipalign}" input="@{in.package}" output="@{out.package}" verbose="${verbose}" />
- </sequential>
- </macrodef>
- <macrodef name="run-tests-helper">
- <attribute name="emma.enabled" default="false" />
- <element name="extra-instrument-args" optional="yes" />
- <sequential>
- <echo>Running tests ...</echo>
- <exec executable="${adb}" failonerror="true">
- <arg line="${adb.device.arg}" />
- <arg value="shell" />
- <arg value="am" />
- <arg value="instrument" />
- <arg value="-w" />
- <arg value="-e" />
- <arg value="coverage" />
- <arg value="@{emma.enabled}" />
- <extra-instrument-args />
- <arg value="${manifest.package}/${test.runner}" />
- </exec>
- </sequential>
- </macrodef>
- <macrodef name="record-build-key">
- <attribute name="key" default="false" />
- <attribute name="value" default="false" />
- <sequential>
- <propertyfile file="${out.build.prop.file}" comment="Last build type">
- <entry key="@{key}" value="@{value}" />
- </propertyfile>
- </sequential>
- </macrodef>
- <macrodef name="record-build-info">
- <sequential>
- <record-build-key key="build.last.target" value="${build.target}" />
- <record-build-key key="build.last.is.instrumented" value="${build.is.instrumented}" />
- <record-build-key key="build.last.is.packaging.debug" value="${build.is.packaging.debug}" />
- <record-build-key key="build.last.is.signing.debug" value="${build.is.signing.debug}" />
- </sequential>
- </macrodef>
- <macrodef name="uninstall-helper">
- <attribute name="app.package" default="false" />
- <sequential>
- <echo>Uninstalling @{app.package} from the default emulator or device...</echo>
- <exec executable="${adb}" failonerror="true">
- <arg line="${adb.device.arg}" />
- <arg value="uninstall" />
- <arg value="@{app.package}" />
- </exec>
- </sequential>
- </macrodef>
- <!-- ********** Build Targets ********** -->
- <!-- this target simply force running -setup making
- the project info be read. To be used as
- ant all clean
- to clean the main project as well as the libraries and tested project
- 运行-setup,在此之前必须运行clean,
- -->
- <target name="all" depends="-setup" />
- <!-- clean target -->
- <target name="clean" description="Removes output files created by other targets.">
- <delete dir="${out.absolute.dir}" verbose="${verbose}" />
- <delete dir="${gen.absolute.dir}" verbose="${verbose}" />
- <!-- if we know about a tested project or libraries, we clean them too. This
- will only work if the target 'all' was called first -->
- <if condition="${project.is.test}">
- <then>
- <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
- <subant failonerror="true">
- <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
- <target name="all" />
- <target name="clean" />
- </subant>
- </then>
- </if>
- <if>
- <condition>
- <isreference refid="project.libraries" />
- </condition>
- <then>
- <!-- 有libraries关联工程的时候,调用libraries工程中build.xml -->
- <subant buildpathref="project.libraries" antfile="build.xml" failonerror="true">
- <target name="all" />
- <target name="clean" />
- </subant>
- </then>
- </if>
- </target>
- <!-- generic setup 初始化-->
- <target name="-setup">
- <if>
- <condition>
- <not>
- <isset property="setup.done" />
- </not>
- </condition>
- <then>
- <property name="setup.done" value="true" />
- <echo>Gathering info for ${ant.project.name}...</echo>
- <!-- load project properties, resolve Android target, library dependencies
- and set some properties with the results.
- All property names are passed as parameters ending in -Out
- 加载project properties,设置 Android target,依赖的library工程和一些其他的属性
- -->
- <setup projectTypeOut="android.project.type" androidJarFileOut="android.jar" androidAidlFileOut="android.aidl" renderScriptExeOut="renderscript" renderScriptIncludeDirOut="android.rs" bootclasspathrefOut="android.target.classpath" projectLibrariesRootOut="project.libraries" projectLibrariesJarsOut="project.libraries.jars" projectLibrariesResOut="project.libraries.res" projectLibrariesPackageOut="project.libraries.package" projectLibrariesLibsOut="project.libraries.libs" targetApiOut="target.api" />
- <!-- sets a few boolean based on android.project.type
- to make the if task easier -->
- <condition property="project.is.library" else="false">
- <equals arg1="${android.project.type}" arg2="library" />
- </condition>
- <condition property="project.is.test" else="false">
- <equals arg1="${android.project.type}" arg2="test" />
- </condition>
- <!-- If a test project, resolve absolute path to tested project. -->
- <if condition="${project.is.test}">
- <then>
- <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
- </then>
- </if>
- </then>
- </if>
- </target>
- <!-- Pre build setup
- 预编译
- -->
- <target name="-build-setup" depends="-setup">
- <!-- read the previous build mode -->
- <property file="${out.build.prop.file}" />
- <!-- if empty the prop won't be set, so set it to the current target
- to provide a default value equal to the current build -->
- <property name="build.last.target" value="${build.target}" />
- <!-- also set the default value for whether the build is instrumented -->
- <property name="build.last.is.instrumented" value="${build.is.instrumented}" />
- <property name="build.last.is.packaging.debug" value="${build.is.packaging.debug}" />
- <property name="build.last.is.signing.debug" value="${build.is.signing.debug}" />
- <!-- compile the libraries if any
- 编译libraries
- -->
- <if>
- <condition>
- <isreference refid="project.libraries" />
- </condition>
- <then>
- <echo>Building Libraries</echo>
- <subant buildpathref="project.libraries" antfile="build.xml" target="${build.target}" failonerror="true" />
- <echo>
- </echo>
- <echo>############################################</echo>
- <echo>**** Back to project ${ant.project.name} ****</echo>
- <echo>############################################</echo>
- </then>
- </if>
- <!-- compile the main project if this is a test project
- 编译主工程,如果这是测试工程
- -->
- <if condition="${project.is.test}">
- <then>
- <!-- figure out which target must be used to build the tested project.
- If emma is enabled, then use 'instrument' otherwise, use 'debug' -->
- <condition property="tested.project.target" value="instrument" else="debug">
- <isset property="emma.enabled" />
- </condition>
- <echo>Building tested project at ${tested.project.absolute.dir}</echo>
- <subant target="${tested.project.target}" failonerror="true">
- <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
- </subant>
- <echo>
- </echo>
- <echo>############################################</echo>
- <echo>**** Back to project ${ant.project.name} ****</echo>
- <echo>############################################</echo>
- </then>
- </if>
- <!-- Value of the hasCode attribute (Application node) extracted from manifest file -->
- <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:hasCode" output="manifest.hasCode" default="true" />
- <!-- create a path with all the jar files, from the main project and the
- libraries
- 创建一个path,关联所有的jar文件。每个工程下的libs下的jar文件
- -->
- <path id="jar.libs.ref">
- <fileset dir="${jar.libs.absolute.dir}" includes="*.jar" />
- <path refid="project.libraries.jars" />
- </path>
- <!-- special case for instrumented: if the previous build was
- instrumented but not this one, clear out the compiled code
- 特殊情况被打断,清除已编译的代码
- -->
- <if>
- <condition>
- <and>
- <istrue value="${build.last.is.instrumented}" />
- <isfalse value="${build.is.instrumented}" />
- </and>
- </condition>
- <then>
- <echo>Switching from instrumented to non-instrumented build.</echo>
- <echo>Deleting previous compilation output:</echo>
- <delete dir="${out.classes.absolute.dir}" verbose="${verbose}" />
- </then>
- </if>
- <echo>Creating output directories if needed...</echo>
- <mkdir dir="${resource.absolute.dir}" />
- <mkdir dir="${jar.libs.absolute.dir}" />
- <mkdir dir="${out.absolute.dir}" />
- <mkdir dir="${out.res.absolute.dir}" />
- <do-only-if-manifest-hasCode>
- <mkdir dir="${gen.absolute.dir}" />
- <mkdir dir="${out.classes.absolute.dir}" />
- </do-only-if-manifest-hasCode>
- </target>
- <!-- empty default pre-build target. Create a similar target in
- your build.xml and it'll be called instead of this one. -->
- <target name="-pre-build" />
- <!-- Code Generation: compile resources (aapt -> R.java), aidl, renderscript
- 通过appt 生成R.jar文件
- -->
- <target name="-code-gen">
- <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping aidl/renderscript/R.java">
- <echo>----------</echo>
- <echo>Handling aidl files...</echo>
- <aidl executable="${aidl}" framework="${android.aidl}" genFolder="${gen.absolute.dir}">
- <source path="${source.absolute.dir}" />
- </aidl>
- <!-- renderscript generates resources so it must be called before aapt -->
- <echo>----------</echo>
- <echo>Handling RenderScript files...</echo>
- <renderscript executable="${renderscript}" framework="${android.rs}" genFolder="${gen.absolute.dir}" resFolder="${resource.absolute.dir}/raw" targetApi="${target.api}">
- <source path="${source.absolute.dir}" />
- </renderscript>
- <echo>----------</echo>
- <echo>Handling Resources...</echo>
- <aapt executable="${aapt}" command="package" verbose="${verbose}" manifest="AndroidManifest.xml" androidjar="${android.jar}" rfolder="${gen.absolute.dir}" nonConstantId="${android.library}" projectLibrariesResName="project.libraries.res" projectLibrariesPackageName="project.libraries.package">
- <res path="${resource.absolute.dir}" />
- </aapt>
- </do-only-if-manifest-hasCode>
- </target>
- <!-- empty default pre-compile target. Create a similar target in
- your build.xml and it'll be called instead of this one. -->
- <target name="-pre-compile" />
- <!-- Compiles this project's .java files into .class files.
- 编译
- -->
- <target name="-compile" depends="-build-setup, -pre-build, -code-gen, -pre-compile">
- <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
- <!-- If android rules are used for a test project, its classpath should include
- tested project's location
- 如果是测试工程,classpath应该包括test的位置
- -->
- <condition property="extensible.classpath" value="${tested.project.absolute.dir}/bin/classes" else=".">
- <isset property="tested.project.absolute.dir" />
- </condition>
- <condition property="extensible.libs.classpath" value="${tested.project.absolute.dir}/${jar.libs.dir}" else="${jar.libs.dir}">
- <isset property="tested.project.absolute.dir" />
- </condition>
- <javac encoding="${java.encoding}" source="${java.source}" target="${java.target}" debug="true" extdirs="" destdir="${out.classes.absolute.dir}" bootclasspathref="android.target.classpath" verbose="${verbose}" classpath="${extensible.classpath}" classpathref="jar.libs.ref">
- <src path="${source.absolute.dir}" />
- <src path="${gen.absolute.dir}" />
- <classpath>
- <fileset dir="${extensible.libs.classpath}" includes="*.jar" />
- </classpath>
- </javac>
- <!-- if the project is a library then we generate a jar file
- 如果工程是library工程,则生成jar文件
- -->
- <if condition="${project.is.library}">
- <then>
- <echo>Creating library output jar file...</echo>
- <property name="out.library.jar.file" location="${out.absolute.dir}/classes.jar" />
- <if>
- <condition>
- <length string="${android.package.excludes}" trim="true" when="greater" length="0" />
- </condition>
- <then>
- <echo>Custom jar packaging exclusion: ${android.package.excludes}