致命异常:版本build

时间:2019-05-15 05:13:28

标签: kotlin gson retrofit

我在应用的发行版本中遇到一个奇怪的问题。 这是我的例外

Fatal Exception: java.lang.NullPointerException`
throw with null exception
in.hopq.hopq.authentication.models.AppUpdateSourceDO$AppUpdate.getMinAllowedVersion (AppUpdateSourceDO.java:3)
in.hopq.hopq.authentication.activities.SplashActivity$onCreate$1.onChanged (SplashActivity.java:48)
in.hopq.hopq.authentication.activities.SplashActivity$onCreate$1.onChanged (SplashActivity.java:31)

Pojo文件

data class AppUpdateSourceDO(
    @SerializedName("app_update")
    val appUpdate: AppUpdate,
    @SerializedName("message")
    val message: String,
    @SerializedName("success")
    val success: Boolean
) {
data class AppUpdate(
        @SerializedName("excluded_versions")
        val excludedVersions: List<ExcludedVersion>,
        @SerializedName("min_allowed_version")
        val minAllowedVersion: Int,
        @SerializedName("min_allowed_version_ios")
        val minAllowedVersionIos: String,
        @SerializedName("recommended_version")
        val recommendedVersion: Int?
) {
    data class ExcludedVersion(
            @SerializedName("version")
            val version: String
    )
}
}

这是我的保护文件

##OKHTTP3
-keepattributes Signature
-keepattributes *Annotation*
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
-dontnote okhttp3.**
-dontwarn okio.**
-dontwarn retrofit2.Platform$Java8
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*

8 个答案:

答案 0 :(得分:4)

完全禁用R8可能不是一个好主意。但是通过在您的 Proguard Rules 文件中添加以下几行可能会解决此问题-

-keepclassmembers,allowobfuscation class * {
    @com.google.gson.annotations.SerializedName <fields>;
  }
-keep,allowobfuscation @interface com.google.gson.annotations.SerializedName

一位Google开发人员也建议将此作为理想的解决方案。您可以找到他的答案here,也可以关注有关它的整个讨论。

答案 1 :(得分:2)

最终解决了这个问题。这是由于新的R8代码混淆。只需将其添加到gradle.properties文件

即可从您的项目中禁用它

android.enableR8=false

您还可以将其添加到Proguard Rules文件中。

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

但是,将其添加到proguard并没有真正解决问题。

答案 2 :(得分:1)

我想,由于明确键入了异常,因此您在json字段min_allowed_version中收到null:

Fatal Exception: java.lang.NullPointerException throw with null 
exceptionin.hopq.hopq.authentication.models.AppUpdateSourceDO$AppUpdate.getMinAllowedVersion (AppUpdateSourceDO.java:3)

这意味着,当您调用minAllowedVersion字段的getter并返回null时,您捕获了NPE。尝试使用null安全性,也许所有方法都可以正常工作。

data class AppUpdate(
        @SerializedName("excluded_versions")
        val excludedVersions: List<ExcludedVersion> = listOf(),
        @SerializedName("min_allowed_version")
        val minAllowedVersion: Int? = null,
        @SerializedName("min_allowed_version_ios")
        val minAllowedVersionIos: String? = null,
        @SerializedName("recommended_version")
        val recommendedVersion: Int? = null
)

答案 3 :(得分:0)

似乎GSON和R8不能很好地配合工作,它的写法是here

  

实际上,以下内容也应该起作用:

     

-keepclassmembers,allowobfuscation类* {         @ com.google.gson.annotations.SerializedName;       }   -keep,allowobfuscation @interface com.google.gson.annotations.SerializedName

     

这将最小化(混淆)字段名称和属性   也可以进一步减小最终APK的大小。

此外,您可以在sample of Gson中看到以下规则:

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { <fields>; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

##---------------End: proguard configuration for Gson  ----------

答案 4 :(得分:0)

如果@SerializedName批注始终用于数据类,则可以使用以下keep规则

-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
 }

如果未使用@SerializedName批注,则可以对每个数据类使用以下保守规则:

-keepclassmembers class MyDataClass {
  !transient <fields>;
 }

有关更多信息,请查看以下链接:-

https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md

答案 5 :(得分:0)

使用@Keep批注是处理proguard文件的合理选择。只需用@Keep注释数据类,整个类及其成员将不会被缩小。

当所有属性的名称与json字段的名称匹配并且不需要用@SerializedName注释属性时,它特别有用。具有@SerializedName带注释字段(在其他答案中提到)的类的Proguard规则不适用于这种情况。

答案 6 :(得分:0)

您可能需要使用

-keepclassmembers enum * { *; }

保留您的枚举

答案 7 :(得分:0)

在我的情况下,将android.enableR8=true添加到gradle.properties中,将-keepclassmembers,allowobfuscation class * { @com.google.gson.annotations.SerializedName <fields>; }添加到我的proguard-rules.pro中,达到了目的