首先把android sdk下的tools目录加到系统path环境变量里, 要么就得直接指定android.bat的绝对路径
对于一个新项目, 可以用这个命令创建需要的ant编译环境(可以看到android项目默认的文件结构)
android create project -k com.foo -a Test1 -t android-8 -p d:\temp
如果是已经存在的项目, 对主项目和子项目都运行
项目目录> android update project -s -p . -t android-19
-s 是因为带子项目
-t 是指定目标版本, 版本不对会导致编译失败
其中
build.xml 是ant任务文件, 基本不用修改
custom_rules.xml 对于需要自行配置的编译任务, 写到这个文件里, 会被build.xml加载
ant.properties ant运行中涉及的变量写到这里
local.properties 里面设定了sdk.dir的路径, 不用修改
project.properties 设定了编译目标和项目类型, 如果有子项目的话, 还有子项目的路径, 不用修改
然后执行下面的命令就进行编译了
项目目录>D:\apache-ant-1.8.4\bin\ant.bat clean 项目目录>D:\apache-ant-1.8.4\bin\ant.bat release
根据中途报的错, 再做调整
如果子项目编译出错, 可以分别在子项目目录下运行ant clean 和 ant release, 直到排除错误
两个相似的custom_rules.xml 例子
<?xml version="1.0" encoding="UTF-8"?> <project name="custom_rules"><property name="generated.dir" value="gen" /><property name="generated.absolute.dir" location="${generated.dir}" /><property name="java.compilerargs" value="-s '${generated.absolute.dir}'" /> <target name="-pre-compile"><mkdir dir="${generated.absolute.dir}" /></target><target name="-compile" depends="-build-setup, -pre-build, -code-gen, -pre-compile"><do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..."><!-- merge the project's own classpath and the tested project's classpath --><path id="project.javac.classpath"><path refid="project.all.jars.path" /><path refid="tested.project.classpath" /><fileset dir="compile-libs" includes="*.jar"/></path><javac encoding="${java.encoding}"source="${java.source}" target="${java.target}"debug="true" extdirs="" includeantruntime="false"destdir="${out.classes.absolute.dir}"bootclasspathref="project.target.class.path"verbose="${verbose}"classpathref="project.javac.classpath"fork="${need.javac.fork}"><src path="${source.absolute.dir}" /><src path="${gen.absolute.dir}" /><compilerarg line="${java.compilerargs}" /></javac><!-- if the project is instrumented, intrument the classes --><if condition="${build.is.instrumented}"><then><echo level="info">Instrumenting classes from ${out.absolute.dir}/classes...</echo><!-- build the filter to remove R, Manifest, BuildConfig --><getemmafilterappPackage="${project.app.package}"libraryPackagesRefId="project.library.packages"filterOut="emma.default.filter"/><!-- define where the .em file is going. This may have beensetup already if this is a library --><property name="emma.coverage.absolute.file" location="${out.absolute.dir}/coverage.em" /><!-- 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"metadatafile="${emma.coverage.absolute.file}"><filter excludes="${emma.default.filter}" /><filter value="${emma.filter}" /></instr></emma></then></if><!-- if the project is a library then we generate a jar file --><if condition="${project.is.library}"><then><echo level="info">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 level="info">Custom jar packaging exclusion: ${android.package.excludes}</echo></then></if><propertybyreplace name="project.app.package.path" input="${project.app.package}" replace="." with="/" /><jar destfile="${out.library.jar.file}"><fileset dir="${out.classes.absolute.dir}"includes="**/*.class"excludes="${project.app.package.path}/R.class ${project.app.package.path}/R$*.class ${project.app.package.path}/BuildConfig.class"/><fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" /></jar></then></if></do-only-if-manifest-hasCode></target> </project>
另一个
<?xml version="1.0" encoding="UTF-8"?> <project name="app_project" default="help"><property name="generated.dir" value=".apt_generated" /><property name="generated.absolute.dir" location="${generated.dir}" /><property name="java.compilerargs" value="-s '${generated.absolute.dir}'" /><target name="-pre-compile"><mkdir dir="${generated.absolute.dir}" /></target><!-- Compiles this project's .java files into .class files. --><target name="-compile" depends="-pre-build, -build-setup, -code-gen, -pre-compile"><do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..."><!-- merge the project's own classpath and the tested project's classpath --><path id="project.javac.classpath"><path refid="project.all.jars.path" /><path refid="tested.project.classpath" /><path path="${java.compiler.classpath}" /><fileset dir="compile-libs" includes="*.jar" /></path><javac encoding="${java.encoding}"source="${java.source}" target="${java.target}"debug="true" extdirs="" includeantruntime="false"destdir="${out.classes.absolute.dir}"bootclasspathref="project.target.class.path"verbose="${verbose}"classpathref="project.javac.classpath"fork="${need.javac.fork}"><src path="${source.absolute.dir}" /><src path="${gen.absolute.dir}" /><compilerarg line="${java.compilerargs}" /></javac><!-- if the project is instrumented, intrument the classes --><if condition="${build.is.instrumented}"><then><echo level="info">Instrumenting classes from ${out.absolute.dir}/classes...</echo><!-- build the filter to remove R, Manifest, BuildConfig --><getemmafilterappPackage="${project.app.package}"libraryPackagesRefId="project.library.packages"filterOut="emma.default.filter"/><!-- define where the .em file is going. This may have been setup already if this is a library --><property name="emma.coverage.absolute.file" location="${out.absolute.dir}/coverage.em" /><!-- 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"metadatafile="${emma.coverage.absolute.file}"><filter excludes="${emma.default.filter}" /><filter value="${emma.filter}" /></instr></emma></then></if><!-- if the project is a library then we generate a jar file --><if condition="${project.is.library}"><then><echo level="info">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 level="info">Custom jar packaging exclusion: ${android.package.excludes}</echo></then></if><propertybyreplace name="project.app.package.path" input="${project.app.package}" replace="." with="/" /><jar destfile="${out.library.jar.file}"><fileset dir="${out.classes.absolute.dir}"includes="**/*.class"excludes="${project.app.package.path}/R.class ${project.app.package.path}/R$*.class ${project.app.package.path}/BuildConfig.class"/><fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" /></jar></then></if></do-only-if-manifest-hasCode></target> </project>
ant.properties的例子, 和上面的xml是对应的
key.store=D:/workAndroid/files/android_key.store key.alias=alia key.store.password=111111 key.alias.password=111111 java.encoding=UTF-8 java.target=7 java.source=7
在生成的apk中使用版本号文件名, 而不是用默认的 xxx-release.apk
http://jeffreysambells.com/2013/02/14/build-your-android-apk-with-the-manifest-version-number
<target name="-set-release-mode"depends="rename-release-with-version-number,android_rules.-set-release-mode"><echo message="target: ${build.target}"></echo></target><target name="rename-release-with-version-number"><xmlproperty file="AndroidManifest.xml" prefix="themanifest" collapseAttributes="true"/><!-- see ${sdk.dir}/tools/ant/build.xml -set-release-mode --><property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-${themanifest.manifest.android:versionName}-release-unsigned.apk" /><property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-${themanifest.manifest.android:versionName}-release.apk" /></target>
The -set-release-mode
target overrides the same target in ${sdk.dir}/tools/ant/build.xml
where the out.final.file
file name is originally defined. To add the version number, I override -set-release-mode
by calling my rename-release-with-version-number
target in the dependencies and then calling the original android_rules.-set-release-mode
to finish any other setup there.
The rename-release-with-version-number
target simply reads in the manifest and adds the version number to both out.final.file
and out.packaged.file
.
Now the build APK is ProjectName-version-release.apk
and it’s automatically used by the rest of the ant build process without clumsy file renaming.