参考
https://developer.android.com/studio/build/apk-analyzer
https://medium.com/androiddevelopers/making-the-most-of-the-apk-analyzer-c066cb871ea2
https://www.cnblogs.com/yuezhusust/p/6905065.html
Android Studio包含了APK Analyzer,可在构建过程完成后立即深入了解APK的组成,使用APK Analyzer不仅能够减少你花在debug上的时间,而且还能减少你的APK大小。
使用APK Analyzer,你可以完成以下操作:
- 查看APK中文件的绝对大小和相对大小。(译注:相对大小指的是该文件占整个APK大小的百分比)
- 理解DEX文件的组成。(译注:能看到DEX文件中包含了哪些类)
- 快速查看APK中文件的最终版本(比如AndroidManifest.xml)。(译注:AndroidManifest.xml、resources.arsc本来是二进制形式显示的,APK Analyzer能够解析并显示这些文件的内容)
- 对比两个APK。(译注:新版APK和旧版APK之间文件大小的差异)
这里有3种方法访问APK Analyzer:
- 拖拽APK到Android Studio的编辑器窗口中。
- 切换到Project视图,然后在默认的build/ouputs/apk/目录下双击APK文件。
- 在菜单栏中选择Build > Analyzer APK,并且选择APK。
注意:当使用APK Analyzer分析debug的APK,请使用Build > Build
APK或gradle命令生成的APK。点击ToolBar中的Run将会生成Instant Run的APK。APK
Analyzer不能分析通过Instant Run生成的APK,因为它们仅供开发使用,并动态加载大多数资源,判断APK是否是Intant
Run生成的可以通过看APK中是否有instant-run.zip文件。
查看文件和大小信息
APK就是一个zip包。APK Analyzer显示每个文件或目录作为一个实体,实体的层级说明了APK文件的结构。
如图1,APK Analyzer对每个实体显示了raw file size和download file size。Raw File Size表示实体在磁盘中解压后的大小,而Download Size表示实体在Google Play中压缩后的大小。% of Total Download Size表示实体的download size占APK总的download size的百分比。
译注:图1中,最上面的1.4M是指APK在磁盘中的大小,而1.2M是指从Google Play中下载的大小。
图1:在APK Analyzer中的文件大小
译注:通过查看各个目录或文件的大小,我们能发现APK中哪个区域的文件太大了,比如如果dex太大,我们是不是引入了重复功能的第三方库(比如Glide和Fresco),或者抽取出一个精简的第三方库(精简ffmpeg库);如果res目录太大,我们可以看看哪些图片过大了,需要通过tinypng压缩,或者用webp代替。
查看AndroidManifest.xml
如果项目中包含了多个AndroidManifest.xml或者包含提供manifest文件的library,在APK中他们将被合并为一个manifest文件。在APK中manifest文件是普通的二进制文件,但是在APK Analyzer中查看manifest文件,该文件是以XML形式显示的。这种显示形式让我们能理解应用中的任何变化。比如,你能看到library中的AndroidManifest.xml是怎么合入最后的AndroidManifest.xml的。
另外,这种显示形式提供了lint的能力,会在右上角显示警告、错误提示。图2显示了manifest文件的错误提示
查看DEX文件
APK Analyzer的DEX文件浏览器让你能够快速了解DEX文件的信息。我们能看到类、包、总的引用和声明个数,这些信息能够帮助我们决定是否使用multi-dex或者移除依赖使得满足64K方法数限制。
图5展示了一个中等大小的APP(方法数接近64K)。每个包、类、方法都列有Defined Method和Referenced Method。Referenced Method列是DEX文件中引用的全部方法,它包含了你定义的方法、依赖的library、定义在标准Java和Android包中的方法。Defined Method列只包含了定义在DEX文件中方法,因此它是Referenced Method方法的子集。注意当你引入一个依赖,在依赖中定义的方法会包含在Defined Method和Referenced Method中。还要注意,混淆压缩也会改变DEX文件的内容。
过滤DEX文件树视图
在“类别”列表上方,APK Analyzer提供了用于查看所选DEX文件内容的过滤器。
要使用过滤器显示类中的所有方法和字段,请执行以下操作:
- 在File列表中,选择classes.dex文件。
- 在class列表中,导航并选择一个class
- 展开class
- 切换显示fileds来显示或隐藏class fileds
- 切换显示methods来显示或隐藏class methods
- 切换显示所有引用methods或fileds来显示或隐藏引用的packages,classes, methods和fileds,斜体节点是在所选DEX文件中没有定义的引用。
DEX文件可以引用在不同文件中定义的方法和字段。 例如:
System.out.println()是对Android框架中println()方法的引用。
加载Proguard映射
过滤图标旁边是Proguard映射图标。 它们将显示为灰色,直到您加载一组Proguard映射文件,这些文件向DEX查看器添加功能,例如反混淆名称(mapping.txt),显示已删除的节点(usage.txt)以及指示无法删除的节点(seeds.txt)。 Proguard映射文件适用于启用Proguard的APK,并且必须和生成APK有相同的构建。
要加载Proguard映射文件,请执行以下操作:
1.点击 Load Proguard Mappings.
2.导航到包含映射文件的项目文件夹,并加载所有文件,文件的任意组合或包含这些文件的文件夹。
映射文件通常位于project/app/build/outputs/mappings/release/中。 如果文件选择器检测到此项目结构,则默认为release文件夹。 首先,文件选择器检查与mapping.txt,seeds.txt和usage.txt完全匹配的文件名。 接下来,文件选择器检查包含文本映射,用法或种子的文件名,并以.txt结尾。 例如,release-seeds-1.10.15.txt是一个匹配项。
以下列表描述了映射文件:
- seeds.txt:Proguard配置阻止在收缩过程中被删除的节点以粗体显示。
- mapping.txt:启用反混淆名称,以便您可以恢复由Proguard进行模糊处理的节点的原始名称。 例如,您可以将模糊的节点名称(如a,b,c)还原为MyClass,MainActivity和myMethod()。
- usage.txt:启用Show removed节点,以便显示Proguard在收缩期间删除的类,方法和字段。 已恢复的节点以删除线显示。
有关使用Proguard来混淆和最小化代码的更多信息,请参阅Shrink your code and resources.
显示字节码,查找用法,并生成Keep规则
Show Bytecode:反编译选中的class,method或fileds,并在对话框中显示smail(非Java代码)字节码.
Find usages: 显示DEX代码的哪些其他部分对所选类或方法的引用(图7)。 如果加载了seeds.txt,则以粗体显示的节点表示Proguard配置会阻止它们在收缩期间被删除:
Generate Proguard Keep rule: 显示Proguard规则,您可以复制并粘贴到项目Proguard配置文件中,以防止在Proguard收缩阶段删除给定的包,类,方法或字段(图8)。 有关更多信息,请参阅 Customize which code to keep.
查看代码和资源实体
不同的构建任务会改变APK文件最后的实体。比如混淆压缩规则能改变你最后的代码和图片资源。在APK Analyzer中能够快速查看文件的最终版本:点击实体,就能在下面看到文件的内容,包含文字和图片实体的预览。
APK Analyzer也能展示文本或二进制文件。比如点击resources.arsc能够让你看到针对配置特定的值(例如一个字符串资源的特定语言的翻译)。如图4,你能看到每个字符串资源的翻译。
比较APK文件
APK Analyzer能比较两个不同APK中各个实体的大小。这对于我们了解为何你的APP相比上个版本变大了是很有用的。
在发布一个新版APK之前,在APK Analyzer中导入你即将发布的APK。在右上角点击Compare With,选择上一个版本的APK,点击OK。然后就会出现类似图的对话框,允许你比较之间的差别。
下图显示了一个APP的debug和release包的差别,不同的编译类型会导致实体的不同。