使用带有proguard的Android生产代码中的Hamcrest Matchers时出现运行时错误

时间:2015-01-16 10:11:54

标签: java android validation proguard hamcrest

我正在编写一个应用程序,其中包含带有数字的文本字段的表单。为了检查输入是否有效,我决定使用Hamcrest Matchers。我定义了:

public static <T> boolean checkThat(T actual, Matcher<? super T> matcher) {
    return matcher.matches(actual);
}

这样我可以使用像:

这样的东西
if(checkThat(doubleFromText,greaterThan(0.0)) doSomething();

现在这在调试模式下工作得很好,但是当我为生产版本启用proguard时,应用程序立即崩溃,并显示以下消息(通过回扫获得):

java.lang.Error: Cannot determine correct type for matchesSafely() method.
        at org.hamcrest.internal.ReflectiveTypeFinder.findExpectedType(Unknown Source)
                                                      canObtainExpectedTypeFrom
        at org.hamcrest.TypeSafeMatcher.<init>(Unknown Source)
        at org.hamcrest.TypeSafeMatcher.<init>(Unknown Source)
        at org.hamcrest.number.OrderingComparison.<init>(Unknown Source)
        at org.hamcrest.number.OrderingComparison.greaterThan(Unknown Source)
                                                  matchesSafely
        at org.hamcrest.Matchers.greaterThan(Unknown Source)

我该如何解决这个问题?

我做了一个示例问题的最小例子:https://github.com/burgerga/HamcrestMatchersWithProguard


注意:

  • 我将-dontwarn java.beans.**添加到我的proguard规则中以使其编译。
  • 在你开始告诉我之前我应该​​使用if(doubleFromText > 0),我给出的例子是简化的。在我的代码中,我使用类似

    的内容
    checkThat(textIn(myEditText),parsesToDouble(greaterThan(0.0)));
    

    其中parsesToDouble是我写的简单匹配器。我认为这是一种非常灵活和明确的方式来表明我的意图,我只是对如何使用proguard感兴趣。

1 个答案:

答案 0 :(得分:3)

因为Hamcrest使用反射,所以在缩小阶段会删除一些不应删除的方法。通过添加

,我能够再次使用它
-keepclasseswithmembers class org.hamcrest.number.** { *** matchesSafely(...); }

到proguard规则。如果你不关心稍微大一点的apk,你可以添加

-keep class org.hamcrest.** { *; }

确保删除hamcrest中的任何内容。