重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
apk 是Android Package的简写, 在平时的开发过程中,通过点击 Run app 按钮 或者 在命令行中输入
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:国际域名空间、网络空间、营销软件、网站建设、肥西网站维护、网站推广。
这样Android Studio就会启动构建流程,最终输出一个我们想要的APK。
直达官网介绍
对于小白来说,上面一张图已经可以解释apk的构建过程了,不过对于Andoid开发者而言还需要了解一些更详细的构建过程。
详细的对应步骤 和 使用工具如下:
资源文件(res文件夹下的文件)通过 AAPT(Android Asset Packaging Tool)打包生成R.java类(资源索引表)、.arsc资源文件 和res文件。
resources.arsc 是一个App的资源索引表,通过R.java 文件 和 resources.arsc 可以定位到资源的内存地址,resources.arsc文件的作用是通过一样的ID,根据不同的配置索引到最佳的资源显示在UI中。
AIDL (Android Interface Definition Language), 是Android接口定义语言,是Android提供的IPC (Inter Process Communication,进程间通信)的一种独特实现。
如果有aidl文件,这个阶段会生成对应的Java接口文件。
R.java文件、工程源码文件、aidl.java文件, 在这一步通过javac生成.class文件。
源码.class文件和第三方jar或者library通过dx工具打包成dex文件
Android系统的Dalvik虚拟机的可执行文件为DEX格式,所以这里会将上一步中生成的.class文件 和 引用的第三方jar等过程中的.class 一起通过dx工具打包成dex文件
apkbuilder工具会将所有没有编译的资源、.arsc资源、.dex文件打包到一个完成apk文件中
tips:
apksigner工具会对未签名的apk验证签名。得到一个签名后的apk(signed.apk)
apksigner 是google 退出的V2签名方式
Jarsigner 是之前一直使用的V1签名方式
可以通过在命令行中输入apksigner --help来获取详情信息,如果没有特殊需求,使用下面命令即可完成签名
release mode 下使用 aipalign进行align,即对签名后的apk进行对齐处理
所谓对齐,主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用主要是为了减少运行时内存的使用。
zipalign是一个android平台上整理APK文件的工具,它对apk中未压缩的数据进行4字节对齐,对齐后就可以使用mmap函数读取文件,可以像读取内存一样对普通文件进行操作。如果没有4字节对齐,就必须显式的读取,这样比较缓慢并且会耗费额外的内存。
参考文章:
Android-Studio配置构建
浅谈Android打包流程
apk打包流程
END!
下图的是官网对于Android编译打包流程的介绍。
官方的介绍非常笼统,简而言之,其大致流程就是:
编译--DEX--打包--签名和对齐
(好像什么都没Get到,有一种意犹未尽的感觉……)
来一张外国大神的图片(注:这张图少了签名的步骤)
用文字解释一下上图的流程:
首先,我们整理一下编译的输入部分是什么(图中黄色部分):
接下来的步骤:
好了,编译打包的详细流程说完了,接下来我们看看是否能回答开篇的那些问题。
答:aapt工具对于每个资源文件生成了唯一的ID,这些ID保存在R.java文件中。如下是R.java文件的内容:
资源ID是一个4字节的无符号整数,在R.java文件中用16进制表示。其中,最高的1字节表示Package ID,次高1个字节表示Type ID,最低2字节表示Entry ID。
只有一个ID如何能引用到实际资源呢?实际上aapt工具还生成了一个文件resources.arsc,相当于一个资源索引表,或者你理解成一个map也行,map的key是资源ID,value是资源在apk文件中的路径。resources.arsc里面还有其他信息,这个就不多说了。
通过R.java文件和resources.arsc配合,就能引用到实际的资源文件。
答:第7步已经阐述了对齐所做的工作,为什么要进行对齐,这是为了加快资源的访问速度。如果每个资源的开始位置都是上一个资源之后的 4*n字节,那么访问下一个资源就不用遍历,直接跳到4*n字节处判断是不是一个新的资源即可。
如果举例子,那么对齐有点类似于资源数组化,数组的访问速度当然比链表快。
答:xml里面都是各种字符,不利于快速遍历。编译成二进制文件,用数字替换各种符号,一方面能快速访问,另一方面也能减少大小。
android源码目录下的build/envsetup.sh文件,描述编译的命令
- m: Makes from the top of the tree.
- mm: Builds all of the modules in the current directory.
- mmm: Builds all of the modules in the supplied directories.
要想使用这些命令,首先需要设置android脚本编译环境,在源码根目录执行 source build/envsetup.sh
m:编译所有的模块
mm:编译当前目录下的模块,当前目录下要有Android.mk文件
mmm:编译指定路径下的模块,指定路径下要有Android.mk文件
下面举个例子说明,假设我要编译android下的\framework\av\cmds\screenrecord模块,
当前目录为源码根目录,方法如下:
1、source build/envsetup.sh
2、mmm framework/av/cmds/screenrecord
或者 :
1、source build/envsetup.sh
2、cd framework/av/cmds/screenrecord
3、mm
Android 系统提供了三种指令用于编译,他们分别为make、mmm、mm,这三个指令编译的优缺点如下:
例如:make MediaProvider z这种模式对应于单个模块的编译。它的优点是:会把该模块依赖的其他模块一起跟着编译。例如:make libmedia 就会把libmedia依赖库全部编译好。当然缺点也会很明显,那就是它会搜索整个源码来定位MediaProvider 模块所使用的Android.mk文件。并且还要判断该模块依赖的其他模块是否有修改。所以编译时间比较长。
注意:一般的编译方式都会采用增量编译,即只编译发生变化的目标文件,但有时则需要重新编译所有目标文件,那么就可以使用make 命令行的-B选项。例如:mm -B 模块名,或者mm -B、mmm -B。在mm 和 mmm内部也是调用make命令的,而make的-B选项将强制编译所有的目标文件。
您的开发编译机必须达到或超出以下硬件要求:
如果是 Gingerbread (2.3.x) 及更高版本(包括 master 分支),需要使用 64 位环境。如果是较低的版本,则可以在 32 位系统中进行编译。
如果是校验代码,至少需要 100GB 可用磁盘空间;如果要进行编译,则还需要 150GB。如果要进行多次编译或使用 ccache,则需要更多空间。
如果您在虚拟机中运行 Linux,则至少需要 16GB 的 RAM/交换空间(swap)。
在编译Android系统时,需要先执行2条命令,来设置必要的环境变量。
接下来就可以执行make系列命令,来完成不同的需要。
make clean 用来清除编译历史,开始一个全新的编译。
make -j 或 make -j8 启动编译过程。 -j 后面的数字代表要使用的cpu thread的数目。
在完成了全编译后,才能执行生成OTA升级包的操作。
注意事项: