Google Maps APIs Web Services

Os Google Maps Web Services são um conjunto de interfaces HTTP para serviços do Google que fornecem dados geográficos para seus aplicativos de mapa. Este guia apresenta os serviços web e as informações de host comuns a todos os diferentes serviços. Documentações individuais para cada serviço são apresentadas abaixo:

Descubra de qual API você precisa

Use o seletor de API para encontrar a API certa para seu projeto.

Mais informações sobre os serviços Web

O restante deste guia discute técnicas para configurar solicitações de serviço web e analisar respostas. Para obter informações específicas sobre serviços individuais, consulte a documentação apropriada.

O que é um serviço Web?

A Google Maps API fornece esses serviços web como uma interface para solicitar dados da Maps API de serviços externos e usá-los em seus aplicativos do Maps. Esses serviços foram projetados para serem usados em conjunto com um mapa seguindo as restrições de licenciamento dos Termos de Serviços da Maps API.

Esses serviços web usam solicitações HTTP para URLs específicos, passando parâmetros de URL como argumentos para os serviços. Geralmente, esses serviços retornam dados na solicitação HTTP como JSON ou XML para análise e/ou processamento por parte do seu aplicativo.

Uma solicitação de serviço Web típica geralmente tem o seguinte formato:

https://maps.googleapis.com/maps/api/service/output?parameters

onde service indica o serviço solicitado e output indica o formato da resposta (normalmente json ou xml).

A documentação completa de cada serviço se encontra nos guias do desenvolvedor específicos desses serviços. No entanto, este guia apresenta algumas práticas comuns que são úteis para configurar suas solicitações de serviços web e processar as respectivas respostas.

Acesso SSL

https://maps.googleapis.com/maps/api/service/output?parameters

HTTPS é necessário para todas as solicitações de serviço Web da Maps API contendo dados de usuário ou identificadores de desenvolvedor. Solicitações feitas por HTTP que incluem dados confidenciais podem ser rejeitados.

Criar um URL válido

Um URL "válido" pode parecer óbvio. Um URL inserido na barra de endereços de um navegador, por exemplo, pode conter caracteres especiais (por exemplo: "上海+中國"); o navegador precisa converter esses caracteres internamente em códigos diferentes antes de transmiti-los. Da mesma forma, qualquer código que gere ou aceite entradas UTF-8 pode tratar URLs com esse tipo de caracteres como "válidos", mas também precisaria convertê-los antes de enviá-los a um servidor web. Esse processo é chamado de codificação de URL.

É necessário converter caracteres especiais, pois todos os URLs devem seguir a sintaxe determinada pela especificação W3 Uniform Resource Identifier. Efetivamente, isso significa que os URLs devem conter apenas um subconjunto especial de caracteres ASCII: os familiares símbolos alfanuméricos e alguns caracteres reservados para uso como caracteres de controle em URLs. A tabela abaixo resume esses caracteres:

Resumo de caracteres válidos para URLs
ConjuntoCaracteresUso em URLs
Alfanuméricos a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 Strings de texto, uso de esquema (http), portas (8080) etc.
Não reservados - _ . ~ Strings de texto
Reservados ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Caracteres de controle e/ou strings de texto

Ao criar um URL válido, você deve garantir que ele contenha somente os caracteres mostrados acima. Conformar um URL ao uso desse conjunto de caracteres geralmente causa dois problemas, um de omissão e um de substituição.

  • Caracteres que você deseja processar existem fora desse conjunto. Por exemplo, caracteres de idiomas que não usam o alfabeto latino, como 上海+中國, precisam ser codificados usando os caracteres acima. Por convenção popular, espaços (que não são permitidos em URLs) são frequentemente representados pelo caractere +.
  • Caracteres existem no conjunto acima como caracteres reservados, mas precisam ser usados literalmente. Por exemplo, ? é usado em URLs para indicar o início de uma string de consulta. Se quiser usar o nome da banda "? and the Mysterians", será preciso codificar o caractere ?.

Todos os caracteres a receberem a codificação de URL usam um caractere % e um valor hexadecimal de dois caracteres correspondente ao seu caractere UTF-8. Por exemplo, 上海+中國 em UTF-8 teria a codificação de URL %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. A string ? and the Mysterians teria a codificação de URL %3F+and+the+Mysterians.

Alguns caracteres comuns que devem ser codificados:

Caractere inválido Valor codificado
Espaço %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Converter um URL recebido de uma entrada do usuário pode ser complicado. Por exemplo, um usuário pode inserir um endereço como "5th&Main St". Geralmente, você deve criar o URL a partir de suas partes, tratando qualquer entrada do usuário como caracteres literais.

Além disso, URLs têm um limite de 8192 caracteres para todos os serviços Web. Para a maioria dos serviços, esse limite raramente é atingido. Entretanto, observe que alguns serviços têm diversos parâmetros que podem resultar em URLs longos.

Uso adequado das Google APIs

Clientes de API projetados inadequadamente podem processar mais carga do que o necessário tanto na Internet quanto nos servidores do Google. Esta seção contém algumas das melhores práticas para cliente das APIs. Seguir estas melhores práticas pode ajudar você a evitar que o aplicativo seja bloqueado por abuso inadvertido das APIs.

Retirada exponencial

Em casos raros, algo pode dar errado ao servir sua solicitação; você pode receber um código de resposta HTTP 4XX ou 5XX, ou a conexão TCP pode simplesmente falhar em algum lugar entre o cliente e o servidor da Google. Com muita frequência, vale a pena reenviar a solicitação, pois a solicitação seguinte pode ser atendida quando a original falhar. No entanto, é importante não simplesmente ficar em um loop repetido, fazendo solicitações para os servidores da Google. Este comportamento de loop pode sobrecarregar a rede entre o cliente e a Google, causando problemas para várias partes.

Uma melhor abordagem é tentar novamente com intervalos maiores entre as tentativas. Geralmente, o intervalo é aumentado por um fator multiplicativo com cada tentativa, uma abordagem conhecida como Retirada exponencial.

Por exemplo, considere um aplicativo que quer fazer esta solicitação à Google Maps Time Zone API:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

O exemplo de Python a seguir mostra como fazer a solicitação com retirada exponencial:

import json
import time
import urllib
import urllib2

def timezone(lat, lng, timestamp):
    # The maps_key defined below isn't a valid Google Maps API key.
    # You need to get your own API key.
    # See https://developers.google.com/maps/documentation/timezone/get-api-key
    maps_key = 'YOUR_KEY_HERE'
    timezone_base_url = 'https://maps.googleapis.com/maps/api/timezone/json'

    # This joins the parts of the URL together into one string.
    url = timezone_base_url + '?' + urllib.urlencode({
        'location': "%s,%s" % (lat, lng),
        'timestamp': timestamp,
        'key': maps_key,
    })

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 3600  # Set the maximum retry delay to 1 hour.

    while True:
        try:
            # Get the API response.
            response = str(urllib2.urlopen(url).read())
        except IOError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.loads(response.replace('\\n', ''))
            if result['status'] == 'OK':
                return result['timeZoneId']
            elif result['status'] != 'UNKNOWN_ERROR':
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result['error_message'])

        if current_delay > max_delay:
            raise Exception('Too many retry attempts.')
        print 'Waiting', current_delay, 'seconds before retrying.'
        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.

tz = timezone(39.6034810, -119.6822510, 1331161200)
print 'Timezone:', tz

Deve-se também tomar cuidado, pois não há código de tentativa maior na corrente de chamada do aplicativo que leva a solicitações repetidas em uma rápida sucessão.

Solicitações sincronizadas

Grandes números de solicitações sincronizadas às APIs do Google podem parecer um ataque DDoS na infraestrutura da Google e pode ser tratada de acordo. Para evitar isto, é preciso garantir que as solicitações da API não estejam sincronizadas entre os clientes.

Por exemplo, considere um aplicativo que exibe a hora do fuso horário atual. Este aplicativo provavelmente definirá um alarme no sistema operacional do cliente, despertando-o no início do minuto para que a hora exibida possa ser atualizada. O aplicativo não deve fazer chamadas de API como parte do processamento associado a este alarme.

Fazer chamadas de API em resposta a um alarme fixo é ruim, pois resulta em chamadas de API sendo sincronizadas com o início do minuto, distribuídos igualmente entre diversos dispositivos, em vez de serem distribuídos igualmente com o decorrer do tempo. Um aplicativo projetado inadequadamente fazendo isto produzirá um pico de tráfego sessenta vezes maior do que o nível normal no início de cada minuto.

Em vez disso, um bom possível design é ter um segundo alarme definido a um horário escolhido aleatoriamente. Quando este segundo alarme disparar, o aplicativo chama todas as APIs que precisa e armazena os resultados. Quando o aplicativo quer atualizar a tela no início do minuto, ele usa resultados armazenados anteriormente em vez de chamar a API novamente. Com esta abordagem, chamas de API são espalhadas igualmente com o decorrer do tempo. Além disso, as chamadas de API não atrasam a renderização quando a tela está sendo atualizada.

Além do início do minuto, outros momentos de sincronização comuns com os quais se deve tomar cuidado para não escolher são os inícios de horas e de cada dia à meia-noite.

Processar respostas

Como o formato exato de respostas individuais para uma solicitação de serviço web não é garantido (alguns elementos podem estar ausentes ou em vários locais), nunca presuma que o formato retornado de qualquer resposta será o mesmo para consultas diferentes. Em vez disso, você deve processar a resposta e selecionar os valores apropriados por meio de expressões. Esta seção discute como extrair esses valores das respostas dos serviços web de forma dinâmica.

Os serviços Web do Google Maps fornecem respostas fáceis de compreender, mas não exatamente amigáveis. Ao executar uma consulta, em vez de exibir um conjunto de dados, é recomendável extrair alguns valores específicos. Geralmente, você deve analisar as respostas do serviço web e extrair somente os valores pertinentes.

O esquema de análise usado depende de você retornar saída em XML ou JSON. Respostas JSON, que já estão na forma de objetos JavaScript, podem ser processadas no próprio JavaScript do cliente. Respostas XML precisam ser processadas usando um processador de XML e uma linguagem de consulta XML para trabalhar com elementos no formato XML. Nós usamos o XPath nos exemplos a seguir, já que ele é normalmente compatível com as bibliotecas de processamento XML.

Processar XML com XPath

O XML é um formato de informações estruturadas relativamente maduro que é usado para troca de dados. Apesar de não ser tão leve quanto o JSON, o XML oferece suporte a mais idiomas e ferramentas mais robustas. O código de processamento de XML em Java, por exemplo, é integrado aos pacotes javax.xml.

Ao processar respostas XML, você deve usar uma linguagem de consulta apropriada para selecionar nós no documento XML, não presumir que os elementos se encontram em posições absolutas na marcação XML. XPath é uma sintaxe de linguagem para descrever de forma exclusiva nós e elementos em um documento XML. Expressões XPath permitem que você identifique conteúdo específico no documento de resposta XML.

Expressões XPath

Ter alguma familiaridade com o XPath é muito útil ao desenvolver um esquema de análise robusto. Esta seção se concentra em como os elementos de um documento XML são processados com o XPath, permitindo que você processe diversos elementos e crie consultas complexas.

O XPath usa expressões para selecionar elementos em um documento XML, usando uma sintaxe similar à usada para caminhos de diretório. Essas expressões identificam elementos em uma árvore de documentos XML, que se trata de uma árvore hierárquica similar à de um DOM. Geralmente, as expressões do XPath correspondem a todos os nós relacionados aos critérios fornecidos.

Usaremos o XML abstrato a seguir para demonstrar nossos exemplos:

<WebServiceResponse>
 <status>OK</status>
 <result>
  <type>sample</type>
  <name>Sample XML</name>
  <location>
   <lat>37.4217550</lat>
   <lng>-122.0846330</lng>
  </location>
 </result>
 <result>
  <message>The secret message</message>
 </result>
</WebServiceResponse>

Seleção de nós em expressões

As seleções do XPath selecionam nós. O nó raiz engloba todo o documento. Esse nó é selecionado com a expressão especial "/". Observe que o nó raiz não é o nó de nível superior do seu documento XML. Na verdade, esse nó se encontra um nível acima desse elemento de nível superior e inclui-o.

Nós de elementos representam os vários elementos da árvore do documento XML. Um elemento <WebServiceResponse>, por exemplo, representa o elemento de nível superior retornado no exemplo de serviço acima. Você seleciona nós individuais com caminhos absolutos ou relativos, indicados pela presença ou falta de um "/" no início da expressão.

  • Caminho absoluto: a expressão "/WebServiceResponse/result" seleciona todos os nós <result> que são filhos do nó <WebServiceResponse>. Observe que ambos os elementos descendem do nó raiz "/".
  • Caminho relativo do contexto atual: a expressão "result" corresponderia a qualquer elemento <result> no contexto atual. Geralmente, não é preciso se preocupar com contexto, pois normalmente você processa resultados de serviços web com uma só expressão.

Qualquer uma dessas expressões pode ser aprimorada com a adição de um caminho curinga, indicado por barras duplas ("//"). Esse curinga indica que zero ou mais elementos podem ser correspondidos no caminho resultante. A expressão XPath "//formatted_address", por exemplo, corresponde a todos os nós com esse nome no documento atual. A expressão //viewport//lat corresponderia a todos os elementos <lat> que podem rastrear <viewport> como pai.

Por padrão, as expressões XPath correspondem a todos os elementos. Você pode restringir a expressão para corresponder a um determinado elemento. Basta fornecer um predicado, que é envolto por colchetes ([]). A expressão XPath "/GeocodeResponse/result[2] sempre resulta em um segundo resultado, por exemplo.

Tipo de expressão
Nó raiz
Expressão XPath:  "/"
Seleção:
    <WebServiceResponse>
     <status>OK</status>
     <result>
      <type>sample</type>
      <name>Sample XML</name>
      <location>
       <lat>37.4217550</lat>
       <lng>-122.0846330</lng>
      </location>
     </result>
     <result>
      <message>The secret message</message>
     </result>
    </WebServiceResponse>
    
Caminho absoluto
Expressão XPath:  "/WebServiceResponse/result"
Seleção:
    <result>
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    </result>
    <result>
     <message>The secret message</message>
    </result>
    
Caminho com curinga
Expressão XPath:  "/WebServiceResponse//location"
Seleção:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
Caminho com predicado
Expressão XPath:  "/WebServiceResponse/result[2]/message"
Seleção:
    <message>The secret message</message>
    
Todos os filhos do primeiro result
Expressão XPath:  "/WebServiceResponse/result[1]/*"
Seleção:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
O name de um result cujo type é "sample".
Expressão XPath:  "/WebServiceResponse/result[type/text()='sample']/name"
Seleção:
    Sample XML
    

É importante observar que, ao selecionar elementos, você seleciona nós, não só o texto desses objetos. Geralmente, é recomendável iterar todos os nós correspondidos para extrair o texto. Também é possível corresponder aos nós de texto diretamente. Consulte Nós de texto abaixo.

Observe que o XPath também é compatível com nós de atributos, mas todos os serviços web do Google Maps fornecem elementos sem atributos, portanto, essa função não é necessária.

Seleção de texto em expressões

O texto de um documento XML é especificado em expressões XPath com um operador de nó de texto. Esse operador "text()" indica a extração do texto do nó indicado. Por exemplo, a expressão XPath "//formatted_address/text()" retornará todo o texto nos elementos <formatted_address>.

Tipo de expressão
Todos os nós de texto (incluindo espaços)
Expressão XPath:  "//text()"
Seleção:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
Seleção de texto
Expressão XPath:  "/WebServiceRequest/result[2]/message/text()"
Seleção:
    The secret message
    
Seleção com reconhecimento de contexto
Expressão XPath:  "/WebServiceRequest/result[type/text() = 'sample']/name/text()"
Seleção:
    Sample XML
    

Como alternativa, você pode avaliar uma expressão e retornar um conjunto de nós e, em seguida, iterar esse "conjunto de nós", extraindo o texto de cada nó. Usamos essa abordagem no exemplo abaixo.

Para saber mais sobre o XPath, consulte a especificação XPath W3C.

Avaliar XPath em Java

O Java tem amplo suporte para análise de XML e uso de expressões XPath no pacote javax.xml.xpath.*. Por esse motivo, o exemplo de código desta seção usa Java para demonstrar como processar XML e analisar dados de respostas do serviço XML.

Para usar XPath em seu código Java, primeiro é preciso criar uma instância de XPathFactory e chamar newXPath() nessa fábrica para criar um objeto XPath . O objeto então pode processar as expressões XML e XPath passadas usando o método evaluate().

Ao avaliar expressões XPath, não deixe de iterar qualquer "conjunto de nós" possível a ser retornado. Como esses resultados são retornados como nós DOM no código Java, capture esses valores em um objeto NodeList e itere esse objeto para extrair qualquer texto ou valor desses nós.

O código a seguir demonstra como criar um objeto XPath, atribuir XML e uma expressão XPath a ele e avaliar a expressão para imprimir o conteúdo relevante.

import org.xml.sax.InputSource;
import org.w3c.dom.*;
import javax.xml.xpath.*;
import java.io.*;

public class SimpleParser {

  public static void main(String[] args) throws IOException {

	XPathFactory factory = XPathFactory.newInstance();

    XPath xpath = factory.newXPath();

    try {
      System.out.print("Web Service Parser 1.0\n");

      // In practice, you'd retrieve your XML via an HTTP request.
      // Here we simply access an existing file.
      File xmlFile = new File("XML_FILE");

      // The xpath evaluator requires the XML be in the format of an InputSource
	  InputSource inputXml = new InputSource(new FileInputStream(xmlFile));

      // Because the evaluator may return multiple entries, we specify that the expression
      // return a NODESET and place the result in a NodeList.
      NodeList nodes = (NodeList) xpath.evaluate("XPATH_EXPRESSION", inputXml, XPathConstants.NODESET);

      // We can then iterate over the NodeList and extract the content via getTextContent().
      // NOTE: this will only return text for element nodes at the returned context.
      for (int i = 0, n = nodes.getLength(); i < n; i++) {
        String nodeString = nodes.item(i).getTextContent();
        System.out.print(nodeString);
        System.out.print("\n");
      }
    } catch (XPathExpressionException ex) {
	  System.out.print("XPath Error");
    } catch (FileNotFoundException ex) {
      System.out.print("File Error");
    }
  }
}

Faça o download do código em js-v2-samples

Processar JSON com JavaScript

O JSON (Javascript Object Notation) tem uma vantagem óbvia sobre o XML, pois sua resposta é leve. Analisar esse resultado em JavaScript é muito simples, pois seu formato já é um objeto JavaScript válido. Por exemplo, para extrair o valor das chaves formatted_address em um objeto de resultado JSON, basta acessá-las usando o seguinte código:

for (i = 0; i < myJSONResult.results.length; i++) {
  myAddress[i] = myJSONResult.results[i].formatted_address;
}

Observe que, como JSON pode conter diversos valores, é recomendável iterar o tamanho da matriz results para capturar todos os valores possíveis. Na prática, entretanto, pode ser recomendável retornar apenas o primeiro resultado (results[0]).

Analisar JSON em outras linguagens é apenas um pouco mais difícil. O exemplo a seguir em Python inicia uma solicitação do serviço Web de geocodificação e exibe todos os valores formatted_address para o usuário em uma matriz:

import simplejson, urllib

GEOCODE_BASE_URL = 'https://maps.googleapis.com/maps/api/geocode/json'

def geocode(address, **geo_args):
    geo_args.update({
        'address': address
    })

    url = GEOCODE_BASE_URL + '?' + urllib.urlencode(geo_args)
    result = simplejson.load(urllib.urlopen(url))

    print simplejson.dumps([s['formatted_address'] for s in result['results']], indent=2)

if __name__ == '__main__':
    geocode(address="San+Francisco")

Output: [ "San Francisco, CA, USA" ]

Faça o download do código em js-v2-samples

O parâmetro sensor

Anteriormente, a Google Maps API exigia a inclusão do parâmetro sensor para indicar se o aplicativo usou um sensor para determinar a localização do usuário. Esse parâmetro não é mais obrigatório.

Enviar comentários sobre…

Google Maps Web Service APIs
Google Maps Web Service APIs