【问题标题】:Google Places API: Runtime exception not caughtGoogle Places API:未捕获运行时异常
【发布时间】:2018-10-12 07:22:03
【问题描述】:

我遇到了与this question 类似的问题。不过,与那个问题不同的是,我的设置正确(API 密钥在清单中指定,在 Google 控制台上启用了地图和地点 API),因为代码大多数时间都可以工作:

private fun performPlaceDetection() {
        // use the Places API.
        try {
            val placeResult = placeDetectionClient.getCurrentPlace(null)
            placeResult.addOnCompleteListener({ task ->
                val likelyPlaces = task.result
                for (placeLikelihood in likelyPlaces) {
                    Timber.d( String.format("Place '%s' has likelihood: %g",
                            placeLikelihood.place.name,
                            placeLikelihood.likelihood))
                }
                likelyPlaces.release()
            })
        } catch (e: SecurityException) {
            Timber.d("error fetching current place. permissions?: " + e.message)
            e.printStackTrace()
        } catch (e: RuntimeExecutionException) {
            Timber.d("error fetching current place: " + e.message)
            e.printStackTrace()
        }
    }

代码偶尔会失败:

com.google.android.gms.tasks.RuntimeExecutionException: com.google.android.gms.common.api.ApiException: 13: ERROR

或者当我关闭网络连接时,我收到此错误:

com.google.android.gms.tasks.RuntimeExecutionException: com.google.android.gms.common.api.ApiException: 7: NETWORK_ERROR

让我难过的是,无论哪种情况,异常 (RunTimeExecutionException) 都没有被捕获。我知道在 Kotlin 中,所有异常都是未经检查的,但我想如果出现错误它们会被捕获。有什么线索吗?

更新: 看起来像捕获异常inside OnCompleteListener 有效,而外部没有被捕获:

try {
            val placeResult = placeDetectionClient.getCurrentPlace(null)
            placeResult.addOnCompleteListener({ task ->
                try {
                    val likelyPlaces = task.result
                    for (placeLikelihood in likelyPlaces) {
                        Timber.d( String.format("Place '%s' has likelihood: %g",
                                placeLikelihood.place.name,
                                placeLikelihood.likelihood))
                    }
                    likelyPlaces.release()
                } catch (e: Exception) {
                    Timber.d("inner exception: $e")
                }
            })
        } catch(e: Exception) {
            Timber.d("outer exception: " + e::class.qualifiedName)
        } 

我不确定为什么会捕获内部异常。我的猜测是这是因为placeDetectionClient.getCurrentPlace() 异步运行(并且错误是由 Places API 从单独的线程引发的),但我不确定(performPlaceDetection() 是从 Android 应用程序的 MainActivity 调用的)。希望能对此提供一些意见。

【问题讨论】:

  • 您的更新帮助了我.. 请作为答案。谢谢。

标签: android exception exception-handling kotlin google-places-api


【解决方案1】:

看起来像是在 OnCompleteListener 中捕获异常,而外部没有被捕获:

try {
        val placeResult = placeDetectionClient.getCurrentPlace(null)
        placeResult.addOnCompleteListener({ task ->
            try {
                val likelyPlaces = task.result
                for (placeLikelihood in likelyPlaces) {
                     Timber.d( String.format("Place '%s' has likelihood: %g",
                           placeLikelihood.place.name,
                           placeLikelihood.likelihood))
                }
                likelyPlaces.release()
            } catch (e: Exception) {
                Timber.d("inner exception: $e")
            }
        })
    } catch(e: Exception) {
            Timber.d("outer exception: " + e::class.qualifiedName)
} 

我不确定为什么会捕获内部异常。我的猜测是这是因为 placeDetectionClient.getCurrentPlace() 异步运行(并且错误是由 Places API 从单独的线程引发的)但我不确定(从 Android 应用程序的 MainActivity 调用 performPlaceDetection())

【讨论】:

    【解决方案2】:

    请忽略那些告诉您应该使用 try-catch 和来自 Google 图书馆的 Task<T> 的答案。

    这里的问题是人们试图从失败的任务中获得结果。

    如果您查看源代码,您可以清楚地看到,如果您正在访问task.resulttask.exception != null,则实现将抛出RuntimeExecutionException

    您应该像这样访问结果:

    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener {
                if (it.isSuccessful) {
                    val token = it.result?.token
                    if (!token.isNullOrBlank()) {
                        //do something with the token
                    } else {
                        logger.error("Token Is Empty")
                    }
                } else {
                    val error = it.exception ?: Exception("Empty Exception")
                    logger.error("$error")
                }
            }
    

    【讨论】:

      【解决方案3】:

      确保RunTimeExecutionException 是从com.google.android.gms.tasks.RuntimeExecutionException 导入的。您可能从不同的包中导入了它,这意味着它是一个不同的例外。

      【讨论】:

      • 我相信我的导入正确:import com.google.android.gms.tasks.RuntimeExecutionException
      • 我认为实际抛出的异常可能是未捕获的ApiException,稍后抛出RuntimeExecutionException,因为未捕获ApiException。我认为这是因为它嵌套在 RuntimeExecutionException 的异常消息中。你能证实这一点吗?如果是这种情况,我会更新我的答案。
      • 我最初试图捕捉ApiException,但遇到了同样的问题,那就是当我转而尝试捕捉RuntimeExecutionException
      • 在捕获 ApiException 时是否也遇到同样的错误?
      • 您可以尝试添加此 catch 语句吗? catch(e: Exception) { println(e::class.qualifiedName) }
      猜你喜欢
      • 2017-12-30
      • 2014-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 1970-01-01
      • 2020-08-04
      相关资源
      最近更新 更多