From b7cef09f5bce7336feb7bc434512743a718574a0 Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Tue, 6 Dec 2022 15:27:32 +0100 Subject: [PATCH] Reverse geocode location to be more accurate --- .gitlab-ci.yml | 2 + .../e/blisslauncher/core/Preferences.java | 10 +++ .../e/blisslauncher/core/utils/Constants.java | 2 + .../features/weather/ForecastBuilder.java | 4 +- .../features/weather/WeatherInfoView.java | 19 ++++- .../weather/WeatherUpdateService.java | 2 + .../features/weather/WeatherUpdater.java | 81 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 8 files changed, 118 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4434b5da6a..0bea12eddd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,3 +19,5 @@ build: artifacts: paths: - app/build/outputs/apk + before_script: + - sed -i 's/DEFAULT_OWM_KEY/'${DEFAULT_OWM_KEY}'/g' app/src/main/res/values/strings.xml diff --git a/app/src/main/java/foundation/e/blisslauncher/core/Preferences.java b/app/src/main/java/foundation/e/blisslauncher/core/Preferences.java index 91c17ebece..859b4892fc 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/Preferences.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/Preferences.java @@ -236,6 +236,16 @@ public class Preferences { editor.apply(); } + public static void setCachedCity(Context context, String city) { + SharedPreferences.Editor editor = getPrefs(context).edit(); + editor.putString(Constants.CACHED_CITY, city); + editor.apply(); + } + + public static String getCachedCity(Context context) { + return getPrefs(context).getString(Constants.CACHED_CITY, "Unknown"); + } + public static long lastWeatherUpdateTimestamp(Context context) { return getPrefs(context).getLong(Constants.WEATHER_LAST_UPDATE, 0); } diff --git a/app/src/main/java/foundation/e/blisslauncher/core/utils/Constants.java b/app/src/main/java/foundation/e/blisslauncher/core/utils/Constants.java index c0f0655409..a308315abe 100755 --- a/app/src/main/java/foundation/e/blisslauncher/core/utils/Constants.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/utils/Constants.java @@ -39,6 +39,8 @@ public class Constants { public static final String FORCE_WEATHER_LAST_TRY = "last_weather_try"; public static final String WEATHER_DATA = "weather_data"; + public static final String CACHED_CITY = "cached_city"; + // First run is used to hide the initial no-weather message for a better OOBE public static final String WEATHER_FIRST_UPDATE = "weather_first_update"; diff --git a/app/src/main/java/foundation/e/blisslauncher/features/weather/ForecastBuilder.java b/app/src/main/java/foundation/e/blisslauncher/features/weather/ForecastBuilder.java index c37064061f..f0ba009b9d 100644 --- a/app/src/main/java/foundation/e/blisslauncher/features/weather/ForecastBuilder.java +++ b/app/src/main/java/foundation/e/blisslauncher/features/weather/ForecastBuilder.java @@ -72,8 +72,8 @@ public class ForecastBuilder { w.getConditionCode(), WeatherIconUtils.getNextHigherDensity(context))); // City - TextView city = weatherPanel.findViewById(R.id.weather_city); - city.setText(w.getCity()); + TextView textCity = weatherPanel.findViewById(R.id.weather_city); + textCity.setText(Preferences.getCachedCity(context)); // Weather Condition TextView weatherCondition = weatherPanel.findViewById(R.id.weather_condition); 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 a28add39ef..2fd655ffe9 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 @@ -8,6 +8,8 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; +import android.widget.TextView; + import androidx.localbroadcastmanager.content.LocalBroadcastManager; import foundation.e.blisslauncher.R; import foundation.e.blisslauncher.core.Preferences; @@ -25,8 +27,17 @@ public class WeatherInfoView extends LinearLayout { if (WeatherUpdateService.ACTION_UPDATE_FINISHED.equals(intent.getAction())) { updateWeatherPanel(); } + + if (WeatherUpdateService.ACTION_UPDATE_CITY_FINISHED.equals(intent.getAction())) { + final TextView textCity = mWeatherPanel.findViewById(R.id.weather_city); + final String city = intent.getStringExtra(WeatherUpdateService.EXTRA_UPDATE_CITY_KEY); + if (city != null && !city.trim().isEmpty()) { + textCity.setText(city); + } + } } }; + private final BroadcastReceiver mResumeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -61,8 +72,12 @@ public class WeatherInfoView extends LinearLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getContext()); - broadcastManager.registerReceiver(mWeatherReceiver, - new IntentFilter(WeatherUpdateService.ACTION_UPDATE_FINISHED)); + final IntentFilter intentFilter = new IntentFilter(); + + intentFilter.addAction(WeatherUpdateService.ACTION_UPDATE_FINISHED); + intentFilter.addAction(WeatherUpdateService.ACTION_UPDATE_CITY_FINISHED); + + broadcastManager.registerReceiver(mWeatherReceiver, intentFilter); broadcastManager.registerReceiver(mResumeReceiver, new IntentFilter(LauncherActivity.ACTION_LAUNCHER_RESUME)); updateWeatherPanel(); } 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 77d98496e9..d7be85fdf0 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 @@ -15,6 +15,8 @@ public class WeatherUpdateService extends Service { public static final String ACTION_FORCE_UPDATE = "org.indin.blisslauncher.action.FORCE_WEATHER_UPDATE"; public static final String ACTION_UPDATE_FINISHED = "org.indin.blisslauncher.action.WEATHER_UPDATE_FINISHED"; + public static final String ACTION_UPDATE_CITY_FINISHED = "org.indin.blisslauncher.action.WEATHER_UPDATE_CITY_FINISHED"; + public static final String EXTRA_UPDATE_CITY_KEY = "city"; private static final long UPDATE_PERIOD_IN_MS = 5L * 1000L; 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 303aac6ae2..caa76ee31f 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 @@ -16,13 +16,27 @@ import androidx.core.app.ActivityCompat; import androidx.core.location.LocationManagerCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +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 lineageos.weather.LineageWeatherManager; import lineageos.weather.WeatherInfo; import lineageos.weather.WeatherLocation; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; public class WeatherUpdater { @@ -153,6 +167,10 @@ public class WeatherUpdater { } requestWeatherUpdate(getMostRecentLocation()); + + if (!Preferences.useCustomWeatherLocation(mWeakContext.get())) { + reverseGeocodeLocation(getMostRecentLocation()); + } } private void notifyUi(@NonNull Context context, @Nullable WeatherInfo weatherInfo, int status) { @@ -163,6 +181,7 @@ public class WeatherUpdater { } Log.i(TAG, "WeatherInfo=" + weatherInfo); + long now = SystemClock.elapsedRealtime(); Preferences.setCachedWeatherInfo(context, now, weatherInfo); Preferences.setLastWeatherUpdateTimestamp(context, now); @@ -188,4 +207,66 @@ public class WeatherUpdater { long networkTime = mNetworkLocation.getTime(); return gpsTime >= networkTime ? mGpsLocation : mNetworkLocation; } + + private void reverseGeocodeLocation(@NonNull Location location) { + Log.i(TAG, "Reverse geocoding location " + location); + + final String url = "https://api.openweathermap.org/geo/1.0/reverse?lat=" + location.getLatitude() + "&lon=" + + location.getLongitude() + "&limit=1&appid=" + mWeakContext.get().getString(R.string.default_key); + + final OkHttpClient okHttpClient = new OkHttpClient(); + final Request request = new Request.Builder().url(url).build(); + okHttpClient.newCall(request).enqueue(mReverseGeocodeCallback); + } + + private void onReverseGeocoded(@NonNull Response response) { + final ResponseBody body = response.body(); + if (body == null) { + Log.w(TAG, "Reverse geocoding response is empty"); + return; + } + + JsonObject locales; + try { + final String json = body.string(); + final JsonArray array = new JsonParser().parse(json).getAsJsonArray(); + locales = array.get(0).getAsJsonObject().getAsJsonObject("local_names"); + } catch (IOException | IllegalStateException | JsonSyntaxException exception) { + Log.e(TAG, "Exception caught", exception); + return; + } + + if (locales == null) { + Log.e(TAG, "Could not get locales"); + return; + } + + String countryCode = Locale.getDefault().getCountry().toLowerCase(Locale.ROOT); + if (!locales.has(countryCode)) { + countryCode = locales.get("en").getAsString(); + } + + final String city = locales.get(countryCode).getAsString(); + notifyUi(city); + } + + private void notifyUi(@NonNull String city) { + Context context = mWeakContext.get(); + Preferences.setCachedCity(context, city); + final Intent intent = new Intent(WeatherUpdateService.ACTION_UPDATE_CITY_FINISHED); + intent.putExtra(WeatherUpdateService.EXTRA_UPDATE_CITY_KEY, city); + LocalBroadcastManager.getInstance(mWeakContext.get()).sendBroadcast(intent); + } + + private final Callback mReverseGeocodeCallback = new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + Log.e(TAG, "Could not reverse geocode location", e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + onReverseGeocoded(response); + } + }; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01ff014d6d..7b5c62ab4a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,6 +9,8 @@ Unknown Cancel + DEFAULT_OWM_KEY + Tornado Tropical Storm -- GitLab