refactor: use shared met-weather library for home-screen MET weather (v0.3.7)
Some checks failed
Android Main Branch CI / Build, Sign & Upload (push) Has been cancelled
Update CHANGELOG.md / changelog (push) Has been cancelled
Validate Gradle Wrapper / Validation (push) Has been cancelled
Android Release CI / Build, Sign & Release (push) Has been cancelled

- 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:
2026-08-20 12:58:52 +02:00
parent 1d5a568218
commit a42f913875
11 changed files with 240 additions and 103 deletions

View File

@@ -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)

View File

@@ -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")
}
}

View File

@@ -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 = ""
)

View File

@@ -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>
}