diff options
author | Danny Baumann <dannybaumann@web.de> | 2013-11-12 11:27:35 +0100 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2013-11-12 14:21:43 +0000 |
commit | c26ad6a2b4fb8b3faeb782eabe2709f11a906ee1 (patch) | |
tree | 3ad9e408337f0f6aafb8e9e0bbe9e3166244c409 | |
parent | 2166b4ab503380286c8a8ff612bdbb7d6289bb80 (diff) | |
download | android_packages_apps_LockClock-c26ad6a2b4fb8b3faeb782eabe2709f11a906ee1.tar.gz android_packages_apps_LockClock-c26ad6a2b4fb8b3faeb782eabe2709f11a906ee1.tar.bz2 android_packages_apps_LockClock-c26ad6a2b4fb8b3faeb782eabe2709f11a906ee1.zip |
Go back to weather RSS parsing instead of using YQL.
YQL is rate limited (2000 queries per IP and hour); some people seem
to hit this limitation.
Change-Id: Ib1945cf716447fbc23e9a54f6494076b21bd71d7
-rw-r--r-- | src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java | 128 |
1 files changed, 93 insertions, 35 deletions
diff --git a/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java b/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java index 4bb657d..dc714cb 100644 --- a/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java +++ b/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java @@ -26,17 +26,26 @@ import com.cyanogenmod.lockclock.misc.Preferences; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; +import java.io.IOException; +import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + public class YahooWeatherProvider implements WeatherProvider { private static final String TAG = "YahooWeatherProvider"; private static final String URL_WEATHER = - "http://query.yahooapis.com/v1/public/yql?format=json&q=" + - Uri.encode("select * from weather.forecast where woeid ="); + "http://weather.yahooapis.com/forecastrss?w=%s&u=%s"; private static final String URL_LOCATION = "http://query.yahooapis.com/v1/public/yql?format=json&q=" + Uri.encode("select woeid, postal, admin1, admin2, admin3, " + @@ -91,51 +100,100 @@ public class YahooWeatherProvider implements WeatherProvider { public WeatherInfo getWeatherInfo(String id, String localizedCityName) { String unit = Preferences.useMetricUnits(mContext) ? "c" : "f"; - String params = "\"" + id + "\" and u = \"" + unit + "\""; - String url = URL_WEATHER + Uri.encode(params); + String url = String.format(URL_WEATHER, id, unit); String response = HttpRetriever.retrieve(url); if (response == null) { return null; } + SAXParserFactory factory = SAXParserFactory.newInstance(); try { - JSONObject rootObject = new JSONObject(response); - JSONObject results = rootObject.getJSONObject("query").getJSONObject("results"); - JSONObject data = results.getJSONObject("channel"); - - String city = localizedCityName != null - ? localizedCityName : data.getJSONObject("location").getString("city"); - - JSONObject wind = data.getJSONObject("wind"); - JSONObject units = data.getJSONObject("units"); - JSONObject item = data.getJSONObject("item"); - JSONObject conditions = item.getJSONObject("condition"); - JSONObject forecast = item.getJSONArray("forecast").getJSONObject(0); - - WeatherInfo w = new WeatherInfo(mContext, id, city, - /* forecastDate */ conditions.getString("date"), - /* condition */ conditions.getString("text"), - /* conditionCode */ conditions.getInt("code"), - /* temperature */ (float) conditions.getDouble("temp"), - /* low */ (float) forecast.getDouble("low"), - /* high */ (float) forecast.getDouble("high"), - /* tempUnit */ units.getString("temperature"), - /* humidity */ (float) data.getJSONObject("atmosphere").getDouble("humidity"), - /* wind */ (float) wind.optDouble("speed", -1), - /* windDir */ wind.optInt("direction", -1), - /* speedUnit */ units.getString("speed"), - System.currentTimeMillis()); - - Log.d(TAG, "Weather updated: " + w); - return w; - } catch (JSONException e) { - Log.w(TAG, "Weather condition data is invalid.", e); + SAXParser parser = factory.newSAXParser(); + StringReader reader = new StringReader(response); + WeatherHandler handler = new WeatherHandler(); + parser.parse(new InputSource(reader), handler); + + if (handler.isComplete()) { + WeatherInfo w = new WeatherInfo(mContext, id, + localizedCityName != null ? localizedCityName : handler.city, null, + handler.condition, handler.conditionCode, handler.temperature, + handler.forecasts.get(0).low, handler.forecasts.get(0).high, + handler.temperatureUnit, handler.humidity, handler.windSpeed, + handler.windDirection, handler.speedUnit, + System.currentTimeMillis()); + Log.d(TAG, "Weather updated: " + w); + return w; + } + } catch (ParserConfigurationException e) { + Log.e(TAG, "Could not create XML parser", e); + } catch (SAXException e) { + Log.e(TAG, "Could not parse weather XML", e); + } catch (IOException e) { + Log.e(TAG, "Could not parse weather XML", e); } return null; } + private static class WeatherHandler extends DefaultHandler { + String city; + String temperatureUnit, speedUnit; + int windDirection, conditionCode; + float humidity, temperature, windSpeed; + String condition; + ArrayList<DayForecast> forecasts = new ArrayList<DayForecast>(); + + private static class DayForecast { + float low, high; + int conditionCode; + String condition; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + if (qName.equals("yweather:location")) { + city = attributes.getValue("city"); + } else if (qName.equals("yweather:units")) { + temperatureUnit = attributes.getValue("temperature"); + speedUnit = attributes.getValue("speed"); + } else if (qName.equals("yweather:wind")) { + windDirection = (int) stringToFloat(attributes.getValue("direction"), -1); + windSpeed = stringToFloat(attributes.getValue("speed"), -1); + } else if (qName.equals("yweather:atmosphere")) { + humidity = stringToFloat(attributes.getValue("humidity"), -1); + } else if (qName.equals("yweather:condition")) { + condition = attributes.getValue("text"); + conditionCode = (int) stringToFloat(attributes.getValue("code"), -1); + temperature = stringToFloat(attributes.getValue("temp"), Float.NaN); + } else if (qName.equals("yweather:forecast")) { + DayForecast day = new DayForecast(); + day.low = stringToFloat(attributes.getValue("low"), Float.NaN); + day.high = stringToFloat(attributes.getValue("high"), Float.NaN); + day.condition = attributes.getValue("text"); + day.conditionCode = (int) stringToFloat(attributes.getValue("code"), -1); + if (!Float.isNaN(day.low) && !Float.isNaN(day.high) && day.conditionCode >= 0) { + forecasts.add(day); + } + } + } + public boolean isComplete() { + return temperatureUnit != null && speedUnit != null && conditionCode >= 0 + && !Float.isNaN(temperature) && !forecasts.isEmpty(); + } + private float stringToFloat(String value, float defaultValue) { + try { + if (value != null) { + return Float.parseFloat(value); + } + } catch (NumberFormatException e) { + // fall through to the return line below + } + return defaultValue; + } + } + public WeatherInfo getWeatherInfo(Location location) { String locale = mContext.getResources().getConfiguration().locale.getCountry(); String params = String.format(Locale.US, "\"%f %f\" and lang=\"%s\"", |