diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherInfoView.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherInfoView.java index c6a56ee597f9369410107d124101c2378f92f8c2..adf4d32a8fdcab8446b150822ba63e71009a19fe 100644 --- a/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherInfoView.java +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherInfoView.java @@ -19,7 +19,6 @@ public class WeatherInfoView extends LinearLayout { private View mWeatherPanel; private View mWeatherSetupTextView; - private Context mContext; private final BroadcastReceiver mWeatherReceiver = new BroadcastReceiver() { @Override @@ -47,7 +46,6 @@ public class WeatherInfoView extends LinearLayout { public WeatherInfoView(Context context, AttributeSet attrs) { super(context, attrs); - mContext = context; } @Override @@ -64,7 +62,7 @@ public class WeatherInfoView extends LinearLayout { }); findViewById(R.id.weather_setting_imageview).setOnClickListener(v -> startWeatherPreferences()); findViewById(R.id.weather_refresh_imageview).setOnClickListener(v -> { - WeatherUpdater.getInstance(mContext).forceWeatherRequest(); + WeatherUpdater.getInstance(getContext().getApplicationContext()).forceWeatherRequest(); }); } diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdateService.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdateService.java index 182169233a2fa69b9b1917afd230cdeaab68ea80..500d2f034a5d4a926a2c7cd02aaaeb49c74c917d 100644 --- a/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdateService.java +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdateService.java @@ -34,7 +34,7 @@ public class WeatherUpdateService extends Service { mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); - mWeatherUpdater = WeatherUpdater.getInstance(this); + mWeatherUpdater = WeatherUpdater.getInstance(getApplicationContext()); executePeriodicRequest(); } diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdater.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdater.java index 5c9da50655d1829ba55971d906c325911d86f9e9..ad404d397760fe89e268cc731ba9cfe251ac9455 100644 --- a/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdater.java +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/WeatherUpdater.java @@ -6,13 +6,13 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.location.Location; -import android.location.LocationManager; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.SystemClock; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; -import androidx.core.location.LocationManagerCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.google.gson.JsonArray; @@ -24,10 +24,12 @@ import com.google.gson.JsonSyntaxException; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.Locale; -import java.util.concurrent.Executors; import foundation.e.blisslauncher.R; import foundation.e.blisslauncher.core.Preferences; +import foundation.e.blisslauncher.features.weather.location.FusedLocationFetcher; +import foundation.e.blisslauncher.features.weather.location.LocationFetcher; +import foundation.e.blisslauncher.features.weather.location.NetworkGpsLocationFetcher; import lineageos.weather.LineageWeatherManager; import lineageos.weather.WeatherInfo; import lineageos.weather.WeatherLocation; @@ -44,10 +46,7 @@ public class WeatherUpdater { private static final String TAG = "WeatherUpdater"; private static final long DEFAULT_FORCE_REQUEST_PERIOD_IN_MS = 10L * 1000L; - private final LocationManager mLocationManager; private final WeakReference mWeakContext; - private Location mGpsLocation; - private Location mNetworkLocation; private long mForceRequestPeriodInMs = DEFAULT_FORCE_REQUEST_PERIOD_IN_MS; private static WeatherUpdater mInstance = null; @@ -62,7 +61,6 @@ public class WeatherUpdater { private WeatherUpdater(@NonNull Context context) { mWeakContext = new WeakReference<>(context); - mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); } public void checkWeatherRequest() { @@ -123,11 +121,11 @@ public class WeatherUpdater { return; } - LocationManagerCompat.getCurrentLocation(mLocationManager, LocationManager.GPS_PROVIDER, null, - Executors.newFixedThreadPool(1), this::onNewLocationFetched); + LocationFetcher locationFetcher = VERSION.SDK_INT >= VERSION_CODES.S + ? new FusedLocationFetcher(mWeakContext.get(), this::onNewLocationFetched) + : new NetworkGpsLocationFetcher(mWeakContext.get(), this::onNewLocationFetched); - LocationManagerCompat.getCurrentLocation(mLocationManager, LocationManager.NETWORK_PROVIDER, null, - Executors.newFixedThreadPool(1), this::onNewLocationFetched); + locationFetcher.fetchLocation(); } protected boolean hasMissingPermissions() { @@ -166,16 +164,10 @@ public class WeatherUpdater { Timber.tag(TAG).i("New location fetched:%s", location); - if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { - mGpsLocation = location; - } else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { - mNetworkLocation = location; - } - - requestWeatherUpdate(getMostRecentLocation()); + requestWeatherUpdate(location); if (!Preferences.useCustomWeatherLocation(mWeakContext.get())) { - reverseGeocodeLocation(getMostRecentLocation()); + reverseGeocodeLocation(location); } else { Timber.tag(TAG).w("Do not reverse geocode location. User is using a custom location."); } @@ -198,24 +190,6 @@ public class WeatherUpdater { mForceRequestPeriodInMs = DEFAULT_FORCE_REQUEST_PERIOD_IN_MS; } - 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; - } - private void reverseGeocodeLocation(@NonNull Location location) { Timber.tag(TAG).i("Reverse geocoding location %s", location); @@ -250,12 +224,13 @@ public class WeatherUpdater { } if (defaultCityName == null) { - Timber.tag(TAG).e("Could not get default city name"); + Timber.tag(TAG).w("Could not get default city name"); return; } if (locales == null) { - Timber.tag(TAG).e("Could not get locales"); + Timber.tag(TAG).i("Could not get locales. Fallbacking to default city name %s", defaultCityName); + notifyUi(defaultCityName); return; } @@ -263,7 +238,9 @@ public class WeatherUpdater { String countryCode = Locale.getDefault().getCountry().toLowerCase(Locale.ROOT); final JsonElement jsonElement = locales.get(countryCode); if (jsonElement == null) { - Timber.tag(TAG).e("Could not get city name in country code: %s", countryCode); + Timber.tag(TAG).i("Could not get city name in country code: %s. Fallbacking to default city name %s", + countryCode, defaultCityName); + notifyUi(defaultCityName); return; } diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/location/FusedLocationFetcher.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/location/FusedLocationFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..bf647777a33e5b77119c5aa4422199707534008d --- /dev/null +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/location/FusedLocationFetcher.java @@ -0,0 +1,47 @@ +package foundation.e.blisslauncher.features.weather.location; + +import android.content.Context; +import android.location.Location; +import android.location.LocationManager; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.core.location.LocationManagerCompat; + +import java.util.concurrent.Executors; + +import timber.log.Timber; + +public class FusedLocationFetcher extends LocationFetcher { + + public FusedLocationFetcher(@NonNull Context context, @NonNull Callback callback) { + this.context = context; + this.callback = callback; + locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + @Override + public void fetchLocation() { + if (!checkPermission()) { + Timber.w("Could not fetch location. Missing permission."); + return; + } + + if (VERSION.SDK_INT >= VERSION_CODES.S) { + LocationManagerCompat.getCurrentLocation(locationManager, LocationManager.FUSED_PROVIDER, null, + Executors.newFixedThreadPool(1), this::onLocationFetched); + } + } + + @RequiresApi(api = VERSION_CODES.S) + private void onLocationFetched(@Nullable Location location) { + if (location == null && checkPermission()) { + location = locationManager.getLastKnownLocation(LocationManager.FUSED_PROVIDER); + } + + callback.onNewLocation(location); + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/location/LocationFetcher.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/location/LocationFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..75fa27385653d0d28f3e6139f5d1257d69c3a522 --- /dev/null +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/location/LocationFetcher.java @@ -0,0 +1,31 @@ +package foundation.e.blisslauncher.features.weather.location; + +import android.Manifest.permission; +import android.content.Context; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationManager; + +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; + +public abstract class LocationFetcher { + + protected LocationManager locationManager; + protected Callback callback; + + protected Context context; + + public interface Callback { + void onNewLocation(@Nullable Location location); + } + + public abstract void fetchLocation(); + + protected boolean checkPermission() { + return ActivityCompat.checkSelfPermission(context, + permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED + || ActivityCompat.checkSelfPermission(context, + permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; + } +} diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/location/NetworkGpsLocationFetcher.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/location/NetworkGpsLocationFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..c2112647a2840a317702180eaa3c04a28e23f63b --- /dev/null +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/location/NetworkGpsLocationFetcher.java @@ -0,0 +1,73 @@ +package foundation.e.blisslauncher.features.weather.location; + +import android.content.Context; +import android.location.Location; +import android.location.LocationManager; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.location.LocationManagerCompat; + +import java.util.concurrent.Executors; + +import timber.log.Timber; + +public class NetworkGpsLocationFetcher extends LocationFetcher { + + private Location gpsLocation; + private Location networkLocation; + + public NetworkGpsLocationFetcher(@NonNull Context context, @NonNull Callback callback) { + this.context = context; + locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + this.callback = callback; + } + + @Override + public void fetchLocation() { + if (!checkPermission()) { + Timber.w("Could not fetch location. Missing permission."); + return; + } + + LocationManagerCompat.getCurrentLocation(locationManager, LocationManager.GPS_PROVIDER, null, + Executors.newFixedThreadPool(1), this::onLocationFetched); + + LocationManagerCompat.getCurrentLocation(locationManager, LocationManager.NETWORK_PROVIDER, null, + Executors.newFixedThreadPool(1), this::onLocationFetched); + } + + private void onLocationFetched(@Nullable Location location) { + + if (location == null) { + return; + } + + if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { + gpsLocation = location; + } else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { + networkLocation = location; + } + + callback.onNewLocation(getMostRecentLocation()); + } + + private Location getMostRecentLocation() { + if (networkLocation == null && gpsLocation == null) { + throw new IllegalStateException(); + } + + if (gpsLocation == null) { + return networkLocation; + } + + if (networkLocation == null) { + return gpsLocation; + } + + long gpsTime = gpsLocation.getTime(); + long networkTime = networkLocation.getTime(); + return gpsTime >= networkTime ? gpsLocation : networkLocation; + } + +}