找回密码
 会员注册
查看: 27|回复: 0

一款APK是怎么诞生的?

[复制链接]

2

主题

0

回帖

7

积分

新手上路

积分
7
发表于 2024-9-20 19:44:05 | 显示全部楼层 |阅读模式
作者:hockeyli,腾讯PCG客户端开发工程师一、APK组成解析在开始解析Android构建流程之前,我们先来看下构建的最终产物APK的整体组成:APK主要由五个部分组成,分别是:Dex:.class文件处理后的产物,Android系统的可执行文件Resource:资源文件,主要包括layout、drawable、animator,通过R.XXX.id引用Assets:资源文件,通过AssetManager进行加载Library:so库存放目录META-INF:APK签名有关的信息1.1Apk分析工具工欲善其事,必先利其器,既然想分析APK必然少不了好用的工具。①AndroidStudio自带的APK分析器通过APK分析器,我们可以完成这些操作:查看APK中文件(如DEX和Android资源文件)的绝对大小和相对大小了解DEX文件的组成快速查看APK中文件(如AndroidManifest.xml)的最终版本对两个APK进行并排比较②ClassyShark 可以做为AS自带APK分析器的补充,帮我们分析dex中的详细数据,以及查看APK中的总方法数以及各个模块的方法数分布。1.2Dex知识点拓展当我们在Android查看一个APK的时候,可以看到右上角有DefinedMethods和ReferencedMethods,但大多数人可能不知道这两者的区别,这里简单说明下:DefinedMethods:在这个Dex中定义的方法;ReferencedMethods:DefinedMethods以及DefinedMethods引用到的方法。Android有64K引用限制,当type_ids、method_ids或者field_ids超过65536(64*1024)的时候,需要进行dex分包,为了Dex的数量尽可能少,我们需要尽量实现「Dex信息有效率」的提升。Dex 信息有效率 = Defined Methods 数量 / Referenced Methods 数量二、构建源码导读当我们用AndroidStudio进行安装包构建的时候,会发现其实是运行了一连串的Task,也就是说其实是这些task的配合,最终构建出我们的APK的。2.1源码引入如果我们想更了解Android的构建流程,对于相关的源码肯定是要有所了解的。那我们如何看到这些Task相关的源码呢,我们知道Android是用Gradle进行构建的,也就意味着这些task其实都是放在Gradle中,我们想看Gradle中源码的话,可以在build.gradle将Gradle进行编译。compileOnly "com.android.tools.build:gradle:3.0.1"编译完之后,可以在ApplicationTaskManager#createTasksForVariantScope中找到创建这些Task相关的代码,也就意味着顺藤摸瓜找到这些Task的真正实现逻辑。2.2BuildConfigTask详解这里以BuildConfig文件的生成为例,来梳理下如何查看某个task的代码逻辑。生成BuildConfig文件,是通过ApplicationTaskManager中通过createBuildConfigTask来创建对应的task。顺着代码逻辑,我们找到最终真正实现这个逻辑的是:GenerateBuildConfig这个task,GenerateBuildConfig是继承自BaseTask,这里有个小技巧是,Task中真正的执行逻辑都是在带着@TaskAction注解的方法上的,所以我们能很快找到对应的generate()方法。可以看到生成BuildConfig整体的逻辑还是比较简单的,其实就是将build.gradle中自带的属性以及我们自定义的属性进行读取,然后通过JavaWriter生成对应的BuildConfig文件。2.3获取所有task对应的类名看到上面的例子,可能有些人会抛出一个疑问就是那我们怎么确定构建中执行的task具体对应哪个类呢,这里提供一个小技巧,其实我们可以在taskGraph构建完成之后,将所有taskname以及对应的class进行打印。例如在build.gradle中加入这个代码之后,我们在运行的时候,就会把task所对应的类名也都一起打印出来。三、构建流程梳理可以看到Android构建中会涉及到多个工具,我们可以通过open$ANDROID_HOME/build-tools来查看相关的构建工具。四、手动构建APK最后我们通过命令行来手动打包一个可执行的APK,能让我们对APK构建的理解更加深入。首先需要准备下代码、资源文件、AndroidManifest这些构建APK的必要文件。①通过aapt2compile将res资源编译成.flat的二进制文件:aapt2 compile -o build/res.zip --dir res②通过aapt2link将.flat和AndroidManifest进行连接,转化成不包含dex的apk和R.java:aapt2 link build/res.zip -I $ANDROID_HOME/platforms/android-30/android.jar --java build --manifest AndroidManifest.xml -o build/app-debug.apk③通过javac将Java文件编译成.class文件:javac -d build -cp $ANDROID_HOME/platforms/android-30/android.jar com/**/**/**/*.java④通过d8将.class文件转化成dex文件:d8 --output build/ --lib $ANDROID_HOME/platforms/android-30/android.jar build/com/tencent/hockeyli/androidbuild/*.class⑤合并dex⽂件和资源⽂件:zip -j build/app-debug.apk build/classes.dex⑥对apk通过apksigner进行签名:apksigner sign -ks ~/.android/debug.keystore build/appdebug.apk
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 23:59 , Processed in 0.850900 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表