在室外使用手机查询附近的兴趣点,采用的开源的osmdroid,实现POI的查询的几种开源方案:
1.采用FlickrPOIProvider实现:
POI Provider using Flickr service to get geolocalized photos.
@see http://www.flickr.com/services/api/flickr.photos.search.html
package org.osmdroid.bonuspack.location; import java.util.ArrayList; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.util.BoundingBoxE6; import org.osmdroid.util.GeoPoint; import android.util.Log; /** * POI Provider using Flickr service to get geolocalized photos. * @see http://www.flickr.com/services/api/flickr.photos.search.html * @author M.Kergall */ public class FlickrPOIProvider { protected String mApiKey; /** * @param apiKey the registered API key to give to Flickr service. * @see http://www.flickr.com/help/api/ */ public FlickrPOIProvider(String apiKey){ mApiKey = apiKey; } private String getUrlInside(BoundingBoxE6 boundingBox, int maxResults){ StringBuffer url = new StringBuffer("http://api.flickr.com/services/rest/?method=flickr.photos.search"); url.append("&api_key="+mApiKey); url.append("&bbox="+boundingBox.getLonWestE6()*1E-6); url.append(","+boundingBox.getLatSouthE6()*1E-6); url.append(","+boundingBox.getLonEastE6()*1E-6); url.append(","+boundingBox.getLatNorthE6()*1E-6); url.append("&has_geo=1"); url.append("&format=json&nojsoncallback=1"); url.append("&per_page="+maxResults); //From Flickr doc: "Geo queries require some sort of limiting agent in order to prevent the database from crying." //And min_date_upload is considered as a limiting agent. So: url.append("&min_upload_date=2005/01/01"); //Ask to provide some additional attributes we will need: url.append("&extras=geo,url_sq"); url.append("&sort=interestingness-desc"); return url.toString(); } /* public POI getPhoto(String photoId){ String url = "http://api.flickr.com/services/rest/?method=flickr.photos.getInfo" + "&api_key=" + mApiKey + "&photo_id=" + photoId + "&format=json&nojsoncallback=1"; Log.d(BonusPackHelper.LOG_TAG, "getPhoto:"+url); String jString = BonusPackHelper.requestStringFromUrl(url); if (jString == null) { Log.e(BonusPackHelper.LOG_TAG, "FlickrPOIProvider: request failed."); return null; } try { POI poi = new POI(POI.POI_SERVICE_FLICKR); JSONObject jRoot = new JSONObject(jString); JSONObject jPhoto = jRoot.getJSONObject("photo"); JSONObject jLocation = jPhoto.getJSONObject("location"); poi.mLocation = new GeoPoint( jLocation.getDouble("latitude"), jLocation.getDouble("longitude")); poi.mId = Long.parseLong(photoId); JSONObject jTitle = jPhoto.getJSONObject("title"); poi.mType = jTitle.getString("_content"); JSONObject jDescription = jPhoto.getJSONObject("description"); poi.mDescription = jDescription.getString("_content"); //truncate description if too long: if (poi.mDescription.length() > 300){ poi.mDescription = poi.mDescription.substring(0, 300) + " (...)"; } String farm = jPhoto.getString("farm"); String server = jPhoto.getString("server"); String secret = jPhoto.getString("secret"); JSONObject jOwner = jPhoto.getJSONObject("owner"); String nsid = jOwner.getString("nsid"); poi.mThumbnailPath = "http://farm"+farm+".staticflickr.com/"+server+"/"+photoId+"_"+secret+"_s.jpg"; poi.mUrl = "http://www.flickr.com/photos/"+nsid+"/"+photoId; return poi; }catch (JSONException e) { e.printStackTrace(); return null; } } */ /** * @param fullUrl * @return the list of POI */ public ArrayList<POI> getThem(String fullUrl){ //for local debug: fullUrl = "http://10.0.2.2/flickr_mockup.json"; Log.d(BonusPackHelper.LOG_TAG, "FlickrPOIProvider:get:"+fullUrl); String jString = BonusPackHelper.requestStringFromUrl(fullUrl); if (jString == null) { Log.e(BonusPackHelper.LOG_TAG, "FlickrPOIProvider: request failed."); return null; } try { JSONObject jRoot = new JSONObject(jString); JSONObject jPhotos = jRoot.getJSONObject("photos"); JSONArray jPhotoArray = jPhotos.getJSONArray("photo"); int n = jPhotoArray.length(); ArrayList<POI> pois = new ArrayList<POI>(n); for (int i=0; i<n; i++){ JSONObject jPhoto = jPhotoArray.getJSONObject(i); String photoId = jPhoto.getString("id"); POI poi = new POI(POI.POI_SERVICE_FLICKR); poi.mLocation = new GeoPoint( jPhoto.getDouble("latitude"), jPhoto.getDouble("longitude")); poi.mId = Long.parseLong(photoId); poi.mType = jPhoto.getString("title"); poi.mThumbnailPath = jPhoto.getString("url_sq"); String owner = jPhoto.getString("owner"); poi.mUrl = "http://www.flickr.com/photos/"+owner+"/"+photoId; pois.add(poi); } int total = jPhotos.getInt("total"); Log.d(BonusPackHelper.LOG_TAG, "done:"+n+" got, on a total of:"+total); return pois; }catch (JSONException e) { e.printStackTrace(); return null; } } /** * @param boundingBox * @param maxResults * @return list of POI, Flickr photos inside the bounding box. Null if technical issue. */ public ArrayList<POI> getPOIInside(BoundingBoxE6 boundingBox, int maxResults){ String url = getUrlInside(boundingBox, maxResults); return getThem(url); } }
2。采用GeoNames services实现:
package org.osmdroid.bonuspack.location; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Locale; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.bonuspack.utils.HttpConnection; import org.osmdroid.util.BoundingBoxE6; import org.osmdroid.util.GeoPoint; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import android.util.Log; /** * POI Provider using GeoNames services. * Currently, "find Nearby Wikipedia" and "Wikipedia Articles in Bounding Box" services. * @see http://www.geonames.org * @author M.Kergall */ public class GeoNamesPOIProvider { protected String mUserName; /** * @param account the registered "username" to give to GeoNames service. * @see http://www.geonames.org/login */ public GeoNamesPOIProvider(String account){ mUserName = account; } private String getUrlCloseTo(GeoPoint p, int maxResults, double maxDistance){ StringBuffer url = new StringBuffer("http://api.geonames.org/findNearbyWikipediaJSON?"); url.append("lat="+p.getLatitudeE6()*1E-6); url.append("&lng="+p.getLongitudeE6()*1E-6); url.append("&maxRows="+maxResults); url.append("&radius="+maxDistance); //km url.append("&lang="+Locale.getDefault().getLanguage()); url.append("&username="+mUserName); return url.toString(); } private String getUrlInside(BoundingBoxE6 boundingBox, int maxResults){ StringBuffer url = new StringBuffer("http://api.geonames.org/wikipediaBoundingBoxJSON?"); url.append("south="+boundingBox.getLatSouthE6()*1E-6); url.append("&north="+boundingBox.getLatNorthE6()*1E-6); url.append("&east="+boundingBox.getLonEastE6()*1E-6); url.append("&west="+boundingBox.getLonWestE6()*1E-6); url.append("&maxRows="+maxResults); url.append("&lang="+Locale.getDefault().getLanguage()); url.append("&username="+mUserName); return url.toString(); } /** * @param fullUrl * @return the list of POI */ public ArrayList<POI> getThem(String fullUrl){ Log.d(BonusPackHelper.LOG_TAG, "GeoNamesPOIProvider:get:"+fullUrl); String jString = BonusPackHelper.requestStringFromUrl(fullUrl); if (jString == null) { Log.e(BonusPackHelper.LOG_TAG, "GeoNamesPOIProvider: request failed."); return null; } try { JSONObject jRoot = new JSONObject(jString); JSONArray jPlaceIds = jRoot.getJSONArray("geonames"); int n = jPlaceIds.length(); ArrayList<POI> pois = new ArrayList<POI>(n); for (int i=0; i<n; i++){ JSONObject jPlace = jPlaceIds.getJSONObject(i); POI poi = new POI(POI.POI_SERVICE_GEONAMES_WIKIPEDIA); poi.mLocation = new GeoPoint(jPlace.getDouble("lat"), jPlace.getDouble("lng")); poi.mCategory = jPlace.optString("feature"); poi.mType = jPlace.getString("title"); poi.mDescription = jPlace.optString("summary"); poi.mThumbnailPath = jPlace.optString("thumbnailImg", null); /* This makes loading too long. * Thumbnail loading will be done only when needed, with POI.getThumbnail() if (poi.mThumbnailPath != null){ poi.mThumbnail = BonusPackHelper.loadBitmap(poi.mThumbnailPath); } */ poi.mUrl = jPlace.optString("wikipediaUrl", null); if (poi.mUrl != null) poi.mUrl = "http://" + poi.mUrl; poi.mRank = jPlace.optInt("rank", 0); //other attributes: distance? pois.add(poi); } Log.d(BonusPackHelper.LOG_TAG, "done"); return pois; }catch (JSONException e) { e.printStackTrace(); return null; } } //XML parsing seems 2 times slower than JSON parsing public ArrayList<POI> getThemXML(String fullUrl){ Log.d(BonusPackHelper.LOG_TAG, "GeoNamesPOIProvider:get:"+fullUrl); HttpConnection connection = new HttpConnection(); connection.doGet(fullUrl); InputStream stream = connection.getStream(); if (stream == null){ return null; } GeoNamesXMLHandler handler = new GeoNamesXMLHandler(); try { SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); parser.parse(stream, handler); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } connection.close(); Log.d(BonusPackHelper.LOG_TAG, "done"); return handler.mPOIs; } /** * @param position * @param maxResults * @param maxDistance in km. 20 km max for the free service. * @return list of POI, Wikipedia entries close to the position. Null if technical issue. */ public ArrayList<POI> getPOICloseTo(GeoPoint position, int maxResults, double maxDistance){ String url = getUrlCloseTo(position, maxResults, maxDistance); return getThem(url); } /** * @param boundingBox * @param maxResults * @return list of POI, Wikipedia entries inside the bounding box. Null if technical issue. */ public ArrayList<POI> getPOIInside(BoundingBoxE6 boundingBox, int maxResults){ String url = getUrlInside(boundingBox, maxResults); return getThem(url); } } class GeoNamesXMLHandler extends DefaultHandler { private String mString; double mLat, mLng; POI mPOI; ArrayList<POI> mPOIs; public GeoNamesXMLHandler() { mPOIs = new ArrayList<POI>(); } @Override public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { if (localName.equals("entry")){ mPOI = new POI(POI.POI_SERVICE_GEONAMES_WIKIPEDIA); } mString = new String(); } @Override public void characters(char[] ch, int start, int length) throws SAXException { String chars = new String(ch, start, length); mString = mString.concat(chars); } @Override public void endElement(String uri, String localName, String name) throws SAXException { if (localName.equals("lat")) { mLat = Double.parseDouble(mString); } else if (localName.equals("lng")) { mLng = Double.parseDouble(mString); } else if (localName.equals("feature")){ mPOI.mCategory = mString; } else if (localName.equals("title")){ mPOI.mType = mString; } else if (localName.equals("summary")){ mPOI.mDescription = mString; } else if (localName.equals("thumbnailImg")){ if (mString != null && !mString.equals("")) mPOI.mThumbnailPath = mString; } else if (localName.equals("wikipediaUrl")){ if (mString != null && !mString.equals("")) mPOI.mUrl = "http://" + mString; } else if (localName.equals("rank")){ mPOI.mRank = Integer.parseInt(mString); } else if (localName.equals("entry")) { mPOI.mLocation = new GeoPoint(mLat, mLng); mPOIs.add(mPOI); }; } }
3.采用 Nominatim service
package org.osmdroid.bonuspack.location; import java.net.URLEncoder; import java.util.ArrayList; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.util.BoundingBoxE6; import org.osmdroid.util.GeoPoint; import android.graphics.Bitmap; import android.util.Log; /** * POI Provider using Nominatim service. <br> * See https://wiki.openstreetmap.org/wiki/Nominatim<br> * and http://open.mapquestapi.com/nominatim/<br> * * @author M.Kergall */ public class NominatimPOIProvider { /* As the doc lacks a lot of features, source code may help: https://trac.openstreetmap.org/browser/applications/utils/nominatim/website/search.php * featuretype= to select on feature type (country, city, state, settlement)<br> * format=jsonv2 to get a place_rank<br> * offset= to offset the result ?... <br> * polygon=1 to get the border of the poi as a polygon<br> * nearlat & nearlon = ???<br> * routewidth/69 and routewidth/30 ???<br> */ public static final String MAPQUEST_POI_SERVICE = "http://open.mapquestapi.com/nominatim/v1/"; public static final String NOMINATIM_POI_SERVICE = "http://nominatim.openstreetmap.org/"; protected String mService; public NominatimPOIProvider(){ mService = NOMINATIM_POI_SERVICE; } public void setService(String serviceUrl){ mService = serviceUrl; } private StringBuffer getCommonUrl(String type, int maxResults){ StringBuffer urlString = new StringBuffer(mService); urlString.append("search?"); urlString.append("format=json"); urlString.append("&q=["+URLEncoder.encode(type)+"]"); urlString.append("&limit="+maxResults); urlString.append("&bounded=1"); return urlString; } private String getUrlInside(BoundingBoxE6 bb, String type, int maxResults){ StringBuffer urlString = getCommonUrl(type, maxResults); urlString.append("&viewbox="+bb.getLonWestE6()*1E-6+"," +bb.getLatNorthE6()*1E-6+"," +bb.getLonEastE6()*1E-6+"," +bb.getLatSouthE6()*1E-6); return urlString.toString(); } private String getUrlCloseTo(GeoPoint p, String type, int maxResults, double maxDistance){ int maxD = (int)(maxDistance*1E6); BoundingBoxE6 bb = new BoundingBoxE6(p.getLatitudeE6()+maxD, p.getLongitudeE6()+maxD, p.getLatitudeE6()-maxD, p.getLongitudeE6()-maxD); return getUrlInside(bb, type, maxResults); } /** * @param url full URL request * @return the list of POI, of null if technical issue. */ public ArrayList<POI> getThem(String url){ Log.d(BonusPackHelper.LOG_TAG, "NominatimPOIProvider:get:"+url); String jString = BonusPackHelper.requestStringFromUrl(url); if (jString == null) { Log.e(BonusPackHelper.LOG_TAG, "NominatimPOIProvider: request failed."); return null; } try { JSONArray jPlaceIds = new JSONArray(jString); int n = jPlaceIds.length(); ArrayList<POI> pois = new ArrayList<POI>(n); Bitmap thumbnail = null; for (int i=0; i<n; i++){ JSONObject jPlace = jPlaceIds.getJSONObject(i); POI poi = new POI(POI.POI_SERVICE_NOMINATIM); poi.mId = jPlace.optLong("osm_id"); poi.mLocation = new GeoPoint(jPlace.getDouble("lat"), jPlace.getDouble("lon")); poi.mCategory = jPlace.optString("class"); poi.mType = jPlace.getString("type"); poi.mDescription = jPlace.optString("display_name"); poi.mThumbnailPath = jPlace.optString("icon", null); if (i==0 && poi.mThumbnailPath != null) { //first POI, and we have a thumbnail: load it thumbnail = BonusPackHelper.loadBitmap(poi.mThumbnailPath); } poi.mThumbnail = thumbnail; pois.add(poi); } return pois; } catch (JSONException e) { e.printStackTrace(); return null; } } /** * @param position * @param type an OpenStreetMap feature. * See http://wiki.openstreetmap.org/wiki/Map_Features or http://code.google.com/p/osmbonuspack/source/browse/trunk/OSMBonusPackDemo/res/values/poi_tags.xml * @param maxResults the maximum number of POI returned. * Note that in any case, Nominatim will have an absolute maximum of 100. * @param maxDistance to the position, in degrees. * Note that it is used to build a bounding box around the position, not a circle. * @return the list of POI, null if technical issue. */ public ArrayList<POI> getPOICloseTo(GeoPoint position, String type, int maxResults, double maxDistance){ String url = getUrlCloseTo(position, type, maxResults, maxDistance); return getThem(url); } /** * @param boundingBox * @param type OpenStreetMap feature * @param maxResults * @return list of POIs, null if technical issue. */ public ArrayList<POI> getPOIInside(BoundingBoxE6 boundingBox, String type, int maxResults){ String url = getUrlInside(boundingBox, type, maxResults); return getThem(url); } /** * @param path * Warning: a long path may cause a failure due to the url to be too long. * Using a simplified route may help (see Road.getRouteLow()). * @param type OpenStreetMap feature * @param maxResults * @param maxWidth to the path. Certainly not in degrees. Probably in km. * @return list of POIs, null if technical issue. */ public ArrayList<POI> getPOIAlong(ArrayList<GeoPoint> path, String type, int maxResults, double maxWidth){ StringBuffer urlString = getCommonUrl(type, maxResults); urlString.append("&routewidth="+maxWidth); urlString.append("&route="); boolean isFirst = true; for (GeoPoint p:path){ if (isFirst) isFirst = false; else urlString.append(","); String lat = Double.toString(p.getLatitudeE6()*1E-6); lat = lat.substring(0, Math.min(lat.length(), 7)); String lon = Double.toString(p.getLongitudeE6()*1E-6); lon = lon.substring(0, Math.min(lon.length(), 7)); urlString.append(lat+","+lon); //limit the size of url as much as possible, as post method is not supported. } return getThem(urlString.toString()); } }
4.采用PicasaPOIProvider实现:
package org.osmdroid.bonuspack.location; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.bonuspack.utils.HttpConnection; import org.osmdroid.util.BoundingBoxE6; import org.osmdroid.util.GeoPoint; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import android.util.Log; /** * POI Provider using Picasa service. * @see https://developers.google.com/picasa-web/docs/2.0/reference * @author M.Kergall */ public class PicasaPOIProvider { String mAccessToken; /** * @param accessToken the account to give to the service. Null for public access. * @see https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol#CreatingAccount */ public PicasaPOIProvider(String accessToken){ mAccessToken = accessToken; } private String getUrlInside(BoundingBoxE6 boundingBox, int maxResults){ StringBuffer url = new StringBuffer("http://picasaweb.google.com/data/feed/api/all?"); url.append("bbox="+boundingBox.getLonWestE6()*1E-6); url.append(","+boundingBox.getLatSouthE6()*1E-6); url.append(","+boundingBox.getLonEastE6()*1E-6); url.append(","+boundingBox.getLatNorthE6()*1E-6); url.append("&max-results="+maxResults); url.append("&thumbsize=64c"); //thumbnail size: 64, cropped. url.append("&fields=entry(title,summary,media:group,gphoto:id,georss:where,link)"); if (mAccessToken != null){ //TODO: warning: not tested... url.append("&access_token="+mAccessToken); } return url.toString(); } public ArrayList<POI> getThem(String fullUrl){ Log.d(BonusPackHelper.LOG_TAG, "PicasaPOIProvider:get:"+fullUrl); HttpConnection connection = new HttpConnection(); connection.doGet(fullUrl); InputStream stream = connection.getStream(); if (stream == null){ return null; } PicasaXMLHandler handler = new PicasaXMLHandler(); try { SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); parser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces", false); parser.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes", true); parser.parse(stream, handler); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } connection.close(); Log.d(BonusPackHelper.LOG_TAG, "done"); return handler.mPOIs; } /** * @param boundingBox * @param maxResults * @return list of POI, Picasa photos inside the bounding box. Null if technical issue. */ public ArrayList<POI> getPOIInside(BoundingBoxE6 boundingBox, int maxResults){ String url = getUrlInside(boundingBox, maxResults); return getThem(url); } } class PicasaXMLHandler extends DefaultHandler { private String mString; double mLat, mLng; POI mPOI; ArrayList<POI> mPOIs; public PicasaXMLHandler() { mPOIs = new ArrayList<POI>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("entry")){ mPOI = new POI(POI.POI_SERVICE_PICASA); } else if(qName.equals("media:thumbnail")){ mPOI.mThumbnailPath = attributes.getValue("url"); } else if (qName.equals("link")){ String rel = attributes.getValue("rel"); if ("http://schemas.google.com/photos/2007#canonical".equals(rel)){ mPOI.mUrl = attributes.getValue("href"); } } mString = new String(); } @Override public void characters(char[] ch, int start, int length) throws SAXException { String chars = new String(ch, start, length); mString = mString.concat(chars); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("gml:pos")) { String[] coords = mString.split(" "); mLat = Double.parseDouble(coords[0]); mLng = Double.parseDouble(coords[1]); } else if (qName.equals("gphoto:id")){ mPOI.mId = Long.parseLong(mString); } else if (qName.equals("media:title")){ mPOI.mType = mString; } else if (qName.equals("summary")){ mPOI.mDescription = mString; } else if (qName.equals("entry")) { mPOI.mLocation = new GeoPoint(mLat, mLng); mPOIs.add(mPOI); mPOI = null; }; } }
5.采用基于 OpenStreetMap data and Nominatim 的API
package org.osmdroid.bonuspack.location; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.osmdroid.bonuspack.utils.BonusPackHelper; import android.content.Context; import android.location.Address; import android.util.Log; /** * Implements an equivalent to Android Geocoder class, based on OpenStreetMap data and Nominatim API. <br> * See http://wiki.openstreetmap.org/wiki/Nominatim * or http://open.mapquestapi.com/nominatim/ * @author M.Kergall */ public class GeocoderNominatim { public static final String NOMINATIM_SERVICE_URL = "http://nominatim.openstreetmap.org/"; public static final String MAPQUEST_SERVICE_URL = "http://open.mapquestapi.com/nominatim/v1/"; protected Locale mLocale; protected String mServiceUrl; protected void init(Context context, Locale locale){ mLocale = locale; setService(NOMINATIM_SERVICE_URL); //default service } public GeocoderNominatim(Context context, Locale locale){ init(context, locale); } public GeocoderNominatim(Context context){ init(context, Locale.getDefault()); } static public boolean isPresent(){ return true; } /** * Specify the url of the Nominatim service provider to use. * Can be one of the predefined (NOMINATIM_SERVICE_URL or MAPQUEST_SERVICE_URL), * or another one, your local instance of Nominatim for instance. */ public void setService(String serviceUrl){ mServiceUrl = serviceUrl; } /** * Build an Android Address object from the Nominatim address in JSON format. * Current implementation is mainly targeting french addresses, * and will be quite basic on other countries. */ protected Address buildAndroidAddress(JSONObject jResult) throws JSONException{ Address gAddress = new Address(mLocale); gAddress.setLatitude(jResult.getDouble("lat")); gAddress.setLongitude(jResult.getDouble("lon")); JSONObject jAddress = jResult.getJSONObject("address"); int addressIndex = 0; if (jAddress.has("road")){ gAddress.setAddressLine(addressIndex++, jAddress.getString("road")); gAddress.setThoroughfare(jAddress.getString("road")); } if (jAddress.has("suburb")){ //gAddress.setAddressLine(addressIndex++, jAddress.getString("suburb")); //not kept => often introduce "noise" in the address. gAddress.setSubLocality(jAddress.getString("suburb")); } if (jAddress.has("postcode")){ gAddress.setAddressLine(addressIndex++, jAddress.getString("postcode")); gAddress.setPostalCode(jAddress.getString("postcode")); } if (jAddress.has("city")){ gAddress.setAddressLine(addressIndex++, jAddress.getString("city")); gAddress.setLocality(jAddress.getString("city")); } else if (jAddress.has("town")){ gAddress.setAddressLine(addressIndex++, jAddress.getString("town")); gAddress.setLocality(jAddress.getString("town")); } else if (jAddress.has("village")){ gAddress.setAddressLine(addressIndex++, jAddress.getString("village")); gAddress.setLocality(jAddress.getString("village")); } if (jAddress.has("county")){ //France: departement gAddress.setSubAdminArea(jAddress.getString("county")); } if (jAddress.has("state")){ //France: region gAddress.setAdminArea(jAddress.getString("state")); } if (jAddress.has("country")){ gAddress.setAddressLine(addressIndex++, jAddress.getString("country")); gAddress.setCountryName(jAddress.getString("country")); } if (jAddress.has("country_code")) gAddress.setCountryCode(jAddress.getString("country_code")); /* Other possible OSM tags in Nominatim results not handled yet: * subway, golf_course, bus_stop, parking,... * house, house_number, building * city_district (13e Arrondissement) * road => or highway, ... * sub-city (like suburb) => locality, isolated_dwelling, hamlet ... * state_district */ return gAddress; } public List<Address> getFromLocation(double latitude, double longitude, int maxResults) throws IOException { String url = mServiceUrl + "reverse?" + "format=json" + "&accept-language=" + mLocale.getLanguage() //+ "&addressdetails=1" + "&lat=" + latitude + "&lon=" + longitude; Log.d(BonusPackHelper.LOG_TAG, "GeocoderNominatim::getFromLocation:"+url); String result = BonusPackHelper.requestStringFromUrl(url); //Log.d("NOMINATIM", result); if (result == null) throw new IOException(); try { JSONObject jResult = new JSONObject(result); Address gAddress = buildAndroidAddress(jResult); List<Address> list = new ArrayList<Address>(); list.add(gAddress); return list; } catch (JSONException e) { throw new IOException(); } } public List<Address> getFromLocationName(String locationName, int maxResults, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude) throws IOException { String url = mServiceUrl + "search?" + "format=json" + "&accept-language=" + mLocale.getLanguage() + "&addressdetails=1" + "&limit=" + maxResults + "&q=" + URLEncoder.encode(locationName); if (lowerLeftLatitude != 0.0 && lowerLeftLongitude != 0.0){ //viewbox = left, top, right, bottom: url += "&viewbox=" + lowerLeftLongitude + "," + upperRightLatitude + "," + upperRightLongitude + "," + lowerLeftLatitude + "&bounded=1"; } Log.d(BonusPackHelper.LOG_TAG, "GeocoderNominatim::getFromLocationName:"+url); String result = BonusPackHelper.requestStringFromUrl(url); //Log.d(BonusPackHelper.LOG_TAG, result); if (result == null) throw new IOException(); try { JSONArray jResults = new JSONArray(result); List<Address> list = new ArrayList<Address>(); for (int i=0; i<jResults.length(); i++){ JSONObject jResult = jResults.getJSONObject(i); Address gAddress = buildAndroidAddress(jResult); list.add(gAddress); } return list; } catch (JSONException e) { throw new IOException(); } } public List<Address> getFromLocationName(String locationName, int maxResults) throws IOException { return getFromLocationName(locationName, maxResults, 0.0, 0.0, 0.0, 0.0); } }