android - Firebase Crashlytics 使用 Retrofit 和协程报告 Android 项目上的假崩溃

标签 android kotlin okhttp crashlytics coroutine

当某个网络请求返回 400 时,Crashlytics 报告我的项目发生崩溃。我已经能够复制此问题,并且应用程序按预期显示错误弹出窗口,但它没有崩溃。我非常有信心该应用程序不会以 Crashlytics 中指定的速度崩溃,但是,我对这些数字感到担忧,并且希望它们是准确的。

最重要的是,Crashlytics 显示这种崩溃发生在应用程序的非常旧版本中,而实际上它没有发生(在将 kotlin 或协程添加到项目中之前)。

这是堆栈跟踪:

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 block 。而且因为它是一个不同的协程,所以异常不会被父级捕获,因此您也需要在那里捕获异常。

旧答案:

我也遇到同样的问题。它是在重写从 Rx 到协程的所有请求后开始的。报告同时显示在 Play 管理中心和 Crashlytics 中,但有不同的异常(exception)情况。

这是我的代码示例:

@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 block 内捕获,并且根本不会崩溃。异常(exception)示例:

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)

真的很令人沮丧,因为我每天都会收到数千份报告。

关于android - Firebase Crashlytics 使用 Retrofit 和协程报告 Android 项目上的假崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61367166/

相关文章:

java - 在 Spring Boot 应用程序中,负载均衡器请求有时会在 AWS 上意外失败

java - 如何在 HTTP POST/GET 中发送空参数

android - 带有多个文本的按钮

Android - Google Talk Intent

javascript - 是什么阻止 HtmlUnit 加载 PSN 商店页面?

Kotlin 。我可以获得所有实现特定接口(interface)的对象吗

android - picasso 不加载图像

android - 如何从 Android 的操作栏中删除分隔符?

android - 如何滑动到同一 fragment 但包含其他数据:?

android - 在 ViewModel 中收集流。需要repeatOnLifeCycle 吗?