用ant的build.xml构建自动化打包android apk 完全详解(打包系列教程之二)

版权声明:本文为博主原创文章,请尊重原创,未经博主允许禁止转载,保留追究权 https://blog.csdn.net/javazejian/article/details/50579416

打包系列教程目录:

纯ant命令行打包android apk之图文从原理角度完全详解android打包过程(打包系列教程之一)

用ant的build.xml构建自动化打包android apk 完全详解(打包系列教程之二)

Android 多渠道打包之混淆文件ProGuard技术详解-特别篇(打包系列教程之三)

android studio gradle 多渠道打包之完全详解(打包系列教程之四)

android studio gradle 多版本多apk打包(打包系列教程之五)

详解高速神器python脚步打包android apk,超级快!!(打包系列教程之六)


通过上一篇文章内容的学习,我们基本已经明白了android打包签名apk的主要操作与流程,那么这一篇文章我们就将上一篇文章的打包内容转化成ant的build.xml文件进行自动化打包,这样可以避免我们上一篇文章的敲打命令行的繁琐操作,从而让我们离自动化操作更近一步(建议先了解一下ant的基本用法,可以看这篇文章:http://blog.csdn.net/jason0539/article/details/44836769)。

我们还是跟上一篇一样,根据以下步骤一步步来进行。

(1). 生成用于应用的R.java;

(2). 编译所有java文件为class文件;

(3). 打包class文件和jar包为classes.dex;

(4). 打包assets和res资源为资源压缩包(例如res.zip,名字可以自己定义);

(5). 构建classes.dex和res.zip生成未签名的APK;

(6). 生成有签名的APK;

(7). 对签名包进行zipalign优化;

 注意这里的目录跟上一篇的文章的目录是有区别的,上一篇的内容是为了演示方便,才把生成的文件都存放在桌面的ant文件的gen目录和bin目录下,本篇默认路径都是cd到工程目录的根目录下,所以生成的文件也存放在工程目录原有的gen文件夹和bin文件下。


在工程开始之前,我们先要指定一些常量或者属性以及做一些初始化操作

<!-- ANT环境变量 -->  
    <!--
	    <property environment="env" />
	    <property name="sdk.dir" value="${env.ANDROID_HOME}"/>  
	    <echo> ${sdk.dir} </echo>  
    -->
    
 <!-- 项目所在文件夹 -->  
 <property name="project-dir" value="/Users/zejian/Documents/eclipse-java-mars-1-macosx-cocoa-x86_64/workspace/Command4Ant" />  
 <!-- JAVA目录(获取操作系统环境变量JAVA_HOME的值) -->  
 <property name="java_home" value="/Library/Java/JavaVirtualMachines/jdk1.7.0_75.jdk/Contents/Home" />
 <!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->  
 <property name="sdk-folder" value="/Users/zejian/Documents/androidStudio/SDK" />  
 <!-- 指定平台对应的android.jar -->
 <property name="android-jar" value="${sdk-folder}/platforms/android-22/android.jar" />
 <!-- SDK指定平台目录 -->  
 <property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-22"/>  
 <!-- SDK中tools目录 -->  
 <property name="sdk-tools" value="${sdk-folder}/tools" />  
 <!-- SDK中build_tools目录 -->  
 <property name="build-tools" value="${sdk-folder}/build-tools/23.0.2" /> 
 <!-- SDK指定平台中tools目录 -->  
 <property name="sdk-platform-tools" value="${sdk-platform-folder}/tools" />  
  
 <!-- 使用到的命令(当前系统为mac) -->  
 <property name="aapt" value="${build-tools}/aapt" />  
 <property name="aidl" value="${build-tools}/aidl" />  
 <property name="dx" value="${build-tools}/dx" /> 
 <property name="zipalign" value="${build-tools}/zipalign" />  
 <property name="apkbuilder" value="${sdk-tools}/apkbuilder" />  
 <property name="jarsigner" value="${java_home}/bin/jarsigner" /> 
  
 <target name="init">  
   <echo>start initing ... </echo>  
    <delete>  
      <fileset dir="gen"></fileset>  
    </delete>  
    <mkdir dir="gen" />  
    <delete>  
      <fileset dir="bin/classes"></fileset>  
    </delete>  
    <mkdir dir="bin/classes" />  
    <echo>finish initing. </echo>  
 </target>  


这里主要定义了android的sdk目录,java的home目录以及tools工具和build_tools工具,后初始化文件夹。对于environment="env"这个属性常量,我很诧异,因为在我的mac电脑上,无论我怎么测试都读不到我定义的java和android环境变量,最终还是选择了绝对路径定义(如有知晓原因,请劳烦给我留言,谢谢!)。

1.生成用于应用的R.java 

aapt package -f -m -J gen -S res -M AndroidManifest.xml  -I /Users/zejian/Documents/androidStudio/SDK/platforms/android-22/android.jar 
参数含义如下:

-f 如果编译生成的文件已经存在,强制覆盖。

-m 使生成的包的目录存放在-J参数指定的目录

-J 指定生成的R.java 的输出目录路径(存放在桌面的gen)

-S 指定res文件夹的路径

-I 指定某个版本平台的android.jar文件的路径(我使用的是API-22)

转换成ant (注意依据当前项目的根目录

        <echo>1.正在生成用于应用的R.java存放到gen(使用aapt) ... </echo>  
          <exec executable="${aapt}">  
              <arg value="package" />  
              <arg value="-m" />  
              <arg value="-J" />  
              <arg value="gen" />  
              <arg value="-S" />  
              <arg value="res" />  
              <arg value="-M" />  
              <arg value="AndroidManifest.xml" />  
              <arg value="-I" />  
              <arg value="${android-jar}" />  
              <arg value="--auto-add-overlay" /> <!-- 覆盖资源 -->  
          </exec>  
  	<echo>步骤1已经完成... </echo> 
2.编译所有java文件为class文件
javac -target 1.7 -bootclasspath /Users/zejian/Documents/androidStudio/SDK/platforms/android-22/android.jar -d bin src/com/example/command4ant/*.java gen/com/example/command4ant/R.java
含义如下:

-target <jdk版本>            生成特定 jdk 版本的类文件

-bootclasspath <路径>        覆盖引导类文件的位置

-d <目录>                    指定存放生成的类文件的位置

-sourcepath <路径>           指定查找输入源文件的位置

转换成ant (注意依据当前项目的根目录

 <echo>2.正在编译所有java文件为class文件(包含src和gen目录)... </echo>  
      <javac  target="1.7" destdir="bin/classes" bootclasspath="${android-jar}">  
          <src path="src" />  
          <src path="gen" />  
      </javac>  
 <echo>步骤2已经完成... </echo>
3. 打包class文件和jar包为classes.dex
dx --dex --output=bin/classes.dex bin

参数含义如下:

--output=<要生成的classes.dex路径>  <要处理的class文件的路径>

转换成ant (注意依据当前项目的根目录

       <echo>3.正在打包class文件和jar包为classes.dex... </echo>  
          <exec executable="${dx}" failοnerrοr="true">   
               <arg value="--dex" />   
               <arg value="--output=${project-dir}/bin/classes.dex" />   
               <arg path="${project-dir}/bin/classes" />  
          </exec>   
       <echo>步骤3已经完成... </echo>  
4. 打包assets和res资源为资源压缩包(例如res.zip,名字可以自己定义)

aapt package -f -M AndroidManifest.xml -S res -I /Users/zejian/Documents/androidStudio/SDK/platforms/android-22/android.jar -A assets -F bin/res.zip  

参数含义:

-f 如果编译生成的文件已经存在,强制覆盖。

-m 使生成的包的目录存放在-J参数指定的目录

-S 指定res文件夹的路径

-I 指定某个版本平台的android.jar文件的路径

-A 指定assert文件夹的路径

-F 指定输出文件完整路径

转换成ant (注意依据当前项目的根目录

<echo>4.正在打包assets和res资源为资源压缩包res.zip...(include res, assets, AndroidManifest.xml)</echo>  
   <exec executable="${aapt}">  
     <arg value="package" />  
     <arg value="-f" />  
     <arg value="-M" />  
     <arg value="AndroidManifest.xml" />  
     <arg value="-S" />  
     <arg value="res" />  
     <arg value="-A" />  
     <arg value="assets" />  
     <arg value="-I" />  
     <arg value="${android-jar}" />  
     <arg value="-F" />  
     <arg value="bin/resources.ap_" />  
     <arg value="--auto-add-overlay" />  
  </exec>  
<echo>步骤4已经完成... </echo>  
5.构建classes.dexres.zip生成未签名的APK
apkbuilder bin/unsigned_command4Ant.apk -v -u -z bin/res.zip -f bin/classes.dex 
参数含义:

第一个参数是存放打包后的文件完整路径

-v Verbose 显示过程信息

-u 创建一个无签名的包

-z 指定apk资源路径

-f 指定dex文件路径

转换成ant (注意依据当前项目的根目录

<echo>5.正在构建classes.dex和res.zip生成未签名的APK(unsigned.apk)... </echo>  
   <exec executable="${apkbuilder}">  
       <arg value="${project-dir}/bin/unsigned.apk" />  
       <arg value="-u" />  
       <arg value="-z" />  
       <arg value="${project-dir}/bin/resources.ap_" />  
       <arg value="-f" />  
       <arg value="${project-dir}/bin/classes.dex" />  
   </exec>  
<echo>步骤5已经完成... </echo>  
6.生成有签名的APK
jarsigner -verbose -keystore debug4zj -storepass debug4zj -keypass debug4zj -signedjar bin/signed_command4Ant.apk bin/unsigned_command4Ant.apk debug4zj  
参数含义:

-verbose  签名/验证时输出详细信息

-keystore  密钥库路径

-storepass  用于密钥库完整性的口令(密码)

-keypass    专用密钥的口令(密码)

-signedjar   已签名的 apk 文件的名称 (第一个apk是签名之后的文件, 第二个apk是需要签名的文件)

转换成ant (注意依据当前项目的根目录

<echo>6.正在生成有签名的APK... </echo>  
  <exec executable="${jarsigner}">  
       <arg value="-keystore" />  
       <arg value="${project-dir}/debug4zj" />  
       <arg value="-storepass" />  
       <arg value="debug4zj" />  
       <arg value="-keypass" />  
       <arg value="debug4zj" />  
       <arg value="-signedjar" />  
       <arg value="${project-dir}/bin/signed.apk" />  
       <arg value="${project-dir}/bin/unsigned.apk" />  
       <arg value="debug4zj" />  
  </exec>  
<echo>步骤6已经完成... </echo>  
7. 对签名包进行zipalign优化
zipalign -v 4 bin/signed.apk bin/zipalign_signed.apk  
参数含义:

-v 输出详细信息

- 需要zipalign优化的apk  优化后的apk名称以及存放位置

转换成ant (注意依据当前项目的根目录

 <echo>7.正在对签名包进行zipalign优化... </echo>  
   <exec executable="${zipalign}">
       <arg value="-v" />
       <arg value="4" />
       <arg value="${project-dir}/bin/signed.apk" /> <!-- signed apk -->
       <arg value="${project-dir}/bin/zipalign_signed.apk" /> <!-- zipalign output -->
   </exec>
<echo>步骤7已经完成... </echo>  
到此打包流程的转换成ant的build.xml就完成了,最后给出完成的build.xml文件:
<?xml version="1.0" encoding="utf-8"?>  
<project default="main" basedir=".">  
    <!-- ANT环境变量 -->  
    <!--
	    <property environment="env" />
	    <property name="sdk.dir" value="${env.ANDROID_HOME}"/>  
	    <echo> ${sdk.dir} </echo>  
    -->
    
    <!-- 项目所在文件夹 -->  
    <property name="project-dir" value="/Users/zejian/Documents/eclipse-java-mars-1-macosx-cocoa-x86_64/workspace/Command4Ant" />  
  <!-- JAVA目录(获取操作系统环境变量JAVA_HOME的值) -->  
  <property name="java_home" value="/Library/Java/JavaVirtualMachines/jdk1.7.0_75.jdk/Contents/Home"/>
    <!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->  
    <property name="sdk-folder" value="/Users/zejian/Documents/androidStudio/SDK" />  
    <!-- 指定平台对应的android.jar -->
    <property name="android-jar" value="${sdk-folder}/platforms/android-22/android.jar" />
    <!-- SDK指定平台目录 -->  
    <property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-22"/>  
    <!-- SDK中tools目录 -->  
    <property name="sdk-tools" value="${sdk-folder}/tools" />  
     <!-- SDK中build_tools目录 -->  
    <property name="build-tools" value="${sdk-folder}/build-tools/23.0.2" /> 
    <!-- SDK指定平台中tools目录 -->  
    <property name="sdk-platform-tools" value="${sdk-platform-folder}/tools" />  
  
    <!-- 使用到的命令(当前系统为mac) -->  
    <property name="aapt" value="${build-tools}/aapt" />  
    <property name="aidl" value="${build-tools}/aidl" />  
    <property name="dx" value="${build-tools}/dx" /> 
    <property name="zipalign" value="${build-tools}/zipalign" />  
    <property name="apkbuilder" value="${sdk-tools}/apkbuilder" />  
    <property name="jarsigner" value="${java_home}/bin/jarsigner" />    

     <target name="init">  
      <echo>start initing ... </echo>  
        <delete>  
            <fileset dir="gen"></fileset>  
        </delete>  
          <mkdir dir="gen" />  
        <delete>  
            <fileset dir="bin/classes"></fileset>  
        </delete>  
        <mkdir dir="bin/classes" />  
      <echo>finish initing. </echo>  
    </target>  
      
    <target name="main" depends="init">  
     <echo>1.正在生成用于应用的R.java存放到gen(使用aapt) ... </echo>  
          <exec executable="${aapt}">  
              <arg value="package" />  
              <arg value="-m" />  
              <arg value="-J" />  
              <arg value="gen" />  
              <arg value="-S" />  
              <arg value="res" />  
              <arg value="-M" />  
              <arg value="AndroidManifest.xml" />  
              <arg value="-I" />  
              <arg value="${android-jar}" />  
              <arg value="--auto-add-overlay" /> <!-- 覆盖资源 -->  
          </exec>  
    <echo>步骤1已经完成... </echo>  
    <echo>2.正在编译所有java文件为class文件(包含src和gen目录)... </echo>  
     <javac target="1.7" destdir="bin/classes" bootclasspath="${android-jar}">  
              <src path="src" />  
              <src path="gen" />  
       </javac>  
    <echo>步骤2已经完成... </echo>  
         
           
    <echo>3.正在打包class文件和jar包为classes.dex... </echo>  
          <exec executable="${dx}" failοnerrοr="true">   
               <arg value="--dex" />   
               <arg value="--output=${project-dir}/bin/classes.dex" />   
               <arg path="${project-dir}/bin/classes" />  
          </exec>   
            <echo>步骤3已经完成... </echo>  
           
   <echo>4.正在打包assets和res资源为资源压缩包res.zip...(res, assets, AndroidManifest.xml)</echo> 
          <exec executable="${aapt}">  
               <arg value="package" />  
               <arg value="-f" />  
               <arg value="-M" />  
               <arg value="AndroidManifest.xml" />  
               <arg value="-S" />  
               <arg value="res" />  
               <arg value="-A" />  
               <arg value="assets" />  
               <arg value="-I" />  
               <arg value="${android-jar}" />  
               <arg value="-F" />  
               <arg value="bin/resources.ap_" />  
               <arg value="--auto-add-overlay" />  
          </exec>  
            <echo>步骤4已经完成... </echo>  
    <echo>5.正在构建classes.dex和res.zip生成未签名的APK(unsigned.apk)...</echo>  
          <exec executable="${apkbuilder}">  
               <arg value="${project-dir}/bin/unsigned.apk" />  
               <arg value="-u" />  
               <arg value="-z" />  
               <arg value="${project-dir}/bin/resources.ap_" />  
               <arg value="-f" />  
               <arg value="${project-dir}/bin/classes.dex" />  
          </exec>  
    <echo>步骤5已经完成... </echo>  
    <echo>6.正在生成有签名的APK... </echo>  
          <exec executable="${jarsigner}">  
               <arg value="-keystore" />  
               <arg value="${project-dir}/debug4zj" />  
               <arg value="-storepass" />  
               <arg value="debug4zj" />  
               <arg value="-keypass" />  
               <arg value="debug4zj" />  
               <arg value="-signedjar" />  
               <arg value="${project-dir}/bin/signed.apk" />  
               <arg value="${project-dir}/bin/unsigned.apk" />  
               <arg value="debug4zj" />  
          </exec>  
    <echo>步骤6已经完成... </echo>  
    <echo>7.正在对签名包进行zipalign优化... </echo>  
          <exec executable="${zipalign}">
            <arg value="-v" />
            <arg value="4" />
            <arg value="${project-dir}/bin/signed.apk" /> <!-- signed apk -->
            <arg value="${project-dir}/bin/zipalign_signed.apk" /> <!-- zipalign output -->
          </exec>
    <echo>步骤7已经完成... </echo>  
    </target>  
    <target name="clean">  
    </target>  
</project>  
然后我们运行build.xml文件,运行log如下:

打包结果,我们查看一下项目的bin目录:

从图片中我们可以看出打包确实完成了,但细心的同学可能发现log里面又这么一个警告信息:

其实有这个警告的话本身对签名没有影响,但是总感觉不太爽,要想去掉这个警告只要在签名时加上如下代码即可:
<arg value="-tsa"/>
<arg value="https://timestamp.geotrust.com/tsa"/>
这就为该签名包提供了时间戳的机构地址的认证链接,这样就不会报错啦。不过这个我在实际操作中发现,打包到签名时,用的时间特别久,原因就是要去提供的地址验证该时间戳的认证,所以我为了节省时间一般不加。完整代码如下:

      <echo>6.正在生成有签名的APK... </echo>  
          <exec executable="${jarsigner}">  
               <arg value="-tsa"/>
               <arg value="https://timestamp.geotrust.com/tsa"/>
               <arg value="-keystore" />  
               <arg value="${project-dir}/debug4zj" />  
               <arg value="-storepass" />  
               <arg value="debug4zj" />  
               <arg value="-keypass" />  
               <arg value="debug4zj" />  
               <arg value="-signedjar" />  
               <arg value="${project-dir}/bin/signed.apk" />  
               <arg value="${project-dir}/bin/unsigned.apk" />  
               <arg value="debug4zj" />  
          </exec>  
      <echo>步骤6已经完成... </echo>
到此使用ant的build.xml构建自动化打包android apk 就全部分析完。下一篇我会继续分析使用ant实现android的多渠道打包,欢迎继续关注哈。

案例源码下载:http://download.csdn.net/detail/javazejian/9417035

展开阅读全文

没有更多推荐了,返回首页