当前位置: 首页 > 科技观察

APK是如何诞生的?

时间:2023-03-12 22:02:31 科技观察

1。APK组成分析在开始分析Android构建过程之前,我们先来看一下最终产品APK的整体组成:APK主要由五部分组成,分别是:Dex:.class文件处理后的产品,可执行文件Android系统文件Resource:资源文件,主要包括layout、drawable、a??nimator,由R.XXX.id引用Assets:资源文件,通过AssetManager加载Library:so库存放目录META-INF:APK签名相关信息1.1Apk解析工欲善其事,必先利其器。既然要分析APK,就一定要有好用的工具。①AndroidStudio内置的APK分析器通过APK分析器,我们可以完成这些操作:查看APK中文件(如DEX和Android资源文件)的绝对和相对大小了解DEX文件的组成快速查看文件中的文件APK(如ThefinalversionofAndroidManifest.xml)并排比较两个APK②ClassyShark可以作为AS自带的APK分析器的补充,帮助我们分析dex中的详细数据,查看总的APK中的方法数和每个模块的方法数分布。1.2Dex知识点的扩展我们在Android上查看APK的时候,可以看到右上角有DefinedMethods和ReferencedMethods,但是大多数人可能不知道这两者的区别,这里简单解释一下:DefinedMethods:inDex中定义的this方法;ReferencedMethods:DefinedMethods和DefinedMethods引用的方法。Android有64K的引用限制。当type_ids、method_ids或field_ids超过65536(64*1024)时,需要dex分包。为了让dex的数量尽可能少,我们需要尽可能的提高“dex信息的效率”。Dex信息的效率=DefinedMethods个数/ReferencedMethods个数2.构建源码指南当我们使用AndroidStudio构建安装包时,我们会发现实际上运行了一系列的任务,也就是说,它实际上是这些任务的合作最终构建了我们的APK。2.1源码介绍如果我们想更深入地了解Android的构建过程,就必须对相关的源码有一定的了解。那我们怎么看这些Tasks相关的源码呢?我们知道Android是用Gradle构建的,也就是说这些任务其实都是放在Gradle里面的。如果我们想在Gradle中查看源码,可以在build.gradle中设置Gradle编译。compileOnly"com.android.tools.build:gradle:3.0.1"编译完成后,在ApplicationTaskManager#createTasksForVariantScope中可以找到创建这些Task的相关代码,也就是说可以找到这些Task的真正实现逻辑。2.2BuildConfig任务详解这里我们以生成BuildConfig文件为例,梳理一下如何查看一个任务的代码逻辑。生成BuildConfig文件需要在ApplicationTaskManager中通过createBuildConfigTask创建对应的task。顺着代码的逻辑,我们发现真正实现这个逻辑的任务是:GenerateBuildConfig,它继承自BaseTask。这里有个小技巧,Task中真正的执行逻辑在@TaskAction注解的方法上,所以我们可以很快找到对应的generate()方法。可以看出生成BuildConfig的整体逻辑比较简单。其实就是读取build.gradle中的内置属性和我们自定义的属性,然后通过JavaWriter生成对应的BuildConfig文件。2.3获取所有任务对应的类名看到上面的例子,可能有人会问一个问题,我们如何判断构建中执行的任务对应的是哪个类呢?这里有一个小技巧,其实我们可以在taskGraph构建完成后,打印所有的任务名称和对应的类。比如在build.gradle中加入这段代码后,我们运行的时候,任务对应的类名也会一起打印出来。3.梳理构建过程可以看出,Android构建涉及多个工具。我们可以通过打开$ANDROID_HOME/build-tools查看相关的构建工具。4.手动构建APK最后我们通过命令行手动打包一个可执行的APK,可以让我们对APK的构建有更深入的了解。首先,您需要准备构建APK所需的文件,例如代码、资源文件和AndroidManifest。①通过aapt2compile将res资源编译成.flat二进制文件:aapt2compile-obuild/res.zip--dirres②通过aapt2link连接.flat和AndroidManifest,转换成不含dex的apk和R.java:aapt2linkbuild/res.zip-I$ANDROID_HOME/platforms/android-30/android.jar--javabuild--manifestAndroidManifest.xml-obuild/app-debug.apk③通过javac将Java文件编译成.class文件:javac-dbuild-cp$ANDROID_HOME/platforms/android-30/android.jarcom/**/**/**/*.java④通过d8将.class文件转为dex文件:d8--outputbuild/--lib$ANDROID_HOME/platforms/android-30/android.jarbuild/com/tencent/hockeyli/androidbuild/*.class⑤合并dex文件和资源文件:zip-jbuild/app-debug.apkbuild/classes.dex⑥通过apksigner对apk进行签名:apksignersign-ks~/.android/debug.keystorebuild/appdebug.apk