Loading app/build.gradle.kts +0 −3 Original line number Diff line number Diff line Loading @@ -161,7 +161,4 @@ dependencies { // elib implementation(libs.elib) // workmanager implementation(libs.workmanager) } app/src/main/java/foundation/e/blisslauncher/core/utils/Constants.java +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public class Constants { // other shared pref entries public static final String WEATHER_LAST_UPDATE = "last_weather_update"; public static final String WEATHER_LAST_TRY = "last_weather_try"; public static final String WEATHER_DATA = "weather_data"; // First run is used to hide the initial no-weather message for a better OOBE Loading app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherInfoView.java +1 −2 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import foundation.e.blisslauncher.R; import foundation.e.blisslauncher.core.Preferences; import foundation.e.blisslauncher.features.launcher.LauncherActivity; import foundation.e.blisslauncher.features.weather.worker.ForceWeatherRequestWorker; public class WeatherInfoView extends LinearLayout { Loading Loading @@ -54,7 +53,7 @@ public class WeatherInfoView extends LinearLayout { }); findViewById(R.id.weather_setting_imageview).setOnClickListener(v -> startWeatherPreferences()); findViewById(R.id.weather_refresh_imageview).setOnClickListener(v -> { ForceWeatherRequestWorker.start(mContext); WeatherUpdater.getInstance(mContext).forceWeatherRequest(); }); } Loading app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdateService.java +5 −5 Original line number Diff line number Diff line Loading @@ -10,9 +10,6 @@ import android.util.Log; import androidx.annotation.Nullable; import foundation.e.blisslauncher.features.weather.worker.ForceWeatherRequestWorker; import foundation.e.blisslauncher.features.weather.worker.OneShotWeatherRequestWorker; public class WeatherUpdateService extends Service { private static final String TAG = "WeatherUpdateService"; Loading @@ -23,6 +20,7 @@ public class WeatherUpdateService extends Service { private HandlerThread mHandlerThread; private Handler mHandler; private WeatherUpdater mWeatherUpdater; @SuppressLint("MissingPermission") @Override Loading @@ -33,20 +31,22 @@ public class WeatherUpdateService extends Service { mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); mWeatherUpdater = WeatherUpdater.getInstance(this); executePeriodicRequest(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null && ACTION_FORCE_UPDATE.equals(intent.getAction())) { ForceWeatherRequestWorker.start(this); WeatherUpdater.getInstance(this).forceWeatherRequest(); } return START_STICKY; } private void executePeriodicRequest() { OneShotWeatherRequestWorker.start(this); mWeatherUpdater.checkWeatherRequest(); mHandler.removeCallbacksAndMessages(null); mHandler.postDelayed(this::executePeriodicRequest, UPDATE_PERIOD_IN_MS); } Loading app/src/main/java/foundation/e/blisslauncher/features/weather/worker/WeatherRequestWorker.java→app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdater.java +161 −0 Original line number Diff line number Diff line package foundation.e.blisslauncher.features.weather.worker; package foundation.e.blisslauncher.features.weather; import android.Manifest.permission; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; Loading @@ -12,43 +13,121 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.core.location.LocationManagerCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.work.Worker; import androidx.work.WorkerParameters; import java.lang.ref.WeakReference; import java.util.concurrent.Executors; import foundation.e.blisslauncher.core.Preferences; import foundation.e.blisslauncher.features.weather.WeatherUpdateService; import lineageos.weather.LineageWeatherManager; import lineageos.weather.WeatherInfo; import lineageos.weather.WeatherLocation; public abstract class WeatherRequestWorker extends Worker { public class WeatherUpdater { private static final String TAG = "WeatherUpdater"; private final LocationManager mLocationManager; private final WeakReference<Context> mWeakContext; private Location mGpsLocation; private Location mNetworkLocation; private static WeatherUpdater mInstance = null; public static WeatherUpdater getInstance(@NonNull Context context) { if (mInstance == null) { mInstance = new WeatherUpdater(context); } return mInstance; } private WeatherUpdater(@NonNull Context context) { mWeakContext = new WeakReference<>(context); mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); } public void checkWeatherRequest() { Context context = mWeakContext.get(); long refreshPeriod = Preferences.weatherRefreshIntervalInMs(context); long elapsedTime = Math.abs(SystemClock.elapsedRealtime() - Preferences.lastWeatherUpdateTimestamp(context)); Log.i(TAG, "elapsedTime=" + elapsedTime + " vs refreshPeriod=" + refreshPeriod); boolean isRequestAllowed = refreshPeriod != 0 && elapsedTime >= refreshPeriod; if (isRequestAllowed) { updateWeather(); } } public void forceWeatherRequest() { Log.i(TAG, "Forcing weather request"); updateWeather(); } private static final String TAG = "WeatherRequestWorker"; private void updateWeather() { Context context = mWeakContext.get(); Preferences.setLastWeatherUpdateTimestamp(context, SystemClock.elapsedRealtime()); protected final LocationManager locationManager; if (Preferences.useCustomWeatherLocation(context)) { requestCustomWeatherUpdate(context, Preferences.getCustomWeatherLocation(context)); } else { fetchNewLocation(context); } } public WeatherRequestWorker(@NonNull Context context, @NonNull WorkerParameters params) { super(context, params); locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); @SuppressLint("MissingPermission") private void fetchNewLocation(@NonNull Context context) { if (hasMissingPermissions(context)) { Log.e(TAG, "Could not fetch location for missing permission"); return; } @NonNull public abstract Result doWork(); LocationManagerCompat.getCurrentLocation(mLocationManager, LocationManager.GPS_PROVIDER, null, Executors.newFixedThreadPool(1), this::onNewLocationFetched); LocationManagerCompat.getCurrentLocation(mLocationManager, LocationManager.NETWORK_PROVIDER, null, Executors.newFixedThreadPool(1), this::onNewLocationFetched); } protected static boolean hasMissingPermissions(@NonNull Context context) { return ActivityCompat.checkSelfPermission(context, permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED; } protected static void requestWeatherUpdate(@NonNull Context context, @NonNull Location location) { protected static void requestWeatherUpdate(Context context, Location location) { Log.i(TAG, "Requesting weather info for location: " + location); LineageWeatherManager weatherManager = LineageWeatherManager.getInstance(context); weatherManager.requestWeatherUpdate(location, (status, weatherInfo) -> notifyUi(context, weatherInfo, status)); } protected static void requestCustomWeatherUpdate(Context context, WeatherLocation location) { protected static void requestCustomWeatherUpdate(@NonNull Context context, @Nullable WeatherLocation location) { Log.i(TAG, "Requesting weather info for location: " + location); LineageWeatherManager weatherManager = LineageWeatherManager.getInstance(context); weatherManager.requestWeatherUpdate(location, (status, weatherInfo) -> notifyUi(context, weatherInfo, status)); } private synchronized void onNewLocationFetched(@Nullable Location location) { if (location == null) { return; } Log.i(TAG, "New location fetched:" + location); if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { mGpsLocation = location; } else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { mNetworkLocation = location; } requestWeatherUpdate(mWeakContext.get(), getMostRecentLocation()); } protected static void notifyUi(@NonNull Context context, @Nullable WeatherInfo weatherInfo, int status) { if (weatherInfo == null) { Log.i(TAG, "WeatherInfo is null. Status reported: " + status); return; Loading @@ -62,10 +141,21 @@ public abstract class WeatherRequestWorker extends Worker { LocalBroadcastManager.getInstance(context).sendBroadcast(updateIntent); } protected static boolean hasMissingPermissions(Context context) { return ActivityCompat.checkSelfPermission(context, permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED; private Location getMostRecentLocation() { if (mNetworkLocation == null && mGpsLocation == null) { throw new IllegalStateException(); } if (mGpsLocation == null) { return mNetworkLocation; } if (mNetworkLocation == null) { return mGpsLocation; } long gpsTime = mGpsLocation.getTime(); long networkTime = mNetworkLocation.getTime(); return gpsTime >= networkTime ? mGpsLocation : mNetworkLocation; } } Loading
app/build.gradle.kts +0 −3 Original line number Diff line number Diff line Loading @@ -161,7 +161,4 @@ dependencies { // elib implementation(libs.elib) // workmanager implementation(libs.workmanager) }
app/src/main/java/foundation/e/blisslauncher/core/utils/Constants.java +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public class Constants { // other shared pref entries public static final String WEATHER_LAST_UPDATE = "last_weather_update"; public static final String WEATHER_LAST_TRY = "last_weather_try"; public static final String WEATHER_DATA = "weather_data"; // First run is used to hide the initial no-weather message for a better OOBE Loading
app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherInfoView.java +1 −2 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import foundation.e.blisslauncher.R; import foundation.e.blisslauncher.core.Preferences; import foundation.e.blisslauncher.features.launcher.LauncherActivity; import foundation.e.blisslauncher.features.weather.worker.ForceWeatherRequestWorker; public class WeatherInfoView extends LinearLayout { Loading Loading @@ -54,7 +53,7 @@ public class WeatherInfoView extends LinearLayout { }); findViewById(R.id.weather_setting_imageview).setOnClickListener(v -> startWeatherPreferences()); findViewById(R.id.weather_refresh_imageview).setOnClickListener(v -> { ForceWeatherRequestWorker.start(mContext); WeatherUpdater.getInstance(mContext).forceWeatherRequest(); }); } Loading
app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdateService.java +5 −5 Original line number Diff line number Diff line Loading @@ -10,9 +10,6 @@ import android.util.Log; import androidx.annotation.Nullable; import foundation.e.blisslauncher.features.weather.worker.ForceWeatherRequestWorker; import foundation.e.blisslauncher.features.weather.worker.OneShotWeatherRequestWorker; public class WeatherUpdateService extends Service { private static final String TAG = "WeatherUpdateService"; Loading @@ -23,6 +20,7 @@ public class WeatherUpdateService extends Service { private HandlerThread mHandlerThread; private Handler mHandler; private WeatherUpdater mWeatherUpdater; @SuppressLint("MissingPermission") @Override Loading @@ -33,20 +31,22 @@ public class WeatherUpdateService extends Service { mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); mWeatherUpdater = WeatherUpdater.getInstance(this); executePeriodicRequest(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null && ACTION_FORCE_UPDATE.equals(intent.getAction())) { ForceWeatherRequestWorker.start(this); WeatherUpdater.getInstance(this).forceWeatherRequest(); } return START_STICKY; } private void executePeriodicRequest() { OneShotWeatherRequestWorker.start(this); mWeatherUpdater.checkWeatherRequest(); mHandler.removeCallbacksAndMessages(null); mHandler.postDelayed(this::executePeriodicRequest, UPDATE_PERIOD_IN_MS); } Loading
app/src/main/java/foundation/e/blisslauncher/features/weather/worker/WeatherRequestWorker.java→app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdater.java +161 −0 Original line number Diff line number Diff line package foundation.e.blisslauncher.features.weather.worker; package foundation.e.blisslauncher.features.weather; import android.Manifest.permission; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; Loading @@ -12,43 +13,121 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.core.location.LocationManagerCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.work.Worker; import androidx.work.WorkerParameters; import java.lang.ref.WeakReference; import java.util.concurrent.Executors; import foundation.e.blisslauncher.core.Preferences; import foundation.e.blisslauncher.features.weather.WeatherUpdateService; import lineageos.weather.LineageWeatherManager; import lineageos.weather.WeatherInfo; import lineageos.weather.WeatherLocation; public abstract class WeatherRequestWorker extends Worker { public class WeatherUpdater { private static final String TAG = "WeatherUpdater"; private final LocationManager mLocationManager; private final WeakReference<Context> mWeakContext; private Location mGpsLocation; private Location mNetworkLocation; private static WeatherUpdater mInstance = null; public static WeatherUpdater getInstance(@NonNull Context context) { if (mInstance == null) { mInstance = new WeatherUpdater(context); } return mInstance; } private WeatherUpdater(@NonNull Context context) { mWeakContext = new WeakReference<>(context); mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); } public void checkWeatherRequest() { Context context = mWeakContext.get(); long refreshPeriod = Preferences.weatherRefreshIntervalInMs(context); long elapsedTime = Math.abs(SystemClock.elapsedRealtime() - Preferences.lastWeatherUpdateTimestamp(context)); Log.i(TAG, "elapsedTime=" + elapsedTime + " vs refreshPeriod=" + refreshPeriod); boolean isRequestAllowed = refreshPeriod != 0 && elapsedTime >= refreshPeriod; if (isRequestAllowed) { updateWeather(); } } public void forceWeatherRequest() { Log.i(TAG, "Forcing weather request"); updateWeather(); } private static final String TAG = "WeatherRequestWorker"; private void updateWeather() { Context context = mWeakContext.get(); Preferences.setLastWeatherUpdateTimestamp(context, SystemClock.elapsedRealtime()); protected final LocationManager locationManager; if (Preferences.useCustomWeatherLocation(context)) { requestCustomWeatherUpdate(context, Preferences.getCustomWeatherLocation(context)); } else { fetchNewLocation(context); } } public WeatherRequestWorker(@NonNull Context context, @NonNull WorkerParameters params) { super(context, params); locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); @SuppressLint("MissingPermission") private void fetchNewLocation(@NonNull Context context) { if (hasMissingPermissions(context)) { Log.e(TAG, "Could not fetch location for missing permission"); return; } @NonNull public abstract Result doWork(); LocationManagerCompat.getCurrentLocation(mLocationManager, LocationManager.GPS_PROVIDER, null, Executors.newFixedThreadPool(1), this::onNewLocationFetched); LocationManagerCompat.getCurrentLocation(mLocationManager, LocationManager.NETWORK_PROVIDER, null, Executors.newFixedThreadPool(1), this::onNewLocationFetched); } protected static boolean hasMissingPermissions(@NonNull Context context) { return ActivityCompat.checkSelfPermission(context, permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED; } protected static void requestWeatherUpdate(@NonNull Context context, @NonNull Location location) { protected static void requestWeatherUpdate(Context context, Location location) { Log.i(TAG, "Requesting weather info for location: " + location); LineageWeatherManager weatherManager = LineageWeatherManager.getInstance(context); weatherManager.requestWeatherUpdate(location, (status, weatherInfo) -> notifyUi(context, weatherInfo, status)); } protected static void requestCustomWeatherUpdate(Context context, WeatherLocation location) { protected static void requestCustomWeatherUpdate(@NonNull Context context, @Nullable WeatherLocation location) { Log.i(TAG, "Requesting weather info for location: " + location); LineageWeatherManager weatherManager = LineageWeatherManager.getInstance(context); weatherManager.requestWeatherUpdate(location, (status, weatherInfo) -> notifyUi(context, weatherInfo, status)); } private synchronized void onNewLocationFetched(@Nullable Location location) { if (location == null) { return; } Log.i(TAG, "New location fetched:" + location); if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { mGpsLocation = location; } else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { mNetworkLocation = location; } requestWeatherUpdate(mWeakContext.get(), getMostRecentLocation()); } protected static void notifyUi(@NonNull Context context, @Nullable WeatherInfo weatherInfo, int status) { if (weatherInfo == null) { Log.i(TAG, "WeatherInfo is null. Status reported: " + status); return; Loading @@ -62,10 +141,21 @@ public abstract class WeatherRequestWorker extends Worker { LocalBroadcastManager.getInstance(context).sendBroadcast(updateIntent); } protected static boolean hasMissingPermissions(Context context) { return ActivityCompat.checkSelfPermission(context, permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED; private Location getMostRecentLocation() { if (mNetworkLocation == null && mGpsLocation == null) { throw new IllegalStateException(); } if (mGpsLocation == null) { return mNetworkLocation; } if (mNetworkLocation == null) { return mGpsLocation; } long gpsTime = mGpsLocation.getTime(); long networkTime = mNetworkLocation.getTime(); return gpsTime >= networkTime ? mGpsLocation : mNetworkLocation; } }