我在应用的发行版本中遇到一个奇怪的问题。 这是我的例外
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*
答案 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中,达到了目的