Crashlytics在我的项目中报告了当某个网络请求返回400时的崩溃。我已经能够复制这个问题,应用程序正在按照预期显示错误弹出,但它没有崩溃。我很有信心,应用程序没有以Crashlytics中的指示速度崩溃,然而,我很担心这些数字,我希望它们是准确的。
最重要的是,Crashlytics显示,这种崩溃发生在非常老的版本的应用程序中,而它并没有发生(在kotlin或coroutines被添加到项目中之前)。
这里是堆栈跟踪。
Fatal Exception: retrofit2.HttpException: HTTP 400 Bad Request
at retrofit2.KotlinExtensions$await$2$2.onResponse + 49(KotlinExtensions.java:49)
at retrofit2.OkHttpCall$1.onResponse + 129(OkHttpCall.java:129)
at okhttp3.RealCall$AsyncCall.execute + 174(RealCall.java:174)
at okhttp3.internal.NamedRunnable.run + 32(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1113(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 588(ThreadPoolExecutor.java:588)
at java.lang.Thread.run + 818(Thread.java:818)
有谁经历过这样的问题,或者可能知道这里发生了什么?
更新
我已经找到了问题所在。我有一个这样的请求。
viewModelScope.launch {
try {
val response1 = api.request1()
launch {
val response2 = api.request2()
...
}
} catch (e: Exception) {
Log.e("TAG", "Error", e)
}
}
我没有一个 try catch
块内的第二个coroutine。因为是不同的coroutine,异常不会被父程序捕获,所以你需要在那里也捕获异常。
老答案。
我也有同样的问题 从Rx到Coroutine的所有请求重写后开始的。报告在Play Console和Crashlytics中都显示了不同的异常。
以下是我的代码示例。
@Singleton
@Provides
fun providesApi(client: OkHttpClient, gsonConverterFactory: GsonConverterFactory): Api {
return Retrofit.Builder()
.baseUrl("https://url")
.client(client.newBuilder().addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("Header1", ...)
.addHeader("Header2", ...)
.build()
chain.proceed(request)
}.build())
.addConverterFactory(gsonConverterFactory)
.build()
.create(Api::class.java)
}
viewModelScope.launch {
try {
val response = api.request()
} catch (e: Exception) {
Log.e("TAG", "Error", e)
}
}
报告显示它在以下情况下崩溃 chain.proceed(request)
. 但是当我试图通过设置1秒的超时或者甚至在拦截器中手动抛出一个异常来重现它时,所有的异常都在try块中被捕获,而且根本没有崩溃。例子异常。
java.net.SocketTimeoutException:
at okhttp3.internal.http2.Http2Stream$StreamTimeout.newTimeoutException (Http2Stream.java:4)
at okhttp3.internal.http2.Http2Stream$StreamTimeout.exitAndThrowIfTimedOut (Http2Stream.java:8)
at okhttp3.internal.http2.Http2Stream.takeHeaders (Http2Stream.java:24)
at okhttp3.internal.http2.Http2Codec.openResponseBody (Http2Codec.java:2)
at okhttp3.internal.http.CallServerInterceptor.intercept (CallServerInterceptor.java:27)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:2)
at okhttp3.internal.connection.ConnectInterceptor.intercept (ConnectInterceptor.java:4)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:2)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:69)
at okhttp3.internal.cache.CacheInterceptor.intercept (CacheInterceptor.java:69)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:2)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:27)
at okhttp3.internal.http.BridgeInterceptor.intercept (BridgeInterceptor.java:27)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:2)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept (RetryAndFollowUpInterceptor.java:70)
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:2)
at okhttp3.internal.http.RealInterceptorChain.a (RealInterceptorChain.java:6)
at myproject.dagger.Module$providesApi$1.intercept (Module.java:4) <------------------ HERE
at okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.java:2)
at okhttp3.internal.http.RealInterceptorChain.a (RealInterceptorChain.java:6)
at okhttp3.RealCall.getResponseWithInterceptorChain (RealCall.java:12)
at okhttp3.RealCall$AsyncCall.execute (RealCall.java:9)
at okhttp3.internal.NamedRunnable.run (NamedRunnable.java:17)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:636)
at java.lang.Thread.run (Thread.java:764)
异常的例子:
retrofit2.HttpException:
at retrofit2.KotlinExtensions$await$2$2.onResponse (KotlinExtensions.java:2)
at retrofit2.OkHttpCall$1.onResponse (OkHttpCall.java)
at okhttp3.RealCall$AsyncCall.a (RealCall.java)
at okhttp3.internal.NamedRunnable.run (NamedRunnable.java)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587)
at java.lang.Thread.run (Thread.java:841)
真的很沮丧,因为我每天都会收到成千上万的报告。
那么Firebase不会报告一个 Crash
除非在终端用户的设备上运行的应用程序导致了 ANR(Application Not Responding)
错误。
我建议如果可能的话,在其他物理设备上测试应用程序,或者在多个不同的android模拟器上使用firebase报告的版本代码来测试失败。