Google 地方 API: 未捕获运行时异常

Google Places API: Runtime exception not caught

我遇到的问题与 中的问题类似。与那个问题不同的是,我有正确的设置(API 键在清单中指定,地图和地方 APIs 在 Google 控制台上启用)因为代码有效 大多数时间:

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() 是从 MainActivity 调用的Android 应用)。将不胜感激对此的一些投入。

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

看起来在 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 从单独的线程抛出的)但我不确定(从 MainActivity 调用 performPlaceDetection() Android 个应用)

请忽略告诉您应该将 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")
            }
        }