Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e767f76 authored by Jonathan Klee's avatar Jonathan Klee
Browse files

Merge branch 'release-1.6-rc'

parents ee47c4b0 5c6814fa
Loading
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -161,7 +161,4 @@ dependencies {

    // elib
    implementation(libs.elib)

    // workmanager
    implementation(libs.workmanager)
}
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −2
Original line number Diff line number Diff line
@@ -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 {

@@ -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();
        });
    }

+5 −5
Original line number Diff line number Diff line
@@ -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";

@@ -23,6 +20,7 @@ public class WeatherUpdateService extends Service {

    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private WeatherUpdater mWeatherUpdater;

    @SuppressLint("MissingPermission")
    @Override
@@ -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);
    }
+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;
@@ -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;
@@ -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