Android APK 打包过程 MD

Markdown版本笔记我的GitHub首页我的博客我的微信我的邮箱
MyAndroidBlogsbaiqiantaobaiqiantaobqt20094baiqiantao@sina.com

Android APK 打包流程 MD


目录

目录
APK 的打包流程
整体流程
资源的编译和打包
资源ID
资源索引
概况
具体打包过程
aapt阶段
aidl阶段
Java Compiler阶段
dex阶段
apkbuilder阶段
Jarsigner阶段
zipalign阶段

APK 的打包流程

参考

Android的包文件APK分为两个部分:代码和资源,所以打包方面也分为资源打包和代码打包两个方面,这篇文章就来分析资源和代码的编译打包原理。

Android打包流程详图:

apk_package_flow_detail.png

整体流程

APK整体的的打包流程如下图所示:

apk_package_flow.png

具体说来:

  • 通过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_file.png

可以看到resources.arsc里存放了各类资源的索引参数和配置信息。

resources.arsc的文件格式如下所示:
resources_arsc_structure.png

注:整个文件都是有一系列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.dexresources.arscres文件夹(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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387385.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可用于 主成分分析、R型因子分析、简单相应分析 的R语言函数总结

一、主成分分析 主成分分析是多元统计分析的一种常用的降维方法,它以尽量少的信息损失,最大程度将变量个数减少,且彼此间互不相关。提取出来的新变量成为主成分,主成分是原始变量的线性组合。 1.1 KMO检验和Bartlett球形检验 在…

持续集成之Jenkins安装部署

安装JDKJenkins是Java编写的,所以需要先安装JDK,这里采用yum安装,如果对版本有需求,可以直接在Oracle官网下载JDK。 [rootlinux-node1 ~]# yum install -y java-1.8.0 安装Jekins [rootlinux-node1 ~]# cd /etc/yum.repos.d/ […

jenkins svn tomcat ant自动部署

Jenkins Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1、持续的软件版本发布/测试项目。 2、监控外部调用执行的工作。 跟其他持续集成相比,它的主要优点有: 开源,即免…

553 mail from must equal authorized user解决方法

在配置发送邮件通知,验证其正确性时,出现"553 mail from must equal authorized user"提示的错误; 原因在于没有在"系统管理(Manage Jenkins)"的"系统设置(Configure system&…

[Apple开发者帐户帮助]八、管理档案(2)创建临时配置文件(iOS,tvOS,watchOS)...

创建临时配置文件以在设备上运行您的应用程序而无需Xcode。在开始之前,您需要一个App ID,一个分发证书和多个注册设备。 有关完整的临时配置文件工作流程,请转到Xcode帮助中的分发到已注册设备(iOS,tvOS,wa…

解决做好一个机器学习项目的3个问题

机器学习是目前人工智能最令人激动的研究方向之一。我们可能更关注机器学习算法的实现细节,沉浸于机器学习所需要的数学功底,但对于机器学习从业者来说,如何更好更快速的实现一个机器学习项目更值得关注。 正如吴恩达在《机器学习》这门课中所…

[币严区块链]以太坊(ETH)Dapp开发入门教程之宠物商店领养游戏

阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么 除此之外,你最好还了解一些HTML及JavaScript知识。 本文通过实例教大家来开发去中心化应用,应用效果如图: 项目背景 Pete有一个…

怎么通俗易懂地解释贝叶斯网络和它的应用?

作者:小杰链接:https://www.zhihu.com/question/28006799/answer/38996563来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。英语原文:http://www.norsys.com/tutorials/netica/secA/tut…

SVM分类算法的基本理论问题

1.引言   随着网络技术的飞速发展和普及,进入了信息大爆炸的时代。信息无处不在,给我们的学习生活带来了诸多便捷,由于堪称海量的信息量,我们从中获取有用的信息变得困难,解决这一难题就是要对这些大量的信息进行分…

决策树案例理解

小王是一家著名高尔夫俱乐部的经理。但是他被雇员数量问题搞得心情十分不好。某些天好像所有人都來玩高尔夫,以至于所有员工都忙的团团转还是应付不过来,而有些天不知道什么原因却一个人也不来,俱乐部为雇员数量浪费了不少资金。 小王的目的是…

剑指offer-反转链表

反转链表 一、题目描述 输入一个链表,反转链表后,输出新链表的表头。 (看过答案和测试之后,题目隐藏条件是要求链表是不带头结点的) 二、题目思路 就是用三个指针,head、pre、next,head之前都是…

从决策树学习谈到贝叶斯分类算法、EM、HMM

引言 最近在面试中(点击查看:我的个人简历,求职意向,择司标准),除了基础 & 算法 & 项目之外,经常被问到或被要求介绍和描述下自己所知道的几种分类或聚类算法(当然,这完全不代表你将来的面试中会遇…

计算机网络与协议

计算机网络: TCP/IP中只要是能够设定IP地址的计算机就成为主机 网络按其规模可分为: WAN(广域网):覆盖多个远距离区域的远程网络 MAN(城域网):比广域网小一级,连接整个城…

对线性回归、逻辑回归、各种回归的概念学习

回归问题的条件/前提: 1) 收集的数据 2) 假设的模型,即一个函数,这个函数里含有未知的参数,通过学习,可以估计出参数。然后利用这个模型去预测/分类新的数据。 1. 线性回归 假设 特征 和 结果 都…

XGBoost入门及实战

kaggle比赛必备算法XGBoost入门及实战 xgboost一直在kaggle竞赛江湖里被传为神器,它在对结构化数据的应用占据主导地位,是目前开源的最快最好的工具包,与常见的工具包算法相比速度提高了10倍以上! XGBoost is an implementation o…

几个常用算法的适应场景及其优缺点

机器学习算法太多了,分类、回归、聚类、推荐、图像识别领域等等,要想找到一个合适算法真的不容易,所以在实际应用中,我们一般都是采用启发式学习方式来实验。通常最开始我们都会选择大家普遍认同的算法,诸如SVM&#x…

EM算法 案例量则

例子一:理论: 简版:猜(E-step),反思(M-step),重复; 啰嗦版: 你知道一些东西(观察的到的数据), 你不知道一些东西(观察不到…

C#编写TensorFlow人工智能应用 TensorFlowSharp

TensorFlowSharp入门使用C#编写TensorFlow人工智能应用学习。 TensorFlow简单介绍 TensorFlow 是谷歌的第二代机器学习系统,按照谷歌所说,在某些基准测试中,TensorFlow的表现比第一代的DistBelief快了2倍。 TensorFlow 内建深度学习的扩展支持…

马尔可夫链 (Markov Chain)是什么鬼

作者:红猴子链接:https://www.zhihu.com/question/26665048/answer/157852228来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。马尔可夫链 (Markov Chain)是什么鬼 它是随机…

主题模型-LDA浅析

个性化推荐、社交网络、广告预测等各个领域的workshop上都提到LDA模型,感觉这个模型的应用挺广泛的,会后抽时间了解了一下LDA,做一下总结: (一)LDA作用 传统判断两个文档相似性的方法是通过查看两个文档共…