refactor: use shared met-weather library for home-screen MET weather (v0.3.7)
Some checks failed
Some checks failed
- Replace internal MetApiService/MetForecastResponse + Retrofit MET fetch in AppHelper with dk.haugesenspil:met-weather (Gitea maven). - fetchMetWeather now delegates to MetWeatherClient; 15-min cache kept. - Drop MetApiService.kt and MetForecastResponse.kt. release build v0.3.7
This commit is contained in:
@@ -19,8 +19,8 @@ android {
|
||||
applicationId = "app.easy.launcher"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 36
|
||||
versionName = "0.3.6"
|
||||
versionCode = 37
|
||||
versionName = "0.3.7"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
manifestPlaceholders["internetPermission"] = "android.permission.INTERNET"
|
||||
@@ -187,6 +187,7 @@ dependencies {
|
||||
implementation(libs.material)
|
||||
implementation(libs.retrofit)
|
||||
implementation(libs.converter.gson)
|
||||
implementation("dk.haugesenspil:met-weather:0.1.0")
|
||||
implementation(libs.constraintlayout)
|
||||
implementation(libs.navigation.fragment.ktx)
|
||||
implementation(libs.navigation.ui.ktx)
|
||||
|
||||
@@ -33,16 +33,15 @@ import com.github.droidworksstudio.launcher.R
|
||||
import com.github.droidworksstudio.launcher.accessibility.ActionService
|
||||
import com.github.droidworksstudio.launcher.data.dao.AppInfoDAO
|
||||
import com.github.droidworksstudio.launcher.data.entities.AppInfo
|
||||
import com.github.droidworksstudio.launcher.helper.weather.MetForecastResponse
|
||||
import com.github.droidworksstudio.launcher.helper.weather.WeatherResponse
|
||||
import com.github.droidworksstudio.launcher.utils.Constants
|
||||
import com.github.droidworksstudio.launcher.utils.MetApiService
|
||||
import com.github.droidworksstudio.launcher.utils.MetSymbolMapper
|
||||
import com.github.droidworksstudio.launcher.utils.WeatherApiService
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.google.gson.stream.JsonReader
|
||||
import dk.haugesenspil.metweather.MetWeatherClient
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlin.math.roundToInt
|
||||
import retrofit2.Retrofit
|
||||
@@ -57,6 +56,11 @@ import javax.inject.Inject
|
||||
|
||||
class AppHelper @Inject constructor() {
|
||||
|
||||
private companion object {
|
||||
/** MET requires a descriptive User-Agent identifying the app + contact. */
|
||||
const val MET_USER_AGENT = "app.easy.launcher (https://gitea.haugesenspil.dk/jonas/EasyLauncher)"
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant", "PrivateApi")
|
||||
fun expandNotificationDrawer(context: Context) {
|
||||
try {
|
||||
@@ -563,11 +567,12 @@ class AppHelper @Inject constructor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the current temperature and symbol from the MET/Yr API
|
||||
* (api.met.no locationforecast). No API key needed - only a
|
||||
* descriptive User-Agent header. Result is cached for 15 minutes.
|
||||
* Fetches the current temperature and symbol from the MET/Yr API via the
|
||||
* shared `met-weather` library (api.met.no locationforecast). No API key
|
||||
* needed - only a descriptive User-Agent header. Result is cached for
|
||||
* 15 minutes.
|
||||
*/
|
||||
fun fetchMetWeather(
|
||||
suspend fun fetchMetWeather(
|
||||
context: Context,
|
||||
latitude: Float,
|
||||
longitude: Float,
|
||||
@@ -584,37 +589,18 @@ class AppHelper @Inject constructor() {
|
||||
return cached.second
|
||||
}
|
||||
|
||||
try {
|
||||
val retrofit = Retrofit.Builder()
|
||||
.baseUrl("https://api.met.no/weatherapi/locationforecast/2.0/")
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
|
||||
val service = retrofit.create(MetApiService::class.java)
|
||||
val response = service.getCompact(latitude.toDouble(), longitude.toDouble()).execute()
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body()
|
||||
val timeseries = body?.properties?.timeseries
|
||||
val first = timeseries?.firstOrNull()
|
||||
if (first != null) {
|
||||
val temperature = first.data.instant.details.airTemperature.roundToInt()
|
||||
val symbolCode = first.data.next1Hours?.summary?.symbolCode
|
||||
?: first.data.next6Hours?.summary?.symbolCode
|
||||
?: "cloudy"
|
||||
val result = MetWeatherResult.Success(temperature, symbolCode)
|
||||
context.cacheMetWeather(result)
|
||||
return result
|
||||
}
|
||||
return MetWeatherResult.Failure("Empty forecast")
|
||||
} else {
|
||||
return MetWeatherResult.Failure("MET API error: ${response.code()}")
|
||||
}
|
||||
} catch (e: UnknownHostException) {
|
||||
Log.e("AppHelper", "MET fetch: unknown host api.met.no", e)
|
||||
return MetWeatherResult.Failure("Unknown host: api.met.no")
|
||||
return try {
|
||||
val weather = MetWeatherClient(MET_USER_AGENT)
|
||||
.fetch(latitude.toDouble(), longitude.toDouble())
|
||||
val result = MetWeatherResult.Success(
|
||||
weather.temperatureC.roundToInt(),
|
||||
weather.symbolCode,
|
||||
)
|
||||
context.cacheMetWeather(result)
|
||||
result
|
||||
} catch (e: Exception) {
|
||||
Log.e("AppHelper", "MET fetch failed", e)
|
||||
return MetWeatherResult.Failure(e.message ?: "MET fetch failed")
|
||||
MetWeatherResult.Failure(e.message ?: "MET fetch failed")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.github.droidworksstudio.launcher.helper.weather
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
/**
|
||||
* Locationforecast 2.0 compact response (api.met.no) - only the fields the
|
||||
* home-screen current-weather element needs.
|
||||
*/
|
||||
data class MetForecastResponse(
|
||||
val properties: MetProperties
|
||||
)
|
||||
|
||||
data class MetProperties(
|
||||
val timeseries: List<MetTimeSeries>
|
||||
)
|
||||
|
||||
data class MetTimeSeries(
|
||||
val time: String,
|
||||
val data: MetData
|
||||
)
|
||||
|
||||
data class MetData(
|
||||
val instant: MetInstant,
|
||||
@SerializedName("next_1_hours")
|
||||
val next1Hours: MetNextHours? = null,
|
||||
@SerializedName("next_6_hours")
|
||||
val next6Hours: MetNextHours? = null
|
||||
)
|
||||
|
||||
data class MetInstant(
|
||||
val details: MetDetails
|
||||
)
|
||||
|
||||
data class MetDetails(
|
||||
@SerializedName("air_temperature")
|
||||
val airTemperature: Double = 0.0
|
||||
)
|
||||
|
||||
data class MetNextHours(
|
||||
val summary: MetSummary
|
||||
)
|
||||
|
||||
data class MetSummary(
|
||||
@SerializedName("symbol_code")
|
||||
val symbolCode: String = ""
|
||||
)
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.github.droidworksstudio.launcher.utils
|
||||
|
||||
import com.github.droidworksstudio.launcher.helper.weather.MetForecastResponse
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface MetApiService {
|
||||
|
||||
@Headers(
|
||||
"User-Agent: app.easy.launcher (https://gitea.haugesenspil.dk/jonas/EasyLauncher)"
|
||||
)
|
||||
@GET("compact")
|
||||
fun getCompact(
|
||||
@Query("lat") latitude: Double,
|
||||
@Query("lon") longitude: Double
|
||||
): Call<MetForecastResponse>
|
||||
}
|
||||
Reference in New Issue
Block a user