使用Ant打包Apk

时间:2022-01-21 18:39:16

  文章 Android 使用Ant打渠道包讲解了如何使用Ant打渠道包,没有涉及具体的编译过程,例如使用Ant如何生成R文件等。那么今天,使用Ant来打一个Apk包!

  一、不管使用什么ide来打Apk包,一般会经过以下几个步骤:
1.生成R.java类文件
  使用Android SDK提供用aapt.exe生成R.Java文件。
2.将.aidl文件生成.java类文件
  使用Android SDK提供的aidl.exe生成相应Jva文件。
3.编译.java类文件生成class文件
  使用Jdk的javac命令编译Java源文件生成class文件。
4.将class文件打包生成classes.dex文件
  使用Android SDK提供的dx.bat将class文件转换成classes.dex文件。
5.打包资源文件(包括res、assets、androidmanifest.xml等)
  使用Android SDK提供的aapt.exe生成资源包文件resources.ap_。
6.生成未签名的apk安装文件
  使用Android SDK提供apkbuilder.bat打包资源和classes.dex文件,生成unsigned.apk。
7.对未签名的apk进行签名生成签名后的android文件
  用jarsinger命令对apk认证,生成signed.apk。

或者如下描述,

1.根据资源文件和AndroidManifest.xml生成R.java文件 
2.处理aidl,生成对应的java文件,如果没有aidl,则跳过 
3.编译工程源码(主项目,库)src目录下所有的源码,同时上边生成的R.java和aidl生成的java文件也会被编译生成相应的class文件 
4.将第3步生成的class文件打包生成.dex文件 
5.将资源文件打包,生成初始的apk 
6.将第4步生成的.dex文件加入到apk中生成未签名的包 
7.apk签名 

二、具体操作。

1.新建Android工程。

2.使用Android SDK命令创建Ant的build.xml。命令‘android update project –path .’ 。

3. 在IDE上刷新工程,可以看到项目根目录下多了build.xml以及local.properties两个文件。

这几步就不多说了,详情请参考这篇文章 Android 使用Ant打渠道包。主要还是看看custom_rules.xml这个文件,(custom_rules.xml这个文件需要手动创建),具体代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" >

<!-- 定义一个时间变量,打完包后跟渠道号一起命名apk -->
<tstamp>
<format property="pktime" pattern="yyyyMMddHHmm" locale="hour"/>
</tstamp>

<!-- 定义一个版本号变量,打完包后一起命名apk -->
<property name="version" value="${test.server.url}" />

<property name="basedir" value=" " />
<property name="library-dir" value="${basedir}">
</property>
<!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->
<property name="sdk-folder" value="${sdk.dir}" />
<!-- SDK指定平台目录 -->
<property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-19" />
<!-- SDK中tools目录 -->
<property name="sdk-tools" value="${sdk-folder}/tools" />
<!-- SDK指定平台中tools目录 -->
<property name="sdk-platform-tools" value="${sdk-folder}/build-tools/23.0.1" />

<!-- 使用到的命令(当前系统为windows,如果系统为linux,可将.bat文件替换成相对应的命令) -->
<property name="aapt" value="${sdk-platform-tools}/aapt.exe" />
<property name="aidl" value="${sdk-platform-tools}/aidl.exe" />
<property name="dx" value="${sdk-platform-tools}/dx.bat" />
<property name="apkbuilder" value="${sdk-tools}/apkbuilder.bat" />
<property name="jarsigner" value="${env.JAVA_HOME}/bin/jarsigner" />

<!-- 编译需要的jar; 如果项目使用到地图服务则需要maps.jar -->
<property name="android-jar" value="${sdk-platform-folder}/android.jar" />

<!-- 编译aidl文件所需的预处理框架文件framework.aidl -->
<property name="framework-aidl" value="${sdk-platform-folder}/framework.aidl" />

<!-- 生成R文件的相对目录 -->
<property name="outdir-gen" value="gen" />
<!-- 编译后的文件放置目录 -->
<property name="outdir-bin" value="out" />

<!-- 清单文件 -->
<property name="manifest-xml" value="AndroidManifest.xml" />
<!-- 源文件目录 -->
<property name="resource-dir" value="res" />
<property name="asset-dir" value="assets" />
<!-- java源文件目录 -->
<property name="srcdir" value="src" />
<property name="srcdir-ospath" value="${basedir}/${srcdir}" />
<!-- 外部类库所在目录 -->
<property name="external-lib" value="libs" />
<property name="external-lib-ospath" value="${basedir}/${external-lib}" />

<!-- 生成class目录 -->
<property name="outdir-classes" value="${outdir-bin}" />
<property name="outdir-classes-ospath" value="${basedir}/${outdir-classes}" />

<!-- classes.dex相关变量 -->
<property name="dex-file" value="classes.dex" />
<property name="dex-path" value="${outdir-bin}/${dex-file}" />
<property name="dex-ospath" value="${basedir}/${dex-path}" />

<!-- 经过aapt生成的资源包文件 -->
<property name="resources-package" value="${outdir-bin}/resources.ap_" />
<property name="resources-package-ospath" value="${basedir}/${resources-package}" />

<!-- 未认证apk包 -->
<property name="out-unsigned-package" value="${outdir-bin}/${app.name}-unsigned.apk" />
<property name="out-unsigned-package-ospath" value="${basedir}/${out-unsigned-package}" />

<!-- 证书文件 -->
<property name="keystore-file" value="${key.store}" />

<!-- 已认证apk包 -->
<property name="out-signed-package" value="${outdir-bin}/${app.name}_${pktime}${version}.apk" />
<property name="out-signed-package-ospath" value="${basedir}/${out-signed-package}" />

<target name="buildAll" >
<antcall target="clean" />
<antcall target="init" />
<antcall target="gen-R" />
<antcall target="aidl" />
<antcall target="compile" />
<antcall target="dex" />
<antcall target="package-res-and-assets" />
<antcall target="package" />
<antcall target="jarsigner" />
<antcall target="release" />
</target>

<!-- 初始化工作 -->
<target name="init">
<echo>Initializing all output directories...</echo>
<delete dir="${outdir-bin}" />
<delete dir="${outdir-gen}" />
<mkdir dir="${outdir-bin}" />
<mkdir dir="${outdir-gen}" />
<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">
<!-- package表示打包-->
<arg value="package" />
<!--m,J,gen表示创建包名的目录和R.java到gen目录下 -->
<arg value="-m" />
<arg value="--auto-add-overlay" />
<arg value="-J" />
<arg value="${outdir-gen}" />
<!-- M指定AndroidManifest.xml文件-->
<arg value="-M" />
<arg value="${manifest-xml}" />
<!-- S指定res目录,生成对应的ID,可多个-->
<arg value="-S" />
<!-- 注意点:同时需要调用Library的res-->
<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}" />
<!-- I指定android包的位置-->
<arg value="-I" />
<arg value="${android-jar}" />
<arg value="--auto-add-overlay" /> <!-- 这个重要,覆盖资源,不然报错-->
</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目录-->
<src path="gen" /> <!-- 工程gen目录 -->
<classpath>
<fileset dir="${external-lib-ospath}" includes="*.jar" />
</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}" /> <!-- classes文件位置 -->
<arg value="${external-lib-ospath}" /> <!-- 把libs下所有jar打包 -->
</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" /> <!-- asset目录也打包 -->
<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" /> <!-- u指创建未签名的包-->
<arg value="-z" /> <!-- 资源压缩包 -->
<arg value="${resources-package-ospath}" />
<arg value="-f" /> <!-- dex文件 -->
<arg value="${dex-ospath}" />
<arg value="-rf" />
<arg value="${srcdir-ospath}" />
<arg value="-nf"/> <!-- 把libs下的so库打包 -->
<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="${key.store.password}" />
<arg value="-keypass" />
<arg value="${key.alias.password}" />
<arg value="-signedjar" />
<arg value="${out-signed-package-ospath}" />
<arg value="${out-unsigned-package-ospath}" />
<!-- 不要忘了证书的别名 -->
<arg value="${key.alias}" />
</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>
代码都有注释,如有不清楚的标签,请查Ant看官网文档。

下面再看看ant.properties文件,具体如下,

#keystore
key.store=E:\\me.keystore
#keystore
key.store.password=111111
#alias
key.alias=xinxing
#alias
key.alias.password=111111
apk.dir=./apk
app.name=ant_app
#
version=(1.2.1)
keystore密码,apk名称,版本号等。

三、打包。

1.首先在命令行下,定位到项目所在的目录,

使用Ant打包Apk

2. 在命令行中,输入打包命令,稍等片刻,如出现下面截图,则打包成功,

使用Ant打包Apk

2. 在项目的根目录下,有一个‘out’文件夹,

使用Ant打包Apk 使用Ant打包Apk

         打包前项目截图                                                                                            打包后截图

至此,使用Ant打包就完成了!

四、小结。

  使用Ant打包Apk的步骤就是上面说的7步,每一步都是生成不同的文件或者文件夹。相信,只要你多加练习,也会掌握的!

PS : Demo工程下载链接