Я решил обернуть получение местоположения устройства (один раз, без обновления), используя kotlin coriutines, поэтому, наконец, я получил этот код:
@SuppressLint("MissingPermission")
suspend fun LocationManager.getCurrentLocationOnce(): Location {
return suspendCancellableCoroutine { continuation ->
try {
val locationListener = object : SimpleLocationListener {
override fun onLocationChanged(location: Location?) {
if (location == null) {
this@getCurrentLocationOnce.removeUpdates(this)
continuation.resumeWithException(FailedToRetrieveLocationException("Location is NULL"))
} else {
this@getCurrentLocationOnce.removeUpdates(this)
continuation.resume(location)
}
}
override fun onProviderEnabled(provider: String?) {}
override fun onProviderDisabled(provider: String?) {
this@getCurrentLocationOnce.removeUpdates(this)
continuation.resumeWithException(ProviderDisabledException(provider ?: ""))
}
}
this.requestSingleUpdate(
LocationManager.GPS_PROVIDER,
locationListener,
null
)
} catch (e : Exception) {
continuation.resumeWithException(e)
}
}
}
Когда GPS включен, все работает нормально, но когда GPS включен Программа OFF не работает с исключением ProviderDisabledException
, это из-за:
override fun onProviderDisabled(provider: String?) {
this@getCurrentLocationOnce.removeUpdates(this)
continuation.resumeWithException(ProviderDisabledException(provider ?: ""))
}
Но я не знаю, почему это не удается, потому что на месте, где я использую эту функцию, у меня есть:
try {
val locationManager = (requireActivity().getSystemService(Context.LOCATION_SERVICE) as? LocationManager)
?: throw FailedToRetrieveLocationException("Location Service is null")
val location = locationManager.getCurrentLocationOnce()
log("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle",
"Successfully got location={lat:${location.latitude}, long:${location.longitude}}")
downloadRestaurantsWithLocation(location)
} catch (ex : FailedToRetrieveLocationException) {
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", ex)
throw ex
} catch (providerException : ProviderDisabledException) {
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", providerException)
throw providerException
} catch (e : Exception) {
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", e)
throw e
}
Итак, я регистрирую исключение и повторно бросаю его в функцию вызывающего абонента, а в функции вызывающего абонента я ловлю это исключение:
try {
log("[GOOGLE] downloadRestaurants", "Starting donwload restaurants for GOOGLE")
downloadRestaurantsWithGPSLocationGoogle()
} catch (e : Exception) {
logError("[GOOGLE] error happened while getting location", e)
downloadRestaurantsWithFusedLocationGoogle()
}
И в трассировке стека ошибок у меня есть только это:
E/[GOOGLE] downloadRestaurantsWithGPSLocationGoogle: my.package.location.exceptions.ProviderDisabledException: Provider gps disabled
at my.package.common.location.LocationUtilsKt$getCurrentLocationOnce$$inlined$suspendCancellableCoroutine$lambda$1.onProviderDisabled(LocationUtils.kt:45)
at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:384)
at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:300)
at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:316)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:6878)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
Я не знаю, почему приложение не работает, потому что такой код работает идеально:
lifecycleScope.launch {
try {
throwError()
} catch (e : Exception) {
e.printStackTrace()
}
}
private suspend fun throwError() {
return suspendCancellableCoroutine { continuation ->
continuation.resumeWithException(ProviderDisabledException("TEST"))
}
}