Android开发ProGuard使用技巧掌握
Himanshu Singh 人气:0前言
在构建 Android 应用程序时,我们可能在项目中使用了 ProGuard。在这篇文章中,我们将了解所有功能以及如何在 Android 中有效地使用 ProGuard。
因此,让我们将其分解为以下几点:
什么是 ProGuard?
ProGuard 是 Android 中的免费 java 工具,它可以帮助我们执行以下操作,
- 缩小(缩小)代码:删除项目中未使用的代码。
- 混淆代码:重命名类、字段等的名称。
- 优化代码:做内联函数之类的事情。
简而言之,ProGuard 对我们的项目产生了以下影响,
- 它减小了应用程序的大小。
- 它删除了导致 Android 应用程序的 64K 方法计数限制的未使用类和方法。
- 它通过混淆代码使应用程序难以进行逆向工程。
它对我们的应用程序有什么用处?
在 Android 中,proguard 对于制作可用于生产的应用程序非常有用。它可以帮助我们减少代码并使应用程序更快。默认情况下,Proguard 在 Android Studio 中是开箱即用的,它在很多方面都有帮助,下面提到的很少,
- 它混淆了代码,这意味着它将名称更改为一些较小的名称,例如MainViewModel它可能会将名称更改为A。在混淆应用程序之后,您的应用程序的逆向工程现在成为一项艰巨的任务。
- 它缩小了资源,即忽略了我们的类文件没有调用的资源,没有在我们的android应用程序中使用,比如drawables中的图像等。这将大大减少应用程序的大小。您应该始终缩小您的应用程序以使其重量轻且速度快。
如何在我们的项目中使用它?
要在您的项目中启用 Proguard,请在应用程序的 build.gradle 添加,
buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
在这里,我们minfyEnabled
确实如此,它激活了从文件中获取的proguard,
proguard-android.txt
它在发布块下,这意味着它只会应用于我们生成的构建的发布。
但有时当 proguard 删除太多代码时它可能太多了,它可能会破坏你的代码流。
因此,配置代码我们必须添加一些自定义规则,以确保我们从混淆中删除代码集。我们可以通过在我们的 proguard 中编写自定义规则来解决这个问题,它会在生成构建时遵守。
现在,让我们看看如何在 proguard 中编写自定义规则。
1. 保存类文件假设我们有一个数据类,某些 API 需要它来执行它,但它会生成我们对类进行混淆的构建。例如,我们有一个用户数据类,
data class User(val id: String = "")
我们不想混淆生成构建的类,然后忽略它的混淆,我们使用@Keep
注释并更新代码,例如,
@Keep data class User(val id: String = "")
此注释有助于在缩小时使用 proguard 来忽略该类。这将保留类及其成员函数,即使它们不被使用。
我们还可以使用,
-keep
在生成构建时保留类的选项。使用-keep而不是@Keep,我们可以更好地控制要保留的内容和不保留的内容。
但是,我们也可以通过使用@SerializedName(当使用 Gson 库时)来保留数据模型类中id字段的键,例如,
data class User(@SerializedName("id") val id: String = "")
如果你注意到这里,我们没有使用@Keep。
2. 为班级保留成员假设我们想在收缩时只保留类成员而不是类,然后我们使用,
-keepclassmembers
在 proguard 规则文件中。这将帮助我们忽略特定类的成员。
考虑上面的 User 类,我们希望保留其中的所有公共方法。我们这样写规则,
-keepclassmembers class com.mindorks.sample.User{ public *; }
在这里,类 User 保留所有具有公共修饰符的成员。
3. 保留班级和成员的名字假设我们希望在代码中使用类和类成员的所有相同名称,即如果未使用该类,它将被 proguard 缩小但不会混淆,因为它已经被缩小了,所以没有需要混淆。
要完成我们使用的上述任务,
-keepnames
它的实际使用看起来像,
-keepnames class com.mindorks.sample.GlideModule
在这里,如果 GlideModule 将保留其所有的类名称和成员函数。
4.在Android中使用任何库在使用任何库时,我们可能希望为 proguard 编写一些自定义规则。库可能会在 logcat 中引发警告,或者他们甚至可能没有自己的 proguard 规则!
为了解决这个问题,我们需要在应用程序端添加自定义规则。例如,如果我们开始从任何库中收到警告,那么我们添加,
-dontwarn com.somelibrary.annotations.*
在我们的 proguard 规则中,然后我们不会在日志中看到任何警告。
要为库编写自定义规则,您可以像为自己的类编写任何其他规则一样编写它。
5. 只混淆你的代码考虑一个非常罕见的用例,您只想混淆代码而不压缩任何资源。这是一个非常罕见的用例,但可能对一些小型库有用,然后我们编写如下标志,
-dontshrink -dontoptimize
这将帮助我们不缩小和优化代码而只是混淆。
6. 维护注解在构建应用程序时,ProGuard 会删除所有注释,它可能仍然适用于您项目中的某些代码集。但是假设我们需要不删除注释,那么我们可以选择,
-keepattributes *Annotation*
在这里,它将所有注释的属性保留在您的应用程序中。它默认出现在我们的规则中。
7.优化在 ProGuard 中编写了这么多规则之后,我们可能需要为我们的应用程序提供额外的优化层。首先,我们更新build.gradle文件,例如,
android { buildTypes { release { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') } } }
现在,一般来说,我们不使用此选项,但这里的用例是我们必须执行额外级别的优化。
为了增加优化的周期数,例如我们想检查优化是否正确完成,如果没有完成,它将再次优化它直到我们使用一定次数,
-optimizationpasses 5
在这里,它将运行优化多达 5 次以使其更加优化。
现在,考虑一个示例,与以前相比,我们希望更细粒度地优化最终类,我们使用,
-optimizations class/marking/final
在这里,最终的类将被优化最多 5 倍,或者如果优化已经完成,它甚至可能提前结束。
现在,如果我们想优化我们现在使用的私有字段,
-optimizations field/marking/private
大多数情况下,优化是第一次完成。
如果我们根本不想优化我们使用,
-dontoptimize
这就是我们如何以不同的方式使用 proguard 使我们的应用程序更安全和更轻便的工作方式。
需要注意的重要事项:
- 不要使用MainFragment.class.getSimpleName() 之类的东西作为片段标签。Proguard 可能会在混淆时为不同包中的两个不同片段分配相同的名称(A.class)。在这种情况下,两个片段将具有相同的 TAG。这将导致您的应用程序中的错误。
- 保留 Proguard 的映射文件以追溯到原始代码。您可能必须将其上传到 PlayStore 控制台等不同的地方才能查看崩溃的原始堆栈跟踪。
翻译链接
https://blog.mindorks.com/applying-proguard-in-an-android-application
加载全部内容