Tag Archives: xml

Manipulando los resultados de Google Maps con Java

English

Actualmente trabajo en un proyecto de Android el cual despliega los puntos de interes que se encuentran alrededor de la posicion actual (basado en las coordenadas del GPS). Al inicio la idea era simple, tomar los valores del GPS y utilizar  las APIs o el Search protocol de Google. Sin embargo, no lo pude hacer ya que hay que pagar por cualquiera de los dos servicios (o puede ser gratuito, pero las transacciones diarias estan limitadas).

Asi que estuve modificando los parametros de la busqueda de Google y me di cuenta que el resultado se puede devolver en formato JSON. El siguiente documento muestra como hacer estas modificaciones a la URL de busqueda de Google y como capturar la cadena JSON para convertirla en un objeto de Java.

Las siguientes librerias y aplicaciones fueron utilizadas:

– Windows 7

– Eclipse Galileo

ezmorph-1.0.6

Apache commons (commons-beanutils-1.8.3, commons-collections-3.2, commons-lang-2.3, commons-logging-1.0.4).

1) Programando la Solucion

1.1) Primero, hay que agregar un nuevo proyecto de Java en Eclipse. Se puede utilizar cualquier nombre, en mi caso, este se llama  GoogleMapSearch2JSON:

image

1.2) Despues, hay que crear una nueva clase llamada JsonConverter:

image

Lo primero que hay que hacer es escribir el codigo que genera la solicitud (GET) y captura el resultado. El siguiente URL sera llamado por este codigo:

http://maps.google.com/maps?f=q&source=s_q&output=json&start=0&q=yourquery

Se deben de modificar dos parametros de este URL. El primero es el  valor de output (no traten de cambiarlo a XML, no funcionara); el segundo parametro es la consulta (query), que se pasa a Google. Al abrir esta URL en el navegador (se puede utilizar cualquier valor para el campo de query), un archivo se descargara y al abrirlo en notepad, se debe observar algo como esto:

image

Como se puede ver, esta es la cadena JSON del resultado. Sin embaro, al tratar de abrirlo con algun explorador de JSON, obtendremos un error. Esto se debe a la cadena  while(1)  que se encuentra al inicio del archivo. Si se borra esta cadena y se abre el archivo de nuevo, se debe de observar algo como lo que sigue:

image

La mayor parte de esta informacion  no es util (o al menos para mi); los resultados por la busqueda se encuentran en  OVERLAYS –> MARKERS. Cada marker representa un resultado:

image

Cada “marker” contiene la informacion relacionada a los puntos de interes encontrados; como, el nombre, direccion, latitud, longitud, telefono, etc.

1.3) Despues, hay que programar el metodo que hara todo este proceso de manera automatica. Para lograr esto, se utilizan las clases  URL y URLConnection. Agrega un nuevo metodo publico llamado  mapSearch2JSON y despues escribe el siguente codigo:

public String mapSearch2JSON(String query)
	{
		String jsonString = "";
		query = query.trim().replace(' ', '+');
		String url = "http://maps.google.com/maps?f=q&source=s_q&output=json&start=0&q="+query;
		try {
			URL urlObject = new URL(url);
			URLConnection urlConn = urlObject.openConnection();

			BufferedReader in = new BufferedReader( new InputStreamReader(urlConn.getInputStream()));

			String inputLine;
			while ((inputLine = in.readLine()) != null){
				jsonString = jsonString + inputLine;
	        }
	        	in.close();
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		jsonString = jsonString.replace("while(1);", "");
    	return jsonString;
	}

Basicamente, lo que se hace aqui es remover los caractereres en blanco de la cadena de entrada y reemplazarlos por el caracter “+” (no explicare la razon de esto). Por ultimo, la respuesta del servidor es guardada en la variable  jsonString y la cadena  while(1);  es eliminada.

1.4) Ahora, se debe de “parsear” la cadena JSON recibida del servidor. Pero antes de hacer esto, creamos una clase llamada  Marker  la cual se encargara de guardar la informacio nde cada punto de interes:


public class Marker {
	private String Name;
	private String Address;
	private double Latitude;
	private double Longitude;
	public String getName() {
		return Name;
	}
	public void setName(String name) {
		Name = name;
	}
	public String getAddress() {
		return Address;
	}
	public void setAddress(String address) {
		Address = address;
	}
	public double getLatitude() {
		return Latitude;
	}
	public void setLatitude(double latitude) {
		Latitude = latitude;
	}
	public double getLongitude() {
		return Longitude;
	}
	public void setLongitude(double longitude) {
		Longitude = longitude;
	}

}

Para este caso, solo cubri algunos valores como el nombre, direccion, latitud y longitud. Sin embargo, esta clase puede ser modificada de acuerdo a las necesidades del usuario.

1.5) Regresamos a la clase  JsonConverter y agregamos el siguiente metodo publico:

public ArrayList jsonParser(String json)
	{
		ArrayList markersList = new ArrayList();
		try
		{
			JSONObject jsonObject = (JSONObject)JSONSerializer.toJSON(json);
			JSONObject overlays = jsonObject.getJSONObject("overlays");

			if(!overlays.containsKey("markers"))
				return markersList;

			JSONArray markers = overlays.getJSONArray("markers");

			String name = "";
			String address = "";
			JSONObject marker;
			double latitude;
			double longitude;

			for(int i = 0; i < markers.size(); i++)
			{
				// gets marker object
				Marker markerObj = new Marker();
				marker = markers.getJSONObject(i);

				//gets address value
				address = marker.getString("laddr");

				//gets name value (if it is not empty)
				if(marker.containsKey("name"))
					name = marker.getString("name");

				//gets lat & lon
				JSONObject latlon = marker.getJSONObject("latlng");
				latitude = latlon.getDouble("lat");
				longitude = latlon.getDouble("lng");

				//save all values into Marker object
				markerObj.setName(name);
				markerObj.setAddress(address);
				markerObj.setLatitude(latitude);
				markerObj.setLongitude(longitude);

				//add the object to the list
				markersList.add(markerObj);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return markersList;
	}

Este codigo se encarga de transformar la cadena JSON en un objeto. Despues, busca por las etiquetas  overlays y markers. Cada vez que una etiqueta marker es encontrada, se crea un objeto del mismo tipo y se agrega al . Al final, el metodo regresa una coleccion de  Markers .

1.6) Si se desea hacer una prueba de la solucion, se puede correr el siguiente codigo. Este, se encarga de enviar una solicitud e imprimir los resultados regresados por Google.

public class Main {

	public static void main(String[] args) {
		JsonConverter converter = new JsonConverter();
		String jsonString = converter.mapSearch2JSON("gas station near 1065 La Avenida Street, Mountain View, CA");

		ArrayList markers = converter.jsonParser(jsonString);
		for(Marker marker : markers)
		{
			System.out.println(marker.getName() + " -> " + marker.getAddress());
		}
	}
}

image

Y esto es todo. Ahora es posible utilizar los resultados arrojados por Google a tu conveniencia. Ten en cuenta que los resultados de Google (por default) solo regresa 10 resultados por pagina. Es posible obtener TODOS los resultados utilizando el codigo descrito anteriormente, pero no cubrire la solucion en este documento.

Advertisements