我已将 ProGuard 应用于我的Android应用程序。
我正在使用
android-studio/sdk/tools/proguard/proguard-android.txt
作为配置文件,不做任何改动。
在此文件中,我可以看到有关活动的唯一声明:
We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
由此可见,ProGuard会忽略活动类名,而某些方法会保留原样。这是可以理解的。
但是,在我的应用程序中,我使用
从字符串创建一个Activity类Class.forName("my.app.MyActivity")
然后我开始这个活动,它开始很好。
但这意味着Activity派生类不会被混淆?? 。它应该失败,因为ProGuard没有-keep class
的{{1}}指令,它只有Activity
如果我可以依赖我观察到的行为,请有人解释一下吗?或者我是否误解了-keepclassmembers.
指令?
答案 0 :(得分:11)
因为活动列在清单和引用的类中,所以会自动保留。这是必需的,因为Android框架通过反射访问这些应用程序入口点。
来自here:
构建过程运行工具aapt以基于
bin/proguard.txt
和其他xml文件自动创建配置文件AndroidManifest.xml
。然后,构建过程将配置文件传递给ProGuard。所以ProGuard本身确实不考虑AndroidManifest.xml
,而是aapt + ProGuard。
答案 1 :(得分:3)
来自ProGuard FAQ:
ProGuard是否处理Class.forName调用?
是。 ProGuard自动处理类似Class.forName(“SomeClass”)和SomeClass.class的构造。引用的类在收缩阶段保留,并且在混淆阶段正确替换字符串参数。 对于变量字符串参数,通常无法确定其可能的值。例如,可以从配置文件中读取它们。但是,ProGuard会注意到许多构造,如“(SomeClass)Class.forName(variable).newInstance()”。这些可能表示可能需要保留类或接口SomeClass和/或其实现。开发人员可以相应地调整他的配置。
因此,ProGuard比您预期的更聪明:它会自动检测并处理forName()
使用的简单案例。即使Android清单文件中未引用该类,ProGuard也会在您对forName()
的调用中对类和中的类名进行模糊处理。
对于活动,如果你被这种行为以及ProGuard的Android特定输入所覆盖,那就不会让我感到惊讶,正如@laalto在他的回答中提到的那样。