"Geocodificação é o processo de conversão de endereços (como "1600 Amphitheatre Parkway, Mountain View, CA") em coordenadas geográficas (como latitude 37.423021 e longitude -122.083739), que você pode usar para colocar marcadores ou posicionar o mapa. A Google Geocoding API fornece uma maneira direta de acessar um geocodificador por meio de uma solicitação HTTP. Além disso, o serviço permite que você realize a operação inversa (transformar coordenadas em endereços); esse processo é conhecido como "geocodificação reversa"."
Uma solitação de geocoding deve ter basicamente os seguinte formato:
http://maps.googleapis.com/maps/api/geocode/output?parametersonde output significa o formato do retorno dos dados, que pode ser json(recomendável) ou xml.
Além disso são obrigatórios os parâmetros:
- address — o endereço que você deseja geocodificar
ou
latlng — o valor textual de latitude/longitude para o qual você deseja obter o endereço mais próximo.
- sensor — indica se a solicitação de geocodificação vem ou não de um dispositivo com sensor de localização. Esse valor deve ser true ou false.
A resposta da requisição contém dois elementos raiz:
- status - contém metadados sobre a solicitação. Consulte os Códigos de status no site.
- results - contém uma matriz de informações de endereços geocodificados e informações geométricas.
Eu implementei uma biblioteca bem simples que suporta os dois formatos de resposta: json e xml.
Para interpretar o resultando em json, utilizei a biblioteca lkjson, pois, já tinha utilizado a mesma em outros projetos e achei bastante simples de usar, mais existem outras opções como o SuperObject e Delphi Web Utils.
Para interpretar o formato xml optei por utilizar o Xml Data Binding do delphi, que através de um wizard cria classes tipadas a partir do arquivos xml, deixando todo o processo de transformação transparente.
Basicamente o que fiz foi o seguinte, efetuei uma requisição no serviço de geocodificação no formato xml e salvei os dados retornados em um arquivo xml. Em seguida, utilizei o Xml Data Binding para transformar esse xml em classes. Essas classes são o resultado final da solicitação, seja ela em json ou xml.
Quando a requisição é no formato xml, é utilizado o binding do XmlDocument:
class function TGoogleApiGeoXml.XmlToGeocodeResponse(const AXmlText: String): IGeocodeResponse; var vXmlDocument: IXMLDocument; begin vXmlDocument := TXMLDocument.Create(nil); vXmlDocument.LoadFromXml(UTF8Encode(AXmlText)); Result := vXmlDocument.GetDocBinding('GeocodeResponse', TGeocodeResponse) as IGeocodeResponse; end;
Quando a requisição é no formato json, escrevi o parser "na unha", que retorna o mesmo tipo de objeto da solicitação em xml, deixando a aplicação que consome o serviço utilizar o mesmo sem se importar se é xml ou json.
function TGoogleApiGeoJson.ConvertFromJson(const AJsonText: String): IGeocodeResponse; var vJsonResponse: TlkJSONobject; vResults: TlkJSONbase; begin Result := TGeocodeResponse.NewGeocodeResponse; vJsonResponse := TlkJSONobject(TlkJSON.ParseText(UTF8Encode(AJsonText))); try vResults := TlkJSONlist(TlkJSONlist(vJsonResponse.Field['results']).Field['address_components']).Items[0]; ParseStatus(Result, vJsonResponse); ParseType(Result, vResults); ParseFormattedAddress(Result, vResults); ParseAddresses(Result, vResults); ParseGeometry(Result, vResults); finally vJsonResponse.Free; end; end;
Na sistema em si, o único código que ele precisa executar é esse:
var vResponse: IGeocodeResponse; begin vResponse := TGoogleApiGeocodeDownload.GetGeocode("http://maps.googleapis.com/maps/api/geocode/json_ou_xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true_ou_false"); //Lógica que utiliza a resposta da solicitação
O implementação do método GetGeocode é bastante simples também, ele faz uma requisição HTTP utilizando indy conforme abaixo
class function TGoogleApiGeocodeDownload.HttpGet(Url: String): String; var lHTTP: TIdHTTP; lStream: TStringStream; begin lHTTP := TIdHTTP.Create(nil); lStream := TStringStream.Create(EmptyStr); try lHTTP.Get(Url, lStream); lStream.Position := 0; Result := UTF8Decode(lStream.DataString); finally FreeAndNil(lHTTP); FreeAndNil(lStream); end; end;
E de acordo com o formato dos dados faz uma chamada ao parser correspondente para retornar o objeto.
class function TGoogleApiGeocodeDownload.GetGeocode(AUrl: String): IGeocodeResponse; var vDados: String; vFormato: TOutputFormat; begin vFormato := DiscoverFormat(AUrl); vDados := HttpGet(AUrl); case vFormato of Json: Result := TGoogleApiGeoJson.JsonToGeocodeResponse(vDados); Xml : Result := TGoogleApiGeoXml.XmlToGeocodeResponse(vDados); end; end;
Mais informações sobre limitações de uso e sobre os parâmetros utilizados na requisição HTTP podem ser encontrados aqui.
O código fonte completo com exemplo de como utilizar pode ser acessado aqui no meu bitbucket.
Um abraço e fique ligado nos próximos posts.
Nenhum comentário:
Postar um comentário