Add NominatimGeocoder

pull/1369/head
Alex Baker 4 years ago
parent b8edd4fb72
commit bb4ccd8dd8

@ -7,13 +7,13 @@ import dagger.hilt.components.SingletonComponent
import org.tasks.location.AndroidGeofencing
import org.tasks.location.Geocoder
import org.tasks.location.Geofencing
import org.tasks.location.MapboxGeocoder
import org.tasks.location.NominatimGeocoder
@Module
@InstallIn(SingletonComponent::class)
class FlavorModule {
@Provides
fun getGeocoder(geocoder: MapboxGeocoder): Geocoder = geocoder
fun getGeocoder(geocoder: NominatimGeocoder): Geocoder = geocoder
@Provides
fun getGeofencing(geofencing: AndroidGeofencing): Geofencing = geofencing

@ -0,0 +1,64 @@
package org.tasks.location
import com.google.gson.JsonElement
import com.google.gson.JsonParser
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import org.tasks.DebugNetworkInterceptor
import org.tasks.data.Place
import org.tasks.data.Place.Companion.newPlace
import org.tasks.preferences.Preferences
import java.io.IOException
import javax.inject.Inject
class NominatimGeocoder @Inject constructor(
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
) : Geocoder {
override suspend fun reverseGeocode(mapPosition: MapPosition): Place? =
withContext(Dispatchers.IO) {
val builder = OkHttpClient().newBuilder()
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
val client = builder.build()
val url = "https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=${mapPosition.latitude}&lon=${mapPosition.longitude}"
val response = client.newCall(Request.Builder().get().url(url).build()).execute()
if (response.isSuccessful) {
response.body?.string()?.let { jsonToPlace(it) }
} else {
throw IOException("${response.code} ${response.message}")
}
}
companion object {
internal fun jsonToPlace(json: String): Place? =
JsonParser
.parseString(json).asJsonObject.getAsJsonArray("features")
.takeIf { it.size() > 0 }?.get(0)?.asJsonObject
?.let { feature ->
val geocoding = feature
.get("properties").asJsonObject
.get("geocoding").asJsonObject
val geometry = feature.get("geometry").asJsonObject
newPlace().apply {
val type = geocoding.get("type").asString
name = if (type.equals("house")) {
"${geocoding.get("housenumber").asString} ${geocoding.get("street").asString}"
} else {
geocoding.get("name").asString
}
address = geocoding.get("label").asString
geometry.get("coordinates").asCoordinates.let {
longitude = it.first
latitude = it.second
}
}
}
private val JsonElement.asCoordinates: Pair<Double, Double>
get() = asJsonArray.let { Pair(it[0].asDouble, it[1].asDouble) }
}
}

@ -0,0 +1,33 @@
package org.tasks.location
import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.TestUtilities.readFile
class NominatimGeocoderTest {
@Test
fun pitchGeocode() {
val place = NominatimGeocoder.jsonToPlace(readFile("nominatim/pitch.json"))!!
assertEquals("Guaranteed Rate Field", place.name)
assertEquals(-87.63362064328714, place.longitude, 0.0)
assertEquals(41.82982845, place.latitude, 0.0)
assertEquals(
"Guaranteed Rate Field, West 36th Street, Armour Square, Chicago, Cook County, Illinois, 60616, United States",
place.address
)
}
@Test
fun houseGeocode() {
val place = NominatimGeocoder.jsonToPlace(readFile("nominatim/house.json"))!!
assertEquals("1 Løvenbergvegen", place.name)
assertEquals(11.1658572, place.longitude, 0.0)
assertEquals(60.2301296, place.latitude, 0.0)
assertEquals(
"1, Løvenbergvegen, Mogreina, Ullensaker, Viken, 2054, Norge",
place.address
)
}
}

@ -0,0 +1,41 @@
{
"type": "FeatureCollection",
"geocoding": {
"version": "0.1.0",
"attribution": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
"licence": "ODbL",
"query": "60.2301296,11.1658572"
},
"features": [
{
"type": "Feature",
"properties": {
"geocoding": {
"place_id": 39928913,
"osm_type": "node",
"osm_id": 3110596255,
"type": "house",
"accuracy": 0,
"label": "1, Løvenbergvegen, Mogreina, Ullensaker, Viken, 2054, Norge",
"country": "Norge",
"postcode": "2054",
"county": "Viken",
"city": "Mogreina",
"street": "Løvenbergvegen",
"housenumber": "1",
"admin": {
"level4": "Viken",
"level7": "Ullensaker"
}
}
},
"geometry": {
"type": "Point",
"coordinates": [
11.1658572,
60.2301296
]
}
}
]
}

@ -0,0 +1,45 @@
{
"type": "FeatureCollection",
"geocoding": {
"version": "0.1.0",
"attribution": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
"licence": "ODbL",
"query": "41.8299365,-87.633806"
},
"features": [
{
"type": "Feature",
"properties": {
"geocoding": {
"place_id": 258870464,
"osm_type": "relation",
"osm_id": 3834547,
"type": "pitch",
"accuracy": 0,
"label": "Guaranteed Rate Field, West 36th Street, Armour Square, Chicago, Cook County, Illinois, 60616, United States",
"name": "Guaranteed Rate Field",
"country": "United States",
"postcode": "60616",
"state": "Illinois",
"county": "Cook County",
"city": "Chicago",
"district": "Armour Square",
"street": "West 36th Street",
"admin": {
"level4": "Illinois",
"level6": "Cook County",
"level8": "Chicago",
"level10": "Armour Square"
}
}
},
"geometry": {
"type": "Point",
"coordinates": [
-87.63362064328714,
41.82982845
]
}
}
]
}
Loading…
Cancel
Save