【问题标题】:Retrofit2 proguard occur: java.lang.AbstractMethodError: abstract method "void retrofit2.Callback.onResponse(retrofit2.Call, retrofit2.Response)"Retrofit2 proguard 发生:java.lang.AbstractMethodError:抽象方法“void retrofit2.Callback.onResponse(retrofit2.Call, retrofit2.Response)”
【发布时间】:2018-10-25 10:09:32
【问题描述】:

我正在开发一个自定义模块项目,其中有一个管理器类(下面称为“ManagerClass”)作为该模块的主要入口。在这个类中,我使用retrofit2 将http API 与入队模式连接起来。

现在,让我抓狂的是,在Debug buildType中,整个模块运行正常!但是如果我要制作JAR,那就意味着在发布模式下,我想混合模块并发生异常!

这是我的 API 方法:

public void apiGetPublicIpInfo2(Callback<TestIp> callback) {
    Call<TestIp> call = apiService.getPublicIpInfo("http://ipinfo.io/json");
    call.enqueue(callback);
}

这是我在ManagerClass中的用法:

mApiManager.apiGetPublicIpInfo2(new Callback<TestIp>() {
        @Override
        public void onResponse(Call<TestIp> call, Response<TestIp> response) {
            ...
        }

        @Override
        public void onFailure(Call<TestIp> call, Throwable t) {
            ...
        }
    });

但如果我创建 JAR,它会变成这样:

enter image description here

retrofit2.Callback的抽象方法onResponseonFailure混用了!

结果是:

java.lang.AbstractMethodError: abstract method "void retrofit2.Callback.onResponse(retrofit2.Call, retrofit2.Response)"
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
    at android.os.Handler.handleCallback(Handler.java:809)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:166)
    at android.app.ActivityThread.main(ActivityThread.java:7377)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963)

proguard-rules.pro 文件是普通类型,就像:

-keep class com.----.ManagerClass {
    public <fields>;
    public <methods>;
}

即使我把它改成

-keep class com.----.ManagerClass {
    *;
}

匿名内部类“new Callback(){}”的重写方法onResponseonFailure还是混的……

我的模块 build.gradle 是:

apply plugin: 'com.android.library'
android {
    compileSdkVersion 26

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 26
        versionCode 1
        versionName "0.0.1"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            jniDebuggable true
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            jniDebuggable false
        }
    }
    lintOptions {
        abortOnError false
    }
}
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
}

在我尝试了一些方法(例如编辑 proguard 文件)后,我不知道如何修复它。

【问题讨论】:

  • 你的改造版本是什么?
  • 最新版本“com.squareup.retrofit2:retrofit:2.4.0”
  • 可以添加build.gradle 文件的代码(所有依赖项)吗?
  • 我刚刚更新了问题。感谢您关注我的问题~

标签: java android gradle retrofit2 android-proguard


【解决方案1】:

尝试设置此选项:

-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

更多详细设置见:https://github.com/square/retrofit/blob/master/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro

【讨论】:

  • 我试过了,但在我看来,当我像你说的那样做时,异常仍然发生,原因是回调仍然在未混淆的情况下调用 onResponse。但是我的模块被混淆了,所以覆盖方法 onResponse 变成了方法“a”。无论如何,当我不混淆我的模块时没有问题
【解决方案2】:

解决了我的问题:

# 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
-dontwarn org.xmlpull.v1.**
-dontwarn okhttp3.**

-dontwarn retrofit2.**
-keep class retrofit2.** { *; }


-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

-dontwarn javax.annotation.GuardedBy
-dontwarn javax.annotation.**

您需要保留模型,不要混淆它们。我看到你的模型有错误,sqlite 不能在你的模型上工作。应该是这样的:

-keep class package.to.yourmodels.** { *; }

【讨论】:

  • 我试过了。当我像你说的那样做时,异常仍然发生,原因是回调仍然在未混淆的情况下调用 onResponse。但是我的模块被混淆了,所以覆盖方法 onResponse 变成了方法“a”。无论如何,正如你的想法,当我不混淆我的模块时没有问题。但这是我的要求……
猜你喜欢
  • 2016-12-20
  • 2016-06-10
  • 2017-08-24
  • 2017-05-11
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
相关资源
最近更新 更多