通过ant脚本,编译打包android工程

时间:2021-08-03 14:52:45

通过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工程

通过命令打包的脚本:见附件bulid0.xml,这个ant脚本只能编译打包一个单独的android工程或依赖一个library 的android工程


<?xml version="1.0" encoding="UTF-8"?>
<project name="ant" default="release">
<!-- ANT环境变量 -->
<property environment="env" />
<!-- 应用名称 -->

<property name="appName" value="TestPack" />
<property name="basedir" value="" />
<property name="library-dir" value="">
</property>
<!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->
<!-- <property name="sdk-folder" value="${env.ANDROID_SDK_HOME}" /> -->
<property name="sdk-folder" value="" />
<!-- SDK指定平台目录 -->
<property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-4" />
<!-- 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="lib" />
<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}/release.keystore" />

<!-- 已认证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="" />
<arg value="-keypass" />
<arg value="" />
<arg value="-signedjar" />
<arg value="${out-signed-package-ospath}" />
<arg value="${out-unsigned-package-ospath}" />
<!-- 不要忘了证书的别名 -->
<arg value="" />
</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>


Android官方提供的打包脚本: 1400多行,我加了中文注释,希望能看懂。

详见build.xml

<?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}</echo>
</then>
</if>
<jar destfile="${out.library.jar.file}">
<fileset dir="${out.classes.absolute.dir}" excludes="**/R.class **/R$*.class" />
<fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" />
</jar>
</then>
</if>

<!-- if the project is instrumented, intrument the classes
如果工程被打断,插入相关的class
-->
<if condition="${build.is.instrumented}">
<then>
<echo>Instrumenting classes from ${out.absolute.dir}/classes...</echo>
<!-- It only instruments class files, not any external libs -->
<emma enabled="true">
<instr verbosity="${verbosity}" mode="overwrite" instrpath="${out.absolute.dir}/classes" outdir="${out.absolute.dir}/classes">
</instr>
<!-- TODO: exclusion filters on R*.class and allowing custom exclusion from
user defined file -->
</emma>
</then>
</if>
</do-only-if-manifest-hasCode>
</target>

<!-- empty default post-compile target. Create a similar target in
your build.xml and it'll be called instead of this one. -->
<target name="-post-compile" />

<!-- Obfuscate target
This is only active in release builds when proguard.config is defined
in default.properties.

To replace Proguard with a different obfuscation engine:
Override the following targets in your build.xml, before the call to <setup>
-release-obfuscation-check
Check whether obfuscation should happen, and put the result in a property.
-debug-obfuscation-check
Obfuscation should not happen. Set the same property to false.
-obfuscate
check if the property set in -debug/release-obfuscation-check is set to true.
If true:
Perform obfuscation
Set property out.dex.input.absolute.dir to be the output of the obfuscation
混淆代码
-->
<target name="-obfuscate">
<if condition="${proguard.enabled}">
<then>
<property name="obfuscate.absolute.dir" location="${out.absolute.dir}/proguard" />
<property name="preobfuscate.jar.file" value="${obfuscate.absolute.dir}/original.jar" />
<property name="obfuscated.jar.file" value="${obfuscate.absolute.dir}/obfuscated.jar" />
<!-- input for dex will be proguard's output -->
<property name="out.dex.input.absolute.dir" value="${obfuscated.jar.file}" />

<!-- Add Proguard Tasks -->
<property name="proguard.jar" location="${android.tools.dir}/proguard/lib/proguard.jar" />
<taskdef name="proguard" classname="proguard.ant.ProGuardTask" classpath="${proguard.jar}" />

<!-- Set the android classpath Path object into a single property. It'll be
all the jar files separated by a platform path-separator.
Each path must be quoted if it contains spaces.
-->
<pathconvert property="android.libraryjars" refid="android.target.classpath">
<firstmatchmapper>
<regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"' />
<identitymapper />
</firstmatchmapper>
</pathconvert>

<!-- Build a path object with all the jar files that must be obfuscated.
This include the project compiled source code and any 3rd party jar
files. -->
<path id="project.jars.ref">
<pathelement location="${preobfuscate.jar.file}" />
<path refid="jar.libs.ref" />
</path>
<!-- Set the project jar files Path object into a single property. It'll be
all the jar files separated by a platform path-separator.
Each path must be quoted if it contains spaces.
-->
<pathconvert property="project.jars" refid="project.jars.ref">
<firstmatchmapper>
<regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"' />
<identitymapper />
</firstmatchmapper>
</pathconvert>

<mkdir dir="${obfuscate.absolute.dir}" />
<delete file="${preobfuscate.jar.file}" />
<delete file="${obfuscated.jar.file}" />
<jar basedir="${out.classes.absolute.dir}" destfile="${preobfuscate.jar.file}" />
<proguard>
@${proguard.config}
-injars ${project.jars}
-outjars "${obfuscated.jar.file}"
-libraryjars ${android.libraryjars}
-dump "${obfuscate.absolute.dir}/dump.txt"
-printseeds "${obfuscate.absolute.dir}/seeds.txt"
-printusage "${obfuscate.absolute.dir}/usage.txt"
-printmapping "${obfuscate.absolute.dir}/mapping.txt"
</proguard>
</then>
</if>
</target>

<!-- Converts this project's .class files into .dex files
将.class 打包成.dex文件
-->
<target name="-dex" depends="-compile, -post-compile, -obfuscate">
<do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
<!-- only convert to dalvik bytecode is *not* a library -->
<do-only-if-not-library elseText="Library project: do not convert bytecode...">
<!-- special case for instrumented builds: need to use no-locals and need
to pass in the emma jar.
特殊情况下,检测build,需要通过emma
-->
<if condition="${build.is.instrumented}">
<then>
<dex-helper nolocals="true">
<external-libs>
<fileset file="${emma.dir}/emma_device.jar" />
</external-libs>
</dex-helper>
</then>
<else>
<dex-helper />
</else>
</if>
</do-only-if-not-library>
</do-only-if-manifest-hasCode>
</target>

<!-- Updates the pre-processed PNG cache 处理png 图片-->
<target name="-crunch">
<exec executable="${aapt}" taskName="crunch">
<arg value="crunch" />
<arg value="-v" />
<arg value="-S" />
<arg path="${resource.absolute.dir}" />
<arg value="-C" />
<arg path="${out.res.absolute.dir}" />
</exec>
</target>

<!-- Puts the project's resources into the output package file
This actually can create multiple resource package in case
Some custom apk with specific configuration have been
declared in default.properties.
打包资源文件
-->
<target name="-package-resources" depends="-crunch">
<!-- only package resources if *not* a library project -->
<do-only-if-not-library elseText="Library project: do not package resources...">
<aapt executable="${aapt}" command="package" versioncode="${version.code}" versionname="${version.name}" debug="${build.is.packaging.debug}" manifest="AndroidManifest.xml" assets="${asset.absolute.dir}" androidjar="${android.jar}" apkfolder="${out.absolute.dir}" nocrunch="${build.packaging.nocrunch}" resourcefilename="${resource.package.file.name}" resourcefilter="${aapt.resource.filter}" projectLibrariesResName="project.libraries.res" projectLibrariesPackageName="project.libraries.package" previousBuildType="${build.last.target}" buildType="${build.target}">
<res path="${out.res.absolute.dir}" />
<res path="${resource.absolute.dir}" />
<!-- <nocompress /> forces no compression on any files in assets or res/raw -->
<!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
</aapt>
</do-only-if-not-library>
</target>

<!-- Packages the application. 打包-->
<target name="-package" depends="-dex, -package-resources">
<!-- only package apk if *not* a library project -->
<do-only-if-not-library elseText="Library project: do not package apk...">
<if condition="${build.is.instrumented}">
<then>
<package-helper>
<extra-jars>
<!-- Injected from external file -->
<jarfile path="${emma.dir}/emma_device.jar" />
</extra-jars>
</package-helper>
</then>
<else>
<package-helper />
</else>
</if>
</do-only-if-not-library>
</target>

<target name="-set-mode-check">
<fail if="out.final.file" message="Cannot run two different modes at the same time. If you are running more than one debug/release/instrument type targets, call them from different Ant calls." />
</target>

<!-- ********** Debug specific targets ********** -->

<!-- 设置debug-->

<target name="-set-debug-files" depends="-set-mode-check">

<property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-debug-unaligned.apk" />
<property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-debug.apk" />
</target>

<target name="-set-debug-mode">
<!-- record the current build target -->
<property name="build.target" value="debug" />

<property name="build.is.instrumented" value="false" />

<!-- whether the build is a debug build. always set. -->
<property name="build.is.packaging.debug" value="true" />

<!-- signing mode: debug -->
<property name="build.is.signing.debug" value="true" />

</target>

<!--debug 模式下,不使用混淆-->
<target name="-debug-obfuscation-check">
<!-- proguard is never enabled in debug mode -->
<property name="proguard.enabled" value="false" />
</target>

<!-- Builds debug output package -->
<target name="-do-debug" depends="-set-debug-mode, -debug-obfuscation-check, -package">
<!-- only create apk if *not* a library project -->
<do-only-if-not-library elseText="Library project: do not create apk...">
<sequential>
<zipalign-helper in.package="${out.packaged.file}" out.package="${out.final.file}" />
<echo>Debug Package: ${out.final.file}</echo>
</sequential>
</do-only-if-not-library>
</target>

<!-- Builds debug output package -->
<target name="debug" depends="-set-debug-files, -do-debug" description="Builds the application and signs it with a debug key.">
<record-build-info />
</target>


<!-- ********** Release specific targets ********** -->
<!-- 发布的targets -->

<!-- called through target 'release'. Only executed if the keystore and
key alias are known but not their password.
需要输入key.alias.password,key.store.password
-->
<target name="-release-prompt-for-password" if="has.keystore" unless="has.password">
<!-- Gets passwords -->
<input message="Please enter keystore password (store:${key.store}):" addproperty="key.store.password" />
<input message="Please enter password for alias '${key.alias}':" addproperty="key.alias.password" />
</target>

<!-- called through target 'release'. Only executed if there's no
keystore/key alias set -->
<target name="-release-nosign" unless="has.keystore">
<!-- no release builds for library project -->
<do-only-if-not-library elseText="">
<sequential>
<echo>No key.store and key.alias properties found in build.properties.</echo>
<echo>Please sign ${out.packaged.file} manually</echo>
<echo>and run zipalign from the Android SDK tools.</echo>
</sequential>
</do-only-if-not-library>
<record-build-info />
</target>


<!-- 检查是否混淆代码 -->
<target name="-release-obfuscation-check">
<condition property="proguard.enabled" value="true" else="false">
<and>
<isset property="build.is.mode.release" />
<isset property="proguard.config" />
</and>
</condition>
<if condition="${proguard.enabled}">
<then>
<!-- Secondary dx input (jar files) is empty since all the
jar files will be in the obfuscated jar -->
<path id="out.dex.jar.input.ref" />
</then>
</if>
</target>

<target name="-set-release-mode" depends="-set-mode-check">
<property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-release-unsigned.apk" />
<property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-release.apk" />

<!-- record the current build target -->
<property name="build.target" value="release" />

<property name="build.is.instrumented" value="false" />

<!-- release mode is only valid if the manifest does not explicitly
set debuggable to true. default is false. -->
<xpath input="AndroidManifest.xml" expression="/manifest/application/@android:debuggable" output="build.is.packaging.debug" default="false" />

<!-- signing mode: release -->
<property name="build.is.signing.debug" value="false" />

<if condition="${build.is.packaging.debug}">
<then>
<echo>*************************************************</echo>
<echo>**** Android Manifest has debuggable=true ****</echo>
<echo>**** Doing DEBUG packaging with RELEASE keys ****</echo>
<echo>*************************************************</echo>
</then>
<else>
<!-- property only set in release mode.
Useful for if/unless attributes in target node
when using Ant before 1.8 -->
<property name="build.is.mode.release" value="true" />
</else>
</if>
</target>

<!-- This runs -package-release and -release-nosign first and then runs
only if release-sign is true (set in -release-check,
called by -release-no-sign)-->
<target name="release" depends="-set-release-mode, -release-obfuscation-check, -package, -release-prompt-for-password, -release-nosign" if="has.keystore" description="Builds the application. The generated apk file must be signed before
it is published.">

<!-- only create apk if *not* a library project -->
<do-only-if-not-library elseText="Library project: do not create apk...">
<sequential>
<property name="out.unaligned.file" location="${out.absolute.dir}/${ant.project.name}-release-unaligned.apk" />

<!-- Signs the APK -->
<echo>Signing final apk...</echo>
<signjar jar="${out.packaged.file}" signedjar="${out.unaligned.file}" keystore="${key.store}" storepass="${key.store.password}" alias="${key.alias}" keypass="${key.alias.password}" verbose="${verbose}" />

<!-- Zip aligns the APK -->
<zipalign-helper in.package="${out.unaligned.file}" out.package="${out.final.file}" />
<echo>Release Package: ${out.final.file}</echo>
</sequential>
</do-only-if-not-library>
<record-build-info />
</target>

<!-- ********** Instrumented specific targets ********** -->
<!--需要插入的特殊 targets-->

<!-- These targets are specific for the project under test when it
gets compiled by the test projects in a way that will make it
support emma code coverage -->

<target name="-set-instrumented-mode" depends="-set-mode-check">
<property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-instrumented-unaligned.apk" />
<property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-instrumented.apk" />

<!-- whether the build is an instrumented build. -->
<property name="build.is.instrumented" value="true" />
</target>

<!-- Builds instrumented output package -->
<target name="instrument" depends="-set-instrumented-mode, -do-debug" description="Builds an instrumented packaged.">
<!-- only create apk if *not* a library project -->
<do-only-if-not-library elseText="Library project: do not create apk...">
<sequential>
<zipalign-helper in.package="${out.packaged.file}" out.package="${out.final.file}" />
<echo>Instrumented Package: ${out.final.file}</echo>
</sequential>
</do-only-if-not-library>
<record-build-info />
</target>

<!-- ********** Test project specific targets ********** -->
<!-- 测试工程特殊的targets -->

<!-- enable code coverage -->
<target name="emma">
<property name="emma.enabled" value="true" />
</target>

<!-- fails if the project is not a test project -->
<target name="-test-project-check">
<!-- can't use project.is.test since the setup target is not run -->
<if>
<condition>
<isset property="tested.project.dir" />
</condition>
<else>
<fail message="Project is not a test project." />
</else>
</if>
</target>

<target name="test" depends="-test-project-check" description="Runs tests from the package defined in test.package property">

<property name="tested.project.absolute.dir" location="${tested.project.dir}" />

<property name="test.runner" value="android.test.InstrumentationTestRunner" />

<!-- Application package of the tested project extracted from its manifest file -->
<xpath input="${tested.project.absolute.dir}/AndroidManifest.xml" expression="/manifest/@package" output="tested.manifest.package" />
<xpath input="AndroidManifest.xml" expression="/manifest/@package" output="manifest.package" />

<property name="emma.dump.file" value="/data/data/${tested.manifest.package}/coverage.ec" />

<if condition="${emma.enabled}">
<then>
<echo>WARNING: Code Coverage is currently only supported on the emulator and rooted devices.</echo>
<run-tests-helper emma.enabled="true">
<extra-instrument-args>
<arg value="-e" />
<arg value="coverageFile" />
<arg value="${emma.dump.file}" />
</extra-instrument-args>
</run-tests-helper>
<echo>Downloading coverage file into project directory...</echo>
<exec executable="${adb}" failonerror="true">
<arg line="${adb.device.arg}" />
<arg value="pull" />
<arg value="${emma.dump.file}" />
<arg value="coverage.ec" />
</exec>
<echo>Extracting coverage report...</echo>
<emma>
<report sourcepath="${tested.project.absolute.dir}/${source.dir}" verbosity="${verbosity}">
<!-- TODO: report.dir or something like should be introduced if necessary -->
<infileset dir=".">
<include name="coverage.ec" />
<include name="coverage.em" />
</infileset>
<!-- TODO: reports in other, indicated by user formats -->
<html outfile="coverage.html" />
</report>
</emma>
<echo>Cleaning up temporary files...</echo>
<delete file="coverage.ec" />
<delete file="coverage.em" />
<echo>Saving the report file in ${basedir}/coverage/coverage.html</echo>
</then>
<else>
<run-tests-helper />
</else>
</if>
</target>


<!-- ********** Install/uninstall specific targets ********** -->
<!-- 安装和卸载 -->

<target name="install" description="Installs the newly build package. Must be used in conjunction with a build target
(debug/release/instrument). If the application was previously installed, the application
is reinstalled if the signature matches.">
<!-- only do install if *not* a library project -->
<do-only-if-not-library elseText="Library project: nothing to install!">
<if>
<condition>
<isset property="out.final.file" />
</condition>
<then>
<if>
<condition>
<resourceexists>
<file file="${out.final.file}" />
</resourceexists>
</condition>
<then>
<echo>Installing ${out.final.file} onto default emulator or device...</echo>
<exec executable="${adb}" failonerror="true">
<arg line="${adb.device.arg}" />
<arg value="install" />
<arg value="-r" />
<arg path="${out.final.file}" />
</exec>

<!-- now install the tested project if applicable -->
<!-- can't use project.is.test since the setup target might not have run -->
<if>
<condition>
<isset property="tested.project.dir" />
</condition>
<then>
<property name="tested.project.absolute.dir" location="${tested.project.dir}" />

<!-- figure out which tested package to install based on emma.enabled -->
<condition property="tested.project.install.target" value="installi" else="installd">
<isset property="emma.enabled" />
</condition>
<subant target="${tested.project.install.target}" failonerror="true">
<fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
</subant>
</then>
</if>
</then>
<else>
<fail message="File ${out.final.file} does not exist." />
</else>
</if>
</then>
<else>
<echo>Install file not specified.</echo>
<echo>
</echo>
<echo>'ant install' now requires the build target to be specified as well.</echo>
<echo>
</echo>
<echo>
</echo>
<echo> ant debug install</echo>
<echo> ant release install</echo>
<echo> ant instrument install</echo>
<echo>This will build the given package and install it.</echo>
<echo>
</echo>
<echo>Alternatively, you can use</echo>
<echo> ant installd</echo>
<echo> ant installr</echo>
<echo> ant installi</echo>
<echo> ant installt</echo>
<echo>to only install an existing package (this will not rebuild the package.)</echo>
<fail />
</else>
</if>
</do-only-if-not-library>
</target>

<target name="installd" depends="-set-debug-files, install" description="Installs (only) the debug package." />
<target name="installr" depends="-set-release-mode, install" description="Installs (only) the release package." />
<target name="installi" depends="-set-instrumented-mode, install" description="Installs (only) the instrumented package." />
<target name="installt" depends="-test-project-check, installd" description="Installs (only) the test and tested packages." />


<!-- Uninstalls the package from the default emulator/device -->
<target name="uninstall" description="Uninstalls the application from a running emulator or device.">
<!-- Name of the application package extracted from manifest file -->
<xpath input="AndroidManifest.xml" expression="/manifest/@package" output="manifest.package" />

<if>
<condition>
<isset property="manifest.package" />
</condition>
<then>
<uninstall-helper app.package="${manifest.package}" />
</then>
<else>
<echo>Could not find application package in manifest. Cannot run 'adb uninstall'.</echo>
</else>
</if>

<!-- Now uninstall the tested project, if applicable -->
<!-- can't use project.is.test since the setup target might not have run -->
<if>
<condition>
<isset property="tested.project.dir" />
</condition>
<then>
<property name="tested.project.absolute.dir" location="${tested.project.dir}" />

<!-- Application package of the tested project extracted from its manifest file -->
<xpath input="${tested.project.absolute.dir}/AndroidManifest.xml" expression="/manifest/@package" output="tested.manifest.package" />
<if>
<condition>
<isset property="tested.manifest.package" />
</condition>
<then>
<uninstall-helper app.package="${tested.manifest.package}" />
</then>
<else>
<echo>Could not find tested application package in manifest. Cannot run 'adb uninstall'.</echo>
</else>
</if>
</then>
</if>

</target>


<target name="help">
<!-- displays starts at col 13
|13 80| -->
<echo>Android Ant Build. Available targets:</echo>
<echo> help: Displays this help.</echo>
<echo> clean: Removes output files created by other targets.</echo>
<echo> The 'all' target can be used to clean dependencies</echo>
<echo> (tested projects and libraries)at the same time</echo>
<echo> using: 'ant all clean'</echo>
<echo> debug: Builds the application and signs it with a debug key.</echo>
<echo> release: Builds the application. The generated apk file must be</echo>
<echo> signed before it is published.</echo>
<echo> instrument:Builds an instrumented package and signs it with a</echo>
<echo> debug key.</echo>
<echo> test: Runs the tests. Project must be a test project and</echo>
<echo> must have been built. Typical usage would be:</echo>
<echo> ant [emma] debug installt test</echo>
<echo> emma: Transiently enables code coverage for subsequent</echo>
<echo> targets.</echo>
<echo> install: Installs the newly build package. Must either be used</echo>
<echo> in conjunction with a build target (debug/release/</echo>
<echo> instrument) or with the proper suffix indicating</echo>
<echo> which package to install (see below).</echo>
<echo> If the application was previously installed, the</echo>
<echo> application is reinstalled if the signature matches.</echo>
<echo> installd: Installs (only) the debug package.</echo>
<echo> installr: Installs (only) the release package.</echo>
<echo> installi: Installs (only) the instrumented package.</echo>
<echo> installt: Installs (only) the test and tested packages.</echo>
<echo> uninstall: Uninstalls the application from a running emulator or</echo>
<echo> device.</echo>
</target>
</project>