diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4434b5da6ab7e16ce02d0e70c018ade234e7f9c7..0bea12eddd934d3e656a276e5c9c8b1b14ebaf07 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 91c17ebece0937c397bcf419db5acfc742fc5c6b..859b4892fc171b7d744f5c7073b1a527405158db 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 c0f06554091206724a099972697f20e19f52fd9e..a308315abe1e829e12ef4aabeacff82e5aec2e77 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 c37064061f736ebea3bf1af5a7c5278934ffdfbc..f0ba009b9d590d417a303c118ddc5fd60cac4be3 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 a28add39efccc4f7489deda9e9065c226a4ae32c..2fd655ffe9c666dccaa73fa8272c09df0591cf8f 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 77d98496e9e8c9a0d854629e46ffc3fe5d3b10a3..d7be85fdf0155b6f3963a7ceaf9bc70772b1a782 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 303aac6ae2b76067b46d64d30a719200b36be523..caa76ee31fec00d9a8d3f473586d1407557970bb 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 01ff014d6d00efae037782047c9cdc40e07994f6..7b5c62ab4a9de89f5bf336f0227453e626377e64 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