在拥有ide工具后打包变得简单化,特别是在拥有android studio之后,通过对gradle的配置更是进一步简化打包的流程,可能很多人对原始的打包流程已经比较陌生,今天就来介绍一下通过原生的ant配置,编写ant文件来自动打包。
一、打包原理
先上图,图是网上拷过来的,比较清楚,有部分有问题,在生成未签名的apk时,现在已经不用apkbuilder,因为在更新sdk3.0后,已将此移除,所以图片仅供参考,下面具体我将做说明。
我们重点关心的是(1)这个过程的输入是什么?(2)这个过程的输出是什么?(3)这个过程使用了什么工具?
步骤中提到的工具如下表:
名称 | 功能介绍 | 在操作系统中的路径 |
aapt | Android资源打包工具 | ${ANDROID_SDK_HOME}/platform-tools/appt |
aidl | Android接口描述语言转化为.java文件的工具 | ${ANDROID_SDK_HOME}/platform-tools/aidl |
javac | Java Compiler | ${JDK_HOME}/javac或/usr/bin/javac |
dex | 转化.class文件为Davik VM能识别的.dex文件 | ${ANDROID_SDK_HOME}/platform-tools/dx |
apkbuilder | 生成apk包 | ${ANDROID_SDK_HOME}/tools/opkbuilder |
jarsigner | .jar文件的签名工具 | ${JDK_HOME}/jarsigner或/usr/bin/jarsigner |
zipalign | 字节码对齐工具 | ${ANDROID_SDK_HOME}/tools/zipalign |
二、打包具体实现
配置环境windows7(其他没试过),ant1.9.7,jdk1.7(千万不要用1.8,重要再讲三遍),配置项目为eclipse项目(4.1),studio项目配置我在下一篇再说
1.doc命令行
aapt package -f -m -J ./gen -S res -M AndroidManifest.xml -I E:\newsdk\newsdk\platforms\android-20\android.jar
转成ant文件
<exec executable="aapt">
<arg value="package"/>
<arg value="-m"/>
<arg value="-J"/>
<arg value="${project-dir}\gen"/>
<arg value="-S"/>
<arg value="${project-dir}\res"/>
<arg value="-M"/>
<arg value="${project-dir}\AndroidManifest.xml"/>
<arg value="-I"/>
<arg value="${android-jar}"/>
<arg value="--auto-add-overlay"/> <!-- 覆盖资源 -->
</exec>
-f 如果编译生成的文件已经存在,强制覆盖。
-m 使生成的包的目录存放在-J参数指定的目录
-J 指定生成的R.java 的输出目录路径
-S 指定res文件夹的路径
-I 指定某个版本平台的android.jar文件的路径
-A 指定assert文件夹的路径
这里要注意,可能会报缺失资源的错误,这里需要确保的是,建立项目是最低版本不能低于4.0,否则就会缺失资源
2.doc命令行
javac -bootclasspath E:\newsdk\newsdk\platforms\android-20\android.jar -d bin src\com\example\apktest\*.java gen\com\example\apktest\R.java
转成ant文件
<javac bootclasspath="${android-jar}" destdir="${project-dir}\bin/classes" encoding="utf-8" target="1.7">
<src path="${project-dir}\src"/>
<src path="${project-dir}\gen"/>
<classpath>
<fileset dir="${project-dir}\libs" includes="*.jar"/>
</classpath>
</javac>
-target <版本> 生成特定 VM 版本的类文件
-bootclasspath <路径> 覆盖引导类文件的位置
-d <目录> 指定存放生成的类文件的位置
-sourcepath <路径> 指定查找输入源文件的位置
3.doc命令行
dx --dex --output=F:\workspace\apktest\bin\classes.dex F:\workspace\apktest\bin\classes
转成ant文件
<exec executable="dx.bat" failοnerrοr="true">
<arg value="--dex"/>
<arg value="--output=${project-dir}\bin\classes.dex"/>
<arg path="${project-dir}\bin\classes"/>
</exec>
--output=<要生成的classes.dex路径> <要处理的class文件的路径>
4.doc命令行
aapt package -f -M AndroidManifest.xml -S res -I E:\newsdk\newsdk\platforms\android-20\android.jar -F bin\resources
转成ant文件
<exec executable="aapt">
<arg value="package"/>
<arg value="-f"/>
<arg value="-M"/>
<arg value="${project-dir}\AndroidManifest.xml"/>
<arg value="-S"/>
<arg value="${project-dir}\res"/>
<arg value="-A"/>
<arg value="${project-dir}\assets"/>
<arg value="-I"/>
<arg value="${android-jar}"/>
<arg value="-F"/>
<arg value="${project-dir}\bin\resources.ap_"/>
<arg value="--auto-add-overlay"/>
</exec>
5.doc命令行(这里由于apkbuilder已经被删所以不用)
java -cp E:\newsdk\newsdk\tools\lib\sdklib.jar com.android.sdklib.build.ApkBuilderMain testApk.apk -v -u -z bin
\resources.ap_ -f bin\classes.dex -rf src
转成ant文件
<exec executable="java">
<arg value="-cp"/>
<arg value="${sdk-folder}\tools\lib\sdklib.jar"/>
<arg value="com.android.sdklib.build.ApkBuilderMain"/>
<arg value="${project-dir}\bin\unsigned.apk"/>
<arg value="-v"/>
<arg value="-u"/>
<arg value="-z"/>
<arg value="${project-dir}\bin\resources.ap_"/>
<arg value="-f"/>
<arg value="${project-dir}\bin\classes.dex"/>
<arg value="-rf"/>
<arg value="${project-dir}\src"/>
</exec>
6.doc命令行(这里签名需要keystore文件,还不知道keystore是什么就去查查吧)
jarsigner -verbose -keystore E:\jdk1.7.0_79\bin\mydemo.keystore -signedjar testApks.apk testApk.apk E:\jdk1.7.0_79\bin\mydemo.keystore
转成ant文件
<exec executable="jarsigner">
<arg value="-verbose"/>
<arg value="-storepass"/>
<arg value="${password}"/>
<arg value="-keystore"/>
<arg value="mydemo.keystore"/>
<arg value="-signedjar"/>
<arg value="${project-dir}\bin\signed.apk"/>
<arg value="${project-dir}\bin\unsigned.apk"/>
<arg value="mydemo.keystore"/>
</exec>
好到此完成打包操作,一般想要做成工具,可以写个bat脚本去执行,也可以放在java代码中执行,或根据具体需求再加一个svn持续更新项目(反正我是这样做的)。
上一份完整的文件吧:
<?xml version="1.0" encoding="utf-8" standalone="no"?><project default="main">
<property environment="env"/>
<property name="project-dir" value="F:\workspace\fisrtDeom"/>
<property name="password" value="123456"/>
<property name="keyword" value="975594655"/>
<property name="sdk-folder" value="${env.ANDROID_SDK_HOME}"/>
<property name="android-jar" value="${sdk-folder}\platforms\android-20\android.jar"/>
<target name="init">
<echo>start initing ... </echo>
<mkdir dir="${project-dir}\gen"/>
<delete>
<fileset dir="${project-dir}\gen"/>
</delete>
<mkdir dir="${project-dir}\bin/classes"/>
<delete>
<fileset dir="${project-dir}\bin/classes"/>
</delete>
<echo>finish initing. </echo>
</target>
<target depends="init" name="main">
<echo>generating R.java for project to dir gen (using aapt) ... </echo>
<exec executable="aapt">
<arg value="package"/>
<arg value="-m"/>
<arg value="-J"/>
<arg value="${project-dir}\gen"/>
<arg value="-S"/>
<arg value="${project-dir}\res"/>
<arg value="-M"/>
<arg value="${project-dir}\AndroidManifest.xml"/>
<arg value="-I"/>
<arg value="${android-jar}"/>
<arg value="--auto-add-overlay"/> <!-- 覆盖资源 -->
</exec>
<javac bootclasspath="${android-jar}" destdir="${project-dir}\bin/classes" encoding="utf-8" target="1.7">
<src path="${project-dir}\src"/>
<src path="${project-dir}\gen"/>
<classpath>
<fileset dir="${project-dir}\libs" includes="*.jar"/>
</classpath>
</javac>
<echo>packaging class files (include the third-party jars) to calsses.dex ... </echo>
<exec executable="dx.bat" failοnerrοr="true">
<arg value="--dex"/>
<arg value="--output=${project-dir}\bin\classes.dex"/>
<arg path="${project-dir}\bin\classes"/>
</exec>
<echo>packaging resource (include res, assets, AndroidManifest.xml, etc.) to res.zip ... </echo>
<exec executable="aapt">
<arg value="package"/>
<arg value="-f"/>
<arg value="-M"/>
<arg value="${project-dir}\AndroidManifest.xml"/>
<arg value="-S"/>
<arg value="${project-dir}\res"/>
<arg value="-A"/>
<arg value="${project-dir}\assets"/>
<arg value="-I"/>
<arg value="${android-jar}"/>
<arg value="-F"/>
<arg value="${project-dir}\bin\resources.ap_"/>
<arg value="--auto-add-overlay"/>
</exec>
<echo>building unsigned.apk ... </echo>
<exec executable="java">
<arg value="-cp"/>
<arg value="${sdk-folder}\tools\lib\sdklib.jar"/>
<arg value="com.android.sdklib.build.ApkBuilderMain"/>
<arg value="${project-dir}\bin\unsigned.apk"/>
<arg value="-v"/>
<arg value="-u"/>
<arg value="-z"/>
<arg value="${project-dir}\bin\resources.ap_"/>
<arg value="-f"/>
<arg value="${project-dir}\bin\classes.dex"/>
<arg value="-rf"/>
<arg value="${project-dir}\src"/>
</exec>
<echo>signing the unsigned apk to final product apk ... </echo>
<exec executable="jarsigner">
<arg value="-verbose"/>
<arg value="-storepass"/>
<arg value="${password}"/>
<arg value="-keystore"/>
<arg value="mydemo.keystore"/>
<arg value="-signedjar"/>
<arg value="${project-dir}\bin\signed.apk"/>
<arg value="${project-dir}\bin\unsigned.apk"/>
<arg value="mydemo.keystore"/>
</exec>
</target>
<target name="clean">
</target>
</project>