欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android项目构建Apk包流程

程序员文章站 2022-12-04 08:38:29
最近在学习webpack、weex等前端知识,说起weex,一直都在填坑中,目前还没爬出来了! 好了,回归到本文的主题,但是都不够细致,比较笼统的介绍有关Apk打包的过程。所以...

最近在学习webpack、weex等前端知识,说起weex,一直都在填坑中,目前还没爬出来了! 好了,回归到本文的主题,但是都不够细致,比较笼统的介绍有关Apk打包的过程。所以,本文再次详细描述下,Android项目构建Apk包流程。

一. 前言

当我们使用Android Studio开发Android时,点击运行按钮,就会自动生成一个Apk文件,至于这个Apk是如何生成的,我们并不知道。而这个Apk中包含哪些东西呢?我们还是可以知道的。怀着好奇的心态,我们先来解压一个Apk,看看他的庐山真面目。

随便找一个Apk文件,修改它的后缀名为rar或者zip(其实Apk格式的文件就是一个压缩文件)。如下图所示,

Android项目构建Apk包流程

其中app-debug.rar文件是app-debug.apk修改后缀名后得到的,而app-debug文件夹是app-debug.rar文件解压后生成的,

Android项目构建Apk包流程

上面这张截图是app-debug文件夹中的东东,可以看到大致包含5部分:

1. META-INF 文件夹,该文件夹中包含该Apk的签名信息以及该Apk中所有文件的哈希值的计算结果;

2. res文件夹,存放的是资源文件,例如动画、颜色、图片和布局等资源;下面给出一张res文件夹的中文件列表的截图,

Android项目构建Apk包流程

3. dex文件,该文件是适用于Dalvik虚拟机的字节码文件,是通过dx工具将class文件转化生成的;

4.resources.arsc,它是一个资源索引表,是由aapt根据res资源文件转化生成的二进制文件;(下面会继续补充该文件的作用);

5.AndroidManifest.xml,这个文件,我们都知道,这是Apk的清单文件,配置了各种权限以及注册Activity、service等组件。(这个文件是压缩处理过的,直接打开是乱码,需要借助其他工具)

二. 打包。

首先来看一张Google官方给出的Apk构建流程,如下图所示,

Android项目构建Apk包流程

根据上图,就能大致得出构建Apk的整个流程,

1. aapt工具将res中的资源生成R.java文件和resources.arsc文件;

2. 如果有aidl,那么aidl工具会将aidl接口转化为java类;

3. javac将所有的java类编译为class文件;

4. 如果有代码混淆,则会加入代码混淆;

5. dx.bat将所有的class文件转化为classes.dex文件;

6. ApkBuild将所有的资源(assets、so、jni)、resources.arcs以及上一步生成的dex文件,打包生成一个apk文件;

7. 对上一步生成的apk进行签名;

8. 使用Zipalign对签名后的apk进行优化。

下面详细分析下各步骤的实现细节。

2.1. 资源打包。(这一部分引用了网上一位博主的内容,详细连接见下文)

开发app时,需要代码和资源。最终生成的apk中代码转换为了dex文件,那么apk文件中的资源是否还是app开发时那些资源文件呢?或者说这些资源文件是否发生了什么变化?引用老罗一张关于资源打包过程以及查找的图:

Android项目构建Apk包流程

从上图可以看出:
1). 除了assets和res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理.xml文件会被编译为二进制的xml,所以解压apk后,无法直接打开xml文件。
2). 除了assets资源之外,其它的资源都会被赋予一个资源ID。
3). 打包工具负责编译和打包资源,编译完成之后,会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源ID常量,供在代码中索引资源。
4). 应用程序配置文件AndroidManifest.xml同样会被编译成二进制的XML文件,然后再打包到APK里面去。
5). 应用程序在运行时最终是通过AssetManager来访问资源,或通过资源ID来访问,或通过文件名来访问。

在生成的apk中,只有assets和res/raw资源被原装不动地打包进apk。其它的资源都会被编译或者处理。可以使用如下命令查看apk中的文件列表:
aapt l -v apkfile
将apk直接解压后,会发现xml都打不开,提示格式不对,因为其已经变为二进制xml了。另外PNG等图片也会进行相应的优化。还有就是多了一个resources.arsc文件。

2.2 aidl处理。

aidl,全名Android Interface Definition Language,即Android接口定义语言。是我们在编写进程间通信的时候,定义的接口。输入:aidl后缀的文件。输出:可用于进程通信的C/S端java代码,位于build/generated/source/aidl。

2.3 生成class文件。

这一步是将整个代码中的所有的java文件通过javac编译为class文件.

2.4 生成dex文件。

通过dex工具将项目中所有的class文件(也包含第三方库中的)生成dex文件。

2.5 生成Apk文件。

通过apkbuilder工具 将所有的资源(res和assets)、resources.arsc和dex文件(可能是多个)打包生成Apk文件。

2.6 Apk签名。

上一步生成的Apk文件是没有签名的,也就是说,是无法安装到Android设备中的。android的应用程序需要签名才能在android设备上安装,签名apk文件有两种情况:一种是在调试程序时进行签名,使用eclipse开发android程序时,在编译调试程序时会自己使用一个debug.keystore对apk进行签名;另一种是打包发布时对程序进行签名,这种情况下需要提供一个符合android开发文档中要求的签名文件。签名的方法也分两种:一种是使用jdk中提供的jarsigner工具签名;另一种是使用android源码中提供的signapk工具,它的代码位于android系统源码build\tools\signapk目录下。

2.7 Apk优化。

这一步需要使用的工具为zipalign,它位于android-sdk\tools目录,源码位于android系统源码的build\tools\zipalign目录,它的主要工作是将spk包进行对齐处理,使spk包中的所有资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时速度会更快,验证apk文件是否对齐过的工作由ZipAlign.cpp文件的verify()函数完成,处理对齐的工作则由process()函数完成。

以上就是构建APk的全过程。相信看到这里,小伙伴们对Apk的构建过程更清晰明了了!

三. 补充。

3.1 aapt。

aapt----Android Asset Packaging Tool,即Android资源打包工具,位于SDK的build-tools目录下。该工具的作用是将Android中的res资源生成R.java文件以及将资源文件生成一个二进制文件(resources.arsc)。在打包Apk时,需要使用到该工具。

其中,R.java文件,相信开发Android的小伙伴们都知道,每当我们创建一个资源例如一个字符串,aapt就会在R.java文件中自动生成一个常量(ID),我们在使用某资源时,需要引用该资源对应的R.java文件的资源ID。下面是R.java文件的部分代码截图,

Android项目构建Apk包流程

resources.arsc,是aapt工具编译资源时生成的重要文件。App资源能根据配置的变化,索引到相应的资源都要依赖它。例如Android设备语言,屏幕设备尺寸不同时,app通过同样的ID但却能找到不同的资源进行显示。因为resources.arsc是二进制文件,所以解压后,直接打开是乱码。

总结下:

R.java文件,定义了各个资源ID常量,在使用时需要使用该ID;resources.arsc,保存的是一个资源索引表。

3.2Dalvik虚拟机。

Dalvik是Google公司自己设计用于Android平台的Java虚拟机,它是Android平台的重要组成部分,支持dex格式(Dalvik Executable)的Java应用程序的运行。dex格式是专门为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。Google对其进行了特定的优化,使得Dalvik具有高效、简洁、节省资源的特点。从Android系统架构图知,Dalvik虚拟机运行在Android的运行时库层。

当你的应用安装在手机上后,应用程序的代码将会以字节码保存,每次冷启动一个应用的时候,Dalvik虚拟机将字节码转换为机器码,然后交给硬件来执行;每次冷启动的时候,Dalvik虚拟机就要重复将字节码转换为机器码的动作,而在这个阶段,我们只能等待,静静的看着应用启动,虽然每次都耗时较长,但是不会占用过多的内存。因此在Android4.4发布时,谷歌推出了新的Android虚拟机ART虚拟机,ART-Android Runtime,即Android运行时。ART虚拟机也是将字节码转换为机器码,但是它和Dalvik虚拟机的工作模式不一样,在ART模式下,当你在安装应用的时候,它就将字节码转换为机器码,并且保存起来,当在启动一个应用的时候,就直接运行这个机器码,因此,启动速度就比较快。

Java虚拟机-JVM和Dalvik虚拟机的区别。

1).Java虚拟机运行的是Java字节码(保存在class文件中),Dalvik运行的是Dalvik字节码(由Java字节码转化而来,打包到DEX文件中)。

2).Dalvik可执行文件更小。
由于Android SDK中的dx文件对常量池进行了压缩,使得相同字符串、常量在DEX文件中只出现一次。

3).Java虚拟机与Daivik虚拟机架构不同 。
Java虚拟机基于栈结构,资源开销大,Dalvik虚拟机基于寄存器结构,数据由寄存器直接传递,这样的方式比基于栈结构的方式快得多。