【问题标题】:ProtocolException: Too many follow-up requests: 21 with Proguard and OkHttp 3.0 in AndroidProtocolException:太多后续请求:Android 中使用 Proguard 和 OkHttp 3.0 的 21 个
【发布时间】:2017-03-29 01:22:20
【问题描述】:

我正在使用 Retrofit 2.1.0 和 OkHttp 3.4.2 创建一个应用程序。

在调试模式下,将 minifyEnabled 设置为 false,一切正常,但是一旦我将 minifyEnabled 更改为 true,我就会得到以下异常:

HTTP FAILED: java.net.ProtocolException: Too many follow-up requests: 21

我的 OkHttp 的 Proguard 规则如下:

-keep class com.squareup.okhttp3.** {
    *;
}
-dontwarn okhttp3.**
-dontwarn okio.**

我不明白为什么会抛出这个异常,也不明白为什么应用程序似乎发出了 21 个跟进请求。谁能帮帮我?

【问题讨论】:

    标签: android proguard retrofit2 android-proguard okhttp3


    【解决方案1】:

    我刚刚遇到了同样的错误:java.net.ProtocolException: Too many follow-up requests: 21。为了您的兴趣,我使用的是 Retrofit 2.5.0 和 OkHttp 3.14.1,尽管版本并不重要。

    我也只有在启用 Proguard 时才会出现此错误(实际上我使用的是 R8,但结果是一样的)。这很重要,并暗示了根本原因。

    有什么问题?我使用 OAuth 进行身份验证,像往常一样添加“授权”标头。当令牌过期时,服务器会发送 401 Unauthorized。由于我使用 OkHttp Authenticator 来刷新令牌,所以当收到 401 时会调用 authenticate 方法。

    问题是我使用 Gson 解析这个 401 Unauthorized 请求的响应,像这样:

    override fun authenticate(route: Route?, response: Response): Request? {
        val responseError: ResponseError? = response.body()?.let {
            Gson().fromJson(it.string(), ResponseError::class.java) // <- Fails!
        }
        // Check server response and decide if should refresh token...
    }
    

    但是由于 ResponseError 类被 proguard 混淆了,它的字段与服务器发送的 JSON 的名称不匹配,这使得 Gson().fromJson 失败,因此令牌不是神清气爽。结果是重复执行网络调用,直到抛出异常。

    修复很简单。只需将@Keep 添加到ResponseError

    import androidx.annotation.Keep
    
    @Keep
    data class ResponseError(
        val error: String? = null,
        val error_description: String? = null
    )
    

    由于您的问题仅发生在启用 proguard 的情况下,因此请求或响应类可能被混淆,从而导致 JSON 解析失败。或者,您可能正在使用带有混淆类的 Gson.fromJsonGson.fromJson 将一些 JSON 保存到共享首选项。

    要解决此问题,请将@SerializedName 和/或@Keep 添加到您的所有请求和响应中(特别是枚举,这会带来更多麻烦)。或者,您可以简单地将所有请求和响应放入一个包和exclude it。除了请求和响应之外,还要特别注意任何Gson.fromJsonGson.fromJson 呼叫。

    为了帮助诊断问题,您可以通过检查在app/build/outputs/mapping/release/mapping.txt 中找到的映射文件(对于发布版本)来检查 proguard/R8 的功能。它包含 proguard/R8 对您的代码所做的所有转换。

    您还可以通过 Build -> Analyze APK... 分析 APK... 您会以非常简单的方式查看哪些类被混淆了。您可以同时分析 2 个 APK(一个已缩小,一个未缩小)并进行比较。

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 2016-05-10
      • 1970-01-01
      • 2018-07-13
      • 1970-01-01
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 2019-08-27
      相关资源
      最近更新 更多