Android中APK打包流程

东坡下载 2018年05月22日 10:44:13

      aapt: android application package tool,SDK

      (Android打包流程图)

      #Android打包流程

      1.通过aapt工具将 资源文件(res)、清单文件(AndroidManifest.xml)生成对应的R.java文件

      * 在项目的根目录下新建 gen目录,并且依次在gen目录下新建清单文件总包名对应的文件目录

      > 例如: 清单文件中包名是org.zdc.android,那么就在gen目录中新建目录结构为

      > gen/org/zdc/android

      * 通过命令生成R.java

      aapt package -f -m -J [gen目录] -S [res目录] -I [android.jar目录] -M [AndroidManifest.xml目录]

      2. 通过aidl工具 将 aidl文件转化为java文件

      aidl -I[src目录] -p[aidl框架环境文件(framework.aidl)] -o[aidl输出目录(gen)] [要转换的aidl文件(your.aidl)]

      3. 通过javac工具,将*.java文件转化为*.class文件

      javac -encoding [编码] -target [版本(1.6 or 1.7)] -bootclasspath [android.jar] -cp [依赖的jar(多个用;隔开;结尾)] -d [class文件输出目录] [要编译的java文件(多个用空格分开)]

      4. 将libs下的jar解压到输出目录中

      jar xvf [jar文件]

      5. 通过dex命令 将class文件转换为dex文件

      dx.bat --dex --output=[全路径的输出文件(classes.dex)] [全路径的class文件对应的目录]

      > [全路径的class文件对应的目录] : 如果此目录依赖了其他的jar文件,需要用 `|`分隔开

      > 命令: dex.bat --dex --output=输出路径 需要转换的class文件对应的路径

      6. 通过aapt工具生成资源文件包

      aapt package -f -M [清单文件(AndroidManifest.xml)] -S [资源文件目录(res)] -A [资产文件目录(assets)] -I [android环境jar(android.jar)] -F [输出的文件(resoures.ap_)]

      7. 生成未签名的apk安装文件

      apkbuilder [apk输出路径] -u -z [打包好的资源文件全路径] -f [全路径dex文件]  -rf  [src全路径]  -rj  [全路径的libs目录]

      8. 生成签名的apk安装文件

      * 生成签名文件

      keytool -genkeypair -alias zdc -keyalg RSA -validity 3650 -keypass 123456 -storepass 123456 -keystore zdc.keystore

      >  -alias : 签名的别名

      >  -validity : 签名的时效

      >  -keyalg : 加密的算法,一般都用RSA

      >  -keystore : 生成的签名路径

      >  -keypass : 密钥库的密码

      >  -storepass :密钥的密码

      * 通过签名文件给apk文件进行签名

      jarsigner -keystore 签名文件 -keypass 签名密码 -storepass 签名文件的密码 -signedjar 生成的签名文件 未签名的文件 签名的别名

      # 命令详解

      * package 命令: 打包编译android资源

      aapt p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \

      [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \

      [--min-sdk-version VAL] [--target-sdk-version VAL] \

      [--max-sdk-version VAL] [--app-version VAL] \

      [--app-version-name TEXT] [--custom-package VAL] \

      [-I base-package [-I base-package ...]] \

      [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \

      [-S resource-sources [-S resource-sources ...]] [-F apk-file] [-J R-file-dir] \

      [raw-files-dir [raw-files-dir] ...]

      > []的参数都是可选参数。

      > __[-d]:  指定一个或多个设备的资源文件被添加,多个资源文件用逗号隔开__

      > __[-f]:  是否覆盖已经存在的文件(添加此参数即为覆盖,否则不覆盖)__

      > __[-m]:  打包资源的文件目录,目录地址是`-J`参数指定__

      > __[-J]:  知道R文件生成的目录__

      > __[-S]:  需要打包的资源文件目录__

      > __[-I]:  指定环境android.jar的文件目录__

      > __[-M]:  清单文件的路径__

      #指令打包之R文件生成

      1、API文档路径:

      develop  ->  tools  ->  buid system(打包系统,主要介绍打包的原理过程)  ->  查看流程图

      2、AAPT:Android Application Package Tool  android应用打包工具

      路径:sdk -> buildtools – 版本 -> aapt

      操作步骤:

      ①配置java环境,建议使用JDK1.6,因为JDK1.7/1.8对指令操作有缺陷。

      ②拷贝工程到CMD文件夹(自己创建),删除工程中自动生成的目录和文件(.setting、bin、gen、.classpath、.project)。

      3、使用指令进行操作

      ①在当前工程根目录下中创建gen目录,在gen目录下根据工程包名创建不同的目录。

      ②CMD指令进入到当前工程的目录下

      ③执行命令

      aapt package -f -m -J gen -S res -I ...\sdk\platforms\android-16\android.jar -M AndroidManifest.xml

      #.aidl转java文件

      1、工具指令路径:sdk -> platform-tools -> aidl.exe

      2、framework.aidl路径:sdk -> platforms -> android-14 –>framework.aidl

      3、使用指令

      aidl -Isrc -pD:\...\sdk\platforms\android-16\framework.aidl -ogen 项目路径\src\aidl目录\ITelephony.aidl

      注意:有的aidl不会产生java文件

      #指令打包之java转class

      1、Application source code:应用源码,指的就是我们工程中.java文件,比如src下的文件等等。

      2、Java Compiler:java编译器,R.java、Application source code和java InterFaces是通过java编译器编译成.class文件的

      3、操作指令:

      ①在工程的根目录下创建bin目录,在bin目录中classes目录

      ②使用指令进行操作

      javac -encoding utf-8 -bootclasspath D:\...\sdk\platforms\android-16\android.jar -cp libs\android-support-v4.jar; -d bin\classes .\gen\cn\zdc\packagedemo\R.java

      4、解压jar包

      因为jar包或者库文件也在我们工程中的,所以在转化的时候需要将jar包或者库文件中的class文件一起转化成dex

      ①进入到bin目录下的classes目录下

      ②使用指令(两个依次使用)

      jar xvf ..\..\libs\nineoldandroids-2.4.0.jar

      #指令打包之class转dex

      1、将class文件转化成dex文件

      ①使用指令进入到工程的bin目录下的classes目录中

      ②使用指令

      dx --dex --output=项目路径\bin\classes.dex 项目路径\bin\classes

      #指令打包之生成未签名的apk

      1、打包Apk需要三个元素

      ①编译后的资源文件

      ②dex文件

      ③其他资源

      2、操作步骤:

      ①得到编译后的资源文件,使用指令

      aapt package -f -M AndroidManifest.xml -S res -A assets -I D:\...\sdk\platforms\android-16\android.jar  -F bin\resources.ap_

      ②使用dex和.ap_资源打包Apk

      需要使用apkbuilder工具,路径:sdk\tools\apkbuilder.bat

      指令:

      apkbuilder 项目路径\bin\mobliesafe.apk -u -z 项目路径\bin\resources.ap_ -f 项目路径\bin\classes.dex -rf 项目路径\src -rj 项目路径\libs

      3.注意:这个打包的apk是不能安装的,因为android系统安装apk需要知道apk的签名

      #指令打包之生成签名的apk

      打包一个签名的apk需要两步操作

      1.生成签名文件

      2.根据签名文件进行打包的apk

      操作步骤:

      1.生成签名文件

      ①指令工具路径:Java -> jdk -> bin -> keytool.exe

      ②使用指令进入到工程的根目录下

      ③使用指令

      keytool -genkeypair -alias zdc -keyalg RSA -validity 3650 -keypass 123456 -storepass 123456 -keystore zdc.keystore

      2.根据签名文件进行打包的apk

      ①指令工具路径:Java -> jdk -> bin -> jarsigner.exe

      ②使用指令

      jarsigner -keystore zdc.keystore -keypass 123456 -storepass 123456 -signedjar bin\mobliesafe_signed.apk bin\mobliesafe.apk zdc

      #ant介绍

      1.环境变量配置

      ANT_HOME ....\apache-ant-1.9.6-bin

      Path %ANT_HOME%\bin

      2.校验

      ant -help  或者 ant -version

      #ant基本操作

      1.脚本必须写在build.xml中

      2.常用标签

      project根标签    name: 项目名称。必填    baseDir: 指定当前目录。(选填)    default: 默认执行的任务。 (选填)Target任务标签 name: 任务名称。必填echo输出打印标签message:指定打印的内容示例:<?xml version="1.0" encoding="utf-8"?><project name="test01"> <target name="helloworld"> <echo message="Hello World"></echo> </target></project>

      3.执行ant

      ①cmd -> ant : 查看build.xml文件是否构建成功

      ②cmd -> ant helloworld : 执行相应的任务

      4.如果不想通过ant helloworld执行任务,也可以设置project的default标签设置默认执行任务

      示例:<project name="test01" default="helloworld"> <target name="helloworld"> <echo message="Hello World"></echo> </target></project>

      4.也可以输出引用

      示例:<project name="test01" default="helloworld"> <target name="helloworld"> <echo message="Hello World"></echo> <echo message="${basedir}"></echo> </target></project>

      ${名称}:引用;${basedir} : 本地路径引用

      5.执行多个任务

      5.1.两个任务

      示例:<project name="test01" default="helloworld"> <target name="helloworld"> <echo message="Hello World"></echo> </target> <target name="printdir" depends="helloworld"> <echo message="${basedir}"></echo> </target></project>

      depends:和哪个任务关联,运行先执行depends中的任务,再执行当前任务

      运行Cmd -> ant printdir,这时候就会先打印第一个任务,在打印第二个任务

      5.2.三个任务

      示例:<project name="test01" default="helloworld"> <target name="helloworld"> <echo message="Hello World"></echo> </target> <target name="printdir" depends="helloworld"> <echo message="${basedir}"></echo> </target> <target name="helloAndroid" depends="helloworld,printdir"> <echo message="helloAndroid"></echo> </target></project>

      多个任务depends中使用“,”分隔

      #ant的文件操作

      1.添加文件

      示例:<project name="test02"> <target name="mkdir"> <mkdir dir="hehe"></mkdir> </target></project>

      mkdir:表示创建目录,dir:是目录的名称

      2.删除目录

      示例:<project name="test02"> <target name="deldir"> <delete dir="hehe"></delete> </target></project>

      delete:删除目录,dir:目录的名称

      3.创建文件

      因为创建出来文件还需要编辑,ant没有这么强大,所以不能创建文件

      4.删除文件

      创建文件test.txt示例:<project name="test02"> <target name="delfile"> <delete file="test.txt"></delete> </target></project>file:文件的名称

      #ant执行javac指令

      1.创建java文件

      2.使用ant执行编译指令

      原先:编译:javac Test.java执行java Test

      示例:

      <project name="test03"> <target name="javac"> <javac> <src path="."/> <exclude name="Test.java"/> <exclude name="Test1.java"/> </javac> </target></project>

      javac:标示javac指令,src:根目录,exclude:表示不编译哪个文件

      #ant打包手机卫士

      在eclipse的手机卫士的项目根目录中新建文件build.xml,发现无法进行快捷提示,这是因为缺少ant.dtd系统文件,将ant.dtd导入到工程的根目录下在,在重新创建build.xml,创建的时候点击下一步,不要直接点击完成,在跳转的下一个界面中选择导入自己的dtd文件,完成即可

      1.生成R文件

      1.1.创建存放R文件的目录,工程 -> build

      1.2.创建gen目录

      示例:

      <!-- 创建R文件存放的目录 --><target name="init"> <!-- 当下次调用的时候,要将文件目录删除,重新创建 --> <delete dir="${builddir}"></delete> <!-- 创建build\gen --> <mkdir dir="${gendir}"/></target>

      路径下面还会用,抽取路径

      <property name="builddir" location="${basedir}/build"/><property name="gendir" location="${builddir}/gen" />

      property : 设置属性

      2.运行

      window -> show view -> ant -> 点击加号将build.xml添加到ant中,如果出现错误将build.xml中的<!DOCTYPE pro                                                                                                 ject SYSTEM "ant.dtd" >注释调用,点击运行即可

      3.生成R文件

      3.1.生成R文件需要aapt,但是aapt是在sdk目录下的,如何去获取呢?可以通过环境变量获取

      示例:<property environment="env"/><property name="sdkhome" location="${env.SDK_HOME}"/><property name="aapt" location="${sdkhome}/build-tools/19.1.0/aapt.exe"/>environment : 表示设置环境变量的标示

      3.2.生成R文件

      示例:

      <!-- 创建R文件思路: 1.找到aapt2.运行aapt指令:aapt package -f -m -J gen -S res -I d:\...\sdk\platforms\android-14\android.jar -M AndroidManifest.xml--><target name="genR" depends="init"> <exec executable="${aapt}"> <arg value="package"></arg> <arg value="-f"></arg> <arg value="-m"></arg> <arg value="-J"></arg> <arg value="${gendir}"></arg> <arg value="-S"></arg> <arg value="${resdir}"></arg> <arg value="-I"></arg> <arg value="${androidjar}"></arg> <arg value="-M"></arg> <arg value="${manifest}"></arg> </exec></target>

      exec : 执行指令    executable:执行什么指令,ant无法通过快捷提示出来的。

      3.3.在执行的时候还需要创建保存目录

      示例:

      <!-- 创建R文件2:设置各种目录 --><!-- res --><property name="resdir" location="${basedir}/res"></property><!-- android.jar --><property name="androidjar" location="${sdkhome}/platforms/android-14/android.jar"></property><!-- AndroidManifest.xml --><property name="manifest" location="${basedir}/AndroidManifest.xml"></property>

      4.aidl转化java文件操作:

      4.1.设置属性获取aidl工具

      示例:

      <property name="aidl" location="${sdkhome}/build-tools/19.1.0/aidl.exe"></property>

      4.2.执行指令

      因为有多个aidl文件所以需要执行多个aidl指令,在ant中exec标签是执行一条指令,apply标签执行多条指令

      示例:

      <target name="aidltojava" depends="mkR"> <apply executable="${aidl}"> <arg value="-I${srcdir}"/> <arg value="-p${frameworkaidl}"/> <arg value="-o${gendir}"/> <fileset dir="${srcdir}" includes="**/*.aidl"/> </apply></target>

      fileset : 执行的文件的组,dir:文件存放的根目录 includes:文件的位置

      **/*.aidl : **/:表示:aidl文件的上级目录  *.aidl:任何aidl文件

      4.3.将相应的目录生成一下

      示例:

      <property name="srcdir" location="${basedir}/src"></property><!-- framwork.aidl --><property name="frameworkaidl" location="${sdkhome}/platforms/android-14/framework.aidl"></property>

      5.java转class操作

      5.1.创建classes目录,修改init任务

      示例:

      <target name="init"> <delete dir="${builddir}"></delete> <mkdir dir="${gendir}"/>   <mkdir dir="${classesdir}"></mkdir></target>

      5.2.设置转化操作

      示例:

      <target name="javattoclass" depends="aidltojava"> <javac encoding="utf-8" bootclasspath="${androidjar}" destdir="${classesdir}"> <classpath>         <fileset dir="${lisbsdir}" includes="**/*.jar"></fileset> </classpath> <src path="${srcdir}"></src> <src path="${gendir}"></src> </javac></target>

      classpath : 表示设置路径组,fileset:标示多个文件

      5.3.设置路径属性

      示例:

      <property name="lisbsdir" location="${basedir}/libs"></property><property name="classesdir" location="${builddir}/classes"></property>

      6.解压jar包

      示例:

      <target name="unjar" depends="javattoclass"> <unjar dest="${classesdir}"> <fileset dir="${lisbsdir}" includes="**/*.jar"></fileset> </unjar></target>

      7.class文件转dex文件

      7.1.获取dx工具

      示例:

      <property name="dx" location="${sdkhome}/platform-tools/dx.bat"></property>

      7.2.设置执行任务

      示例:

      <target name="classtodex" depends="unjar"> <exec executable="${dx}">       <arg value="--dex"></arg>       <arg value="--output=${classesdex}"></arg>       <arg value="${classesdir}"></arg>         </exec></target>

      7.3.设置路径

      示例:

      <property name="classesdex" location="${builddir}/classes.dex"></property>

      8.打包资源文件

      8.1.设置执行任务

      示例:

      <target name="restoresources" depends="classtodex"> <exec executable="${aapt}"> <arg value="package"></arg> <arg value="-f"></arg> <arg value="-M"></arg> <arg value="${manifest}"></arg> <arg value="-S"></arg> <arg value="${resdir}"></arg> <arg value="-A"></arg> <arg value="${assetsdir}"></arg> <arg value="-I"></arg> <arg value="${androidjar}"></arg> <arg value="-F"></arg> <arg value="${resourcesap}"></arg> </exec></target>

      8.2.设置路径

      示例:

      <property name="assetsdir" location="${basedir}/assets"></property><property name="resourcesap" location="${builddir}/resources.ap_"></property>

      9.生成未签名的apk

      9.1.获取打包指令

      示例:

      <property name="apkbuilder" location="${sdkhome}/tools/apkbuilder.bat"></property>

      9.2.设置执行任务

      示例:

      <target name="unsignedapk" depends="restoresources"> <exec executable="${apkbuilder}"> <arg value="${unsingedapk}"></arg> <arg value="-u"></arg> <arg value="-z"></arg> <arg value="${resourcesap}"></arg> <arg value="-f"></arg> <arg value="${classesdex}"></arg> <arg value="-rf"></arg> <arg value="${srcdir}"></arg> <arg value="-rj"></arg> <arg value="lisbsdir"></arg> </exec></target>

      9.3.设置路径

      示例:

      <property name="unsingedapk" location="${builddir}/mobliesafe_unsigned.apk"></property>

      10.生成签名的apk

      将之前用命令写的key文件拷贝到工程的根目录下

      10.1.获取执行指令工具

      示例:

      <property name="javahome" location="${env.JAVA_HOME}"></property><property name="jarsigner" location="${javahome}/bin/jarsigner.exe"></property>

      10.2.设置执行任务

      <target name="signedapk" depends="unsignedapk"> <exec executable="${jarsigner}"> <arg value="-keystore"></arg> <arg value="${keystore}"></arg> <arg value="-keypass"></arg> <arg value="123456"></arg> <arg value="-storepass"></arg> <arg value="123456"></arg> <arg value="-signedjar"></arg> <arg value="${signedpakdir}"></arg> <arg value="${unsingedapk}"></arg> <arg value="zdc85"></arg> </exec> </target>

      10.3.设置路径

      示例:

      <property name="keystore" location="${basedir}/zdc85.keystore"></property><property name="signedpakdir" location="${builddir}/mobliesafe_signed.apk"></property>

      11.资源混淆

      11.1.解压AndResGuard-master.zip,在其中的tool_output找到AndResGuard-cli-1.1.4.jar

      11.2.将AndResGuard-cli-1.1.4.jar拷贝到工程的tools目录下

      11.3.将config.xml文件拷贝到工程的tools目录下

      11.4.修改config.xml文件

      示例:

      <resproguard> <issue id="sign" isactive="true"> <!--the signature file path, in window use \, in linux use /, and the default path is the running location--> <path value="zdc85.keystore"/> <!--storepass--> <storepass value="123456"/> <!--keypass--> <keypass value="123456"/> <!--alias--> <alias value="zdc85"/> </issue> </resproguard>

      11.5.使用指令测试,必须使用JDK1.7,并且路径不能有空格

      D:\java\jdk7\bin\java.exe -jar AndResGuard-cli-1.1.4.jar ..\build\mobliesafe_unsigned.apk

      11.6.解决7za的错误

      将SevenZip\executable目录下找到7za-windows_x86_64.exe拷贝到工程的tools目录下

      11.7.将key文件也放到目录下重新执行命令

      D:\java\jdk7\bin\java.exe -jar AndResGuard-cli-1.1.4.jar ..\build\mobliesafe_unsigned.apk -7zip 7za-windows_x86_64.exe

      11.8.设置ant执行任务

      设置JDK1.7路径

      示例:

      <property  name="java7"  location="D://java/jdk7/bin/java.exe" /> 设置执行任务示例:<target name="proguardResourceApk" depends="unsignedapk"> <exec executable="${java7}"> <arg value="-jar" /> <arg value="tools/AndResGuard-cli-1.1.4.jar" /> <arg value="${unsingedapk}" /> <arg value="-7zip" /> <arg value="tools/7za-windows_x86_64.exe" /> </exec></target>   

      注意:这时候需要将config.xml拷贝到根目录下