原文链接:https://jebware.com/blog/?p=418
如果搜索Java活Android库的ProGuard规则,你会在StackOverflow上看到一堆回答,告诉你要这样做:
-keep class com.foo.library.** { *; }
这个建议很糟糕,你永远都不应该这样做。首先,它过于宽泛——包中的双星号表示该顶级包下的每个包里的所有类;而花括号内的星号用于这些类中的每个成员(变量,方法和常量)。也就是说,它使用与库中的所有代码。如果你是用这个规则,Jack Wharton将会对你大喊:
其次,这盘文章是关于什么的,是指令的开始,即“keep”。你几乎不想用-keep;如果确实需要ProGurad规则,则通常需要以下更具体的变体之一。但是ProGuard手册花了我一些时间来弄清楚我的情况适用于哪个变体,所以我制作了一些表格以便快速查阅。(ProGuard手册非常有用,我强烈建议你仔细阅读。)
无规则
为了开始学习,先看看默认情况。如果不对任何类指定keep指令,那么ProGuard就会这样做,这是正常的事情——即要压缩(例如,去除无用代码),也要混淆(例如,重命名事物)类和类成员。
-keep
看,这就是为什么我说你几乎不应该使用-keep。-keep基诺那个了所有的ProGuard效益。不压缩,不混淆;即不用于类,也不用于成员。在实际的使用情况下,可以让ProGuard执行少量工作。即使通过反射访问变量,例如,可以删除或者重命名未使用的类。所以让我们看看其他具体的-keep变体。
-keepclassmembers
这个变体只保护类的成员不被压缩和混淆。也就是说,如果类未被使用,则删除类。如果类被使用,保留并重命名该类。类里的成员维持不变,仍然是之前的名字。
-keepnames
这个变体压缩类及成员,但不混淆它们。也就是说,未使用的代码将被移除。剩下的代码则维持原状。
-keepclassmembernames
这是最宽容的keep指令;它允许ProGuard完成几乎所有工作。移除未使用的类,剩下的类被重命名,类中未使用的成员将被移除,剩余的成员保留原来的名称。
-keepclasseswithmembers
这个变体没有表格,因为它与-keep作用一致。区别是它只适用于拥有类规范中所有成员的类。
-keepclasseswithmembernames
同样的,这条规则与-keepnames一致。区别也是它只适用于拥有类规范中所有成员的类。
结论
如果希望ProGuard做尽可能多的工作,就要选择上面最少红色X块,同时还能满足需求的指令。