Android - 仅在发布 apk 时出现,java.lang.IllegalArgumentException : Unable to create converter for class

标签 android gson realm proguard retrofit2

我正在使用retrofitgsonrealm,我真的不知道是什么导致了这个错误,但它只发生在当 minifyEnabledtrue 时发布 apk,所以我猜这是一个 proguard 问题,但我不知道到底是什么问题。

这是我的错误:

java.lang.IllegalArgumentException: Unable to create converter for class com.ool.oolapp.data.models.NewsFeedResponse
   for method a.getPosts
   at retrofit2.ServiceMethod$Builder.methodError(Unknown Source)
   at retrofit2.ServiceMethod$Builder.createResponseConverter(Unknown Source)
   at retrofit2.ServiceMethod$Builder.build(Unknown Source)
   at retrofit2.Retrofit.loadServiceMethod(Unknown Source)
   at retrofit2.Retrofit$1.invoke(Unknown Source)
   at java.lang.reflect.Proxy.invoke(Proxy.java:393)
   at $Proxy1.getPosts(Unknown Source)
   at com.ool.oolapp.data.a.b.a(Unknown Source)
   at com.ool.oolapp.data.b.k.a(Unknown Source)
   at com.ool.oolapp.data.b.k.a(Unknown Source)
   at com.ool.oolapp.home.a.c.a(Unknown Source)
   at com.ool.oolapp.home.b.b.b(Unknown Source)
   at com.ool.oolapp.home.b.b.a(Unknown Source)
   at com.ool.oolapp.home.view.d.v(Unknown Source)
   at android.support.v4.b.p.L(Unknown Source)
   at android.support.v4.b.v.a(Unknown Source)
   at android.support.v4.b.v.e(Unknown Source)
   at android.support.v4.b.v.a(Unknown Source)
   at android.support.v4.b.g.e(Unknown Source)
   at android.support.v4.b.v.b(Unknown Source)
   at android.support.v4.b.v.a(Unknown Source)
   at android.support.v4.b.v.b(Unknown Source)
   at android.support.v4.b.v.b(Unknown Source)
   at android.support.v4.b.g.d(Unknown Source)
   at android.support.v4.b.aa.b(Unknown Source)
   at android.support.v4.view.ViewPager.a(Unknown Source)
   at android.support.v4.view.ViewPager.c(Unknown Source)
   at android.support.v4.view.ViewPager.onMeasure(Unknown Source)
   at android.view.View.measure(View.java:18794)
   at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
   at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
   at android.view.View.measure(View.java:18794)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
   at android.support.v7.widget.ContentFrameLayout.onMeasure(Unknown Source)
   at android.view.View.measure(View.java:18794)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
   at android.view.View.measure(View.java:18794)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
   at android.view.View.measure(View.java:18794)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
   at android.view.View.measure(View.java:18794)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
   at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643)
   at android.view.View.measure(View.java:18794)
   at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2100)
   at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1216)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1452)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
   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)

这是 com.ool.oolapp.data.models.NewsFeedResponse:

public class NewsFeedResponse {
    @SerializedName("posts")
    private List<Post> posts;

    public List<Post> getPosts() {
        return posts;
    }

    public void setPosts(List<Post> posts) {
        this.posts = posts;
    }
}

Post.java:

    @RealmClass
public class Post implements RealmModel {
    @PrimaryKey
    @SerializedName("postId")
    private int postId;
    @SerializedName("userId")
    private int userId;
    @SerializedName("userDto")
    private UserDto userDto;
    @SerializedName("caption")
    private String caption;
    @SerializedName("voiceDuration")
    private int voiceDuration;
    @SerializedName("commentCount")
    private int commentCount;
    @SerializedName("likesCount")
    private int likesCount;
    @SerializedName("shareCount")
    private int shareCount;
    @SerializedName("picUrl")
    private String picUrl;
    @SerializedName("voiceUrl")
    private String voiceUrl;
    @SerializedName("creationDate")
    @JsonAdapter(TimestampDeserializer.class)
    private Date creationDate;
    @SerializedName("comments")
    private RealmList<Comment> comments;

    public Post() {
    }

    public Post(String picUrl, String caption, int voiceDuration) {
        this.picUrl = picUrl;
        this.caption = caption;
        this.voiceDuration = voiceDuration;
    }

    public String getCreatedFrom()
    {
        return Utility.getCreatedFromString(creationDate);
    }

    public int getPostId() {
        return postId;
    }

    public String getPicUrl() {
        return picUrl;
    }

    public void setPicUrl(String picUrl) {
        this.picUrl = picUrl;
    }

    public int getVoiceDuration() {
        return voiceDuration;
    }

    public void setVoiceDuration(int voiceDuration) {
        this.voiceDuration = voiceDuration;
    }

    public String getVoiceUrl() {
        return voiceUrl;
    }

    public void setVoiceUrl(String voiceUrl) {
        this.voiceUrl = voiceUrl;
    }

    public int getUserId() {
        return userId;
    }

    public void setPostId(int postId) {
        this.postId = postId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
    }

    public int getCommentCount() {
        return commentCount;
    }

    public void setCommentCount(int commentCount) {
        this.commentCount = commentCount;
    }

    public int getLikesCount() {
        return likesCount;
    }

    public void setLikesCount(int likesCount) {
        this.likesCount = likesCount;
    }

    public int getShareCount() {
        return shareCount;
    }

    public void setShareCount(int shareCount) {
        this.shareCount = shareCount;
    }

    public RealmList<Comment> getComments() {
        return comments;
    }

    public void setComments(RealmList<Comment> comments) {
        this.comments = comments;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public UserDto getUserDto() {
        return userDto;
    }

    public void setUserDto(UserDto userDto) {
        this.userDto = userDto;
    }
}

我的 UserDto 类:

@RealmClass
public class UserDto implements RealmModel {
    @PrimaryKey
    @SerializedName("userId")
    private int userId;
    @SerializedName("fName")
    private String fName;
    @SerializedName("lName")
    private String lName;
    @SerializedName("pictureLocation")
    private String pictureLocation;

    public UserDto() {}

    public UserDto(int userId, String fname, String lname, String pictureLocation) {
        setUserId(userId);
        setfName(fname);
        setlName(lname);
        setPictureLocation(pictureLocation);
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getFName() {
        return fName;
    }

    public String getLName() {
        return lName;
    }

    public String getPictureLocation() {
        return pictureLocation;
    }

    public void setfName(String fName) {
        this.fName = fName;
    }

    public void setlName(String lName) {
        this.lName = lName;
    }

    public void setPictureLocation(String pictureLocation) {
        this.pictureLocation = pictureLocation;
    }
}

这是我的 retrofit 配置:

private Retrofit.Builder createRetrofitBuilder() {
    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
    if(BuildConfig.BUILD_TYPE.equals("release")) {
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
    } else {
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    }
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(httpLoggingInterceptor)
            .build();
    GsonBuilder gsonBuilder = new GsonBuilder();
    return new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()));
}

最后是我的 Proguard 文件:

    # retrofit
    # Platform calls Class.forName on types which do not exist on Android to determine platform.
    -dontnote retrofit2.Platform
    # Platform used when running on Java 8 VMs. Will not be used at runtime.
    -dontwarn retrofit2.Platform$Java8
    # Retain generic type information for use by reflection by converters and adapters.
    -keepattributes Signature
    # Retain declared checked exceptions for use by a Proxy instance.
    -keepattributes Exceptions
    #okio
    -dontwarn okio.**
    #Picasso
    -dontwarn com.squareup.okhttp.**
    #retrolambda
    -dontwarn java.lang.invoke.*
    -dontwarn **$$Lambda$*

    # Amazon AWS
    -dontwarn com.fasterxml.jackson.core.**
    # Guava
    -dontwarn sun.misc.Unsafe
    -dontwarn java.lang.ClassValue

    -keep class retrofit2.** { *; }
    -keep class com.ool.oolapp.data.models.** {*;}
    -keepclassmembernames interface * {
        @retrofit2.http.* <methods>;
    }
    -keepattributes *Annotation*

最佳答案

似乎 Retrofit 在 getPosts() 方法中失败了,很可能是因为找不到 Post 类。似乎您没有包含 Realm 特定的 ProGuard 规则:

-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class *
-dontwarn javax.**
-dontwarn io.realm.**

强制所有用 @RealmModule 注释的类在混淆和修整期间被保留。将这些规则添加到您的 ProGuard 文件应该可以解决问题。

关于Android - 仅在发布 apk 时出现,java.lang.IllegalArgumentException : Unable to create converter for class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44813631/

相关文章:

java - RadioGroup 扩展 RelativeLayout?

json - 如何防止 Gson 序列化/反序列化字段的第一个字符(下划线)?

Android - 使用哪个 Active Android 或 Realm

ios - 如何以编程方式备份​​ Realm 文件?

ios - 从 Realm 对象创建的用户具有相同的主键 Realm

android - 如何使用 Android NDK SQLite3 扩展 json1

android - 以编程方式将默认样式设置回按钮

android - 为什么样本使用?引用样式 listSeparatorTextViewStyle 时?

json - GSON/JSON : Weird special char (umlaut) issue

java - 我无法从 JSON 数组获取图像字节,有人可以帮助我吗?