Android APK 打包过程 MD
Markdown版本笔记 | 我的GitHub首页 | 我的博客 | 我的微信 | 我的邮箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
Android APK 打包流程 MD
目录
APK 的打包流程
整体流程
资源的编译和打包
资源ID
资源索引
概况
具体打包过程
aapt阶段
aidl阶段
Java Compiler阶段
dex阶段
apkbuilder阶段
Jarsigner阶段
zipalign阶段
APK 的打包流程
参考
Android的包文件APK分为两个部分:代码和资源
,所以打包方面也分为资源打包和代码打包两个方面,这篇文章就来分析资源和代码的编译打包原理。
Android打包流程详图:
整体流程
APK整体的的打包流程如下图所示:
具体说来:
- 通过
AAPT
工具进行资源文件(包括AndroidManifest.xml、布局文件、各种xml资源等)的打包,生成R.java文件。 - 通过
AIDL
工具处理AIDL文件,生成相应的Java文件。 - 通过
Javac
工具编译项目源码,生成Class文件。 - 通过
DX
工具将所有的Class文件转换成DEX文件,该过程主要完成Java字节码转换成Dalvik字节码,压缩常量池以及清除冗余信息等工作。 - 通过
ApkBuilder
工具将资源文件、DEX文件打包生成APK文件。 - 利用
KeyStore
对生成的APK文件进行签名。 - 如果是正式版的APK,还会利用
ZipAlign
工具进行对齐处理,对齐的过程就是将APK文件中所有的资源文件举例文件的起始距离都偏移4字节的整数倍,这样通过内存映射访问APK文件的速度会更快。
上述流程都是Android Studio在编译时调用各种编译命令
自动完成的,具体说来,如下所示:
1、创建Android工程。
android create project \
-n packageTest2 \
-a MainActivity \
-k com.package.test2 \
-t android-23 \
-p ./PackageTest2
2、编译R文件
aapt package \
-f \
-J ./gen \
-M ./AndroidManifest.xml \
-S ./res/ \
-I /Users/RadAsm/Library/AndroidSDK/sdk/platforms/android-23/android.jar
3、编译源代码文件
javac -source 1.6 \
-target 1.6 \
-cp /Users/RadAsm/Library/AndroidSDK/sdk/platforms/android-23/android.jar \
./src/com/packtest/test1/MainActivity.java ./src/com/packtest/test1/R.java \
-d ./gen/classes
4、编译DEX文件
dx --dex \
--verbose \
--output ./gen/dex/packtest1.dex
./gen/classes/
5、生成APK文件
aapt package
-f \
-J ./gen \
-M ./AndroidManifest.xml \
-S ./res/ \
-I /Users/RadAsm/Library/AndroidSDK/sdk/platforms/android-23/android.jar \
-F ./output/res.apk
6、APK文件对齐
zipalign -v -p 4 packagetest_unsigned.apk packagetest_aligned_unsigned.apk
7、APK签名
apksigner sign --ks my-release-key.jks my-app.apk
以上便是APK打包的整个流程,我们再来总结一下:
- 除了assets和res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理;
- 除了assets资源之外,其它的资源都会被赋予一个资源ID;
- 打包工具负责编译和打包资源,编译完成之后,会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源ID常量。
- 应用程序配置文件AndroidManifest.xml同样会被编译成二进制的XML文件,然后再打包到APK里面去。
- 应用程序在运行时通过AssetManager来访问资源,或通过资源ID来访问,或通过文件名来访问。
理解了整体的流程,我们再来看看具体的细节。
资源的编译和打包
在分析资源的编译和打包之前,我们先来了解一下Android程序包里有哪些资源。
我们知道Android应用程序的设计也是代码与资源相分离
的,Android的资源文件可以分为两大类:
assets:assets资源放在主工程assets目录下,它里面保存一些原始的文件,可以以任何方式来进行组织,这些文件最终会原封不动的被打包进APK文件中。
获取asset资源也十分简单,如下所示:
InputStream is = getAssets.open("fileName");
res:res资源放在主工程的res目录下,这类资源一般都会在编译阶段生成一个资源ID供我们使用。
res资源包含了我们开发中使用的各种资源,具体说来:
- animator
- anim
- color
- drawable
- layout
- menu
- raw
- values
- xml
这些资源的含义大家应该都很熟悉,这里就不再赘述。
上述9种类型的资源文件,除了raw
类型资源,以及Bitmap文件的drawable
类型资源之外,其它的资源文件均为文本格式的XML
文件,它们在打包的过程中,会被编译成二进制格式的XML文件。这些二进制格式的XML文件分别有一个字符串资源池,用来保存文件中引用到的每一个字符串,包括XML元素标签、属性名称、属性值,以及其它的一切文本值所使用到的字符串。这样原来在文本格式的XML文件中的每一个放置字符串的地方在二进制格式的XML文件中都被替换成一个索引到字符串资源池的整数值,这写整数值统一保存在
R.java
类中,R.java会和其他源文件一起编译到APK中去。
前面我们提到xml编写的Android资源文件都会编译成二进制格式的xml文件,资源的打包都是由AAPT
工具来完成的,资源打包主要有以下流程:
- 解析
AndroidManifest.xml
,获得应用程序的包名称,创建资源表。 - 添加被引用资源包,被添加的资源会以一种资源ID的方式定义在
R.java
中。 - 资源打包工具创建一个
AaptAssets
对象,收集当前需要编译的资源文件,收集到的资源保存在AaptAssets对象对象中。 - 将上一步AaptAssets对象保存的资源,添加到资源表
ResourceTable
中去,用于最终生成资源描述文件resources.arsc
。 - 编译
values
类资源,这类资源包括数组、颜色、尺寸、字符串等值。 - 给bag、style、array这类资源分配资源ID。
- 编译xml资源文件,编译的流程分为四步:① 解析xml文件 ② 赋予属性名称资源ID ③ 解析属性值 ④ 将xml文件从文本格式转换为二进制格式。
- 生成资源索引表
resources.arsc
。
资源ID
每个Android项目里都有有一个R.java文件,如下所示:
public final class R {//...public static final class anim {public static final int abc_fade_in=0x7f010000;}public static final class attr {public static final int actionBarDivider=0x7f020000;}public static final class string {public static final int actionBarDivider=0x7f020000;}//...
}
每个资源项后的整数就是资源ID,资源ID是一个4字节的无符整数,如下所示:
- 最高字节是Package ID表示命名空间,标明资源的来源,Android系统自己定义了两个Package ID,系统资源命名空间:0x01 和 应用资源命名空间:0x7f。
- 次字节是Type ID,表示资源的类型,例如:anim、color、string等。
- 最低两个字节是Entry ID,表示资源在其所属资源类型中所出现的次序。
资源索引
上面提到,最终生成的是资源索引表resources.arsc
,Android正是利用这个索引表根据资源ID进行资源的查找,为不同语言、不同地区、不同设备提供相对应的最佳资源。查找是通过Resources和AssetManger来完成的,这个我们下面会讲。
resources.arsc 是一个编译后的二进制文件,在Android Stduio里打开以后是这样的,如下所示:
可以看到resources.arsc里存放了各类资源的索引参数和配置信息。
resources.arsc的文件格式如下所示:
注:整个文件都是有一系列chuck(块)构成的,chuck是整个文件的划分单位,每个模块都是一个chuck,chuck最前面是一个ResChunk_header的结构体,用来描述整个chunk的信息,更多关于索引表格式的细节,可以查阅源码:
? ResourceTypes.h
resources.arsc 索引表从上至下文件格式依次为:
- 文件头:数据结构用ResTable_header来描述,用来描述整个文件的信息,包括文件头大小,文件大小,资源包Package的数量等信息。
- 全局字符串池:存放所有的字符串,所以资源复用这些字符串,字符串里存放的是资源文件的路径名和资源值等信息。全局字符串池分为资源类型(type)字符串池和
- 资源包:会有多个(例如:系统资源包、应用资源包)。
资源包也被划分为以下几个部分:
- 包头:描述资源包相关信息。
- 资源类型字符串池:存放资源的类型。
- 资源名称字符串池:存放资源的名称。
- 配置列表:存放语音、位置等手机配置信息,用来作为查找资源的标准。
从这里可以看到resources.arsc索引表存在很多常量池,常量池的使用目的也很明显,就是提供资源的复用率,减少resources.arsc索引表的体积,提高索引效率。
概况
参考
Android APK是如何来的呢?
怀着这个问题去查资料,发现了下边这张图。
解压一个普通的apk文件后,解压出来的文件包括:
- classes.dex:.dex文件
- resources.arsc:resources resources文件
- AndroidManifest.xml:AndroidManifest.xml文件
- res:uncompiled resources
- META-INF:签名文件夹
MANIFEST.MF
文件:版本号以及每一个文件的哈希值(BASE64),包括资源文件。这个是对每个文件的整体进行SHA1(hash)。CERT.SF
:这个是对每个文件的头3行进行SHA1 hash。CERT.RSA
:这个文件保存了签名和公钥证书。
具体打包过程
aapt阶段
使用aapt来打包res资源文件,生成R.java、resources.arsc和res文件(二进制 & 非二进制如res/raw和pic保持原样)
- res目录,有9种子目录
- R.java文件。里面拥有很多个静态内部类,比如layout,string等。每当有这种资源添加时,就在R.java文件中添加一条静态内部类里的静态常量类成员,且所有成员都是int类型。
- resources.arsc文件。这个文件记录了所有的应用程序资源目录的信息,包括每一个资源名称、类型、值、ID以及所配置的维度信息。我们可以将这个文件想象成是一个资源索引表,这个资源索引表在给定资源ID和设备配置信息的情况下,能够在应用程序的资源目录中快速地找到最匹配的资源。
aidl阶段
AIDL,Android接口定义语言,Android提供的IPC的一种独特实现。
这个阶段处理.aidl文件,生成对应的Java接口文件。
Java Compiler阶段
通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件。
dex阶段
通过dex命令,将.class文件和第三方库中的.class文件处理生成classes.dex。
apkbuilder阶段
将classes.dex
、resources.arsc
、res
文件夹(res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理)、Other Resources(assets
文件夹)、AndroidManifest.xml
打包成apk文件。
Jarsigner阶段
对apk进行签名,可以进行Debug和Release 签名。
zipalign阶段
release mode 下使用 aipalign 进行align,即对签名后的apk进行对齐处理。
Zipalign是一个android平台上整理APK文件的工具,它对apk中未压缩的数据进行4字节对齐,对齐后就可以使用mmap
函数读取文件,可以像读取内存一样对普通文件进行操作。如果没有4字节对齐,就必须显式的读取,这样比较缓慢并且会耗费额外的内存。
在 Android SDK 中包含一个名为 zipalign
的工具,它能够对打包后的 app 进行优化。 其位于 SDK 的 \build-tools\23.0.2\zipalign.exe
目录下
2019-2-18
转载于:https://www.cnblogs.com/baiqiantao/p/10398653.html
Android APK 打包过程 MD相关推荐
- android Apk打包过程概述_android是如何打包apk的
最近看了老罗分析android资源管理和apk打包流程的博客,参考其他一些资料,做了一下整理,脱离繁琐的打包细节和数据结构,从整体上概述了apk打包的整个流程. 流程概述: 1.打包资源文件,生成R. ...
- rn android mac打包,React-Native之MAC平台Android apk打包流程
MAC :Android打包流程7步走:(详情参照英文官网) 1).使用keytool首先生成keystore(包含storeFile file.storePassword .keyAlias .ke ...
- Android Apk 打包
这里重点介绍的是利用jdk中的两个工具对Android的应用程序包apk文件进行签名. 主要分为3个步骤:第一步生成签名文件,第二步对apk文件签名,第三步验证签名. 以下是执行命令,注意此段命令所生 ...
- Android APK打包流程
目录 一.概述 二.打包流程 1.打包资源文件,生成R.java文件 2.处理aidl文件,生成相应的Java文件 3.编译项目源代码,生成class文件 4.转换所有的class文件,生成class ...
- 【SealDEV 倾情奉献】Android APK 安装过程详解
开发 Android 应用后,一般都会安装到手机上去运行,了解应用是如何安装到手机上的,可以更好的理解应用的本质,理解应用是如何运行的,在自己开发的应用遇到一些问题时,会从更深层次去分析,快速定位找到 ...
- Android apk打包流程★
1.apk打包 Android开发中打包apk主要有两种方式: ①使用Android Studio集成直接生成apk: ②使用ant工具在命令行方式下打包apk. 不管哪种方式,打包apk的本质过程都 ...
- Meteor android apk打包两种方式
Meteor apk 打包 首先进入你的所要打包的meteor工程 一.生成apk meteor build ~/build-output-directory --server=guoyoujinl ...
- Android apk打包命名规则
摘要:前言在日常的开发过程中,许多刚入行的开发者在apk打包命名.应用迭代版本的档案留存管理上都比较混乱--产生这些问题的原因无外乎以下两种:一是之前没有相关的操作经验.头尾不能兼顾;一是公司没有制定 ...
- Android apk安装过程
Android安装包.APK是类似Symbian Sis或Sisx的文件格式.通过将APK文件直接传到Android模拟器或Android手机中执行即可安装. Android应用安装有如下四种方式 1 ...
最新文章
- Python3 与 C# 面向对象之~封装
- python难学嘛-终于明白0基础学python难吗
- C#+WebSocket+WebRTC多人语音视频系统
- 计算机服务业纳税,2018年全国软件和信息技术服务业增值税、消费税、营业税等各税收收入情况(附各地区)...
- project 模板_施工进度计划表不会做?18个横道图自动生成模板,直接在线编辑...
- leetcode_median of two sorted arrays
- k8s资源清单:常用字段说明及pod增删查示例
- 关于线程池,那些你还不知道的事
- Java多线程之线程池7大参数、底层工作原理、拒绝策略详解
- 个人或者企业怎么进行app开发?开发一款APP应用大概须要多少钱?
- 微软:Win11很受欢迎、正式版将于秋季如期发布
- java个人中心修改界面怎么整_怎么对个人中心页面访问进行控制
- 生成验证码封装(新版)
- 对象锁 区别 类锁
- GIS+BIM专题二:SuperMap对接DGN数据流程
- 外卖程序_淘宝客系统_淘客小程序-淘客系统,外卖返利程序,外卖程序,返利程序
- wildfly ejb开发环境搭建(一):wildfly安装及数据源配置
- 非因解读 | Multiplex immunofluorescnece-多重免疫荧光结合单细胞蛋白组技术探索肿瘤微环境
- Excel数据分析和建模
- Flixel横板游戏制作教程(十一)—JetPack(飞行背包)
热门文章
- centos7服务器文件同步,centos7文件实时同步工具lsyncd
- linux 认证考试 题库,Linux认证考试题库及答案
- java scala 获取类_在Scala 2.10中获取java.lang.Class [T]的Scala类型
- woocommerce 分类到菜单_Woocommerce商店显示分类
- cpri带宽不足的解决方法_白皮书:FPGA赋能下一代通信和网络解决方案(第四部分)...
- c++ boost多线程学习(一)
- Linux内核逻辑结构
- 【数据结构基础笔记】【树】
- 在给定约束下可以使用a,b和c形成的字符串数
- 合页损失,铰链损失_多点铰链损失功能 使用Python的线性代数