From 5bace7d656561e7f6541ad658b87d1a2964d0bb8 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Mon, 11 Jul 2022 18:40:52 +0200 Subject: [PATCH] Fix crashes when no Geocoder is available --- .../weather/LatLonWeatherProvider.kt | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/weather/src/main/java/de/mm20/launcher2/weather/LatLonWeatherProvider.kt b/weather/src/main/java/de/mm20/launcher2/weather/LatLonWeatherProvider.kt index 0f0aa74b..e46df997 100644 --- a/weather/src/main/java/de/mm20/launcher2/weather/LatLonWeatherProvider.kt +++ b/weather/src/main/java/de/mm20/launcher2/weather/LatLonWeatherProvider.kt @@ -9,6 +9,9 @@ import de.mm20.launcher2.ktx.putDouble import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.IOException +import kotlin.math.abs +import kotlin.math.absoluteValue +import kotlin.math.roundToInt /** * A WeatherProvider that uses lat/lon locations only (instead of provider specific location IDs) @@ -21,7 +24,12 @@ abstract class LatLonWeatherProvider : WeatherProvider() val geocoder = Geocoder(context) val locations = withContext(Dispatchers.IO) { - geocoder.getFromLocationName(query, 10) + try { + geocoder.getFromLocationName(query, 10) + } catch (e: IOException) { + CrashReporter.logException(e) + emptyList() + } } return locations.mapNotNull { LatLonWeatherLocation( @@ -37,9 +45,7 @@ abstract class LatLonWeatherProvider : WeatherProvider() lon: Double ): WeatherUpdateResult? { return try { - val locationName = Geocoder(context).getFromLocation(lat, lon, 1) - .firstOrNull() - ?.formatToString() ?: "$lat/$lon" + val locationName = getLocationName(lat, lon) loadWeatherData( LatLonWeatherLocation( name = locationName, @@ -53,6 +59,39 @@ abstract class LatLonWeatherProvider : WeatherProvider() } } + private suspend fun getLocationName(lat: Double, lon: Double): String { + if (!Geocoder.isPresent()) return formatLatLon(lat, lon) + return withContext(Dispatchers.IO) { + try { + Geocoder(context).getFromLocation(lat, lon, 1) + .firstOrNull() + ?.formatToString() ?: formatLatLon(lat, lon) + } catch (e: IOException) { + CrashReporter.logException(e) + formatLatLon(lat, lon) + } + } + } + + private fun formatLatLon(lat: Double, lon: Double): String { + val absLat = lat.absoluteValue + val absLon = lon.absoluteValue + + val dLat = absLat.toInt() + val dLon = absLon.toInt() + + val mLat = ((absLat - dLat) * 60).roundToInt() + + val mLon = ((absLon - dLon) * 60).roundToInt() + + + val dmsLat = "$dLat°$mLat'${if (lat >= 0) "N" else "S"}" + + val dmsLon = "$dLon°$mLon'${if (lat >= 0) "E" else "W"}" + + return "$dmsLat $dmsLon" + } + override fun setLocation(location: WeatherLocation?) { location as LatLonWeatherLocation? preferences.edit {