📜  如何在 Android 应用中正确使用 Proguard?

📅  最后修改于: 2022-05-13 01:58:44.517000             🧑  作者: Mango

如何在 Android 应用中正确使用 Proguard?

在为您的 Android 应用程序编写代码时,可能会有一些不必要的代码行,并且可能会增加您的应用程序 APK 的大小。除了无用的代码之外,您可能已经在程序中合并了许多库,但并未使用每个库提供的所有功能。此外,您可能已经开发了一些将来会过时的代码并且未能将其删除。这些因素是导致应用程序 APK 大小增加的原因。 Android 具有 Proguard 功能以最小化 APK 的大小。使用 Proguard 有助于实现下面列出的三个功能:

  1. 缩小代码
  2. 混淆代码
  3. 优化代码

因此,Proguard 将帮助您缩小 APK 的大小,删除不必要的类和方法,并使您的程序难以进行逆向工程。所以,在使用 Proguard 时,你需要记住一些事情。在本文中,我们将了解在我们的 Android 应用程序中使用 Proguard 时必须考虑的一些方面。所以让我们从第一点开始。

Proguard 应从数据类中排除

几乎每个 Android 应用程序都包含一个 Data 或 Model 类,用于从远程数据库中检索数据。因此,如果您使用 Proguard,Progurde 将修改类、变量和方法名称。

例如,如果您有一个名为 User 的类,并且它具有诸如 firstName 和 lastName 之类的变量,Proguard 会将您的 User 类重命名为 A 或类似的名称。同时,您的变量名称可能会更改为某些 x、y 或 z。结果,如果您尝试将相同变量的数据放入数据库中,您将获得运行时错误,因为数据库中不存在这样的字段。

为了避免这种情况,请指示 Proguard 保留 User 类的变量和方法,而不是混淆它们。为此,将以下行添加到您的 proguard-rules.pro 文件中:

-keep class full.class.name.of.your.project.here.** { *; }

通过添加前一行,Proguard 将不会对所选类中的代码进行混淆或优化。

使用 Proguard 时,不要使用 Fragment TAG

Proguard 的大部分问题都是由其混淆特性引起的。与片段相同。

每当我们创建 Fragment 时,我们都会将一些 String TAG 定义为 FragmentName.class。使用 getSimpleName() 获取 TAG 并在我们的 Fragment 中使用它。但是,如果您使用 Proguard,这可能会导致您的应用程序出现问题。假设我们在 firstfragment 包中有两个片段,在 secondfragment 包中名为 Fragment1 和 Fragment2。这样一来,Proguard 会把第一个fragment 包改成“a”,把第二个fragment 包改成“b”,但是Proguard 也可以把Fragment1 的名字改成“a”(因为包和Fragment 不同,所以名字可以相同)和 Fragment2 为“a”,因为 Fragment2 是不同的包。

但是,如果您当前正在使用 FragmentName.class.getSimpleName(),这将导致混淆,因为 Fragment1.class.getSimpleName() 已更改为 a.class.getSimpleName() 并且 Fragment2.class.getSimpleName() 已更改为a.class.getSimpleName() ()。两个 TAG 值都会对调用哪个片段感到困惑。因此应该避免使用 FragmentName.class.getSimpleName()。

照顾反射

当您的类和方法可以动态访问时,例如通过反射,您必须确保您的类或函数被混淆。例如,如果您从 XML 文件(通常使用反射)引用您的代码并同时使用 Proguard,Proguard 会将您的类名更改为“a”或 XML 代码中的类似名称,不会进行任何更改,这将导致找不到类或找不到方法异常。

因此,始终在 Proguard 规则中包含使用反射的类。

查看手柄

当您在 Android 应用程序中构建自己的视图时,请确保您创建的视图类包含在 Proguard 规则中,否则您将收到类未找到错误。

例如,如果您创建一个名为 com.geeksforgeeks.android 的简单视图并在 XML 文件中使用它,Proguard 会将您的视图类名称更改为“a”或类似名称,并且您在 XML 中的代码使用 com.geeksforgeeks .android,但没有这样的类,因为它已更改为“a”。

正在添加库的 Proguard 规则

我们在 Android 应用程序中使用了很多开源库。但是,如果您使用 Progurad,则还必须提供您正在使用的库的 Proguard 规则(如果有)。

您可以通过阅读您使用的库的 README.md 文件并将提供的 Proguard 规则添加到您的应用程序来找到库的 Proguard 规则。可以在此处找到 Retrofit 库的 Proguard 规则的示例。

维护本机代码

在您的Android 应用程序中使用本机代码时,即在您的Android 应用程序中使用c++ 代码时,您必须注意Proguard 混淆的影响。 Proguard 通常只能检查Java类。因此,如果您从 C++ 代码调用Java方法并且该函数已被 Proguard 混淆,则 JNI 将抛出未找到方法错误。

-keepclasseswithmembernames your.class.name.here * { native ; }

JAR/APK 资源加载

在Java中,我们可以从 JAR 文件中加载资源,某些库也可以从 APK 文件中加载资源。这不是问题,但是如果我们使用 Proguard,Proguard 会更改这些资源文件的名称,并且这些文件不会在所需的包中被发现。因此,从 APK 加载资源的类的名称应该保存在您的 Proguard 规则中。

另一个专业提示

完成代码优化后,将所有文件放在根包中,以消除对完全限定名称(如 com.geeksforgeeks.android.example)的需要。要启用此功能,请在您的 proguard-rules.pro 文件中包含以下行:

-repackageclasses

结论

在本文中,我们了解了在我们的 Android 应用程序中使用 Proguard 时应遵循的注意事项。我们发现了如何在 Proguard 中维护特定的类。我们还学习了如何从第三方库添加 Proguard 规则。