今天跟着大佬的Blog来学习一下 Apk打包编译的流程。传送门
流程图
上图中的绿色部分就是APK编译打包的工具。从图中可以知道使用的工具有:
APPT、AIDL、Java Compiler(javac)、dex、apkbuilder、Jarsigner、zipalign。
来看看它们的作用及工具存储路径:
名称 | 功能 | 操作系统中的路径 |
---|---|---|
APPT | Android资源的打包工具 | ${ANDROID_SDK_HOME}/platform-tools/appt |
AIDL | Android接口,描述语言转化为.java文件的工具 | ${ANDROID_SDK_HOME}/platform-tools/aidl |
javac | java编译工具,将源文件转化为.class文件 | ${JDK_HOME}/javac或/usr/bin/javac |
dex | 将.class文件转化为DVM能识别的.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 |
1、打包资源文件,生成R.java文件
appt工具可以将资源打包,生成一个R.java,appt有下面一些参数:
-d one or more device assets to include, separated by commas
-f force overwrite of existing files
-g specify a pixel tolerance to force images to grayscale, default 0
-j specify a jar or zip file containing classes to include
-k junk path of file(s) added
-m make package directories under location specified by -J
-u update existing packages (add new, replace older, remove deleted files)
-v verbose output
-x create extending (non-application) resource IDs
-z require localization of resource attributes marked with
localization="suggested"
-A additional directory in which to find raw asset files
-G A file to output proguard options into.
-F specify the apk file to output
-I add an existing package to base include set
-J specify where to output R.java resource constant definitions
-M specify full path to AndroidManifest.xml to include in zip
-P specify where to output public resource definitions
-S directory in which to find resources. Multiple directories will be scann
appt在应用程序目录下新建一个gen目录,创建后再gen目录下生成包结构以及目录树,还有R.java文件。
2、处理AIDL文件,生成对应.java文件
如果有些程序没有涉及到AIDL,那这一步就省了。
AIDL工具将.aidl文件生成.java文件,它有如下参数:
-I<DIR> search path for import statements.
-d<FILE> generate dependency file.
-p<FILE> file created by --preprocess to import.
-o<FOLDER> base output folder for generated files.
-b fail when trying to compile a parcelable.
值得注意的是:这个工具的参数与参数值之间不能有空格
这里是将testService转化成java文件的例子。
3、javac编译java文件
这一步java compiler编译源代码生成字节码。
javac的参数有下面:
-g 生成所有调试信息
-g:none 不生成任何调试信息
-g:{lines,vars,source} 只生成某些调试信息
-nowarn 不生成任何警告
-verbose 输出有关编译器正在执行的操作的消息
-deprecation 输出使用已过时的 API 的源位置
-classpath <路径> 指定查找用户类文件和注释处理程序的位置
-cp <路径> 指定查找用户类文件和注释处理程序的位置
-sourcepath <路径> 指定查找输入源文件的位置
-bootclasspath <路径> 覆盖引导类文件的位置
-extdirs <目录> 覆盖安装的扩展目录的位置
-endorseddirs <目录> 覆盖签名的标准路径的位置
-proc:{none,only} 控制是否执行注释处理和/或编译。
-processor <class1>[,<class2>,<class3>...]要运行的注释处理程序的名称;绕过默认的搜索进程
-processorpath <路径> 指定查找注释处理程序的位置
-d <目录> 指定存放生成的类文件的位置
-s <目录> 指定存放生成的源文件的位置
-implicit:{none,class} 指定是否为隐式引用文件生成类文件
-encoding <编码> 指定源文件使用的字符编码
-source <版本> 提供与指定版本的源兼容性
-target <版本> 生成特定 VM 版本的类文件
-version 版本信息
-help 输出标准选项的提要
-Akey[=value] 传递给注释处理程序的选项
-X 输出非标准选项的提要
-J<标志> 直接将 <标志> 传递给运行时系统
4、将.class转化为DVM识别的.dex文件
DVM是不识别.class的,所以要通过dex工具将java字节码转化成dex字节码。
dex文件在SDK文件的dx下,下面是转化一个.class文件
5、打包生成.apk文件
向apkbuilder中传入的参数为:
- 之前打包的的资源文件(gen目录下)
- 之前生成的.dex文件
- libs文件(比如jni/ndk中的so库,如果没有用到就不会传入)
通过apkbuilder产生一个没有签名的apk
6、对apk文件签名
使用jarsigner对apkbuilder产生的apk进行签名
用到的参数有:
用法:jarsigner [选项] jar 文件别名
[-keystore <url>] 密钥库位置
[-storepass <口令>] 用于密钥库完整性的口令
[-storetype <类型>] 密钥库类型
[-keypass <口令>] 专用密钥的口令(如果不同)
[-sigfile <文件>] .SF/.DSA 文件的名称
[-signedjar <文件>] 已签名的 JAR 文件的名称
[-digestalg <算法>] 摘要算法的名称
[-sigalg <算法>] 签名算法的名称
[-verify] 验证已签名的 JAR 文件
[-verbose] 签名/验证时输出详细信息
[-certs] 输出详细信息和验证时显示证书
[-tsa <url>] 时间戳机构的位置
[-tsacert <别名>] 时间戳机构的公共密钥证书
[-altsigner <类>] 替代的签名机制的类名
[-altsignerpath <路径列表>] 替代的签名机制的位置
[-internalsf] 在签名块内包含 .SF 文件
[-sectionsonly] 不计算整个清单的散列
[-protected] 密钥库已保护验证路径
[-providerName <名称>] 提供者名称
[-providerClass <类> 加密服务提供者的名称
[-providerArg <参数>]] ... 主类文件和构造函数参数
7、对签名后的.apk文件进行对齐处理
就是使用zipalign进行字节码的对齐,没有对齐是不能发布上架的。