4

I'm having problems similar to the one at this question. Unlike in that question though, I have the correct set up (API keys are specified in the manifest, maps & places APIs enabled on the Google console) because the code works most of the time:

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()
        }
    }

The code occasionally fails with this:

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

or when I turn off network connectivity, I get this error:

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

What stumps me is that in either case, the exception (RunTimeExecutionException) is not caught. I understand that in Kotlin, all exceptions are unchecked but I'd imagine they'd be caught if there was an error. Any clues?

UPDATE: Looks like catching the exception inside the OnCompleteListener works, whereas the outer one is not caught:

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)
        } 

I'm not sure why the inner exception is caught. My guess is that it's because placeDetectionClient.getCurrentPlace() runs asynchronously (and that the errors are thrown by the Places API from a separate thread) but I'm not sure (performPlaceDetection() is called from the MainActivity of an Android app). Would appreciate some input on this one.

kip2
  • 6,473
  • 4
  • 55
  • 72

3 Answers3

4

Looks like catching the exception inside the OnCompleteListener works, whereas the outer one is not caught:

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)
} 

I'm not sure why the inner exception is caught. My guess is that it's because placeDetectionClient.getCurrentPlace() runs asynchronously (and that the errors are thrown by the Places API from a separate thread) but I'm not sure (performPlaceDetection() is called from the MainActivity of an Android app)

kip2
  • 6,473
  • 4
  • 55
  • 72
2

Please kindly ignore the answers telling that you should use try-catch with a Task<T> from Google Libraries.

The issue here is that people are trying to get a result from a failed task.

If you look at the source code you can clearly see that if you are accessing task.result and task.exception != null the implementation will throw a RuntimeExecutionException.

You should access the result like this:

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")
    }
}
Alexander M.
  • 3,308
  • 2
  • 20
  • 31
1

Make sure RunTimeExecutionException is imported fromcom.google.android.gms.tasks.RuntimeExecutionException. You might have imported it from a different package, which would mean it is a different exception.

J. Leander
  • 354
  • 1
  • 2
  • 12
  • I believe I have the correct import: `import com.google.android.gms.tasks.RuntimeExecutionException` – kip2 May 02 '18 at 12:13
  • I think the actual thrown exception might be ApiException, which is uncaught and the RuntimeExecutionException is thrown later, because ApiException is uncaughed. I think this because it is nested within the exception message of RuntimeExecutionException. Can you verify this? I'll update my answer if this was the case. – J. Leander May 02 '18 at 13:57
  • I initially tried to catch `ApiException` but had the same problem, and that is when I switched to trying to catch `RuntimeExecutionException` instead – kip2 May 02 '18 at 14:25
  • Do you get the same error when catching ApiException instead? – J. Leander May 02 '18 at 14:49
  • could you try to add this catch statement? `catch(e: Exception) { println(e::class.qualifiedName) }` – J. Leander May 02 '18 at 14:59
  • I turned off connectivity (to force a network-related `RuntimeExecutionException`) and tried to catch the generic `Exception`, and like before, it's not caught and I just end up with the usual error: `com.google.android.gms.tasks.RuntimeExecutionException: com.google.android.gms.common.api.ApiException: 7: NETWORK_ERROR at com.google.android.gms.tasks.zzu.getResult(Unknown Source:17) at com.example.app.MyActivity$performPlaceDetection$1.onComplete(MyActivity.kt:197)` – kip2 May 03 '18 at 09:20