`
longgangbai
  • 浏览: 7332247 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

           在室外使用手机查询附近的兴趣点,采用的开源的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);
	}
	
}

 

 

 

分享到:
评论

相关推荐

    抓取高德POI生成GIS

    通过对"高德poi2GIS.py"文件的学习和实践,你可以深入理解如何将网络爬虫与GIS分析结合,从而实现从互联网数据到可视化地理信息的全过程。这不仅有助于提升编程技能,也有利于掌握GIS在实际问题中的应用。

    java_poi实现excel导入导出

    Java POI 实现 Excel 导入导出 Java POI 是一个流行的 Java 库,用于处理 Microsoft Office 文件格式,包括 Excel 文件。在本文中,我们将详细介绍如何使用 Java POI 实现 Excel 导入导出功能。 1. 什么是 Java ...

    arcgis api 结合高德POI搜索.zip

    - **高德地图API**:学习如何注册并获取API密钥,理解查询接口的参数和返回数据结构,以及如何将结果在地图上展示。 - **坐标转换**:由于天地图和高德地图可能使用不同的坐标系统,所以开发者需要知道如何在它们...

    GIS设计器,设计器支持所见即所得的POI添加、删除、修改等功能

    开源的GIS设计器意味着它的源代码对公众开放,开发者可以根据需求进行二次开发,添加自定义功能或者改进现有功能。这种开放性不仅鼓励社区协作,也为企业和个人提供了极大的灵活性和定制化可能性。 GIS设计器的应用...

    Springboot+Poi实现Excel的导入导出

    在本项目中,Spring Boot结合MyBatis和POI,实现了一个完整的数据流转流程:从MySQL数据库中查询数据,使用POI将查询结果集转换为Excel文件保存到本地;反之,也可以读取本地Excel文件,将其中的数据导入到MySQL...

    POI实现word和excel在线预览

    本项目提供的"POI实现word和excel在线预览"是基于Apache POI的一个实用工具集,它能够帮助开发者实现在Web环境下对这些文件的在线预览功能,无需用户下载文件到本地即可查看内容,提高了用户体验和数据安全性。...

    java实现poi模板生成PPT文件代码

    Java中的Apache POI库是一个强大的工具,用于读取、创建和修改Microsoft Office格式的文件,包括PPT(PowerPoint)文档。在这个项目中,我们将会探讨如何使用POI API来生成PPT文件,特别是通过模板的方式。以下是...

    POI学习笔记详细说明

    POI学习笔记第二版更详细的POI学习笔记第二版更详细的

    Java实现POI导出Excel

    Java实现POI导出Excel是Java开发者常用的一种技术,用于生成和操作Microsoft Office Excel文件。在Java中,Apache POI库提供了对微软Office文档格式的支持,包括读取和写入Excel文件。这篇博客文章...

    自定义标签实现POI导出

    标题“自定义标签实现POI导出”表明我们即将探讨的是如何使用Apache POI库来创建自定义的Excel导出功能。Apache POI是Java语言中用于读写Microsoft Office格式文件(如Word、Excel)的一个开源库。在这个场景中,...

    java 实现word 转PDF (采用第三方技术 IText、Poi、Jsoup)

    java 实现word 转PDF (采用第三方技术 IText、Poi、Jsoup)iText-2.0.8.jar core-renderer.jar iTextAsian.jar iTextAsianCmaps.jar jsoup-1.8.1.jar

    【GIS应用】南京市2020年POI数据集(包括餐饮、风景名胜、公共设施、公司企业、超市等).zip

    【GIS应用】南京市2020年POI数据集提供了丰富的地理信息,涵盖了城市中的餐饮、风景名胜、公共设施、公司企业以及超市等多个类别,是理解和分析南京市城市功能、商业布局以及居民生活的重要资源。POI(Point of ...

    基于poi的excel导入.doc

    "POI导入Excel知识点" POI简介 Apache POI是一个开源的Java库,用于处理Microsoft Office文档,包括Excel、Word、PowerPoint等。POI提供了一个纯Java的解决方案,用于读取、写入和操作Office文档。 POI中的Excel...

    java实现poi 在线预览,excel,word直接在页面显示,附带文件上传,多文件上传

    所需poi的jar包: commons-collections4-4.1.jar poi-3.17.jar poi-examples-3.17.jar poi-excelant-3.17.jar poi-ooxml-3.17.jar poi-ooxml-schemas-3.17.jar poi-scratchpad-3.17.jar xmlbeans-2.6.0.jar maven...

    POI导出 POI导出 POI导出

    POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI导出POI...

    poi全家桶ooxml-schemas/poi/poi-examples/poi-ooxml/poi-ooxml-schemas/poi-scratchpad

    标题中的"poi全家桶ooxml-schemas/poi/poi-examples/poi-ooxml/poi-ooxml-schemas/poi-scratchpad"提及的是Apache POI项目中的多个关键组件和目录结构。Apache POI是一个开源的Java库,专门用于读写Microsoft Office...

    基于SpringBoot和POI实现单线程和多线程导出Excel.zip

    基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip...

    最新南京信息点poi数据shp格式gis地理小区学校大厦等等各类无偏移坐标2022年3月

    标题中的“最新南京信息点poi数据shp格式gis地理小区学校大厦等等各类无偏移坐标2022年3月”表明这是一份关于南京地区的GIS(Geographic Information System,地理信息系统)数据,具体是点状地物信息,且以SHP...

    地图poi 多类POI数据服务实现

    地图poi获取数据分类,包含餐饮、住宿、娱乐等30大类,约共1400W条POI数据。

    2023年部分城市poi矢量数据

    标题 "2023年部分城市poi矢量数据" 提供了...总之,这份数据集是GIS学习和实践的宝贵资源,涵盖了多个中国主要城市的POI信息,可以用来提升GIS技能,同时对于数据分析、城市规划和地理研究等领域也有着重要的参考价值。

Global site tag (gtag.js) - Google Analytics