标签: androidAndroidantlibrary脚本
2012-11-16 18:21
17206人阅读
收藏
举报
通过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工程
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" />
-
- <property file="project.properties" />
-
- <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
- -->
-
-
-
-
- <!-- You can override these values in your build.xml or build.properties.
- Overriding any other properties may result in broken 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. -->
-
-
-
- <property name="version.code" value="11" />
- <property name="version.name" value="111" />
- <property name="aapt.resource.filter" value="" />
-
-
- <property name="java.encoding" value="UTF-8" />
- <property name="java.target" value="1.6" />
- <property name="java.source" value="1.6" />
-
-
- <property name="verbose" value="false" />
-
-
-
-
-
- <path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
- </path>
-
-
- <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" />
-
-
-
-
- <!-- 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" />
-
-
- <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 -->
-
-
- <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_" />
-
-
- <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>
-
-
-
- <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>
-
-
- <property name="build.packaging.nocrunch" value="true" />
-
-
-
-
- <!-- macro to do a task on if project.is.library is false.
- elseText attribute is displayed otherwise -->
-
- <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>
-
-
-
- <!-- 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" />
-
-
- <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>
-
- <subant buildpathref="project.libraries" antfile="build.xml" failonerror="true">
- <target name="all" />
- <target name="clean" />
- </subant>
- </then>
- </if>
- </target>
-
-
- <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 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">
-
-
- <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}" />
-
- <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>
-
-
- <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>
-
-
- <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=