Por que eu devo ler este artigo:

O advento e popularização da computação móvel, através de smartphones e tablets, trouxe consigo a demanda por aplicações de geolocalização. Quer seja para saber o caminho mais curto entre um ponto e outro ou localizar a pizzaria mais próxima de casa, a orientação e navegação através de mapas vem se tornando um item cada vez mais presente em nosso dia a dia.

Esse artigo tem como objetivo apresentar a integração da API do Google em dispositivos rodando o sistema operacional Android. A realização dessa integração será demonstrada através de um exemplo simples onde será implementada uma rota de navegação através de um ponto de origem e destino informados pelo usuário utilizando a API do Google para geolocalização, a Google Directions API.

O termo geolocalização refere-se à identificação da localização geográfica no mundo real de um objeto, como um radar, telefone celular ou terminal de computador conectado à Internet.

Na computação, um software de geolocalização é usado para deduzir a localização geográfica de dispositivo conectado à Internet, usando como uma das abordagens possíveis a identificação pelo número IP do dispositivo, para finalmente chegar à sua localização.

Os serviços baseados em geolocalização (SLBL´S) geralmente são divididos em duas categorias principais: serviços ‘push’ e serviços ‘pull’. Serviços push implicam que um usuário recebe informação (em função de sua localização) sem ter que requisitá-la ativamente. Um exemplo prático seria o envio de uma notificação de ofertas de um estabelecimento comercial do qual o usuário está se aproximando.

No caso de serviços pull, a informação só é enviada ao usuário caso este a requisite explicitamente. Um exemplo seria no caso do usuário desejar saber onde se encontra o restaurante mais próximo.

A geolocalização abre um vasto nicho de aplicações a serem exploradas, tais como:

  • Serviços de Informação: Os serviços desta categoria fornecem instruções de como se chegar a um destino desejado, indicam onde encontrar um determinado serviço ou pessoa nas redondezas, ou localizam um usuário perdido em um mapa;
  • Serviços de Emergência: Em situações de emergências, o fator tempo normalmente é determinante para se evitar consequências mais graves. O uso de tecnologias de localização possibilita um menor tempo de resposta, desde o instante em que ocorre o fato em questão até o momento em que chega o auxílio. As aplicações mais claras desta categoria seriam na área médica e na área de segurança. Pessoas idosas ou com algum tipo de doença poderiam ter seus sinais vitais monitorados por dispositivos móveis, e estes automaticamente emitiriam um sinal de alerta no caso de alguma anomalia ser detectada. No caso de aplicações de segurança, esse sinal poderia ser disparado por iniciativa do usuário ou em decorrência de algum evento suspeito. O sinal emitido indicaria a localização do usuário e equipes de socorro seriam deslocadas até o local;
  • Serviços de Rastreamento: Um exemplo claro de aplicação desta categoria é o rastreamento de frotas de veículos transportando mercadorias. É possível monitorar todo o percurso de cada veículo e identificar comportamentos suspeitos no caso de mudanças de itinerário não previstas. Essa aplicação é particularmente útil para seguradoras, pois aumenta as chances de se encontrar os veículos em caso de sinistro;
  • Serviços de Disseminação de Informação: Um exemplo prático seria a disseminação de propagandas. Anunciantes poderiam enviar mensagens de promoções temporárias a clientes potenciais que estejam nas redondezas de seu estabelecimento, e um novo tipo personalizado de B2C (Business to Consumer) se estabeleceria de forma dinâmica e localizada, aumentando tremendamente a eficiência dos anúncios e o potencial de venda. Um exemplo prático seria um restaurante oferecendo ofertas de refeições para pessoas caminhando pela vizinhança durante o horário de almoço.

Obtendo a localização de um objeto

Existem basicamente duas formas de se obter a localização geográfica de um objeto: por GPS e pela triangulação de antenas.

GPS

Nos rastreadores usando GPS, o aparelho embarcado determina sua própria posição após conectar-se a pelo menos quatro satélites de uma constelação de satélites americanos. Com os dados recebidos, o equipamento rastreador pode calcular a sua posição, e por consequência a posição do veículo em que está embarcado.

Após isso, ele deve enviar esse dado para uma central, que irá mostrar graficamente a localização do veículo. Esse envio pode ser feito via celular (geralmente via GPRS) ou via satélite. Para envio via satélite na comunicação com as unidades em terra, o satélite envia a posição do veículo a uma estação de comunicação que por sua vez envia as estações intermediárias, servidores, ou mesmo diretamente aos computadores, possibilitando a localização dos veículos.

É possível também a comunicação inversa, tanto no rastreador via GPRS Celular quanto no localizado no satélite. No caso do rastreador satelital, por exemplo, é possível o envio de comandos como: um bloqueio, onde o comando partiria de um computador, seguiria até a estação terrena do satélite, em seguida passaria pelo satélite em órbita e chegaria até o veículo bloqueando-o.

Triangulação de Antenas

No sistema de rastreamento por triangulação de antenas, uma rede de rádio é montada exclusivamente para esse fim. As antenas recebem o sinal de rádio de um equipamento instalado no veículo e, com base nesse sinal e na posição conhecida das antenas, calcula-se a posição do veículo. Não há necessidade nesse caso de um segundo meio para envio da informação de posição como no caso do GPS. Tudo é feito via a própria rede de rádio montada para o serviço.

Diversas empresas que trabalham com frotas de veículos também já aderiram ao aparelho de rastreador que, além de usados para garantir maior segurança, pode ser utilizado como fonte de informações mais específicas. Assim como no caso do o rastreamento dos veículos, é possível calcular o tempo de uma determinada entrega.

Exemplo de aplicações de geolocalização

Find Friend

Desenvolvido pela AT&T e disponível comercialmente em algumas cidades nos EUA, o Find Friend, como o nome sugere, é uma aplicação para aproximação de pessoas. Ele permite que um usuário localize pessoas (previamente cadastradas) e marque encontros com elas. A aplicação pode ainda sugerir pontos de encontros como restaurantes, e direções – com auxílio de mapas – para chegar ao local combinado.

Waze

Waze é um aplicativo GPS baseado em navegação geográfica programado para smartphones que provê informações em tempo real e informações de usuários e detalhes da rota, baixando informação dependendo da localização do dispositivo portátil na rede. Foi desenvolvido pela startup israelense Waze Mobile, que foi adquirida pelo Google em 2013. As pessoas podem relatar acidentes, congestionamentos, velocidade, 'blitzes' policiais, e podem atualizar rodovias, pontos de referência, números de casas, etc. O Waze também identifica os postos de gasolina mais baratos perto do usuário através de sua rota. Em janeiro de 2012, o aplicativo já havia sido baixado 12 milhões de vezes no mundo. Em julho de 2012 o Waze anunciou que havia chegado aos 20 milhões de usuários, metade deles recrutados nos últimos 6 meses. De acordo com o Yahoo!, existiam cerca de 50 milhões de usuários do Waze em junho de 2013.

Visão geral da Google Directions AP

Em junho de 2005, o Google lançou a Google Maps API, uma plataforma que permite ao desenvolvedor integrar o Google Maps em seus aplicativos. Utilizando essa API, torna-se possível embutir mapas do Google Maps em aplicativos web.

A Google Directions API é uma plataforma oferecida pelo Google que permite o cálculo de rotas a partir de um ponto de origem e destino através de uma requisição HTTP e a exibição do mapa utilizando o Google Maps.

Limites de uso

O uso da Google Directions API está sujeito a um limite de consultas de 2.500 solicitações de rotas por dia. Cada pesquisa de rotas conta como uma única solicitação em sua cota diária quando o modo de transporte for dirigir, andar a pé ou de bicicleta. A pesquisa de rotas com transporte público será contada como quatro solicitações.

As solicitações individuais para rotas de carro, a pé ou de bicicleta podem conter até oito pontos de referência intermediários na solicitação. Clientes da API do Google Maps para Empresas podem consultar até 100.000 solicitações de rotas por dia, com até 23 pontos de referência permitidos em cada solicitação. Os pontos de referência não estão disponíveis para rotas com transporte público.

Além disso, as URLs da Google Directions API estão limitadas a 2.048 caracteres, antes da codificação do URL. Como algumas URLs do serviço da Google Directions API podem envolver muitos locais ao longo de um caminho, leve em conta esse limite ao criar URLs.

Criando uma aplicação usando a Google Directions API

Para criar uma aplicação utilizando a Google Directions API, é necessário a obtenção de uma chave de acesso que deverá ser incorporada à aplicação que pretende fazer o uso dos dados da API. A obtenção da chave é feita de forma totalmente gratuita e foi explicada detalhadamente no artigo “Geolocalização Android: GPS, mapas e sintetização de voz no Android” publicado na revista Mobile Magazine Edição 57, bem como as configurações iniciais no aplicativo Android para a utilização da API.

Para criar uma aplicação Android utilizando a Google Directions API será utilizada a IDE Eclipse Kepler com o Android SDK e o plugin ADT.

Para criar um projeto Android, clique com o botão direito no Package Explorer e acesse a opção New > Other > Android Application Project, como mostrado na Figura 1.

Criando um novo aplicativo Android
Figura 1. Criando um novo aplicativo Android

Criando a activity principal

No Android, o termo activity serve para designar uma tela que é mostrada ao usuário final, sendo essa tela composta de dois artefatos:

  • Um arquivo XML contendo o layout da tela propriamente dita;
  • Uma classe Java que controla o estado da activity.

O código do layout do arquivo XML é mostrado na Listagem 1 e consiste de duas caixas de texto para entrada dos dados de origem e destino, respectivamente, e um botão para disparar a execução do desenho da rota. A tela inicial do aplicativo é mostrada na Figura 2.

Tela inicial do aplicativo
Figura 2. Tela inicial do aplicativo

O componente raiz do arquivo é um componente do tipo LinearLayout com a propriedade android:orientation definida como “vertical”. Essa configuração informa ao Android que os componentes serão posicionados um abaixo do outro.

                        
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical"
  android:padding="10dp" >
 
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="3"
    android:orientation="horizontal" >
 
    <TextView
      android:text="Origem"
      android:layout_width="0dp"
      android:layout_weight="1"
      android:layout_height="wrap_content"
      android:textStyle="bold" />

    <EditText
      android:id="@+id/editOrigem"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_weight="2"
      android:inputType="text"
      android:lines="1"
      android:maxLines="1" />
 
</LinearLayout>
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="0dp"
  android:layout_weight="3"
  android:orientation="horizontal" >

  <TextView
    android:text="Destino"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:layout_height="wrap_content"
    android:textStyle="bold" />

  <EditText
    android:id="@+id/editDestino"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="2"
    android:inputType="text"
    android:lines="1"
    android:maxLines="1" />

</LinearLayout>

<Button
    android:id="@+id/btnTracar"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="Traçar" />

</LinearLayout>
Listagem 1. Activity principal do aplicativo

O código da classe gerenciadora da Activity é mostrado na Listagem 2. Essa classe é responsável por recuperar os valores dos componentes definidos no arquivo de layout. É feita a validação dos campos de origem e destino, e caso os mesmos estejam corretamente preenchidos a navegação será delegada para a classe MapActivity, responsável pela exibição do mapa.

A mudança de tela em um aplicativo Android é realizada utilizando um componente do tipo Intent. Um Intent é uma classe presente na API padrão do Android que permite a navegação entre activities, bem como a passagem de parâmetros entre activities utilizando o método putExtra().


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
 
public class MainActivity extends Activity {
      
  private EditText editOrigem;
  private EditText editDestino;
  private Button btnTracar;
 
  @Override
  protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
   
    editOrigem = (EditText) findViewById(R.id.editOrigem);
    editDestino = (EditText) findViewById(R.id.editDestino);
    btnTracar = (Button) findViewById(R.id.btnTracar);

    btnTracar.setOnClickListener(new OnClickListener() {
      /**
      * {@inheritDoc}
      */
      @Override
      public void onClick(final View v) {
        if("".equals(editOrigem.getText().toString().trim())) {
          Toast.makeText(MainActivity.this, "Informe o ponto de partida", 
          Toast.LENGTH_SHORT).show();
        }
        else if("".equals(editDestino.getText().toString().trim())) {
          Toast.makeText(MainActivity.this, "Informe o ponto de destino", 
          Toast.LENGTH_SHORT).show();
        }
        else {
          final Intent intent = new Intent(MainActivity.this, MapActivity.class);
          intent.putExtra("ORIGEM", editOrigem.getText().toString().trim());
          intent.putExtra("DESTINO", editDestino.getText().toString().trim());

          MainActivity.this.startActivity(intent);
        }              
      }
    });
  }
}
Listagem 2. Activity Principal

Recuperando parâmetros e mostrando o mapa

O código da classe MapActivity é mostrado na Listagem 3. Essa classe é responsável por recuperar os valores de origem e destino através do método getStringExtra(), bem como recuperar o fragmento definido na activity responsável pela exibição do mapa, mostrada na Listagem 4.


import android.app.Activity;
import android.os.Bundle;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
 
public class MapActivity extends Activity {
 private GoogleMap gMap;
   
 @Override
 protected void onCreate(final Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_map);

   gMap= ((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();

   final String editOrigem = getIntent().getStringExtra("ORIGEM");
   final String editDestino = getIntent().getStringExtra("DESTINO");

   new RotaTask(this, gMap, editOrigem, editDestino).execute();
 }
}
Listagem 3. Classe responsável por gerenciar a tela do mapa
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:name="com.google.android.gms.maps.MapFragment"/>
Listagem 4. Tela de layout para mapa

A tela de consulta de rotas é mostrada na Figura 3. O mapa com a rota traçada é demonstrado na Figura 4.

Consulta de rota pela API do Google Maps
Figura 3. Consulta de rota pela API do Google Maps
Rota traçada no Google Maps
Figura 4. Rota traçada no Google Maps

Utilizando Fragments e a classe MapFragment

A partir da sua versão 3.0, o Android incluiu em sua API a funcionalidade de fragments, que possibilita desenhar a interface com o usuário de forma mais dinâmica e reutilizável, com o objetivo de suportar diferentes tamanhos de tela.

Um exemplo de utilização de fragments seria um aplicativo de notícias. Em um tablet, teríamos um fragment do lado esquerdo da tela contendo uma listagem de notícias. Ao clicar em um item da lista, seria disponibilizado outro fragment do lado do primeiro contendo os detalhes da notícia escolhida. Em um dispositivo de tamanho de tela menor como um celular, o fragment de detalhe da notícia selecionada ocuparia o espaço inteiro da tela, como esquematizado na Figura 5.

Fragments no Android
Figura 5. Fragments no Android

A forma mais simples de embutir um mapa em um aplicativo Android é criando um fragment do tipo MapFragment. A classe MapFragment é um tipo especial de view presente na API do Google Maps que funciona como um template para a renderização do mapa na aplicação.

A classe GoogleMap é responsável por gerenciar a apresentação do mapa na aplicação. Nela encontramos os métodos responsáveis por adicionar interatividade ao nosso mapa. Uma instância dessa classe é obtida através da chamada ao método getMap() de um objeto da classe MapFragment presente na aplicação.

Utilizando AsyncTasks

No Android, caso não seja especificado nenhum tipo de concorrência, todo o código irá rodar na thread principal. Essa thread é conhecida como UI Thread, também chamada de main() thread.

Isso se torna um problema no caso da existência de processos que demorem muito tempo para serem executados, pois caso exista algum processamento que demore mais de cinco segundos a UI thread deixará de responder e a aplicação apresentará um ANR (Application Not Responding) ao usuário.

Uma das maneiras de contornar esse problema é por meio da utilização de AsyncTasks, que nada mais são do que objetos que encapsulam e tornam transparente ao desenvolvedor a utilização de threads, permitindo ao desenvolvedor realizar operações em background sem que seja necessário conhecimento da API de Threads da plataforma Java.

No nosso exemplo, o código responsável por enviar a requisição HTTP para a Google Directions API estará encapsulado em uma AsyncTask, pois dado que esse é um processamento potencialmente custoso para a aplicação, não corremos o risco de “travar” a thread principal do aplicativo esperando por uma resposta da API. O código da classe AsyncTask é mostrado na Listagem 5.

//imports omitidos...
 
public class RotaTask extends AsyncTask<Void, Integer, Boolean> {
 
  private static final String TOAST_MSG = "Calculando";
  private static final String TOAST_ERR_MAJ = "Impossivel traçar Itinerário";
 
  private Context context;
  private GoogleMap gMap;
  private String editOrigem;
  private String editDestino;
  private final ArrayList<LatLng> lstLatLng = new ArrayList<LatLng>();
 
  public RotaTask(final Context context, final GoogleMap gMap, final String editOrigem, 
  final String editDestino) {
    this.context = context;
    this.gMap= gMap;
    this.editOrigem = editOrigem;
    this.editDestino = editDestino;
  }
 
  /**
  * {@inheritDoc}
  */
  @Override
    protected void onPreExecute() {
      Toast.makeText(context, TOAST_MSG, Toast.LENGTH_LONG).show();
  }
 
  /***
  * {@inheritDoc}
  */
  @Override
  protected Boolean doInBackground(Void... params) {
    try {
      final StringBuilder url = new StringBuilder
      ("http://maps.googleapis.com/maps/api/directions/xml?sensor=false&language=pt");
      url.append("&origin=");
      url.append(editOrigem.replace(' ', '+'));
      url.append("&destination=");
      url.append(editDestino.replace(' ', '+'));

      final InputStream stream = new URL(url.toString()).openStream();

      final DocumentBuilderFactory documentBuilderFactory = 
      DocumentBuilderFactory.newInstance();
      documentBuilderFactory.setIgnoringComments(true);

      final DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

      final Document document = documentBuilder.parse(stream);
      document.getDocumentElement().normalize();

      final String status = document.getElementsByTagName("status").item(0).getTextContent();
      if(!"OK".equals(status)) {
        return false;
      }

      final Element elementLeg = (Element) document.getElementsByTagName("leg").item(0);
      final NodeList nodeListStep = elementLeg.getElementsByTagName("step");
      final int length = nodeListStep.getLength();

      for(int i=0; i<length; i++) {        
        final Node nodeStep = nodeListStep.item(i);

        if(nodeStep.getNodeType() == Node.ELEMENT_NODE) {
          final Element elementStep = (Element) nodeStep;
          decodePolylines(elementStep.getElementsByTagName("points")
          .item(0).getTextContent());
          }
    }

      return true;          
    }
    catch(final Exception e) {
      return false;
    }
  }
 
  private void decodePolylines(final String encodedPoints) {
    int index = 0;
    int lat = 0, lng = 0;

    while (index < encodedPoints.length()) {
      int b, shift = 0, result = 0;

      do {
        b = encodedPoints.charAt(index++) - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
      } while (b >= 0x20);

      int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
      lat += dlat;
      shift = 0;
      result = 0;

      do {
        b = encodedPoints.charAt(index++) - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
      } while (b >= 0x20);

      int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
      lng += dlng;

      lstLatLng.add(new LatLng((double)lat/1E5, (double)lng/1E5));
    }
  }
 
  /**
  * {@inheritDoc}
  */
  @Override
  protected void onPostExecute(final Boolean result) { 
    if(!result) {
      Toast.makeText(context, TOAST_ERR_MAJ, Toast.LENGTH_SHORT).show();
    }
    else {
      final PolylineOptions polylines = new PolylineOptions();
      polylines.color(Color.BLUE);

      for(final LatLng latLng : lstLatLng) {
              polylines.add(latLng);
      }

      final MarkerOptions markerA = new MarkerOptions();
      markerA.position(lstLatLng.get(0));
      markerA.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));

      final MarkerOptions markerB = new MarkerOptions();
      markerB.position(lstLatLng.get(lstLatLng.size()-1));
      markerB.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));

      gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(lstLatLng.get(0), 10));
      gMap.addMarker(markerA);
      gMap.addPolyline(polylines);
      gMap.addMarker(markerB); 
    }
  }
}
Listagem 5. Classe AsyncTask

Como pode ser observado, uma AsyncTask deve implementar os seguintes métodos:

  • onPreExecute(): Esse método é invocado pela thread principal antes da execução da AsyncTask e deve ser usado para executar atividades relevantes para a execução da task, como checagem de parâmetros nulos e abertura de conexões com uma base de dados;
  • doInBackground(): Esse método é executado imediatamente após o término da execução do método onPreExecute() e conterá o processamento que desejamos executar em segundo plano;
  • onPostExecute(): Método é executado após o término do processamento. O retorno do método doInBackground() é passado para esse método como parâmetro.

Para uma AsyncTask funcionar adequadamente, o desenvolvedor deverá atentar para os seguintes pontos:

  • A AsyncTask deve ser carregada na thread principal;
  • O método execute() deve ser chamado na thread principal;
  • Os métodos onPreExecute(), doInBackground() e onPostExecute() não devem ser chamados manualmente.
Nota: De acordo com a documentação da API, as AsyncTasks devem ser utilizadas preferencialmente para processamentos de curta duração(segundos). Operações que necessitem de um processamento mais demorado devem fazer uso das APIs disponibilizadas no pacote java.util.concurrent, como Executor, ThreadPoolExecutor e FutureTask.

Executando a requisição para a Google Directions API

A documentação da Google Directions API especifica que uma requisição deverá ter o seguinte formato:

http://maps.googleapis.com/maps/api/directions/output?parameters

O parâmetro output especifica o tipo de retorno da requisição, que poderá ser XML ou JSON. No nosso exemplo, além desse parâmetro, especificaremos os parâmetros origin e destination, para designar os pontos de origem e destino, respectivamente. Também usaremos o parâmetro sensor, para especificar se a rota vem de um dispositivo de localização, e o parâmetro language como pt-BR, para que o aplicativo entenda buscas textuais na língua portuguesa (ruas, avenidas, etc.).

Utilizaremos a API padrão do Java para realizar o parsing do XML retornado pela aplicação e delegaremos o processamento para o método decodePolilynes(), que é um método utilitário encontrado na Internet (semelhante ao que ocorre com métodos de validação de CPF, por exemplo). Ele será responsável por transformar a rota codificada em um array de objetos do tipo LatLng, que é a classe do Google responsável por encapsular as informações de latitude e longitude.

A classe PolylineOptions agrupa um conjunto de objetos do tipo Polyline, que representam os trechos da rota a ser percorrida entre um ponto e outro. A classe MarkerOptions encapsula um objeto do tipo LatLng, que serve para designar as coordenadas de latitude e longitude de uma determinada localidade. Nela também encontramos o método setIcon(), responsável por adicionar o ícone representativo de uma localidade, no nosso caso ilustrado pelos clássicos “balõezinhos” verde e vermelho.

A classe CameraUpdateFactory, como pode ser deduzido pelo seu nome, é uma classe que atua como “fábrica” para a criação de objetos do tipo CameraUpdate, que são responsáveis por mudar o posicionamento do mapa. O método estático newLatLngZoom() retorna um objeto CameraUpdate que move o centro da tela para uma latitude e longitude especificadas por um objeto do tipo LatLng e modifica o zoom especificado.

Para mudar o nível de zoom do mapa que está sendo apresentado, a classe CameraUpdate disponibiliza outros métodos utilitários como:

  • zoomIn(): este método incrementa o zoom em 1.0;
  • zoomOut(): este método decrementa o zoom em 1.0;
  • zoomTo(float zoom): incrementa o zoom com o valor especificado.

Finalmente, utilizamos o método addPolyline() da classe GoogleMap para renderizar no mapa o caminho a ser percorrido entre o ponto de origem e destino.

Este artigo teve como objetivo introduzir o leitor no mundo dos aplicativos georreferenciados, utilizando a famosa API do Google Maps para demonstrar um exemplo simples de cálculo e exibição de rotas. Esperamos com esse artigo ter despertado no leitor a curiosidade e o interesse em aprofundar o conhecimento nessa fantástica área da computação móvel.

Confira também