Android 开发必备:ProGuard 使用技巧详解

更新:10-27 神话故事 我要投稿 纠错 投诉

大家好,Android 开发必备:ProGuard 使用技巧详解相信很多的网友都不是很明白,包括也是一样,不过没有关系,接下来就来为大家分享关于Android 开发必备:ProGuard 使用技巧详解和的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!

当我们构建应用程序时,使用ProGuard 有很多好处。一些开发人员更关心混淆此功能。对我来说,最大的用处就是打包时去掉dex中无用的代码。

Android示例应用的空间分布图,源代码地址Topeka示例应用。

减小软件包大小有很多好处,例如提高用户粘性和满意度、提高下载速度以及减少连接用户在终端设备上的安装时间,尤其是在新兴市场。当然,有时候你不得不限制你的应用程序的大小,比如Instant App的大小限制为4MB,这时候ProGuard就不可或缺了。

如果以上还不足以说服您使用ProGuard,还有更多优化可以删除无用代码并混淆所有名称:

在某些版本的Android 设备上,DEX 代码会在安装或运行时编译为机器代码。原始DEX 和优化后的机器代码都会保留在设备上,所以只需计算一下:代码越少,意味着编译时间越短,存储占用越少。除了大幅减少代码空间之外,ProGuard 还可以将让所有的标识符(包、类和成员)都使用更短的名字例如a.A 和a.a.B。这个过程是混乱的。混淆以两种方式减少代码:使表示名称的字符串更短;当这些方法或属性具有相同的签名时,这些字符串更容易重用,最终减少字符串池的数量。使用ProGuard是开启资源压缩的先决条件。资源压缩功能会移除您项目中代码没有引用到的资源文件(比如图片资源,一般是APK中最大的部分)。仅将代码中实际使用的方法打包到APK 中,移除代码会帮您避免010 -59000。特别是如果您引用了许多第三方库,这可以大大减少在应用程序中使用Multidex 的需要。64K dex 方法引用问题但在您兴奋不已之前,请继续阅读。当您打开ProGuard 时,在一些非常微妙的情况下您的应用程序会崩溃。虽然在构建应用程序时会发生一些错误并且您会捕获它们,但也有一些错误只能在运行时发现,因此请确保您的应用程序经过彻底测试。

如何使用 ProGuard?

在项目中打开ProGuard 非常简单,只需将以下代码行添加到主应用程序模块的build.gradle 文件中即可:

构建类型{

/* 你通常只想为你的版本启用ProGuard

构建,因为这是一个额外的步骤,会使构建速度变慢,并使调试变得更加困难*/

发布{

minifyEnabled true

proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"

}

}ProGuard自己的配置已经在单独的配置文件中完成。上面的代码中,我已经给出了Android Gradle打包插件中的默认配置,然后我将在proguard-rules.pro中添加其他配置。

您可以在ProGuard 官方网站上找到用户手册。

在深入研究这些配置之前,最好总体了解ProGuard 的工作原理以及我们指定一些额外选项的原因。

您还可以观看Google I/O 会议Shai Barack 的教学视频的一部分。

简单来说,ProGuard 将项目中的.class 文件作为输入,然后查找代码中的所有调用点,计算代码中所有可达的调用图,然后删除剩余部分(即不可达的代码和不会被访问的代码)。称为)。

当你阅读ProGuard手册时,你不需要看输入/输出部分,因为这些Android Gradle打包插件会指定输入源(你和第三方库代码)和Android jar库(你使用为您构建应用程序时)。 Android 框架类)。

正确配置ProGuard 最重要的是让它知道哪些代码不应在运行时删除(当然,如果启用了混淆,请保持它们的名称相同)。当一些类和方法被动态访问时(比如使用反射),在某些情况下,ProGuard在构建调用图时无法正确判断它们的“生死”,导致这些代码被错误地移除。当您的代码仅引用XML 资源(通常使用低级反射)时,也可能会发生这种情况。

在典型的Android 构建过程中,AAPT(资产处理工具)会生成一个额外的ProGuard 规则文件。它会为Android应用程序添加一些特殊的每个 Android 应用都应该使用代码压缩吗?我认为是的!,因此您在Android Manifest.xml中记录的Activity,Services,BroadcastReceivers和ContentProviders将保持不变。这就是为什么上面的动画中MyActivity类没有被删除或者重命名。

AAPT 还keep 规则存储XML 布局文件中使用的所有View 类(及其构造函数)和其他类,例如过渡动画资源中引用的过渡类。构建完成后可以直接查看AAPT生成的配置文件。位置是://build/intermediates/proguard-rules//aapt_rules.txt。

AAPT 在构建时生成的ProGuard 配置文件示例

我将在本文后面详细讨论keep规则,但在此之前最好了解在以下情况下该怎么做:

当 ProGuard 打断了您的构建

在打开ProGuard 的情况下测试所有代码在运行时是否正常工作之前,您需要构建应用程序。不幸的是,ProGuard 可能会发现某些引用的类丢失并发出警告,导致您的构建失败。

解决这个问题的关键是仔细观察构建过程中输出的消息,了解这些警告的内容并定位它们。通常的方法是修复您的依赖项或将keep规则添加到您的ProGuard 配置中。

出现这些警告的原因之一是您的构建路径不包含需要依赖项的JAR,例如使用提供的(仅编译时)依赖项。有时,在Android上,这些代码的依赖项实际上并没有在运行时被调用。让我们看一个真实的例子。

依赖OkHttp 3.8.0 的项目构建消息。

OkHttp 库在3.8.0 版本中向该类添加了新的注释(javax.annotation.Nullable)。但由于它们使用编译时依赖项,这些注释不会打包在最终构建中(即使应用程序明确依赖于com.google.code.findbugs:jsr305),因此ProGuard 会抱怨缺少这些类。

由于我们知道这些注解类在运行时不会被使用,因此我们可以通过在ProGuard 配置中添加-dontwarn规则来安全地忽略这些警告,例如将这些规则添加到OkHttp 文档中:

-dontwarn javax.annotation.Nullable

-dontwarn javax.annotation.ParametersAreNonnullByDefault 您应该经历类似的过程,在输出消息中看到这些警告,然后重新构建,直到构建通过。了解为什么会收到这些警告以及在构建时是否确实缺少这些类非常重要。

现在您可能想使用-dontwarn选项忽略所有警告,但这通常不是一个好主意。在某些情况下,ProGuard 的警告实际上可以帮助您识别崩溃和其他配置问题的罪魁祸首。

你可能想看看Progard的注释(优先级低于警告的消息),它可以帮助你发现一些与反射相关的问题。虽然它不会中断您的构建,但可能会在运行时崩溃。这种情况发生在以下场景中:

当 ProGuard 移除过多的类

在某些情况下,ProGuard 不知道使用了某个类或方法,例如,该类仅在反射期间使用或仅在XML 中引用。为了防止此类代码被删除或混淆,您应该在ProGuard 配置中指定额外的ignorewarnings规则。由您(应用程序开发人员)来发现代码的哪些部分有问题并提供必要的规则。

当运行时发生ClassNotFoundException或MethodNotFoundException时,则意味着您肯定缺少某些类或方法。也许ProGuard 删除了它们,或者由于依赖项配置错误而无法找到它们。因此,在搭建生产环境时(开启ProGuard时),一定要注意彻底测试,正视这些错误。

您有很多选项来配置ProGuard:

keep— 保留所有匹配的类和方法keep— 保留指定的类,当且仅当它们的类因其他原因而保留时(由其他调用站点引用或由其他规则保留) 成员keepclassmembers— 类及其成员当且仅当所有成员都存在于匹配类中时才保留。我建议您开始熟悉ProGuard 中的此类规范语法,其中讨论了上述所有内容。保留上一段中讨论的规则和keepclasseswithmembers选项。另外,这三个keep规则都有不同的版本,仅支持混淆(重命名)而不支持压缩。你可以在ProGuard官网的表格中看到一个概述。

作为编写ProGuard 规则的替代方法,您可以直接将-dontwarn注解添加到您不希望被混淆和删除的类、方法或属性中。请注意,如果您这样做,您将需要将Android 默认ProGuard 配置包含到您的构建中。

APK Analyzer 和 ProGuard

Android Studio 的集成APK 分析器可以帮助您查看哪些类已被ProGuard 删除,并支持为它们生成保留规则。当您在构建APK 时启用ProGuard 时,将在/build/outputs/mapping/目录中输出一些附加文件。这些文件包含有关删除代码和混淆映射的信息。

将ProGuard 映射文件加载到APK 分析器中,以在DEX 视图中查看更多信息

当您将映射文件加载到APK 分析器中(单击“加载Proguard 映射.”按钮)时,您可以在DEX 视图树中看到一些附加功能:

所有名称都经过预先混淆(即您可以看到原始名称)。由ProGuard 配置规则@Keep配置的包、类、方法和属性将以粗体显示。您可以启用“显示删除的节点”选项来查看ProGuard 删除的任何内容(字体将带有删除线)。右键单击树中的节点可以生成保留规则,以便粘贴到配置文件中。

当 ProGuard 移除过少的类

所有应用程序都可以使用Android内置ProGuard的一些安全默认规则,例如保留View的getter和setter方法,因为它们通常是通过反射访问的,而其他一些普通方法和类不会被移动。消除。这可以防止您的应用程序在许多情况下崩溃,但这些配置并不100% 适合您的应用程序。您可以删除默认的ProGuard 文件并使用您自己的文件。

如果你希望ProGuard 删除所有未使用的代码,你应该避免编写过于宽泛的keep 规则,例如添加通配符来匹配整个包,而应使用特定于类的匹配规则或使用上面提到的@Keep 注解。

使用-whyareyoukeeping 选项查看为什么这些类没有被删除。

如果您确实不确定ProGuard 为何不删除您希望其删除的代码,您可以将kept选项添加到ProGuard 配置文件并重建您的应用程序。在构建输出中,您可以看到是什么调用链决定ProGuard 保留此代码。

在APK 分析器中跟踪DEX 中保留了哪些类和方法

另一种方法不太精确,但在任何应用程序中都不需要重建和额外工作。即在APK分析器中打开DEX文件,然后右键单击您感兴趣的类和方法,选择“查找用法”,您将看到参考链,这可能会引导您了解代码的哪些部分使用指定的类或方法,防止其被删除。

ProGuard 和 混淆后的堆栈

我之前提到过,在构建过程中,ProGuard 在处理类文件时会输出映射和日志文件。当您需要保留构建产品时,您应该将这些文件与APK 一起保存。这些映射文件不能被其他版本使用,并且仅在与生成它们的APK 一起使用时才能保证正确。通过这些映射,您可以有效地调试用户设备上发生的崩溃。不然名字都搞混了,定位问题就太困难了。

将APK对应的ProGuard映射文件上传到Google Play Console,获取混淆前的堆栈信息。

当您在Google Play Console 中发布混淆后的生产APK 时,请记住上传每个版本对应的映射文件。在这种情况下,当您查看ANR 崩溃页面时,报告的堆栈将显示真实的类名称、方法名称和行号,而不是缩短和混淆的内容。

关于 ProGuard 和 第三方库

就像您有责任为自己的代码提供keep规则一样,第三方库的作者也有义务为您提供必要的混淆规则配置,以避免因打开Proguard而导致构建失败或应用程序崩溃。

有些项目只是在其文档或自述文件中提到了必要的混淆规则,因此您需要将这些规则复制并粘贴到主ProGuard 配置文件中。但还有更好的方法。如果第三方库的维护者将库发布为AAR,他们可以指定要打包在AAR中的规则,并在应用程序构建时自动暴露给构建系统。通过将以下代码行添加到库模块的build.gradle 文件中:

release { //或者你自己的构建类型

ConsumerProguardFiles ‘consumer-proguard.txt’

}您在consumer-proguard.txt 文件中编写的规则将附加到应用程序的主ProGuard 配置中,并在构建应用程序时使用。

-whyareyoukeeping如果想了解更多关于代码和资源压缩的信息,请参考我们的打开ProGuard 一开始可能会很困难,但我个人认为这个成本是值得的。投入一点时间,您将获得一个轻量级、优化的应用程序。此外,现在花时间配置您的应用程序意味着当实验性ProGuard 替代品R8 准备就绪时您就已经准备好了。因为R8 还可以使用现有的ProGuard 规则文件。

除了让你的代码更小之外,ProGuard 和R8 还可以选择优化你的代码以使其运行得更快,当然这是另一篇文章的主题.

proguard-android.txt 文件之前位于SDK 工具目录(SDK/tools/proguard/proguard-android.txt),但在新版SDK Tools 和Android Gradle 插件版本2.2.0+ 中,它可以在构建期间从Android 下载从插件jar 中解压缩它。构建项目后,您可以在/build/intermediates/proguard-files/目录中找到此配置文件。

感谢丹尼尔·加尔平。

掘金翻译项目是一个翻译高质量互联网技术文章的社区。文章来源为掘金英文分享文章。内容涵盖Android、iOS、React、前端、后端、产品、设计等领域。如果您想看到更多优质翻译,请继续关注掘金翻译计划、官方微博、知乎专栏。

文章分享结束,Android 开发必备:ProGuard 使用技巧详解和的答案你都知道了吗?欢迎再次光临本站哦!

用户评论

摩天轮的依恋

想学习一下Proguard,这篇文章看起来很有用!

    有18位网友表示赞同!

笑叹★尘世美

一直听说ProGuard可以优化APK,终于有时间了解下使用方法了。

    有16位网友表示赞同!

挽手余生ら

现在开发Android应用的话,优化apk大小真是个重要的环节!

    有13位网友表示赞同!

念旧是个瘾。

看完这篇文章后,觉得ProGuard可以用到很多地方哦~

    有16位网友表示赞同!

涐们的幸福像流星丶

之前没有接触过ProGuard,这个翻译看起来很容易理解。

    有5位网友表示赞同!

短发

学习一下ProGuard,以后开发的时候更得心应手了。

    有13位网友表示赞同!

陌颜

希望能详细介绍一下ProGuard的使用场景和效果吧!

    有5位网友表示赞同!

惦着脚尖摘太阳

Android应用越来越流行,优化apk大小确实很重要啊!

    有6位网友表示赞同!

青瓷清茶倾城歌

现在有很多工具可以用来优化代码,ProGuard也是其中之一。

    有15位网友表示赞同!

酒笙倾凉

学习 ProGuard ,能让我们更好地理解Android开发中的一些技巧

    有13位网友表示赞同!

绳情

这篇文章应该能解决很多使用ProGuard遇到问题的

    有7位网友表示赞同!

栀蓝

终于找到了一篇关于ProGuard的详细教程,很期待!

    有9位网友表示赞同!

看我发功喷飞你

优化APK大小可以提升用户体验,值得好好学习一下 ProGuard 。

    有20位网友表示赞同!

发型不乱一切好办

相信这篇翻译教程能够帮助到很多Android开发者!

    有13位网友表示赞同!

几妆痕

希望这篇文章能提供一些实际案例,更直观的展示ProGuard的应用方法。

    有20位网友表示赞同!

我怕疼别碰我伤口

Android开发越来越精细了,需要不断学习新的工具和技巧!

    有7位网友表示赞同!

弃我者亡

ProGuard是一种非常实用的代码混淆工具,可以保护我们的程序安全.

    有14位网友表示赞同!

莫失莫忘

分享这篇翻译教程给大家,希望能帮到想学习ProGuard的开发者们。

    有19位网友表示赞同!

爱情的过失

通过学习 ProGuard ,我们可以编写更健壮、更优秀的 Android 应用!

    有18位网友表示赞同!

艺菲

这篇文章内容看起来很棒!让我了解更多的 android 应用程序优化技巧!

    有14位网友表示赞同!

【Android 开发必备:ProGuard 使用技巧详解】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活

上一篇:历史文化与旅游学院元旦庆典:张灯结彩,共赏璀璨星光 下一篇:高效运营策略中的关键要素分析