使用 APK Analyzer 分析您的构建

Android Studio 包含 APK Analyzer,可在构建过程完成后立即提供关于 APK 或 Android App Bundle 组成的深入分析。使用 APK Analyzer 可以减少您调试应用中 DEX 文件和资源问题的时间,并有助于减小 APK 大小。APK Analyzer 也可以通过命令行使用,命令为 apkanalyzer


使用 APK Analyzer,您可以

  • 查看应用中文件的绝对大小和相对大小,例如 DEX 文件和 Android 资源文件。
  • 了解 DEX 文件的组成。
  • 快速查看应用中文件的最终版本,例如 AndroidManifest.xml 文件。
  • 对两个 APK 或应用包执行并排比较。

项目打开时,有三种方式可以访问 APK Analyzer

  • 将 APK 或应用包拖到 Android Studio 的 Editor 窗口中。
  • Project 窗口中切换到 Project 视图,然后双击默认 build/output/apks/ 目录中的 APK。
  • 在菜单栏中选择 Build > Analyze APK,然后选择您的 APK 或应用包。

查看文件和大小信息

APK 是遵循 ZIP 文件格式的文件。APK Analyzer 会将每个文件或文件夹显示为一个实体,您可以展开该实体以导航到文件夹中。实体的层次结构反映了 APK 文件中文件和文件夹的结构。

APK Analyzer 会显示每个实体的压缩文件大小(或“原始文件大小”)和下载文件大小值,如图 1 所示。原始文件大小表示实体对总 APK 大小的贡献。下载大小表示实体通过 Google Play 交付时的估计压缩大小。占总下载大小的百分比表示实体在 APK 总下载大小中所占的百分比。

图 1. APK Analyzer 中的文件大小。

查看 AndroidManifest.xml

如果您的项目包含多个 AndroidManifest.xml 文件(例如用于产品变体),或者包含也提供清单文件的库,它们会合并到您应用中的单个文件中。此清单文件通常是 APK 或应用包中的二进制文件,但在 APK Analyzer 中选择时,此实体的 XML 形式会被重建并显示。

此查看器可帮助您了解在构建过程中可能对应用所做的任何更改。例如,您可以查看应用所依赖的库中的 AndroidManifest.xml 文件是如何合并到最终 AndroidManifest.xml 文件中的。

此外,此查看器还提供了一些 lint 功能。警告或错误会显示在右上角。图 2 显示了所选清单文件报告的错误。

图 2. 所选清单文件右上角显示错误图标。

查看 DEX 文件

APK Analyzer 的 DEX 文件查看器可让您立即访问应用中 DEX 文件的基础信息。此查看器提供类、软件包、总引用和声明计数,这有助于决定是否使用 multidex 或如何移除依赖项以低于 64K DEX 限制

图 3 显示了一个中等大小的应用,其大小低于 64K DEX 限制。DEX 文件中的每个软件包、类和方法在 Defined MethodsReferenced Methods 列中都列出了计数。

Referenced Methods 列会计算 DEX 文件引用的所有方法。这通常包括在您的代码、依赖库中定义的方法,以及代码使用的标准 Java 和 Android 软件包中定义的方法。这些方法会计入每个 DEX 文件中的 64K 方法限制。

Defined Methods 列仅计算在您的 DEX 文件之一中定义的方法,因此此数字是 Referenced Methods 的一个子集。

图 3. 一个中等大小的应用。

过滤 DEX 文件树状视图

就在 Class 列表上方,APK Analyzer 提供了用于查看所选 DEX 文件内容的过滤器,如图 4 所示。

图 4. DEX 过滤器设置为显示 BuildConfig 的字段和方法。

要使用过滤器显示类中的所有方法和字段,请执行以下操作

  1. File 列表中,选择 classes.dex 文件。
  2. Class 列表中,导航并选择一个类。
  3. 展开您选择的类。
  4. 切换 Show fields 以显示或隐藏类字段。
  5. 切换 Show methods 以显示或隐藏类方法。
  6. 切换 Show all referenced methods or fields 以显示或隐藏引用的软件包、类、方法和字段。

    在树状视图中,斜体节点是在所选 DEX 文件中没有定义的引用。一个 DEX 文件可以引用在不同文件中定义的方法和字段。例如,System.out.println() 是对 Android 框架中 println() 方法的引用。

加载 ProGuard 映射

过滤图标旁边是 ProGuard 映射图标。ProGuard 图标会灰显,直到您加载一组 ProGuard 映射文件,这些文件会向 DEX 查看器添加功能,例如反混淆名称 (mapping.txt)、显示已移除的节点 (usage.txt) 和指示无法移除的节点 (seeds.txt)。

您导入的 ProGuard 映射文件必须是与生成启用了代码压缩的 DEX 文件的构建相同的构建所产生的文件。

图 5. 加载 Proguard 映射...

要加载 ProGuard 映射文件,请执行以下操作

  1. 点击 Load Proguard mappings...
  2. 导航到包含映射文件的项目文件夹,并加载所有文件、文件的任意组合或包含这些文件的文件夹。

    映射文件通常位于 project/app/build/outputs/mappings/release/。如果文件选择器检测到此项目结构,则默认会指向 release 文件夹。

    首先,文件选择器会检查文件名是否精确匹配 mapping.txtseeds.txtusage.txt。接下来,文件选择器会检查文件名中是否包含文本 mappingusageseeds,并且以 .txt 结尾。例如,release-seeds-1.10.15.txt 是匹配项。

以下列表描述了映射文件

  • seeds.txt:ProGuard 配置阻止在压缩期间移除的节点会以粗体显示。
  • mapping.txt:启用 Deobfuscate names ,以便您可以恢复 R8 混淆的节点原始名称。例如,您可以将混淆的节点名称(如 abc)恢复为 MyClassMainActivitymyMethod()
  • usage.txt:启用 Show removed nodes ,以便您可以显示 R8 在压缩期间移除的类、方法和字段。恢复的节点会显示为删除线样式。

    有关使用 R8 混淆和精简代码的更多信息,请参阅压缩、混淆和优化应用

显示字节码、查找用法和生成 Keep 规则

Class 列表视图中的节点具有上下文菜单,其中包含以下选项,可让您查看字节码、查找用法,并显示一个对话框,其中包含要复制和粘贴所选节点的 ProGuard 规则。右键点击 Class 列表视图中的任何节点以显示其上下文菜单。

Show bytecode:反编译所选类、方法或字段,并在对话框中显示 smali 字节码表示形式,如下所示

图 6. init 方法的 DEX 字节码。

Find usages:显示 DEX 代码的其他部分对所选类或方法的引用,如图 7 所示。如果已加载 seeds.txt,则以粗体显示的节点表示 ProGuard 配置阻止它们在压缩期间被移除。

图 7.MyClass 的引用。

Generate Proguard Keep rule:显示您可以复制并粘贴到项目 ProGuard 配置文件中的 ProGuard 规则,如图 8 所示。这可以防止给定的软件包、类、方法或字段在代码压缩阶段被移除。有关详细信息,请参阅自定义要保留的代码

图 8. 您可以从对话框复制到 ProGuard 配置文件的 ProGuard 规则。

查看代码和资源实体

各种构建任务会更改应用中的最终实体。例如,ProGuard 压缩规则可以更改您的最终代码,而图像资源可以被产品变体中的资源覆盖。

要使用 APK Analyzer 查看文件的最终版本,请点击实体以预览文本或图像实体,如图 9 所示。

图 9. 最终图像资源的预览。

APK Analyzer 还可以显示各种文本和二进制文件。例如,resources.arsc 实体查看器可让您查看特定于配置的值,例如字符串资源的语言翻译。在图 10 中,您可以看到每个字符串资源的翻译。

图 10. 翻译后的字符串资源预览。

比较文件

APK Analyzer 可以比较两个不同 APK 或应用包文件中实体的大小。当您需要了解应用与之前版本相比大小增加的原因时,这会很有帮助。

在发布更新的应用之前,请执行以下操作

  1. 将您即将发布的应用程序版本加载到 APK Analyzer 中。
  2. 在 APK Analyzer 的右上角,点击 Compare with previous APK...
  3. 在选择对话框中,找到上次向用户发布的工件,然后点击 OK

    此时会显示一个类似于图 11 的对话框,以帮助您评估更新可能对用户产生的影响。

图 11 显示了某个应用的调试版本和发布版本之间的差异。这些构建类型之间使用了不同的构建选项,这会以不同方式更改底层实体。

图 11. 调试 APK 和发布 APK 之间的差异。