我刚遇到了完全相同的错误:
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)
}
}
由于 ResponseError
类被 Proguard 混淆,导致其字段与服务器发送的 JSON 的名称不匹配,使得 Gson().fromJson
调用失败,结果导致令牌无法刷新。这样就会不停地进行网络调用,直到异常抛出。
解决方法很简单。只需在 ResponseError
上添加 @Keep
注释即可:
import androidx.annotation.Keep
@Keep
data class ResponseError(
val error: String? = null,
val error_description: String? = null
)
由于您的问题仅在启用proguard时出现,因此很可能是某个请求或响应类被混淆导致JSON解析失败。或者您可能正在使用
Gson.fromJson
和
Gson.fromJson
将一些JSON保存到共享首选项中,并使用混淆过的类。
为解决该问题,请在所有请求和响应(特别是枚举类型,它们更容易出现问题)上添加
@SerializedName
和/或
@Keep
。或者,您可以将所有请求和响应放入一个单独的包中,并
将其排除。除了请求和响应之外,还要特别注意任何
Gson.fromJson
和
Gson.fromJson
的调用。
为帮助诊断问题,您可以检查proguard/R8所做的工作,方法是检查您将在
app/build/outputs/mapping/release/mapping.txt
(针对发布版本)中找到的映射文件。它包含proguard/R8对您的代码所做的所有转换。
您还可以通过Build -> Analyze APK... 分析APK。您将以非常简单的方式看到哪些类正在被混淆。您可以同时分析2个APK(一个经过缩小,一个未经缩小)并进行比较。