add Nominatim reverse geocoding API, repository, and domain mapper

This commit is contained in:
PranshulGG committed 2026-05-28 20:40:13 +05:30
1 parent c7f2599a24
commit 8761bae86b
4 files changed
+127

No files matched your search

@@ -0,0 +1,58 @@
package com.pranshulgg.weather_master_app.core.network.sources.address.nominatim
import com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.json.NominatimAddressJson
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
import java.util.concurrent.TimeUnit
interface NominatimApi {
@GET("reverse")
suspend fun reverseGeocode(
@Query("format") format: String = "jsonv2",
@Query("lat") latitude: Double,
@Query("lon") longitude: Double,
@Query("layer") layer: String = "address"
): Response<NominatimAddressJson>
companion object {
const val BASE_URL = "https://nominatim.openstreetmap.org/"
fun create(): NominatimApi {
val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.header(
"User-Agent",
"WeatherMaster (com.pranshulgg.weathermaster; pranshul.devmain@gmail.com)"
)
.build()
chain.proceed(request)
}
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(NominatimApi::class.java)
}
}
}
@@ -0,0 +1,23 @@
package com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.json
import com.google.gson.annotations.SerializedName
data class NominatimAddressJson(
val address: NominatimAddressDataJson
)
data class NominatimAddressDataJson(
val city: String?,
@SerializedName("state_district")
val stateDistrict: String?,
val county: String?,
val road: String?,
val village: String?,
val suburb: String?,
val state: String?,
val country: String
)
@@ -0,0 +1,29 @@
package com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.json
import com.pranshulgg.weather_master_app.core.model.domain.location.Address
import com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.NominatimApi
import com.pranshulgg.weather_master_app.data.local.mapper.locations.toDomain
import java.net.UnknownHostException
import javax.inject.Inject
class NominatimRepository @Inject constructor(
private val api: NominatimApi
) {
suspend fun getAddress(latitude: Double?, longitude: Double?): Address? {
try {
if (latitude == null || longitude == null) return null
val response = api.reverseGeocode("jsonv2", latitude, longitude)
val body = response.body() ?: throw UnknownHostException()
val domain = body.toDomain()
return domain
} catch (e: Exception) {
throw e
}
}
}
@@ -0,0 +1,17 @@
package com.pranshulgg.weather_master_app.data.local.mapper.locations
import com.pranshulgg.weather_master_app.core.model.domain.location.Address
import com.pranshulgg.weather_master_app.core.network.sources.address.nominatim.json.NominatimAddressJson
fun NominatimAddressJson.toDomain(): Address {
val city =
this.address.city ?: this.address.suburb ?: this.address.village ?: this.address.county
?: this.address.road ?: this.address.stateDistrict ?: this.address.state
return Address(
city = city,
country = this.address.country
)
}