我也对这个规则很好奇,所以我研究了一下。
这真的需要吗?与仅使用假设副作用规则相比有什么好处?
此-maximumremovedandroidloglevel 规则旨在与-assumenosideeffects 具有相同的效果,因此它可以用作完全替代.
但是,从最新版本 (3.3.75) 开始,它的性能与 -assumenosideeffects 略有不同。如果您打算删除所有 Log.* 方法调用 - 那么您不应该关心(您可以使用一个或另一个)。但是,如果您只删除这些方法的一部分并且依赖Log#isLoggable,那么我建议您坚持当前的配置,并避免将-maximumremovedandroidloglevel 规则添加到您的proguard 配置文件中。
更深的挖掘
假设我们的源代码中有以下几行代码,然后我将展示使用不同配置进行 R8 处理后的样子。
if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) {
Log.v("FOO_TAG", "verbose message");
}
if (Log.isLoggable("FOO_TAG", Log.WARN)) {
Log.w("FOO_TAG", "warn message");
}
<1>R8 v3.3.75,具有以下规则(注意我已经注释掉了 w 和 e 方法):
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
# public static int w(...);
public static int d(...);
# public static int e(...);
}
产生以下输出:
if (Log.isLoggable("FOO_TAG", 5)) {
Log.w("FOO_TAG", "warn message");
}
R8 按预期删除了 VERBOSE 日志。请注意,它保留Log#isLoggable 方法调用,其中级别(第二个参数)为WARN (5)。
<2>R8 v3.3.75,具有以下规则(4 表示我们要删除直到INFO 的所有日志方法,包括):
-maximumremovedandroidloglevel 4
产生以下输出:
Log.w("FOO_TAG", "warn message");
请注意,此规则保留了 Log#w 方法调用,但删除了 Log#isLoggable 调用(这是行为略有不同的地方)。
这意味着关于 -maximumremovedandroidloglevel 的最新 R8 版本并不像宣传的那样工作 (here):
示例:android.util.log.INFO 的值为 4。因此,
指定 -maximumremovedandroidloglevel 4 将删除所有对
Log.v()、Log.d() 和 Log.i(),以及它将替换对
Log.isLoggable(X, {2, 3, 4}) 为假。
<3>来自main 分支的the tip 的R8,具有以下规则(4 表示我们要删除直到INFO 的所有日志方法,包括):
-maximumremovedandroidloglevel 4
产生以下输出:
if (Log.isLoggable("FOO_TAG", 5)) {
Log.w("FOO_TAG", "warn message");
}
似乎main 分支包含一个修复程序,可以恢复两种方法的行为奇偶性(Log#isLoggable 和WARN 作为参数没有被删除)。
main 和 3.3.75 标签之间的相关差异是这两个提交:1、2。
为什么official documentation 包括-assumenosideeffects 和-maximumremovedandroidloglevel?
根据我的测试 - 这似乎具有误导性,因为他们应该建议使用其中一种,绝对不能同时使用。