diff options
author | DvTonder <david.vantonder@gmail.com> | 2013-12-09 22:06:49 -0500 |
---|---|---|
committer | DvTonder <david.vantonder@gmail.com> | 2013-12-09 22:06:49 -0500 |
commit | 5381fbab6824dc9f72da68ba28c6df7861503570 (patch) | |
tree | d366e9f791207d1783e7e2a1e8e4cf7af041608a /src | |
parent | 142abbc21d2b04dee9d643aa3f1ada8f499f8209 (diff) | |
download | android_packages_apps_LockClock-5381fbab6824dc9f72da68ba28c6df7861503570.tar.gz android_packages_apps_LockClock-5381fbab6824dc9f72da68ba28c6df7861503570.tar.bz2 android_packages_apps_LockClock-5381fbab6824dc9f72da68ba28c6df7861503570.zip |
cLock: Forward port CM10.2 updates
Change-Id: Icec530485324193f76ac7bfe48ca5ca179bd0b7b
Diffstat (limited to 'src')
7 files changed, 250 insertions, 127 deletions
diff --git a/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java b/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java index 30c1bda..d2265cb 100644 --- a/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java +++ b/src/com/cyanogenmod/lockclock/ClockWidgetProvider.java @@ -63,6 +63,8 @@ public class ClockWidgetProvider extends AppWidgetProvider { // Boot completed, schedule next weather update } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { + // On first boot lastUpdate will be 0 thus no need to force an update + // Subsequent boots will use cached data WeatherUpdateService.scheduleNextUpdate(context); // A widget has been deleted, prevent our handling and ask the super class handle it diff --git a/src/com/cyanogenmod/lockclock/ClockWidgetService.java b/src/com/cyanogenmod/lockclock/ClockWidgetService.java index 7726328..1698122 100755 --- a/src/com/cyanogenmod/lockclock/ClockWidgetService.java +++ b/src/com/cyanogenmod/lockclock/ClockWidgetService.java @@ -20,11 +20,13 @@ import android.app.AlarmManager; import android.app.IntentService; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.net.Uri; +import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; import android.text.format.DateFormat; @@ -108,9 +110,20 @@ public class ClockWidgetService extends IntentService { for (int id : mWidgetIds) { boolean showCalendar = false; + // Determine if its a home or a lock screen widget + Bundle myOptions = mAppWidgetManager.getAppWidgetOptions (id); + boolean isKeyguard = false; + if (WidgetUtils.isTextClockAvailable()) { + // This is only available on API 17+, make sure we are not calling it on API16 + // This generates an API level Lint warning, ignore it + int category = myOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1); + isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD; + } + if (D) Log.d("TAG", "For Widget id " + id + " isKeyguard is set to " + isKeyguard); + // Determine which layout to use boolean smallWidget = showWeather && showWeatherWhenMinimized - && WidgetUtils.showSmallWidget(this, id, digitalClock); + && WidgetUtils.showSmallWidget(this, id, digitalClock, isKeyguard); if (smallWidget) { // The small widget is only shown if weather needs to be shown // and there is not enough space for the full weather widget and @@ -143,7 +156,7 @@ public class ClockWidgetService extends IntentService { // Hide the calendar panel if not visible remoteViews.setViewVisibility(R.id.calendar_panel, showCalendar ? View.VISIBLE : View.GONE); - boolean canFitWeather = smallWidget || WidgetUtils.canFitWeather(this, id, digitalClock); + boolean canFitWeather = smallWidget || WidgetUtils.canFitWeather(this, id, digitalClock, isKeyguard); // Now, if we need to show the actual weather, do so if (showWeather && canFitWeather) { WeatherInfo weatherInfo = Preferences.getCachedWeatherInfo(this); @@ -378,6 +391,10 @@ public class ClockWidgetService extends IntentService { int timestampColor = Preferences.weatherTimestampFontColor(this); boolean colorIcons = Preferences.useAlternateWeatherIcons(this); + // Reset no weather visibility + weatherViews.setViewVisibility(R.id.weather_no_data, View.GONE); + weatherViews.setViewVisibility(R.id.weather_refresh, View.GONE); + // Weather Image if (colorIcons) { // No additional color overlays needed @@ -438,27 +455,38 @@ public class ClockWidgetService extends IntentService { * There is no data to display, display 'empty' fields and the 'Tap to reload' message */ private void setNoWeatherData(RemoteViews weatherViews, boolean smallWidget) { - boolean defaultIcons = !Preferences.useAlternateWeatherIcons(this); - final Resources res = getBaseContext().getResources(); int color = Preferences.weatherFontColor(this); + boolean firstRun = Preferences.isFirstWeatherUpdate(this); - // Weather Image - Either the default or alternate set - weatherViews.setImageViewResource(R.id.weather_image, - defaultIcons ? R.drawable.weather_na : R.drawable.weather2_na); - + // Hide the normal weather stuff + String noData = getString(R.string.weather_cannot_reach_provider, getString(R.string.weather_source)); + weatherViews.setViewVisibility(R.id.weather_image, View.INVISIBLE); if (!smallWidget) { - weatherViews.setTextViewText(R.id.weather_city, res.getString(R.string.weather_no_data)); - weatherViews.setViewVisibility(R.id.weather_city, View.VISIBLE); + weatherViews.setViewVisibility(R.id.weather_city, View.GONE); weatherViews.setViewVisibility(R.id.update_time, View.GONE); - weatherViews.setTextColor(R.id.weather_city, color); + weatherViews.setViewVisibility(R.id.weather_temps_panel, View.GONE); + weatherViews.setViewVisibility(R.id.weather_condition, View.GONE); + + // Set up the no data and refresh indicators + weatherViews.setTextViewText(R.id.weather_no_data, noData); + weatherViews.setTextViewText(R.id.weather_refresh, getString(R.string.weather_tap_to_refresh)); + weatherViews.setTextColor(R.id.weather_no_data, color); + weatherViews.setTextColor(R.id.weather_refresh, color); + + // For a better OOBE, dont show the no_data message if this is the first run + weatherViews.setViewVisibility(R.id.weather_no_data, firstRun ? View.GONE : View.VISIBLE); + weatherViews.setViewVisibility(R.id.weather_refresh, firstRun ? View.GONE : View.VISIBLE); + } else { + weatherViews.setTextViewText(R.id.weather_temp, firstRun ? null : noData); + weatherViews.setTextViewText(R.id.weather_condition, firstRun ? null : getString(R.string.weather_tap_to_refresh)); + weatherViews.setTextColor(R.id.weather_temp, color); + weatherViews.setTextColor(R.id.weather_condition, color); } - weatherViews.setViewVisibility(R.id.weather_temps_panel, View.GONE); - weatherViews.setTextViewText(R.id.weather_condition, res.getString(R.string.weather_tap_to_refresh)); - weatherViews.setTextColor(R.id.weather_condition, color); - - // Register an onClickListener on Weather - setWeatherClickListener(weatherViews); + // Register an onClickListener on Weather with the default (Refresh) action + if (!firstRun) { + setWeatherClickListener(weatherViews); + } } private void setWeatherClickListener(RemoteViews weatherViews) { diff --git a/src/com/cyanogenmod/lockclock/misc/Constants.java b/src/com/cyanogenmod/lockclock/misc/Constants.java index 535dcb0..db1b89f 100755 --- a/src/com/cyanogenmod/lockclock/misc/Constants.java +++ b/src/com/cyanogenmod/lockclock/misc/Constants.java @@ -67,7 +67,10 @@ public class Constants { public static final String WEATHER_LAST_UPDATE = "last_weather_update"; public static final String WEATHER_DATA = "weather_data"; - public static final int MAX_CALENDAR_ITEMS = 10; + // 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"; + + public static final int MAX_CALENDAR_ITEMS = 30; public static final long CALENDAR_UPCOMING_EVENTS_FROM_HOUR = 20L; public static final int CALENDAR_FORMAT_TIME = DateUtils.FORMAT_SHOW_TIME diff --git a/src/com/cyanogenmod/lockclock/misc/Preferences.java b/src/com/cyanogenmod/lockclock/misc/Preferences.java index 3cef8ff..a6c5c77 100644 --- a/src/com/cyanogenmod/lockclock/misc/Preferences.java +++ b/src/com/cyanogenmod/lockclock/misc/Preferences.java @@ -29,6 +29,10 @@ public class Preferences { private Preferences() { } + public static boolean isFirstWeatherUpdate(Context context) { + return getPrefs(context).getBoolean(Constants.WEATHER_FIRST_UPDATE, true); + } + public static boolean showDigitalClock(Context context) { return getPrefs(context).getBoolean(Constants.CLOCK_DIGITAL, true); } @@ -166,6 +170,8 @@ public class Preferences { SharedPreferences.Editor editor = getPrefs(context).edit(); editor.putLong(Constants.WEATHER_LAST_UPDATE, timestamp); if (data != null) { + // We now have valid weather data to display + editor.putBoolean(Constants.WEATHER_FIRST_UPDATE, false); editor.putString(Constants.WEATHER_DATA, data.toSerializedString()); } editor.apply(); diff --git a/src/com/cyanogenmod/lockclock/misc/WidgetUtils.java b/src/com/cyanogenmod/lockclock/misc/WidgetUtils.java index 242916e..465ddc2 100644 --- a/src/com/cyanogenmod/lockclock/misc/WidgetUtils.java +++ b/src/com/cyanogenmod/lockclock/misc/WidgetUtils.java @@ -32,6 +32,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Bitmap.Config; import android.os.Build; import android.os.Bundle; +import android.util.Log; import android.util.TypedValue; import com.cyanogenmod.lockclock.R; @@ -41,6 +42,9 @@ public class WidgetUtils { // Widget display and resizing related functionality //=============================================================================================== + private static final String TAG = "WidgetUtils"; + private static final boolean D = Constants.DEBUG; + /** * Load a resource by Id and overlay with a specified color */ @@ -60,7 +64,7 @@ public class WidgetUtils { /** * Decide whether to show the small Weather panel */ - public static boolean showSmallWidget(Context context, int id, boolean digitalClock) { + public static boolean showSmallWidget(Context context, int id, boolean digitalClock, boolean isKeyguard) { Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(id); if (options == null) { // no data to make the calculation, show the list anyway @@ -70,18 +74,32 @@ public class WidgetUtils { int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); int minHeightPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, minHeight, resources.getDisplayMetrics()); - int neededFullSize = (int) resources.getDimension( - digitalClock ? R.dimen.min_digital_weather_height : R.dimen.min_analog_weather_height); + int neededFullSize = 0; + if (isKeyguard) { + neededFullSize = (int) resources.getDimension( + digitalClock ? R.dimen.min_digital_weather_height_lock + : R.dimen.min_analog_weather_height_lock); + } else { + neededFullSize = (int) resources.getDimension( + digitalClock ? R.dimen.min_digital_weather_height + : R.dimen.min_analog_weather_height); + } int neededSmallSize = (int) resources.getDimension(R.dimen.min_digital_widget_height); // Check to see if the widget size is big enough, if it is return true. - return (minHeightPx < neededFullSize && minHeightPx > neededSmallSize); + Boolean result = minHeightPx < neededFullSize && minHeightPx > neededSmallSize; + if (D) { + Log.d(TAG, "showSmallWidget: digital clock = " + digitalClock + " with minHeightPx = " + minHeightPx + + " and neededFullSize = " + neededFullSize + " and neededSmallSize = " + neededSmallSize); + Log.d(TAG, "showsmallWidget result = " + result); + } + return result; } /** * Decide whether to show the full Weather panel */ - public static boolean canFitWeather(Context context, int id, boolean digitalClock) { + public static boolean canFitWeather(Context context, int id, boolean digitalClock, boolean isKeyguard) { Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(id); if (options == null) { // no data to make the calculation, show the list anyway @@ -91,11 +109,25 @@ public class WidgetUtils { int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); int minHeightPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, minHeight, resources.getDisplayMetrics()); - int neededSize = (int) resources.getDimension( - digitalClock ? R.dimen.min_digital_weather_height : R.dimen.min_analog_weather_height); + int neededSize = 0; + if (isKeyguard) { + neededSize = (int) resources.getDimension( + digitalClock ? R.dimen.min_digital_weather_height_lock + : R.dimen.min_analog_weather_height_lock); + } else { + neededSize = (int) resources.getDimension( + digitalClock ? R.dimen.min_digital_weather_height + : R.dimen.min_analog_weather_height); + } // Check to see if the widget size is big enough, if it is return true. - return (minHeightPx > neededSize); + Boolean result = minHeightPx > neededSize; + if (D) { + Log.d(TAG, "canFitWeather: digital clock = " + digitalClock + " with minHeightPx = " + + minHeightPx + " and neededSize = " + neededSize); + Log.d(TAG, "canFitWeather result = " + result); + } + return result; } /** @@ -115,7 +147,13 @@ public class WidgetUtils { digitalClock ? R.dimen.min_digital_calendar_height : R.dimen.min_analog_calendar_height); // Check to see if the widget size is big enough, if it is return true. - return (minHeightPx > neededSize); + Boolean result = minHeightPx > neededSize; + if (D) { + if (D) Log.d(TAG, "canFitCalendar: digital clock = " + digitalClock + " with minHeightPx = " + + minHeightPx + " and neededSize = " + neededSize); + Log.d(TAG, "canFitCalendar result = " + result); + } + return result; } /** diff --git a/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java b/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java index badf20b..94fca71 100755 --- a/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java +++ b/src/com/cyanogenmod/lockclock/weather/WeatherUpdateService.java @@ -301,7 +301,7 @@ public class WeatherUpdateService extends Service { public static void scheduleNextUpdate(Context context) { long lastUpdate = Preferences.lastWeatherUpdateTimestamp(context); if (lastUpdate == 0) { - scheduleUpdate(context, 0, false); + scheduleUpdate(context, 0, true); } else { long interval = Preferences.weatherRefreshIntervalInMs(context); scheduleUpdate(context, lastUpdate + interval - System.currentTimeMillis(), false); diff --git a/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java b/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java index 15addf6..dc714cb 100644 --- a/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java +++ b/src/com/cyanogenmod/lockclock/weather/YahooWeatherProvider.java @@ -26,45 +26,40 @@ 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.Collections; -import java.util.Comparator; 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, " + "locality1, locality2, country from geo.places where " + "(placetype = 7 or placetype = 8 or placetype = 9 " + "or placetype = 10 or placetype = 11) and text ="); + private static final String URL_PLACEFINDER = + "http://query.yahooapis.com/v1/public/yql?format=json&q=" + + Uri.encode("select woeid, city from geo.placefinder where gflags=\"R\" and text ="); private static final String[] LOCALITY_NAMES = new String[] { "locality1", "locality2", "admin3", "admin2", "admin1" }; - private static class YahooLocationResult extends LocationResult { - private int score; - }; - private static final Comparator<YahooLocationResult> LOCATION_COMPARATOR = - new Comparator<YahooLocationResult>() { - @Override - public int compare(YahooLocationResult lhs, YahooLocationResult rhs) { - if (lhs.score == rhs.score) { - return 0; - } - // smaller score at the top - return lhs.score < rhs.score ? -1 : 1; - } - }; - private Context mContext; public YahooWeatherProvider(Context context) { @@ -76,106 +71,162 @@ public class YahooWeatherProvider implements WeatherProvider { String locale = mContext.getResources().getConfiguration().locale.getCountry(); String params = "\"" + input + "\" and lang = \"" + locale + "\""; String url = URL_LOCATION + Uri.encode(params); - JSONArray places = fetchPlaceList(url); - - if (places == null) { + JSONObject jsonResults = fetchResults(url); + if (jsonResults == null) { return null; } - return new ArrayList<LocationResult>(parsePlaces(places)); + try { + JSONArray places = jsonResults.optJSONArray("place"); + if (places == null) { + // Yahoo returns an object instead of an array when there's only one result + places = new JSONArray(); + places.put(jsonResults.getJSONObject("place")); + } + + ArrayList<LocationResult> results = new ArrayList<LocationResult>(); + for (int i = 0; i < places.length(); i++) { + LocationResult result = parsePlace(places.getJSONObject(i)); + if (result != null) { + results.add(result); + } + } + return results; + } catch (JSONException e) { + Log.e(TAG, "Received malformed places data", e); + } + return null; } 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 formattedCoordinates = String.format(Locale.US, "\"%f %f\"", - location.getLatitude(), location.getLongitude()); - String url = URL_LOCATION + Uri.encode(formattedCoordinates); - JSONArray places = fetchPlaceList(url); - if (places == null) { + String locale = mContext.getResources().getConfiguration().locale.getCountry(); + String params = String.format(Locale.US, "\"%f %f\" and lang=\"%s\"", + location.getLatitude(), location.getLongitude(), locale); + String url = URL_PLACEFINDER + Uri.encode(params); + JSONObject results = fetchResults(url); + if (results == null) { return null; } - List<YahooLocationResult> results = parsePlaces(places); - Collections.sort(results, LOCATION_COMPARATOR); + try { + JSONObject result = results.getJSONObject("Result"); + String woeid = result.getString("woeid"); + String city = result.getString("city"); + + Log.d(TAG, "Resolved location " + location + " to " + city + " (" + woeid + ")"); - for (YahooLocationResult result : results) { - Log.d(TAG, "Looking up weather for " + result.city + " (id=" + result.id - + ", score=" + result.score + ")"); - WeatherInfo info = getWeatherInfo(result.id, result.city); + WeatherInfo info = getWeatherInfo(woeid, city); if (info != null) { // cache the result for potential reuse // (the placefinder service API is rate limited) - Preferences.setCachedLocationId(mContext, result.id); + Preferences.setCachedLocationId(mContext, woeid); return info; } + } catch (JSONException e) { + Log.e(TAG, "Received malformed placefinder data", e); } return null; } - private List<YahooLocationResult> parsePlaces(JSONArray places) { - ArrayList<YahooLocationResult> results = new ArrayList<YahooLocationResult>(); - for (int i = 0; i < places.length(); i++) { - try { - YahooLocationResult result = parsePlace(places.getJSONObject(i)); - if (result != null) { - results.add(result); - } - } catch (JSONException e) { - Log.w(TAG, "Found invalid JSON place record, ignoring.", e); - } - } - return results; - } - - private YahooLocationResult parsePlace(JSONObject place) throws JSONException { - YahooLocationResult result = new YahooLocationResult(); + private LocationResult parsePlace(JSONObject place) throws JSONException { + LocationResult result = new LocationResult(); JSONObject country = place.getJSONObject("country"); result.id = place.getString("woeid"); @@ -185,11 +236,9 @@ public class YahooWeatherProvider implements WeatherProvider { result.postal = place.getJSONObject("postal").getString("content"); } - for (int i = 0; i < LOCALITY_NAMES.length; i++) { - String locName = LOCALITY_NAMES[i]; - if (!place.isNull(locName)) { - result.city = place.getJSONObject(locName).getString("content"); - result.score = i; + for (String name : LOCALITY_NAMES) { + if (!place.isNull(name)) { + result.city = place.getJSONObject(name).getString("content"); break; } } @@ -201,22 +250,19 @@ public class YahooWeatherProvider implements WeatherProvider { return result; } - private JSONArray fetchPlaceList(String url) { + private JSONObject fetchResults(String url) { String response = HttpRetriever.retrieve(url); if (response == null) { return null; } + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Request URL is " + url + ", response is " + response); + } + try { JSONObject rootObject = new JSONObject(response); - JSONObject results = rootObject.getJSONObject("query").getJSONObject("results"); - JSONArray places = results.optJSONArray("place"); - if (places == null) { - // Yahoo returns an object instead of an array when there's only one result - places = new JSONArray(); - places.put(results.getJSONObject("place")); - } - return places; + return rootObject.getJSONObject("query").getJSONObject("results"); } catch (JSONException e) { Log.w(TAG, "Received malformed places data", e); } |