aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/cyanogenmod/lockclock/weather
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/cyanogenmod/lockclock/weather')
-rw-r--r--src/com/cyanogenmod/lockclock/weather/WeatherInfo.java261
-rw-r--r--src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java276
-rw-r--r--src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java113
-rw-r--r--src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java35
4 files changed, 533 insertions, 152 deletions
diff --git a/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java b/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java
index bb4a5fa..420900d 100644
--- a/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java
+++ b/src/com/cyanogenmod/lockclock/weather/WeatherInfo.java
@@ -17,99 +17,208 @@
package com.cyanogenmod.lockclock.weather;
import android.content.Context;
+import android.content.res.Resources;
+
import com.cyanogenmod.lockclock.R;
+import com.cyanogenmod.lockclock.misc.Preferences;
+
+import java.text.DecimalFormat;
+import java.util.Date;
public class WeatherInfo {
+ private static final long serialVersionUID = 1L;
- public static final String NODATA = "-";
-
- public String city, forecast_date, condition, condition_code, temp, temp_unit,
- humidity, wind, wind_dir, speed_unit, low, high;
- public long last_sync;
-
- public WeatherInfo() {
- this.city = NODATA;
- this.forecast_date = NODATA;
- this.condition = NODATA;
- this.condition_code = NODATA;
- this.temp = NODATA;
- this.temp_unit = NODATA;
- this.humidity = NODATA;
- this.wind = NODATA;
- this.wind_dir = NODATA;
- this.speed_unit = NODATA;
- this.low = NODATA;
- this.high = NODATA;
- this.last_sync = 0;
- }
+ private static final DecimalFormat sNoDigitsFormat = new DecimalFormat("0");
- public WeatherInfo(Context context, String city, String fdate, String condition, String condition_code,
- String temp, String temp_unit, String humidity,
- String wind, String wind_dir, String speed_unit,
- String low, String high, long last_sync) {
+ private Context mContext;
+
+ private String city;
+ private String forecastDate;
+ private String condition;
+ private int conditionCode;
+ private float temperature;
+ private float lowTemperature;
+ private float highTemperature;
+ private String tempUnit;
+ private float humidity;
+ private float wind;
+ private int windDirection;
+ private String speedUnit;
+ private long timestamp;
+
+ public WeatherInfo(Context context,
+ String city, String fdate, String condition, int conditionCode,
+ float temp, float low, float high, String tempUnit, float humidity,
+ float wind, int windDir, String speedUnit, long timestamp) {
+ this.mContext = context;
this.city = city;
- this.forecast_date = fdate;
+ this.forecastDate = fdate;
this.condition = condition;
- this.condition_code = condition_code;
- this.humidity = humidity + "%";
- this.wind = calcDirection(context, wind_dir) + " " + trimSpeed(wind) + speed_unit;
- this.speed_unit = speed_unit;
- this.last_sync = last_sync;
- // Only the current temperature gets the temp_unit added.
- this.temp_unit = temp_unit;
- this.temp = temp + "°" + temp_unit;
- this.low = low + "°";
- this.high = high + "°";
+ this.conditionCode = conditionCode;
+ this.humidity = humidity;
+ this.wind = wind;
+ this.windDirection = windDir;
+ this.speedUnit = speedUnit;
+ this.timestamp = timestamp;
+ this.temperature = temp;
+ this.lowTemperature = low;
+ this.highTemperature = high;
+ this.tempUnit = tempUnit;
+ }
+
+ public int getConditionResource() {
+ boolean alternativeIcons = Preferences.useAlternateWeatherIcons(mContext);
+ final String prefix = alternativeIcons ? "weather2_" : "weather_";
+ final Resources res = mContext.getResources();
+ final int resId = res.getIdentifier(prefix + conditionCode, "drawable", mContext.getPackageName());
+
+ if (resId != 0) {
+ return resId;
+ }
+
+ return alternativeIcons ? R.drawable.weather2_na : R.drawable.weather_na;
}
- /**
- * find the optimal weather string (helper function for translation)
- *
- * @param conditionCode condition code from Yahoo (this is the main
- * identifier which will be used to find a matching translation
- * in the project's resources
- * @param providedString
- * @return either the defaultString (which should be Yahoo's weather
- * condition text), or the translated version from resources
- */
- public static String getTranslatedConditionString(Context context, int conditionCode,
- String providedString) {
- int resID = context.getResources().getIdentifier("weather_" + conditionCode, "string",
- context.getPackageName());
- return (resID != 0) ? context.getResources().getString(resID) : providedString;
+ public String getCity() {
+ return city;
}
- private String calcDirection(Context context, String degrees) {
- try {
- int deg = Integer.parseInt(degrees);
- if (deg >= 338 || deg <= 22)
- return context.getResources().getString(R.string.weather_N);
- else if (deg < 68)
- return context.getResources().getString(R.string.weather_NE);
- else if (deg < 113)
- return context.getResources().getString(R.string.weather_E);
- else if (deg < 158)
- return context.getResources().getString(R.string.weather_SE);
- else if (deg < 203)
- return context.getResources().getString(R.string.weather_S);
- else if (deg < 248)
- return context.getResources().getString(R.string.weather_SW);
- else if (deg < 293)
- return context.getResources().getString(R.string.weather_W);
- else if (deg < 338)
- return context.getResources().getString(R.string.weather_NW);
- else
- return "";
- } catch (NumberFormatException e) {
+ public String getCondition() {
+ final Resources res = mContext.getResources();
+ final int resId = res.getIdentifier("weather_" + conditionCode, "string", mContext.getPackageName());
+
+ if (resId != 0) {
+ return res.getString(resId);
+ }
+
+ return condition;
+ }
+
+ public Date getTimestamp() {
+ return new Date(timestamp);
+ }
+
+ private String getFormattedValue(float value, String unit) {
+ if (Float.isNaN(highTemperature)) {
+ return "-";
+ }
+ return sNoDigitsFormat.format(value) + unit;
+ }
+
+ public String getFormattedTemperature() {
+ return getFormattedValue(temperature, "°" + tempUnit);
+ }
+
+ public String getFormattedLow() {
+ return getFormattedValue(lowTemperature, "°");
+ }
+
+ public String getFormattedHigh() {
+ return getFormattedValue(highTemperature, "°");
+ }
+
+ public String getFormattedHumidity() {
+ return getFormattedValue(humidity, "%");
+ }
+
+ public String getFormattedWindSpeed() {
+ return getFormattedValue(wind, speedUnit);
+ }
+
+ public String getWindDirection() {
+ int resId;
+
+ if (windDirection < 0) {
return "";
}
+
+ if (windDirection < 23) resId = R.string.weather_N;
+ else if (windDirection < 68) resId = R.string.weather_NE;
+ else if (windDirection < 113) resId = R.string.weather_E;
+ else if (windDirection < 158) resId = R.string.weather_SE;
+ else if (windDirection < 203) resId = R.string.weather_S;
+ else if (windDirection < 248) resId = R.string.weather_SW;
+ else if (windDirection < 293) resId = R.string.weather_W;
+ else if (windDirection < 338) resId = R.string.weather_NW;
+ else resId = R.string.weather_N;
+
+ return mContext.getString(resId);
}
- private String trimSpeed(String speed) {
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WeatherInfo for ");
+ builder.append(city);
+ builder.append("@ ");
+ builder.append(getTimestamp());
+ builder.append(": ");
+ builder.append(getCondition());
+ builder.append("(");
+ builder.append(conditionCode);
+ builder.append("), temperature ");
+ builder.append(getFormattedTemperature());
+ builder.append(", low ");
+ builder.append(getFormattedLow());
+ builder.append(", high ");
+ builder.append(getFormattedHigh());
+ builder.append(", humidity ");
+ builder.append(getFormattedHumidity());
+ builder.append(", wind ");
+ builder.append(getFormattedWindSpeed());
+ builder.append(" at ");
+ builder.append(getWindDirection());
+ return builder.toString();
+ }
+
+ public String toSerializedString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(city).append('|');
+ builder.append(forecastDate).append('|');
+ builder.append(condition).append('|');
+ builder.append(conditionCode).append('|');
+ builder.append(temperature).append('|');
+ builder.append(lowTemperature).append('|');
+ builder.append(highTemperature).append('|');
+ builder.append(tempUnit).append('|');
+ builder.append(humidity).append('|');
+ builder.append(wind).append('|');
+ builder.append(windDirection).append('|');
+ builder.append(speedUnit).append('|');
+ builder.append(timestamp);
+ return builder.toString();
+ }
+
+ public static WeatherInfo fromSerializedString(Context context, String input) {
+ if (input == null) {
+ return null;
+ }
+
+ String[] parts = input.split("\\|");
+ if (parts == null || parts.length != 13) {
+ return null;
+ }
+
+ int conditionCode, windDirection;
+ long timestamp;
+ float temperature, low, high, humidity, wind;
+
try {
- return String.valueOf(Math.round(Float.parseFloat(speed)));
+ conditionCode = Integer.parseInt(parts[3]);
+ temperature = Float.parseFloat(parts[4]);
+ low = Float.parseFloat(parts[5]);
+ high = Float.parseFloat(parts[6]);
+ humidity = Float.parseFloat(parts[8]);
+ wind = Float.parseFloat(parts[9]);
+ windDirection = Integer.parseInt(parts[10]);
+ timestamp = Long.parseLong(parts[12]);
} catch (NumberFormatException e) {
- return "";
+ return null;
}
+
+ return new WeatherInfo(context,
+ /* city */ parts[0], /* date */ parts[1], /* condition */ parts[2],
+ conditionCode, temperature, low, high, /* tempUnit */ parts[7],
+ humidity, wind, windDirection, /* speedUnit */ parts[11], timestamp);
}
}
diff --git a/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java b/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java
new file mode 100644
index 0000000..3e24dd7
--- /dev/null
+++ b/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.lockclock.weather;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.AsyncTask;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+import com.cyanogenmod.lockclock.ClockWidgetProvider;
+import com.cyanogenmod.lockclock.misc.Constants;
+import com.cyanogenmod.lockclock.misc.Preferences;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.w3c.dom.Document;
+
+public class WeatherUpdateService extends Service {
+ private static final String TAG = "WeatherUpdateService";
+ private static final boolean D = Constants.DEBUG;
+
+ private static final String URL_YAHOO_API_WEATHER = "http://weather.yahooapis.com/forecastrss?w=%s&u=";
+
+ public static final String ACTION_FORCE_UPDATE = "com.cyanogenmod.lockclock.action.FORCE_WEATHER_UPDATE";
+
+ private WeatherUpdateTask mTask;
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (D) Log.v(TAG, "Got intent " + intent);
+
+ if (mTask != null && mTask.getStatus() != AsyncTask.Status.FINISHED) {
+ if (D) Log.v(TAG, "Weather update is still active, not starting new update");
+ return START_REDELIVER_INTENT;
+ }
+
+ boolean force = ACTION_FORCE_UPDATE.equals(intent.getAction());
+ if (force) {
+ Preferences.setCachedWeatherInfo(this, 0, null);
+ }
+ if (!shouldUpdate(force)) {
+ Log.d(TAG, "Service started, but shouldn't update ... stopping");
+ stopSelf();
+ return START_NOT_STICKY;
+ }
+
+ mTask = new WeatherUpdateTask();
+ mTask.execute();
+
+ return START_REDELIVER_INTENT;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mTask != null && mTask.getStatus() != AsyncTask.Status.FINISHED) {
+ mTask.cancel(true);
+ mTask = null;
+ }
+ }
+
+ private boolean shouldUpdate(boolean force) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+ NetworkInfo info = cm.getActiveNetworkInfo();
+
+ if (info == null || !info.isConnected()) {
+ if (D) Log.d(TAG, "No network connection is available for weather update");
+ return false;
+ }
+
+ if (!Preferences.showWeather(this)) {
+ if (D) Log.v(TAG, "Weather isn't shown, skip update");
+ return false;
+ }
+
+ long interval = Preferences.weatherRefreshIntervalInMs(this);
+ if (interval == 0 && !force) {
+ if (D) Log.v(TAG, "Interval set to manual and update not forced, skip update");
+ return false;
+ }
+
+ long now = System.currentTimeMillis();
+ long lastUpdate = Preferences.lastWeatherUpdateTimestamp(this);
+ long due = lastUpdate + interval;
+
+ if (D) Log.d(TAG, "Now " + now + " due " + due + "(" + new Date(due) + ")");
+
+ if (lastUpdate != 0 && now < due) {
+ if (D) Log.v(TAG, "Weather update is not due yet");
+ return false;
+ }
+
+ return true;
+ }
+
+ private class WeatherUpdateTask extends AsyncTask<Void, Void, WeatherInfo> {
+ private WakeLock mWakeLock;
+ private Context mContext;
+
+ private static final int RESULT_SUCCESS = 0;
+ private static final int RESULT_FAILURE = 1;
+ private static final int RESULT_CANCELLED = 2;
+
+ public WeatherUpdateTask() {
+ PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mContext = WeatherUpdateService.this;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ mWakeLock.acquire();
+ }
+
+ private String getWoeidForCustomLocation(String location) {
+ // first try with the cached woeid, no need to constantly query constant information
+ String woeid = Preferences.getCachedWoeid(mContext);
+ if (woeid == null) {
+ woeid = YahooPlaceFinder.geoCode(mContext, location);
+ }
+ if (D) Log.v(TAG, "Yahoo location code for " + location + " is " + woeid);
+ return woeid;
+ }
+
+ private String getWoeidForCurrentLocation(Location location) {
+ String woeid = YahooPlaceFinder.reverseGeoCode(mContext,
+ location.getLatitude(), location.getLongitude());
+ if (woeid == null) {
+ // we couldn't fetch up-to-date information, fall back to cache
+ woeid = Preferences.getCachedWoeid(mContext);
+ }
+ if (D) Log.v(TAG, "Yahoo location code for current geolocation " + location + " is " + woeid);
+ return woeid;
+ }
+
+ private Location getCurrentLocation() {
+ LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
+ Location location = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
+ if (D) Log.v(TAG, "Current location is " + location);
+ return location;
+ }
+
+ private Document getDocument(String woeid) {
+ boolean celcius = Preferences.useMetricUnits(mContext);
+ String urlWithUnit = URL_YAHOO_API_WEATHER + (celcius ? "c" : "f");
+
+ try {
+ return new HttpRetriever().getDocumentFromURL(String.format(urlWithUnit, woeid));
+ } catch (IOException e) {
+ Log.e(TAG, "Couldn't fetch weather data", e);
+ }
+ return null;
+ }
+
+ @Override
+ protected WeatherInfo doInBackground(Void... params) {
+ String customLocation = null;
+ String woeid;
+
+ if (Preferences.useCustomWeatherLocation(mContext)) {
+ customLocation = Preferences.customWeatherLocation(mContext);
+ }
+
+ if (customLocation != null) {
+ woeid = getWoeidForCustomLocation(customLocation);
+ } else {
+ Location location = getCurrentLocation();
+ woeid = getWoeidForCurrentLocation(location);
+ }
+
+ if (woeid == null || isCancelled()) {
+ return null;
+ }
+
+ Document doc = getDocument(woeid);
+ if (doc == null || isCancelled()) {
+ return null;
+ }
+
+ return new WeatherXmlParser(mContext).parseWeatherResponse(doc);
+ }
+
+ @Override
+ protected void onPostExecute(WeatherInfo result) {
+ finish(result);
+ }
+
+ @Override
+ protected void onCancelled() {
+ finish(null);
+ }
+
+ private void finish(WeatherInfo result) {
+ if (result != null) {
+ long now = System.currentTimeMillis();
+ Preferences.setCachedWeatherInfo(mContext, now, result);
+ scheduleUpdate(mContext, Preferences.weatherRefreshIntervalInMs(mContext));
+
+ Intent updateIntent = new Intent(mContext, ClockWidgetProvider.class);
+ sendBroadcast(updateIntent);
+ } else if (isCancelled()) {
+ /* cancelled, likely due to lost network - we'll get restarted
+ * when network comes back */
+ } else {
+ /* failure, schedule next download in 30 minutes */
+ long interval = 30 * 60 * 1000;
+ scheduleUpdate(mContext, interval);
+ }
+
+ mWakeLock.release();
+ stopSelf();
+ }
+ }
+
+ private static void scheduleUpdate(Context context, long timeFromNow) {
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ long due = System.currentTimeMillis() + timeFromNow;
+
+ if (D) Log.v(TAG, "Scheduling next update at " + new Date(due));
+ am.set(AlarmManager.RTC_WAKEUP, due, getUpdateIntent(context, false));
+ }
+
+ public static void scheduleNextUpdate(Context context) {
+ long lastUpdate = Preferences.lastWeatherUpdateTimestamp(context);
+ if (lastUpdate == 0) {
+ scheduleUpdate(context, 0);
+ } else {
+ long interval = Preferences.weatherRefreshIntervalInMs(context);
+ scheduleUpdate(context, lastUpdate + interval - System.currentTimeMillis());
+ }
+ }
+
+ public static PendingIntent getUpdateIntent(Context context, boolean force) {
+ Intent i = new Intent(context, WeatherUpdateService.class);
+ if (force) {
+ i.setAction(ACTION_FORCE_UPDATE);
+ }
+ return PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+ public static void cancelUpdates(Context context) {
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ am.cancel(getUpdateIntent(context, true));
+ am.cancel(getUpdateIntent(context, false));
+ }
+}
diff --git a/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java b/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java
index 50c2c98..0a1643f 100644
--- a/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java
+++ b/src/com/cyanogenmod/lockclock/weather/WeatherXmlParser.java
@@ -69,90 +69,67 @@ public class WeatherXmlParser {
mContext = context;
}
+ private String getValueForAttribute(Element root, String tagName, String attributeName) {
+ NamedNodeMap node = root.getElementsByTagName(tagName).item(0).getAttributes();
+ if (node == null) {
+ return null;
+ }
+ return node.getNamedItem(attributeName).getNodeValue();
+ }
+
+ private float getFloatForAttribute(Element root, String tagName, String attributeName)
+ throws NumberFormatException {
+ String value = getValueForAttribute(root, tagName, attributeName);
+ if (value == null) {
+ return Float.NaN;
+ }
+ return Float.parseFloat(value);
+ }
+
+ private int getIntForAttribute(Element root, String tagName, String attributeName)
+ throws NumberFormatException {
+ String value = getValueForAttribute(root, tagName, attributeName);
+ if (value == null) {
+ return -1;
+ }
+ return Integer.parseInt(value);
+ }
+
public WeatherInfo parseWeatherResponse(Document docWeather) {
if (docWeather == null) {
Log.e(TAG, "Invalid doc weather");
return null;
}
- String strCity = null;
- String strDate = null;
- String strCondition = null;
- String strCondition_code = null;
- String strTemp = null;
- String strTempUnit = null;
- String strHumidity = null;
- String strWindSpeed = null;
- String strWindDir = null;
- String strSpeedUnit = null;
- String strHigh = null;
- String strLow = null;
-
try {
Element root = docWeather.getDocumentElement();
root.normalize();
- NamedNodeMap locationNode = root.getElementsByTagName(PARAM_YAHOO_LOCATION).item(0)
- .getAttributes();
- if (locationNode != null) {
- strCity = locationNode.getNamedItem(ATT_YAHOO_CITY).getNodeValue();
- }
-
- NamedNodeMap unitNode = root.getElementsByTagName(PARAM_YAHOO_UNIT).item(0)
- .getAttributes();
-
- if (locationNode != null) {
- strTempUnit = unitNode.getNamedItem(ATT_YAHOO_TEMP_UNIT).getNodeValue();
- strSpeedUnit = unitNode.getNamedItem(ATT_YAHOO_SPEED).getNodeValue();
- }
-
- NamedNodeMap atmosNode = root.getElementsByTagName(PARAM_YAHOO_ATMOSPHERE).item(0)
- .getAttributes();
- if (atmosNode != null) {
- strHumidity = atmosNode.getNamedItem(ATT_YAHOO_HUMIDITY).getNodeValue();
- }
-
- NamedNodeMap conditionNode = root.getElementsByTagName(PARAM_YAHOO_CONDITION).item(0)
- .getAttributes();
- if (conditionNode != null) {
- strCondition = conditionNode.getNamedItem(ATT_YAHOO_TEXT).getNodeValue();
- strCondition_code = conditionNode.getNamedItem(ATT_YAHOO_CODE).getNodeValue();
- strCondition = WeatherInfo.getTranslatedConditionString(mContext, Integer.parseInt(strCondition_code), strCondition);
- strTemp = conditionNode.getNamedItem(ATT_YAHOO_TEMP).getNodeValue();
- strDate = conditionNode.getNamedItem(ATT_YAHOO_DATE).getNodeValue();
- }
-
- NamedNodeMap temNode = root.getElementsByTagName(PARAM_YAHOO_WIND).item(0)
- .getAttributes();
- if (temNode != null) {
- strWindSpeed = temNode.getNamedItem(ATT_YAHOO_SPEED).getNodeValue();
- strWindDir = temNode.getNamedItem(ATT_YAHOO_DIRECTION).getNodeValue();
- }
-
- NamedNodeMap fcNode = root.getElementsByTagName(PARAM_YAHOO_FORECAST).item(0).getAttributes();
- if (fcNode != null) {
- strHigh = fcNode.getNamedItem(ATT_YAHOO_TODAY_HIGH).getNodeValue();
- strLow = fcNode.getNamedItem(ATT_YAHOO_TODAY_LOW).getNodeValue();
- }
+ WeatherInfo w = new WeatherInfo(mContext,
+ /* city */ getValueForAttribute(root, PARAM_YAHOO_LOCATION, ATT_YAHOO_CITY),
+ /* forecastDate */ getValueForAttribute(root, PARAM_YAHOO_CONDITION, ATT_YAHOO_DATE),
+ /* condition */ getValueForAttribute(root, PARAM_YAHOO_CONDITION, ATT_YAHOO_TEXT),
+ /* conditionCode */ getIntForAttribute(root, PARAM_YAHOO_CONDITION, ATT_YAHOO_CODE),
+ /* temperature */ getFloatForAttribute(root, PARAM_YAHOO_CONDITION, ATT_YAHOO_TEMP),
+ /* low */ getFloatForAttribute(root, PARAM_YAHOO_FORECAST, ATT_YAHOO_TODAY_LOW),
+ /* high */ getFloatForAttribute(root, PARAM_YAHOO_FORECAST, ATT_YAHOO_TODAY_HIGH),
+ /* tempUnit */ getValueForAttribute(root, PARAM_YAHOO_UNIT, ATT_YAHOO_TEMP_UNIT),
+ /* humidity */ getFloatForAttribute(root, PARAM_YAHOO_ATMOSPHERE, ATT_YAHOO_HUMIDITY),
+ /* wind */ getFloatForAttribute(root, PARAM_YAHOO_WIND, ATT_YAHOO_SPEED),
+ /* windDir */ getIntForAttribute(root, PARAM_YAHOO_WIND, ATT_YAHOO_DIRECTION),
+ /* speedUnit */ getValueForAttribute(root, PARAM_YAHOO_UNIT, ATT_YAHOO_SPEED),
+ System.currentTimeMillis());
+
+ Log.d(TAG, "Weather updated: " + w);
+ return w;
} catch (Exception e) {
- Log.e(TAG, "Something wrong with parser data: " + e.toString());
+ Log.e(TAG, "Couldn't parse Yahoo weather XML", e);
return null;
}
-
- /* Weather info */
- WeatherInfo yahooWeatherInfo = new WeatherInfo(mContext, strCity, strDate, strCondition, strCondition_code, strTemp,
- strTempUnit, strHumidity, strWindSpeed, strWindDir, strSpeedUnit, strLow, strHigh, System.currentTimeMillis());
-
- Log.d(TAG, "Weather updated for " + strCity + ": " + strDate + ", " + strCondition + "(" + strCondition_code
- + "), " + strTemp + strTempUnit + ", " + strHumidity + "% humidity, " + ", wind: " + strWindDir + " at "
- + strWindSpeed + strSpeedUnit + ", low: " + strLow + strTempUnit + " high: " + strHigh + strTempUnit);
-
- return yahooWeatherInfo;
}
public String parsePlaceFinderResponse(String response) {
try {
-
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(response)));
@@ -170,7 +147,7 @@ public class WeatherXmlParser {
}
}
} catch (Exception e) {
- Log.e(TAG, e.toString());
+ Log.e(TAG, "Couldn't parse Yahoo place finder XML", e);
}
return null;
}
diff --git a/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java b/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java
index 569cef1..c2b3f0d 100644
--- a/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java
+++ b/src/com/cyanogenmod/lockclock/weather/YahooPlaceFinder.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2013 The CyanogenMod Project (DvTonder)
* Copyright (C) 2012 The AOKP Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,25 +18,43 @@
package com.cyanogenmod.lockclock.weather;
import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.cyanogenmod.lockclock.misc.Preferences;
public class YahooPlaceFinder {
- private static final String YAHOO_API_BASE_REV_URL = "http://where.yahooapis.com/geocode?appid=jYkTZp64&q=%1$s,+%2$s&gflags=R";
- private static final String YAHOO_API_BASE_URL = "http://where.yahooapis.com/geocode?appid=jYkTZp64&q=%1$s";
+ private static final String YAHOO_API_BASE_REV_URL = "http://where.yahooapis.com/geocode?appid=EKvCnl4k&q=%1$s,+%2$s&gflags=R";
+ private static final String YAHOO_API_BASE_URL = "http://where.yahooapis.com/geocode?appid=EKvCnl4k&q=%1$s";
public static String reverseGeoCode(Context c, double latitude, double longitude) {
-
String url = String.format(YAHOO_API_BASE_REV_URL, String.valueOf(latitude),
String.valueOf(longitude));
String response = new HttpRetriever().retrieve(url);
- return new WeatherXmlParser(c).parsePlaceFinderResponse(response);
-
+ if (response == null) {
+ return null;
+ }
+
+ String woeid = new WeatherXmlParser(c).parsePlaceFinderResponse(response);
+ if (woeid != null) {
+ // cache the result for potential reuse - the placefinder service API is rate limited
+ Preferences.setCachedWoeid(c, woeid);
+ }
+ return woeid;
}
- public static String GeoCode(Context c, String location) {
+ public static String geoCode(Context c, String location) {
String url = String.format(YAHOO_API_BASE_URL, location).replace(' ', '+');
String response = new HttpRetriever().retrieve(url);
- return new WeatherXmlParser(c).parsePlaceFinderResponse(response);
+ if (response == null) {
+ return null;
+ }
+
+ String woeid = new WeatherXmlParser(c).parsePlaceFinderResponse(response);
+ if (woeid != null) {
+ // cache the result for potential reuse - the placefinder service API is rate limited
+ Preferences.setCachedWoeid(c, woeid);
+ }
+ return woeid;
}
-
}