From 2e2a9e4c449e0c22d64ddf80489eebdeef345637 Mon Sep 17 00:00:00 2001 From: PranshulGG Date: Sun, 24 May 2026 12:47:58 +0530 Subject: [PATCH] add WeatherWorker and WeatherUpdateScheduler to handle background weather updates and widget refreshing --- .../data/worker/WeatherUpdateScheduler.kt | 42 +++++++++ .../data/worker/WeatherWorker.kt | 91 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherUpdateScheduler.kt create mode 100644 app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherWorker.kt diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherUpdateScheduler.kt b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherUpdateScheduler.kt new file mode 100644 index 000000000..ebc7abe24 --- /dev/null +++ b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherUpdateScheduler.kt @@ -0,0 +1,42 @@ +package com.pranshulgg.weather_master_app.data.worker + +import android.content.Context +import androidx.work.Constraints +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.NetworkType +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkManager +import java.util.concurrent.TimeUnit + +object WeatherUpdateScheduler { + fun scheduleWeatherUpdates( + context: Context, + repeatInterval: Int, + ) { + + val constraints = Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + + val request = + PeriodicWorkRequestBuilder( + repeatInterval.toLong(), + TimeUnit.MINUTES + ) + .setConstraints(constraints) + .build() + + + WorkManager.getInstance(context).enqueueUniquePeriodicWork( + "@pranshulgg_weather_master_updates", + ExistingPeriodicWorkPolicy.UPDATE, + request + ) + } + + fun disableWeatherUpdates(context: Context) { + WorkManager.getInstance(context) + .cancelUniqueWork("@pranshulgg_weather_master_updates") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherWorker.kt b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherWorker.kt new file mode 100644 index 000000000..823694858 --- /dev/null +++ b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/WeatherWorker.kt @@ -0,0 +1,91 @@ +package com.pranshulgg.weather_master_app.data.worker + +import android.Manifest +import android.content.Context +import androidx.annotation.RequiresPermission +import androidx.hilt.work.HiltWorker +import androidx.work.CoroutineWorker +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkerParameters +import com.pranshulgg.weather_master_app.core.model.weather.WeatherResult +import com.pranshulgg.weather_master_app.data.provider.WeatherRepositoryProvider +import com.pranshulgg.weather_master_app.data.repository.LocationsRepository +import com.pranshulgg.weather_master_app.data.repository.WeatherUnitsRepository +import com.pranshulgg.weather_master_app.data.worker.notification.WeatherNotification +import com.pranshulgg.weather_master_app.data.worker.widgets.WeatherWidgetUpdater +import com.pranshulgg.weather_master_app.data.worker.widgets.widgetWeatherMapper +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject + +@HiltWorker +class WeatherWorker @AssistedInject constructor( + @Assisted context: Context, + @Assisted params: WorkerParameters, + private val repositoryProvider: WeatherRepositoryProvider, + private val locationsRepository: LocationsRepository, + private val appVisibility: AppVisibility, + private val weatherUnitsRepository: WeatherUnitsRepository +) : CoroutineWorker(context, params) { + + @RequiresPermission(Manifest.permission.POST_NOTIFICATIONS) + override suspend fun doWork(): Result { + + // We only run the worker if app is in the background + if (appVisibility.isForeground) { + return Result.success() + } + + return try { + + val locations = locationsRepository.getLocationsOnce() + val default = locations.find { it.isDefault } + val units = weatherUnitsRepository.getUnitsOnce() + + if (default == null || units == null) { + return Result.success() + } + WeatherNotification.showNotification(default.name) + + + val repo = repositoryProvider.getRepository(default.source) + + val result = repo.getWeather( + location = default, + isManualRefresh = false, + isForceRefresh = true + ) + + if (result !is WeatherResult.Success) { + return Result.success() + } + + val weather = result.weather + + val json = widgetWeatherMapper(weather, applicationContext, units) + + + WeatherWidgetUpdater(applicationContext).update(json) + + return Result.success() + + } catch (e: Exception) { + Result.failure() + } finally { + WeatherNotification.hideNotification() + } + } + + companion object { + + fun startNow(context: Context) { + + val request = + OneTimeWorkRequestBuilder() + .build() + + WorkManager.getInstance(context) + .enqueue(request) + } + } +} \ No newline at end of file