Key the weather worker's location skip on the provider, not on a setting
typing.8 checked WeatherSettingsData.managedLocation, but that only exists once the user has explicitly picked "managed location" for the provider, so weatherProviderSettings stayed empty and the guard never fired: the worker kept requesting a location and retrying every 30s. The real signal is the provider's own capability. BreezyWeatherProvider.getWeatherData() is a hardcoded noop that also manages its own location, so add WeatherProvider.isPushBased and check that instead. Also stop treating a managed location as "pull nothing": those providers still have data to fetch, they just resolve the position themselves, so they now take the WeatherLocation path instead of the auto-location one. Bump to 1.40.2-typing.9 (versionCode 2026091202).
This commit is contained in:
@@ -34,8 +34,8 @@ android {
|
||||
applicationId = "de.mm20.launcher2"
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
targetSdk = libs.versions.targetSdk.get().toInt()
|
||||
versionCode = System.getenv("VERSION_CODE_OVERRIDE")?.toIntOrNull() ?: 2026091201
|
||||
versionName = "1.40.2-typing.8"
|
||||
versionCode = System.getenv("VERSION_CODE_OVERRIDE")?.toIntOrNull() ?: 2026091202
|
||||
versionName = "1.40.2-typing.9"
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,14 @@ interface WeatherProvider {
|
||||
return 1000 * 60 * 60L
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this provider pushes weather updates on its own instead of being polled, and
|
||||
* resolves its location itself. [WeatherUpdateWorker] then has nothing to pull and must not
|
||||
* request a location for it.
|
||||
*/
|
||||
val isPushBased: Boolean
|
||||
get() = false
|
||||
|
||||
suspend fun getWeatherData(location: WeatherLocation): List<Forecast>?
|
||||
suspend fun getWeatherData(lat: Double, lon: Double): List<Forecast>?
|
||||
suspend fun findLocation(query: String): List<WeatherLocation>
|
||||
|
||||
@@ -79,13 +79,12 @@ internal class WeatherRepositoryImpl(
|
||||
}
|
||||
scope.launch {
|
||||
settings.collectLatest {
|
||||
if (it.managedLocation) {
|
||||
// The provider resolves its own location and pushes weather updates, so there
|
||||
// is nothing to poll for.
|
||||
val provider = WeatherProvider.getInstance(it.provider)
|
||||
if (provider.isPushBased) {
|
||||
// The provider sends its updates itself, so there is nothing to poll for.
|
||||
WorkManager.getInstance(context).cancelUniqueWork("weather")
|
||||
return@collectLatest
|
||||
}
|
||||
val provider = WeatherProvider.getInstance(it.provider)
|
||||
val weatherRequest =
|
||||
PeriodicWorkRequestBuilder<WeatherUpdateWorker>(Duration.ofMillis(provider.getUpdateInterval()))
|
||||
.build()
|
||||
@@ -218,20 +217,19 @@ class WeatherUpdateWorker(
|
||||
override suspend fun doWork(): Result {
|
||||
Log.d("WeatherUpdateWorker", "Requesting weather data")
|
||||
val settingsData = settings.first()
|
||||
val provider = WeatherProvider.getInstance(settingsData.provider)
|
||||
|
||||
// A provider with a managed location resolves its position itself and pushes weather
|
||||
// updates instead of being polled (Breezy Weather does both). There is nothing to pull,
|
||||
// and its getWeatherData() always returns null - which used to make this worker request a
|
||||
// location (holding GPS and network listeners for up to ten minutes at a time) and then
|
||||
// return Result.retry() forever, without ever setting lastUpdate, so the update interval
|
||||
// check below could never short-circuit it either.
|
||||
if (settingsData.managedLocation) {
|
||||
Log.d("WeatherUpdateWorker", "Provider manages its own location, nothing to pull")
|
||||
// A push-based provider sends its updates on its own and resolves its own location
|
||||
// (Breezy Weather does both), so there is nothing to pull here. Its getWeatherData()
|
||||
// always returns null, which used to make this worker request a location - registering
|
||||
// GPS and network listeners and holding them for up to ten minutes - and then return
|
||||
// Result.retry() forever, without ever setting lastUpdate, so the interval check below
|
||||
// could never short-circuit it either.
|
||||
if (provider.isPushBased) {
|
||||
Log.d("WeatherUpdateWorker", "Provider pushes updates, nothing to pull")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
val provider = WeatherProvider.getInstance(settingsData.provider)
|
||||
|
||||
val updateInterval = provider.getUpdateInterval()
|
||||
val lastUpdate = settingsData.lastUpdate
|
||||
|
||||
@@ -240,21 +238,26 @@ class WeatherUpdateWorker(
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
val weatherData = if (settingsData.autoLocation) {
|
||||
val latLon = getLastKnownLocation() ?: settingsData.lastLocation
|
||||
if (latLon == null) {
|
||||
Log.e("WeatherUpdateWorker", "Could not get location")
|
||||
return Result.failure()
|
||||
val weatherData = when {
|
||||
// A managed location means the provider resolves the position itself, so requesting
|
||||
// one here would be wasted work that holds the location stack open.
|
||||
settingsData.managedLocation, !settingsData.autoLocation -> {
|
||||
val location = settings.location.first()
|
||||
if (location == null) {
|
||||
Log.e("WeatherUpdateWorker", "Location not set")
|
||||
return Result.failure()
|
||||
}
|
||||
provider.getWeatherData(location)
|
||||
}
|
||||
settings.setLastLocation(latLon)
|
||||
provider.getWeatherData(latLon.lat, latLon.lon)
|
||||
} else {
|
||||
val location = settings.location.first()
|
||||
if (location == null) {
|
||||
Log.e("WeatherUpdateWorker", "Location not set")
|
||||
return Result.failure()
|
||||
else -> {
|
||||
val latLon = getLastKnownLocation() ?: settingsData.lastLocation
|
||||
if (latLon == null) {
|
||||
Log.e("WeatherUpdateWorker", "Could not get location")
|
||||
return Result.failure()
|
||||
}
|
||||
settings.setLastLocation(latLon)
|
||||
provider.getWeatherData(latLon.lat, latLon.lon)
|
||||
}
|
||||
provider.getWeatherData(location)
|
||||
}
|
||||
|
||||
return if (weatherData == null) {
|
||||
|
||||
@@ -20,6 +20,9 @@ class BreezyWeatherProvider(
|
||||
) : WeatherProvider, KoinComponent {
|
||||
private val database: AppDatabase by inject()
|
||||
|
||||
// Breezy sends its weather data to us (see pushWeatherData) and manages its own location.
|
||||
override val isPushBased: Boolean = true
|
||||
|
||||
override suspend fun getWeatherData(location: WeatherLocation): List<Forecast>? {
|
||||
// Noop implementation, because Breezy weather is handled in a special way
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user