public static List<LocationSearchResult> findLocationsAutocomplete(String startsWith) { LOGD(TAG, "Autocompleting locations starting with '" + startsWith + "'"); List<LocationSearchResult> results = new ArrayList<LocationSearchResult>(); HttpURLConnection connection = null; try { connection = Utils.openUrlConnection(buildPlaceSearchStartsWithUrl(startsWith)); XmlPullParser xpp = sXmlPullParserFactory.newPullParser(); xpp.setInput(new InputStreamReader(connection.getInputStream())); LocationSearchResult result = null; // See above method 'getLocationNameFromCoords'. String[] addrs = {"", "", "", "", "", ""}; int state = PARSE_STATE_NONE; // latitude and longitude values are shown in many entries. // But values in <centroid>, not in <boundingBox> are relatively exact one. // So using this flag, get only values in centroid entry. boolean centroid = false; int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String tagName = xpp.getName(); if (eventType == XmlPullParser.START_TAG) { switch (state) { case PARSE_STATE_NONE: if ("place".equals(tagName)) { state = PARSE_STATE_PLACE; result = new LocationSearchResult(); // reset for (int i = 0; i < addrs.length; i++) addrs[i] = ""; } break; case PARSE_STATE_PLACE: if ("name".equals(tagName)) { state = PARSE_STATE_NAME; } else if ("woeid".equals(tagName)) { state = PARSE_STATE_WOEID; } else if ("country".equals(tagName)) { state = PARSE_STATE_COUNTRY; } else if ("admin1".equals(tagName)) { state = PARSE_STATE_ADMIN1; } else if (centroid && "latitude".equals(tagName)) { state = PARSE_STATE_LAT; } else if (centroid && "longitude".equals(tagName)) { state = PARSE_STATE_LNG; } else if ("admin2".equals(tagName)) { state = PARSE_STATE_ADMIN2; } else if ("admin3".equals(tagName)) { state = PARSE_STATE_ADMIN3; } else if ("centroid".equals(tagName)) { // We use lat/lon values in <centroid> entry. centroid = true; } break; } } else if (eventType == XmlPullParser.TEXT) { switch (state) { case PARSE_STATE_WOEID: result.woeid = xpp.getText(); break; case PARSE_STATE_NAME: addrs[0] = xpp.getText(); break; case PARSE_STATE_ADMIN3: addrs[1] = xpp.getText(); break; case PARSE_STATE_ADMIN2: addrs[2] = xpp.getText(); break; case PARSE_STATE_ADMIN1: addrs[3] = xpp.getText(); break; case PARSE_STATE_COUNTRY: addrs[4] = xpp.getText(); break; case PARSE_STATE_LAT: result.lat = xpp.getText(); break; case PARSE_STATE_LNG: result.lng = xpp.getText(); } } else if (eventType == XmlPullParser.END_TAG) { if ("place".equals(tagName)) { String smallLocation = ""; String largeLocation = ""; for (int i = 0; i < addrs.length; i++) { if (TextUtils.isEmpty(addrs[i])) { continue; } else { smallLocation = addrs[i]; for (int j = i + 1; j < addrs.length; j++) { if (TextUtils.isEmpty(addrs[j])) { continue; } if (!smallLocation.equals(addrs[j])) { largeLocation = addrs[j]; break; } } if (!TextUtils.isEmpty(largeLocation)) { largeLocation = ", " + largeLocation; } break; } } result.displayName = smallLocation + largeLocation; result.country = addrs[4]; results.add(result); state = PARSE_STATE_NONE; } else if ("centroid".equals(tagName)) { centroid = false; } else if (state != PARSE_STATE_NONE) { state = PARSE_STATE_PLACE; } } eventType = xpp.next(); } } catch (IOException e) { LOGW(TAG, "Error parsing place search XML"); } catch (XmlPullParserException e) { LOGW(TAG, "Error parsing place search XML"); } finally { if (connection != null) { connection.disconnect(); } } return results; }
public static String getLocationNameFromCoords(double lat, double lng) { LOGD(TAG, "Looking up name for location : " + lat + ", " + lng); String displayName = "N/A"; // reset WOEID. sWoeid = ""; HttpURLConnection connection = null; try { Location tempLoc = new Location(""); tempLoc.setLatitude(lat); tempLoc.setLongitude(lng); connection = Utils.openUrlConnection(buildPlaceSearchUrl(tempLoc)); XmlPullParser xpp = sXmlPullParserFactory.newPullParser(); xpp.setInput(new InputStreamReader(connection.getInputStream())); // addrs have {'name', 'admin3', 'admin2', 'admin1', 'country'}, small -> large. // Not so few places have empty *local*, and/or admin* values in Yahoo place API. // So in some cases, only one name or two names with same values was shown. // For example, "SEOUL" or "SEOUL, SEOUL" can be removed. // So modified algorithm to get names. Not used local fields. // From name to country, skip empty or same value and make "small, large" form. String[] addrs = {"", "", "", "", ""}; String smallLocation = ""; String largeLocation = ""; StringBuffer sb = new StringBuffer(); int state = PARSE_STATE_NONE; int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String tagName = xpp.getName(); if (eventType == XmlPullParser.START_TAG) { switch (state) { case PARSE_STATE_NONE: if ("place".equals(tagName)) { state = PARSE_STATE_PLACE; } break; case PARSE_STATE_PLACE: if ("name".equals(tagName)) { state = PARSE_STATE_NAME; } else if ("admin1".equals(tagName)) { state = PARSE_STATE_ADMIN1; } else if ("admin2".equals(tagName)) { state = PARSE_STATE_ADMIN2; } else if ("admin3".equals(tagName)) { state = PARSE_STATE_ADMIN3; } else if ("country".equals(tagName)) { state = PARSE_STATE_COUNTRY; } else if ("woeid".equals(tagName)) { state = PARSE_STATE_WOEID; } break; } } else if (eventType == XmlPullParser.TEXT) { switch (state) { case PARSE_STATE_NAME: addrs[0] = xpp.getText(); break; case PARSE_STATE_ADMIN3: addrs[1] = xpp.getText(); break; case PARSE_STATE_ADMIN2: addrs[2] = xpp.getText(); break; case PARSE_STATE_ADMIN1: addrs[3] = xpp.getText(); break; case PARSE_STATE_COUNTRY: addrs[4] = xpp.getText(); break; case PARSE_STATE_WOEID: // This method 'getLocationNameFromCoords' itself doesnt need WOEID. // But other method 'getLocationInfo' calls it and needs WOEID. // So in this methdd, save WOEID to private static variable. sWoeid = xpp.getText(); break; } } else if (eventType == XmlPullParser.END_TAG) { if ("place".equals(tagName)) { for (int i = 0; i < addrs.length; i++) { if (TextUtils.isEmpty(addrs[i])) { // if field is empty, skip. continue; } else { smallLocation = addrs[i]; largeLocation = ""; for (int j = i + 1; j < addrs.length; j++) { if (TextUtils.isEmpty(addrs[j])) { continue; } if (!smallLocation.equals(addrs[j])) { // if second name is not empty and not same with previus one // (smallLocation) then it is to be largeLocation. largeLocation = addrs[j]; break; } } break; } } sb.setLength(0); if (!TextUtils.isEmpty(smallLocation)) { sb.append(smallLocation); } if (!TextUtils.isEmpty(largeLocation)) { if (sb.length() > 0) { sb.append(", "); } sb.append(largeLocation); } displayName = sb.toString(); state = PARSE_STATE_NONE; } else if (state != PARSE_STATE_NONE) { state = PARSE_STATE_PLACE; } } eventType = xpp.next(); } } catch (XmlPullParserException xppe) { LOGW(TAG, "Error parsing place name XML"); } catch (MalformedURLException mue) { LOGW(TAG, "Error parsing place name XML"); } catch (IOException ioe) { LOGW(TAG, "Error parsing place name XML"); } finally { if (connection != null) { connection.disconnect(); } } return displayName; }