/* * Android Weather Notification. * Copyright (C) 2010 Denis Nelubin aka Gelin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * http://gelin.ru * mailto:den@gelin.ru */ package ru.gelin.android.weather.notification; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.preference.PreferenceManager; import ru.gelin.android.weather.*; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import static ru.gelin.android.weather.notification.WeatherStorageKeys.*; /** * Stores and retrieves the weather objects to SharedPreferences. * The exact classes of the retrieved Weather can differ from the classes * of the saved weather. */ @SuppressWarnings("deprecation") public class WeatherStorage { /** Preference name for weather (this fake preference is updated * to call preference change listeners) */ static final String WEATHER = "weather"; /** SharedPreferences to store weather. */ SharedPreferences preferences; /** * Creates the storage for context. */ public WeatherStorage(Context context) { this.preferences = PreferenceManager.getDefaultSharedPreferences(context); //Log.d(TAG, "storage for " + context.getPackageName()); } /** * Saves the weather. */ public void save(Weather weather) { Editor editor = preferences.edit(); editor.putLong(WEATHER, System.currentTimeMillis()); //just current time editor.putString(LOCATION, weather.getLocation().getText()); editor.putLong(TIME, weather.getTime().getTime()); editor.putLong(QUERY_TIME, weather.getQueryTime().getTime()); if (weather.getForecastURL() == null) { editor.remove(FORECAST_URL); } else { editor.putString(FORECAST_URL, String.valueOf(weather.getForecastURL())); } if (weather.getUnitSystem() == null) { editor.remove(UNIT_SYSTEM); } else { editor.putString(UNIT_SYSTEM, weather.getUnitSystem().toString()); } int i = 0; for (WeatherCondition condition : weather.getConditions()) { ConditionPreferencesEditor conditionEditor = new ConditionPreferencesEditor(editor, i); conditionEditor.putOrRemove(CONDITION_TEXT, condition.getConditionText()); conditionEditor.putOrRemove(CONDITION_TYPES, condition.getConditionTypes()); Temperature temp = condition.getTemperature(); conditionEditor.putOrRemove(TEMPERATURE_UNIT, temp.getTemperatureUnit()); conditionEditor.putOrRemove(CURRENT_TEMP, temp.getCurrent()); conditionEditor.putOrRemove(LOW_TEMP, temp.getLow()); conditionEditor.putOrRemove(HIGH_TEMP, temp.getHigh()); Humidity hum = condition.getHumidity(); conditionEditor.putOrRemove(HUMIDITY_VALUE, hum.getValue()); conditionEditor.putOrRemove(HUMIDITY_TEXT, hum.getText()); Wind wind = condition.getWind(); conditionEditor.putOrRemove(WIND_SPEED_UNIT, wind.getSpeedUnit()); conditionEditor.putOrRemove(WIND_SPEED, wind.getSpeed()); conditionEditor.putOrRemove(WIND_DIR, wind.getDirection()); conditionEditor.putOrRemove(WIND_TEXT, wind.getText()); Cloudiness cloudiness = condition.getCloudiness(); if (cloudiness == null) { conditionEditor.remove(CLOUDINESS_UNIT); conditionEditor.remove(CLOUDINESS_VALUE); } else { conditionEditor.putOrRemove(CLOUDINESS_UNIT, cloudiness.getCloudinessUnit()); conditionEditor.putOrRemove(CLOUDINESS_VALUE, cloudiness.getValue()); } Precipitation precipitation = condition.getPrecipitation(); if (precipitation == null) { conditionEditor.remove(PRECIPITATION_UNIT); conditionEditor.remove(PRECIPITATION_PERIOD); conditionEditor.remove(PRECIPITATION_VALUE); } else { conditionEditor.putOrRemove(PRECIPITATION_UNIT, precipitation.getPrecipitationUnit()); conditionEditor.putOrRemove(PRECIPITATION_PERIOD, PrecipitationPeriod.PERIOD_1H.getHours()); conditionEditor.putOrRemove(PRECIPITATION_VALUE, precipitation.getValue(PrecipitationPeriod.PERIOD_1H)); } i++; } for (; i < 4; i++) { ConditionPreferencesEditor conditionEditor = new ConditionPreferencesEditor(editor, i); conditionEditor.remove(CONDITION_TEXT); conditionEditor.remove(CONDITION_TYPES, 0); conditionEditor.remove(TEMPERATURE_UNIT); conditionEditor.remove(CURRENT_TEMP); conditionEditor.remove(LOW_TEMP); conditionEditor.remove(HIGH_TEMP); conditionEditor.remove(HUMIDITY_VALUE); conditionEditor.remove(HUMIDITY_TEXT); conditionEditor.remove(WIND_SPEED_UNIT); conditionEditor.remove(WIND_SPEED); conditionEditor.remove(WIND_DIR); conditionEditor.remove(WIND_TEXT); conditionEditor.remove(CLOUDINESS_UNIT); conditionEditor.remove(CLOUDINESS_VALUE); conditionEditor.remove(PRECIPITATION_UNIT); conditionEditor.remove(PRECIPITATION_PERIOD); conditionEditor.remove(PRECIPITATION_VALUE); } editor.commit(); } /** * Loads the weather. * The values of the saved weather are restored, not exact classes. */ public Weather load() { SimpleWeather weather = new ParcelableWeather2(); Location location = new SimpleLocation( preferences.getString(LOCATION, "")); weather.setLocation(location); weather.setTime(new Date(preferences.getLong(TIME, 0))); weather.setQueryTime(new Date(preferences.getLong(QUERY_TIME, System.currentTimeMillis()))); try { weather.setForecastURL(new URL(preferences.getString(FORECAST_URL, ""))); } catch (MalformedURLException e) { weather.setForecastURL(null); } int i = 0; List<WeatherCondition> conditions = new ArrayList<WeatherCondition>(); while (preferences.contains(String.format(CONDITION_TEXT, i))) { ConditionPreferencesReader conditionReader = new ConditionPreferencesReader(preferences, i); SimpleWeatherCondition condition = new SimpleWeatherCondition(); condition.setConditionText(conditionReader.get(CONDITION_TEXT, "")); Collection<WeatherConditionType> types = conditionReader.getEnums(CONDITION_TYPES, WeatherConditionType.class); for (WeatherConditionType type : types) { condition.addConditionType(type); } TemperatureUnit tunit = conditionReader.get(TEMPERATURE_UNIT, TemperatureUnit.F); SimpleTemperature temp = new SimpleTemperature(tunit); temp.setCurrent(conditionReader.get(CURRENT_TEMP, Temperature.UNKNOWN), tunit); temp.setLow(conditionReader.get(LOW_TEMP, Temperature.UNKNOWN), tunit); temp.setHigh(conditionReader.get(HIGH_TEMP, Temperature.UNKNOWN), tunit); condition.setTemperature(temp); SimpleHumidity hum = new SimpleHumidity(); hum.setValue(conditionReader.get(HUMIDITY_VALUE, Humidity.UNKNOWN)); hum.setText(conditionReader.get(HUMIDITY_TEXT, "")); condition.setHumidity(hum); WindSpeedUnit windSpeedUnit = conditionReader.get(WIND_SPEED_UNIT, WindSpeedUnit.MPH); SimpleWind wind = new SimpleWind(windSpeedUnit); wind.setSpeed(conditionReader.get(WIND_SPEED, Wind.UNKNOWN), windSpeedUnit); wind.setDirection(conditionReader.get(WIND_DIR, WindDirection.N)); wind.setText(conditionReader.get(WIND_TEXT, "")); condition.setWind(wind); CloudinessUnit cloudinessUnit = conditionReader.get(CLOUDINESS_UNIT, CloudinessUnit.OKTA); SimpleCloudiness cloudiness = new SimpleCloudiness(cloudinessUnit); cloudiness.setValue(conditionReader.get(CLOUDINESS_VALUE, Cloudiness.UNKNOWN), cloudinessUnit); condition.setCloudiness(cloudiness); PrecipitationUnit precipitationUnit = conditionReader.get(PRECIPITATION_UNIT, PrecipitationUnit.MM); SimplePrecipitation precipitation = new SimplePrecipitation(precipitationUnit); PrecipitationPeriod precipitationPeriod = PrecipitationPeriod.valueOf( conditionReader.get(PRECIPITATION_PERIOD, PrecipitationPeriod.PERIOD_1H.getHours())); precipitation.setValue(conditionReader.get(PRECIPITATION_VALUE, Precipitation.UNKNOWN), precipitationPeriod); condition.setPrecipitation(precipitation); conditions.add(condition); i++; } weather.setConditions(conditions); return weather; } /** * Updates just "weather" preference to signal that the weather update is performed, * but nothing is changed. */ public void updateTime() { Editor editor = preferences.edit(); editor.putLong(WEATHER, System.currentTimeMillis()); //just current time editor.commit(); } private abstract static class ConditionPreferences { int index; protected ConditionPreferences(int index) { this.index = index; } protected String formatKey(String keyTemplate) { return String.format(keyTemplate, this.index); } protected String formatKey(String keyTemplate, int subindex) { return String.format(keyTemplate, this.index, subindex); } } private static class ConditionPreferencesEditor extends ConditionPreferences { SharedPreferences.Editor editor; public ConditionPreferencesEditor(SharedPreferences.Editor editor, int index) { super(index); this.editor = editor; } public void remove(String key) { this.editor.remove(formatKey(key)); } public void remove(String key, int subindex) { this.editor.remove(formatKey(key, subindex)); } public void putOrRemove(String key, String value) { if (value == null || "".equals(value)) { this.editor.remove(formatKey(key)); } else { this.editor.putString(formatKey(key), value); } } public void putOrRemove(String key, Enum value) { if (value == null) { this.editor.remove(formatKey(key)); } else { this.editor.putString(formatKey(key), String.valueOf(value)); } } public void putOrRemove(String key, Collection values) { int i = 0; if (values != null) { for (Object value : values) { this.editor.putString(formatKey(key, i), String.valueOf(value)); i++; } } this.editor.remove(formatKey(key, i)); } public void putOrRemove(String key, int value) { if (value == Integer.MIN_VALUE) { this.editor.remove(formatKey(key)); } else { this.editor.putInt(formatKey(key), value); } } public void putOrRemove(String key, float value) { if (value == Float.MIN_VALUE) { this.editor.remove(formatKey(key)); } else { this.editor.putFloat(formatKey(key), value); } } } private static class ConditionPreferencesReader extends ConditionPreferences { SharedPreferences preferences; public ConditionPreferencesReader(SharedPreferences preferences, int index) { super(index); this.preferences = preferences; } public String get(String key, String defaultValue) { return this.preferences.getString(formatKey(key), defaultValue); } public <E extends Enum<E>> E get(String key, E defaultValue) { Class<? extends Enum> enumClass = defaultValue.getClass(); return (E)Enum.valueOf(enumClass, this.preferences.getString(formatKey(key), String.valueOf(defaultValue))); } public <E extends Enum<E>> Collection<E> getEnums(String key, Class<E> enumClass) { List<E> result = new ArrayList<E>(); int i = 0; while (this.preferences.contains(formatKey(key, i))) { result.add(Enum.valueOf(enumClass, this.preferences.getString(formatKey(key, i), null))); i++; } return result; } public int get(String key, int defaultValue) { return this.preferences.getInt(formatKey(key), defaultValue); } public float get(String key, float defaultValue) { return this.preferences.getFloat(formatKey(key), defaultValue); } } }