java.util.Date null 与 ProGuard

Posted

技术标签:

【中文标题】java.util.Date null 与 ProGuard【英文标题】:java.util.Date null with ProGuard 【发布时间】:2017-01-18 22:29:23 【问题描述】:

项目: https://github.com/dakshj/TMDb_Sample

当我在Development_Debug Build Flavor 中运行应用程序时,模型 Movie.java 返回一个非空 Date 对象,因此使用 DataBinding 处理它 here 工作正常。 TextView 填充了格式化的日期字符串。

但是,当我在 Development_Release Build Flavor 和 minifyEnabled true 中使用完全相同的代码运行应用程序时, 应用程序崩溃,NullPointerException 带有以下堆栈跟踪:

FATAL EXCEPTION: main
Process: com.daksh.tmdbsample, PID: 10470
Theme: themes:default=overlay:com.baranovgroup.nstyle, iconPack:com.baranovgroup.nstyle, fontPkg:com.baranovgroup.nstyle, com.android.systemui=overlay:com.baranovgroup.nstyle, com.android.systemui.navbar=overlay:com.baranovgroup.nstyle
java.lang.NullPointerException: Attempt to invoke virtual method 'long java.util.Date.getTime()' on a null object reference
    at java.util.Calendar.setTime(Calendar.java:1197)
    at java.text.SimpleDateFormat.formatImpl(SimpleDateFormat.java:527)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:829)
    at java.text.DateFormat.format(DateFormat.java:314)
    at com.daksh.tmdbsample.data.model.Movie.a(Unknown Source)
    at com.daksh.tmdbsample.databinding.MovieDetailBinding.b(Unknown Source)
    at android.databinding.ViewDataBinding.a(Unknown Source)
    at android.databinding.ViewDataBinding$6.run(Unknown Source)
    at android.databinding.ViewDataBinding$5.onViewAttachedToWindow(Unknown Source)
    at android.view.View.dispatchAttachedToWindow(View.java:14535)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2836)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2843)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1372)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1115)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6023)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
    at android.view.Choreographer.doCallbacks(Choreographer.java:670)
    at android.view.Choreographer.doFrame(Choreographer.java:606)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5461)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

此外,当我将-dontobfuscate 规则添加到我的 proguard-rules.pro.

请帮我解决这个崩溃问题(我不想将-dontobfuscate 添加到我的 ProGuard 规则中)。

我应该添加哪些 ProGuard 规则?可能是 Gson 和 java.util.Date 的东西?

【问题讨论】:

【参考方案1】:

显然Movie.java 中的这个语法糖停止工作:

@BindingAdapter("releaseDate")

您要么需要重写代码,要么在 proguard 中为此类设置异常。

【讨论】:

然而,@BindingAdapter 的其他用法在启用ProGuard 的情况下工作得很好。见here 和here。【参考方案2】:

您正在将 BindingAdapter 用于被混淆的字段 (releaseDate)。这不起作用,您需要保持该字段不被混淆。我的建议是添加以下内容:

-keep class com.daksh.tmdbsample.data.model.Movie 
    private final java.util.Date releaseDate;

如果您有更多需要保持字段名称不混淆的情况,我建议使用注释来使此类字段保持这样的规则(假设您在它们上使用@SerializedName 注释):

-keepclassmembers class * 
    @com.google.gson.annotations.SerializedName <fields>;

【讨论】:

我只对名称与其在 JSON 字符串中的键不同的字段使用 @SerializedName。所以我想我必须检查每个字段并根据您的第一个建议添加规则。 使用 \@SerializedName 只是一个建议。如果您不想使用它,您还可以查看 Android 支持注释库中的 \@Keep 注释:tools.android.com/tech-docs/support-annotations

以上是关于java.util.Date null 与 ProGuard的主要内容,如果未能解决你的问题,请参考以下文章

java util.Date 转换为sql.Date

java.util.Date与java.sql.Date

java.util.Date 与 java.sql.Date

mybatis报错: java.lang.IllegalArgumentException invalid comparison: java.util.Date and java.lang.Stri

util.date和sql.date的衔接处理

java中,Date如何格式化为“yyyy-MM-dd”格式Date,并可按需求格式输出!(java.util.Date)