【问题标题】:Gson error when enabling proguard启用 proguard 时出现 Gson 错误
【发布时间】:2018-04-12 02:29:30
【问题描述】:

我正在尝试在我的项目中启用 proguard,但我的班级不断被 proguard 混淆,我收到了以下消息:

 Process: com.myapp.myapp, PID: 4313
                                                                 java.lang.IllegalArgumentException: Unable to create converter for class com.myapp.myapp.data.remote.response.LoginResponse
                                                                     for method AccountsEndPoint.login
                                                                     at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:752)
                                                                     at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:738)
                                                                     at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:169)
                                                                     at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
                                                                     at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
                                                                     at java.lang.reflect.Proxy.invoke(Proxy.java:813)
                                                                     at $Proxy1.login(Unknown Source)
                                                                     at com.myapp.myapp.presentation.activities.LoginActivity.a(LoginActivity.java:211)
                                                                     at com.myapp.myapp.presentation.activities.LoginActivity$1.onClick(LoginActivity.java:97)
                                                                     at android.view.View.performClick(View.java:5637)
                                                                     at android.view.View$PerformClick.run(View.java:22429)
                                                                     at android.os.Handler.handleCallback(Handler.java:751)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:154)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                                  Caused by: java.lang.IllegalArgumentException: class com.myapp.myapp.data.b.a.a declares multiple JSON fields named a
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:170)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
                                                                     at com.google.gson.Gson.getAdapter(Gson.java:423)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
                                                                     at com.google.gson.Gson.getAdapter(Gson.java:423)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
                                                                     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
                                                                     at com.google.gson.Gson.getAdapter(Gson.java:423)
                                                                     at retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:64)
                                                                     at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:330)
                                                                     at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:313)
                                                                     at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:736)
                                                                     at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:169) 
                                                                     at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170) 
                                                                     at retrofit2.Retrofit$1.invoke(Retrofit.java:147) 
                                                                     at java.lang.reflect.Proxy.invoke(Proxy.java:813) 
                                                                     at $Proxy1.login(Unknown Source) 
                                                                     at com.myapp.myapp.presentation.activities.LoginActivity.a(LoginActivity.java:211) 
                                                                     at com.myapp.myapp.presentation.activities.LoginActivity$1.onClick(LoginActivity.java:97) 
                                                                     at android.view.View.performClick(View.java:5637) 
                                                                     at android.view.View$PerformClick.run(View.java:22429) 
                                                                     at android.os.Handler.handleCallback(Handler.java:751) 
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                     at android.os.Looper.loop(Looper.java:154) 
                                                                     at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                                     at java.lang.reflect.Method.invoke(Native Method) 
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

我在我的模型中使用@SerializedName 注释,我也将添加到我的proguard-rules.pro:

-keep class com.myapp.myapp.data.remote.request.** { *;}
-keep class com.myapp.myapp.data.remote.response.** { *; }

【问题讨论】:

    标签: android gson proguard android-proguard


    【解决方案1】:

    您是否遇到此错误,请检查您是否:

    1 - 将@SerializedName 添加到模型的属性中。 (这有助于 GSON 找到真实姓名)

    2 - 将此配置添加到您的 proguard 文件中:

    ###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.** { *; }
    
    
    # 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
    
    ##---------------End: proguard configuration for Gson  ----------
    -keep class com.myapp.data.remote.request.** { *; } # <--- Add your models package here
    

    3- 如果您不断收到此错误,请检查您的所有模型是否都在使用 @SerializedName 并且是否在上述规则中包含的包中

    【讨论】:

      【解决方案2】:

      您可能需要从following link 为 gson 添加 proguard。它包含以下内容:

      ##---------------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.** { *; }
      
      # 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
      
      ##---------------End: proguard configuration for Gson  ----------
      

      更新

      您可以尝试通过以下方式保留班级中的字段:

      -keep class com.myapp.myapp.data.remote.request.** { <fields>; }
      -keep class com.myapp.myapp.data.remote.response.** { <fields>; }
      

      【讨论】:

      • 我已经更新了我的答案,添加了如何保留这些字段。
      • 试过你的答案我也试过用这个:-keepclassmembers class com.myapp.myapp.data.remote.request.** { ; } -keepclassmembers 类 com.myapp.myapp.data.remote.response.** { ; }
      【解决方案3】:

      Proguard 会混淆您的类、字段和方法名称,使其无法反序列化。

      首先尝试在模型类的所有字段中使用@SerializedName 注解。

      例如。

      @SerializedName("name")
      private String name;
      

      还使用@ישו אוהב אותך 提到的适当的 proguard 设置。

      如果其中任何一个都不能解决您的问题,最后的办法是禁用 proguard。

      在文件build.gradle中设置minifyEnabled false

      【讨论】:

      • 就像我在问题中所说的那样,我正在使用 @SerializedName 也试图使用 proguard 规则来保持我的班级。
      猜你喜欢
      • 2018-12-17
      • 1970-01-01
      • 2019-11-09
      • 2013-10-07
      • 2019-05-04
      • 2021-04-12
      • 1970-01-01
      • 2015-10-28
      • 2014-07-28
      相关资源
      最近更新 更多