(转)通过ant脚本,编译打包android工程
通过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签名。
通过命令打包的脚本:见附件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多行,我加了中文注释,希望能看懂。
- <?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>