package org.osmdroid.location; import org.oscim.core.BoundingBox; import org.oscim.core.GeoPoint; import org.osmdroid.utils.HttpConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; /** * POI Provider using Picasa service. * * @author M.Kergall * @see "https://developers.google.com/picasa-web/docs/2.0/reference" */ public class PicasaPOIProvider implements POIProvider { static final Logger log = LoggerFactory.getLogger(PicasaPOIProvider.class); 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; } @SuppressWarnings("deprecation") private String getUrlInside(BoundingBox boundingBox, int maxResults, String query) { StringBuffer url = new StringBuffer("http://picasaweb.google.com/data/feed/api/all?"); url.append("bbox=" + boundingBox.getMinLongitude()); url.append("," + boundingBox.getMinLatitude()); url.append("," + boundingBox.getMaxLongitude()); url.append("," + boundingBox.getMaxLatitude()); url.append("&max-results=" + maxResults); url.append("&thumbsize=64c"); //thumbnail size: 64, cropped. url.append("&fields=openSearch:totalResults,entry(summary,media:group/media:thumbnail,media:group/media:title,gphoto:*,georss:where,link)"); if (query != null) url.append("&q=" + URLEncoder.encode(query)); if (mAccessToken != null) { //TODO: warning: not tested... url.append("&access_token=" + mAccessToken); } return url.toString(); } public ArrayList<POI> getThem(String fullUrl) { log.debug("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(); if (handler.mPOIs != null) log.debug("done:" + handler.mPOIs.size() + " got on a total of:" + handler.mTotalResults); return handler.mPOIs; } /** * @param boundingBox ... * @param maxResults ... * @param query - optional - full-text query string. Searches the title, * caption and tags for the specified string value. * @return list of POI, Picasa photos inside the bounding box. Null if * technical issue. */ public List<POI> getPOIInside(BoundingBox boundingBox, String query, int maxResults) { String url = getUrlInside(boundingBox, maxResults, query); return getThem(url); } } class PicasaXMLHandler extends DefaultHandler { private String mString; double mLat, mLng; POI mPOI; ArrayList<POI> mPOIs; int mTotalResults; public PicasaXMLHandler() { mPOIs = new ArrayList<POI>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if (qName.equals("entry")) { mPOI = new POI(POI.POI_SERVICE_PICASA); } else if (qName.equals("media:thumbnail")) { mPOI.thumbnailPath = attributes.getValue("url"); } else if (qName.equals("link")) { String rel = attributes.getValue("rel"); if ("http://schemas.google.com/photos/2007#canonical".equals(rel)) { mPOI.url = attributes.getValue("href"); } } mString = new String(); } @Override public void characters(char[] ch, int start, int length) { String chars = new String(ch, start, length); mString = mString.concat(chars); } @Override public void endElement(String uri, String localName, String qName) { 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.id = mString; } else if (qName.equals("media:title")) { mPOI.type = mString; } else if (qName.equals("summary")) { mPOI.description = mString; } else if (qName.equals("gphoto:albumtitle")) { mPOI.category = mString; } else if (qName.equals("entry")) { mPOI.location = new GeoPoint(mLat, mLng); mPOIs.add(mPOI); mPOI = null; } else if (qName.equals("openSearch:totalResults")) { mTotalResults = Integer.parseInt(mString); } } }