sexta-feira, 8 de maio de 2015

Como obter a localização do usuário via GPS pelo Android

Olá a todos. Chegamos, enfim, a um dos mais aguardados tutoriais de programação Android. Explicaremos aqui como obter a localização do usuário através do hardware de GPS do dispositivo.

Um aparelho Android geralmente é dotado de instrumentos que lhe permitem variadas formas de detectar a posição do usuário no planeta. As mais comuns são: Triangulação de antenas, WPS e GPS.

A detecção através da triangulação de antenas da rede de telefonia móvel se baseia no fato de que a posição pode ser determinada a partir da distância entre o aparelho e as três antenas mais próximas, via interpolação do sinal.

WPS (Wi-Fi Positioning System) utiliza abordagem semelhante, determinando a distância entre o aparelho e os hot-spots WiFi mais próximos. Os hot-spots são geocodificados (sabe-se sua localização), portanto analisando a potência do sinal é possível calcular a posição aproximada do dispositivo móvel.

Por último, o GPS (Global Positioning System) utiliza satélites para descobrir a posição do aparelho móvel. O celular obtém o sinal de um ou mais satélites e de acordo com a triangulação e também com a informação da hora de emissão do sinal embutida na mensagem, é possível determinar sua posição global com uma precisão muito boa.

O sistema Android possui um "gerenciador de localização", cuja função é exatamente permitir que utilizemos o hardware de localização do aparelho de maneira transparente, sem nos preocuparmos com aspectos demasiadamente técnicos, como os descritos nos parágrafos anteriores.

Não é atribuição do desenvolvedor lidar com absolutamente nada relacionado com cálculos matemáticos, comparações de distância ou intensidade de sinal. Tudo isto é totalmente transparente para ele.

Como funciona, então? Num primeiro momento seria lógico concluirmos que deveríamos desenvolver alguma espécie de operação repetitiva (como um pooling), que ficasse verificando de tempos em tempos o equipamento de posicionamento e obtivesse a informação de latitude e longitude. Entretanto, o funcionamento real do gerenciador de localização do Android (locationManager) é exatamente o oposto.

O locationManager na verdade faz sozinho todo o trabalho de verificar a mudança de posição do aparelho. É algo que é executado fora do contexto do nosso aplicativo.

Precisamos apenas dizer ao locationManager que nosso aplicativo está aguardando ser avisado quando ocorrer uma mudança de posição. E também informar com que frequência desejamos ser avisados. A frequência pode ser determinada em duas unidades: tempo ou distância. Podemos configurar o locationManager para nos fornecer as coordenadas GPS a cada 10 segundos, ou a cada 20 metros, por exemplo. Também é possível determinar se utilizaremos a localização via GPS ou REDE. O ajuste fino dessas configurações deve ser feito com critério, pois constitui uma escolha que varia entre maior precisão e menor consumo da bateria do aparelho.

Essa abordagem, do aplicativo permanecer aguardando passivamente ser informado de uma mudança de posição é muito mais econômica do que se fizéssemos, de fato, um pooling e também facilita enormemente a programação. Basta prestarmos atenção ao locationManager e, ao ouvirmos algo, tomarmos uma atitude.

Mas vamos então, ao que interessa:

Primeiro criaremos um novo projeto em nosso ambiente de desenvolvimento, chamado "localizadorGPS". Depois, vamos abrir o arquivo "AndroidManifest.xml" e acrescentar as seguintes permissões:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.LOCATION_HARDWARE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />


Isso basicamente vai nos permitir usar a Internet, determinar o posicionamento via GPS, Rede de telefonia e mostrar alertas de sistema sobre todas as janelas.

O segundo passo é editarmos o arquivo "activity_main.xml" (localizado em res/layout) para que fique conforme o código abaixo (basta copiar e colar):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textViewHello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:padding="15sp" />

    <ScrollView android:id="@+id/scroller"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/textViewHello">
        
    <EditText
        android:id="@+id/editTextPosicoes"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:inputType="none"
        android:textSize="10sp"
        android:gravity="top|left"
        android:focusable="false" />
    
    </ScrollView>   
</RelativeLayout>


O que fizemos aqui foi acrescentar um ScrollView com um EditText dentro. Isto permitirá que mostremos as posições GPS na tela e, conforme o espaço for acabando, o texto continue sendo armazenado, sendo possível visualizar tudo rolando a tela com o dedo, se desejado.

Agora começa a diversão... Vamos abrir o arquivo "MainActivity.java" (da pasta "src"). Logo na descrição da classe, vamos acrescentar: "implements LocationListener", assim:

public class MainActivity extends Activity implements LocationListener
{


Com isto estamos dizendo que desejamos usar o "listener" do hardware de posicionamento do aparelho. Veja que o Eclipse vai mostrar um "X" vermelho, nos pedindo para colocar o "import android.location.LocationListener;". Façamo-lo. Permanecerá ainda outro "X" vermelho. Clique sobre ele e verá que o Eclipse vai oferecer uma opção "Add unimplemented methods", ou seja "Adicionar os métodos não implementados". Vamos, então, clicar nesta opção.

Perceberemos que surgirão automaticamente quatro novos métodos: onLocationChanged, onProviderDisabled, onProviderEnabled e onStatusChanged. Esses são os métodos que serão acionados quando ocorrerem eventos provenientes do locationManager.

O mais importante é o "onLocationChanged", método que será chamado toda vez que o hardware de posicionamento detectar de alguma forma (seja lá qual for) a mudança de posição do dispositivo no globo terrestre.

O "onProviderDisabled" e o "onProviderEnabled" são chamados, respectivamente, caso o usuário habilite ou desabilite os provedores de localização na configuração do celular.

O último, "onStatusChanged", é chamado quando muda a situação do provedor de localização, seja por estar incapaz de extrair a informação de localização ou ainda por ter ficado disponível após um período de indisponibilidade.

Aqui vale uma observação importante. Não é recomendável utilizar os métodos "onProviderDisabled" e "onProviderEnabled" para verificar se o usuário ligou ou desligou as ferramentas de localização na configuração do celular. Por um motivo muito simples: Se, ao iniciar nosso aplicativo, todos os métodos de localização estiverem desabilitados na configuração, não seremos capazes de iniciar o locationManager. Dessa forma, nosso aplicativo não terá como iniciar o Listener. Em outras palavras, nessas circunstâncias, não seremos capazes de saber se o usuário modificou a configuração, porque não estaremos aptos a escutar o broadcast.

A solução é bastante simples: Utilizar um BroadcastReceiver, que é análogo ao Listener e fica aguardando um aviso qualquer do sistema operacional Android. Só que configuraremos um filtro de evento, ou seja, vamos determinar que só queremos ser avisados se o usuário alterar a configuração dos provedores de localização do aparelho, o que é feito da seguinte forma:

filter = new IntentFilter(android.location.LocationManager.PROVIDERS_CHANGED_ACTION);
this.registerReceiver(bReceiver, filter);


Também será necessário determinar quê ação será tomada ao receber essa mensagem do sistema operacional, ou seja, na hora em que o usuário mudar a configuração dos provedores de localização, qual será a atitude do nosso aplicativo, assim:


BroadcastReceiver bReceiver = new BroadcastReceiver()
{      
   @Override
   public void onReceive(Context arg0, Intent arg1)
   {         
      // Chama o método que localiza o usuário.
      localizarUsuario();         
   }
};



Voltando agora ao método "onLocationChanged", o mais importante. Esse método será chamado sempre que houver uma mudança de posição na localização geográfica do aparelho, detectada pelos provedores de localização.

Como parâmetro, o método recebe um objeto "Location". É dele que extrairemos informações como: provedor utilizado, latitude, longitude, altitude (se o dispositivo dispuser de hardware para isso), direção, velocidade, precisão, etc.

Precisão é uma informação importante. Ela indica, em metros, qual a acuracidade conseguida na leitura da localização. Dependendo da aplicação que estamos desenvolvendo, podemos, por exemplo, ignorar leituras com baixa precisão, definindo, desta forma, um mínimo para considerar uma leitura útil.

Em nosso projeto, criaremos no método onLocationChanged a simples funcionalidade de verificar se a precisão é inferior a uma precisão mínima (aqui definda em 2000 metros). Em caso afirmativo, comporemos uma frase de saída contendo as seguintes informações: a maneira de obtenção de posição utilizada, latitude, longitude e raio (precisão). Então mostraremos esta frase na tela do celular:


@Override
public void onLocationChanged(Location location)
{
   // Este método será chamado toda vez que houver uma atualização da localização do usuário.
   // A atualização da localização ocorre de acordo com o configurado no locationManager.

   try
   {
      
      // Obtém a informação da precisão da localização, em metros.
      float precisao=location.getAccuracy();

      // Se a precisão for menor ou igual à precisão mínima exigida (em metros), então mostra a localização na tela.
      // A precisão mínima exigida depende da aplicação.
      if (precisao <= precisaoMinimaExigida)
      {
         // Compõe o texto de saída e acrescenta à caixa de texto.
         String latitude = String.valueOf(location.getLatitude()).substring(0, 10);
         String longitude = String.valueOf(location.getLongitude()).substring(0, 10);
         String novaLinha = location.getProvider() + ": " + latitude + "," + longitude + ", raio:  " + precisao + " m\n" ;
         editTextPosicoes.append( novaLinha );
         
         // Rola o texto da caixa para baixo.
         scroller.smoothScrollTo(0, editTextPosicoes.getBottom());
         
      }
   }
   catch (Exception e)
   {
   }

}

O método principal do projeto, entretanto, será o "localizarUsuario". Ele primeiro verificará se os provedores de localização estão habilitados na configuração do celular. Em caso negativo, emitirá uma caixa de diálogo perguntando ao usuário se deseja habilitá-los. O usuário confirmando, então nosso app abrirá a configuração do dispositivo, para que o próprio usuário ligue o GPS (ou apenas a localização por rede). Caso, por outro lado, o método perceba que a localização via rede está configurada, vai então abrir uma outra caixa de diálogo sugerindo a utilização do GPS para uma maior precisão. Segue o código do método:

public void localizarUsuario()
{

   // Este método efetivamente realiza a localização do usuário, configurando um "locationManager".
   // Através do locationManager o dispositivo utiliza ou o GPS ou a REDE para descobrir a localização
   // do usuário. Note que, na configuração do aparelho, podem estar habilitados ambos os métodos,
   // algum deles, ou nenhum. Para cada caso, uma mensagem de alerta deverá ser mostrada, 
   // questionando o usuário se deseja ligar as ferramentas de localização.
   
   try
   {
               
      // Obtém o locationManager.
      locationManager=(LocationManager) getSystemService(getApplicationContext().LOCATION_SERVICE);

      // Há provedores de localização diversos.
      // O GPS_PROVIDER usa o hardware de GPS dispositivo para obter localização via satélite.
      // O NETWORK_PROVIDER obterá a localização a partir da triangulação de antenas da rede de telefonia celular.

      // Verifica se os provedores de localização estão habilitados.
      provedorREDE_Habilitado=locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
      provedorGPS_Habilitado=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

      
      // Caso não haja nenhum provedor de localização habilitado...
      if (!provedorREDE_Habilitado && !provedorGPS_Habilitado)
      {
                  
         // Não há provedores de localização habilitados.
         // Perguntar ao usuário se deseja habilitar.
         
         // Monta a caixa de diálogo.
         AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
         alertDialogBuilder
               .setMessage("O serviço de localização está desabilitado. Deseja mudar a configuração?")
               .setCancelable(false)
               .setPositiveButton("Configurar",  new DialogInterface.OnClickListener()
               {
                  public void onClick(DialogInterface dialog, int id)
                  {
                     abreConfiguracaoDoDispositivo();
                  }
               });
         
         alertDialogBuilder.setNegativeButton("Cancelar",  new DialogInterface.OnClickListener()
         {
            public void onClick(DialogInterface dialog, int id)
            {
               dialog.cancel();
               editTextPosicoes.setText("Selecione uma forma de obter a localização\npelo menu Configurar.");
            }
         });
      
         alert = alertDialogBuilder.create();
         
         // Mostra a caixa de diálogo.
         if (!alert.isShowing())
         {
            alert.show();
         }

         
      }
      else
      {
         // Limpa o editText.
         editTextPosicoes.setText("");
         
         // Se serviço de localização já foi configurado...
         if (provedorGPS_Habilitado)
         {
            configuraProvedorGPS();
         }
         else
         {
            
            // Caso apenas o serviço de localização por REDE esteja habilitado, sugere o GPS.
            
            // Monta a caixa de diálogo.
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
            alertDialogBuilder
                  .setMessage("Gostaria de habilitar o GPS para uma precisão maior?")
                  .setCancelable(false)
                  .setPositiveButton("Sim",  new DialogInterface.OnClickListener()
                  {
                     public void onClick(DialogInterface dialog, int id)
                     {
                        abreConfiguracaoDoDispositivo();
                     }
                  });
            
            alertDialogBuilder.setNegativeButton("Não",  new DialogInterface.OnClickListener()
            {
               public void onClick(DialogInterface dialog, int id)
               {
                  dialog.cancel();
                  configuraProvedorREDE();
               }
            });
         
            alert = alertDialogBuilder.create();
            
            // Mostra a caixa de diálogo.
            if (!alert.isShowing())
            {
               alert.show();
            }

         }
         
      }
      
   }
   catch (Exception e)
   {
      Log.i("gps", e.getMessage() + " " + e.getLocalizedMessage());
   }

}


É claro, o projeto não se resume apenas aos métodos apresentados acima, que foram descritos apenas para fins didáticos. Portanto, para que seja possível testar a solução por completo, copie e cole o código abaixo na sua MainActivity.java. O código abaixo é o código inteiro:

package com.example.localizadorgps;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.ScrollView;
import android.content.BroadcastReceiver;


public class MainActivity extends Activity implements LocationListener
{
     
   private int precisaoMinimaExigida=2000;    // Precisão do serviço de localização em metros.

   private int intervaloTempoLeituraGPS=5000; // De quanto em quanto tempo (milissegundos) avisará que mudou de posição.
   private int distanciaLeituraGPS=0;         // De quantos em quantos metros avisará que mudou a posição.

   private int intervaloTempoREDE=5000;       // De quanto em quanto tempo (milissegundos) avisará que mudou de posição.
   private int distanciaREDE=0;               // De quantos em quantos metros avisará que mudou posição.
   
   // Define os elementos visuais para exposição das informações no dispositivo.
   private EditText editTextPosicoes;
   private ScrollView scroller;

   // Define o gerenciador de localização.
   private LocationManager locationManager;
      
   // Filtro para definir o evento de broadcast que o app aguardará.
   // No caso "android.location.LocationManager.PROVIDERS_CHANGED_ACTION".
   private IntentFilter filter;
   
   // Caixa de diálogo para interação com o usuário.
   private AlertDialog alert;
   
   // Variáveis de controle dos provedores de localização habilitados na configuração do Android.
   private Boolean provedorGPS_Habilitado;
   private Boolean provedorREDE_Habilitado;

   // Cria um Broadcast Receiver para que a MainActivity seja avisada caso o usuário mude as configurações de localização por fora do app
   // (deslizando a tela para baixo e clicando no ícone do GPS, por exemplo).
   // Isso é necessário porque durante a execução, o usuário tem como mudar as configurações de localização sem usar o próprio aplicativo.
   BroadcastReceiver bReceiver = new BroadcastReceiver()
   {      
      @Override
      public void onReceive(Context arg0, Intent arg1)
      {         
         // Chama o método que localiza o usuário.
         localizarUsuario();         
      }
   };

   
   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);     
      setContentView(R.layout.activity_main);

      // Registra o receiver para que o app seja avisado quando o usuário modificar as configurações de localização do dispositivo.
      filter = new IntentFilter(android.location.LocationManager.PROVIDERS_CHANGED_ACTION);
      this.registerReceiver(bReceiver, filter);      
      
      // Obtém o editText para usar como saída, na tela do dispositivo.
      editTextPosicoes=(EditText) findViewById(R.id.editTextPosicoes);
      editTextPosicoes.setEnabled(false);           
      
      // Obtém o scroller, para permitir a rolagem da caixa de texto onde são exibidas as posições.
      scroller=(ScrollView) findViewById(R.id.scroller);

      // Limpa o editText.
      editTextPosicoes.setText("");
            
      // Chama o método que localiza o usuário.
      localizarUsuario();
            
   }

   public void localizarUsuario()
   {

      // Este método efetivamente realiza a localização do usuário, configurando um "locationManager".
      // Através do locationManager o dispositivo utiliza ou o GPS ou a REDE para descobrir a localização
      // do usuário. Note que, na configuração do aparelho, podem estar habilitados ambos os métodos,
      // algum deles, ou nenhum. Para cada caso, uma mensagem de alerta deverá ser mostrada, 
      // questionando o usuário se deseja ligar as ferramentas de localização.
      
      try
      {
                  
         // Obtém o locationManager.
         locationManager=(LocationManager) getSystemService(getApplicationContext().LOCATION_SERVICE);

         // Há provedores de localização diversos.
         // O GPS_PROVIDER usa o hardware de GPS dispositivo para obter localização via satélite.
         // O NETWORK_PROVIDER obterá a localização a partir da triangulação de antenas da rede de telefonia celular.

         // Verifica se os provedores de localização estão habilitados.
         provedorREDE_Habilitado=locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
         provedorGPS_Habilitado=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

         
         // Caso não haja nenhum provedor de localização habilitado...
         if (!provedorREDE_Habilitado && !provedorGPS_Habilitado)
         {
                     
            // Não há provedores de localização habilitados.
            // Perguntar ao usuário se deseja habilitar.
            
            // Monta a caixa de diálogo.
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
            alertDialogBuilder
                  .setMessage("O serviço de localização está desabilitado. Deseja mudar a configuração?")
                  .setCancelable(false)
                  .setPositiveButton("Configurar",  new DialogInterface.OnClickListener()
                  {
                     public void onClick(DialogInterface dialog, int id)
                     {
                        abreConfiguracaoDoDispositivo();
                     }
                  });
            
            alertDialogBuilder.setNegativeButton("Cancelar",  new DialogInterface.OnClickListener()
            {
               public void onClick(DialogInterface dialog, int id)
               {
                  dialog.cancel();
                  editTextPosicoes.setText("Selecione uma forma de obter a localização\npelo menu Configurar.");
               }
            });
         
            alert = alertDialogBuilder.create();
            
            // Mostra a caixa de diálogo.
            if (!alert.isShowing())
            {
               alert.show();
            }

            
         }
         else
         {
            // Limpa o editText.
            editTextPosicoes.setText("");
            
            // Se serviço de localização já foi configurado...
            if (provedorGPS_Habilitado)
            {
               configuraProvedorGPS();
            }
            else
            {
               
               // Caso apenas o serviço de localização por REDE esteja habilitado, sugere o GPS.
               
               // Monta a caixa de diálogo.
               AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
               alertDialogBuilder
                     .setMessage("Gostaria de habilitar o GPS para uma precisão maior?")
                     .setCancelable(false)
                     .setPositiveButton("Sim",  new DialogInterface.OnClickListener()
                     {
                        public void onClick(DialogInterface dialog, int id)
                        {
                           abreConfiguracaoDoDispositivo();
                        }
                     });
               
               alertDialogBuilder.setNegativeButton("Não",  new DialogInterface.OnClickListener()
               {
                  public void onClick(DialogInterface dialog, int id)
                  {
                     dialog.cancel();
                     configuraProvedorREDE();
                  }
               });
            
               alert = alertDialogBuilder.create();
               
               // Mostra a caixa de diálogo.
               if (!alert.isShowing())
               {
                  alert.show();
               }

            }
            
         }
         
      }
      catch (Exception e)
      {
         Log.i("gps", e.getMessage() + " " + e.getLocalizedMessage());
      }
   }

   public void abreConfiguracaoDoDispositivo()
   {
      // Este método abre a tela de congifuração de localização do dispositivo.
      
      Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
      (MainActivity.this).startActivity(callGPSSettingIntent);     
   }
   
   
   public void configuraProvedorGPS()
   {

      // minTimeGPS é de quanto em quanto tempo (em milissegundos), a informação da localização será atualizada via GPS.
      // minDistanceGPS é de quantos em quantos metros a informação da localização será atualizada via GPS.
      long minTimeGPS=intervaloTempoLeituraGPS;
      long minDistanceGPS=distanciaLeituraGPS;

      // Configura o locationManager para chamar o método OnLocationChanged() de acordo com as premissas estabelecidas.
      locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTimeGPS, minDistanceGPS, this);
   }

   public void configuraProvedorREDE()
   {
      
      // minTimeNETWORK é de quanto em quanto tempo (em milissegundos), a informação da localização será atualizada via triangulação de antenas.
      // minDistanceNETWORK é de quantos em quantos metros a informação da localização será atualizada via via triangulação de antenas.
      long minTimeNETWORK=intervaloTempoREDE;
      long minDistanceNETWORK=distanciaREDE;

      // Configura o locationManager para chamar o método OnLocationChanged() de acordo com as premissas estabelecidas.
      locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, minTimeNETWORK, minDistanceNETWORK, this);
   }
   
   
   @Override
   public void onLocationChanged(Location location)
   {
      // Este método será chamado toda vez que houver uma atualização da localização do usuário.
      // A atualização da localização ocorre de acordo com o configurado no locationManager.

      try
      {
         
         // Obtém a informação da precisão da localização, em metros.
         float precisao=location.getAccuracy();

         // Se a precisão for menor ou igual à precisão mínima exigida (em metros), então mostra a localização na tela.
         // A precisão mínima exigida depende da aplicação.
         if (precisao <= precisaoMinimaExigida)
         {
            // Compõe o texto de saída e acrescenta à caixa de texto.
            String latitude = String.valueOf(location.getLatitude()).substring(0, 10);
            String longitude = String.valueOf(location.getLongitude()).substring(0, 10);
            String novaLinha = location.getProvider() + ": " + latitude + "," + longitude + ", raio:  " + precisao + " m\n" ;
            editTextPosicoes.append( novaLinha );
            
            // Rola o texto da caixa para baixo.
            scroller.smoothScrollTo(0, editTextPosicoes.getBottom());
            
         }
      }
      catch (Exception e)
      {
      }

   }

   @Override
   public void onProviderDisabled(String provider)
   {
   }

   @Override
   public void onProviderEnabled(String provider)
   {     
   }

   @Override
   public void onStatusChanged(String provider, int status, Bundle extras)
   {
   }
        
   @Override
   protected void onDestroy()
   {
      super.onDestroy();
      
      // Desregistra o Broadcast Receiver.
      unregisterReceiver(bReceiver);
   }
   
   @Override
   public boolean onCreateOptionsMenu(Menu menu)
   {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);

      return true;
   }
   
   @Override
   public boolean onOptionsItemSelected(MenuItem item)
   {
      // Lida com os itens do menu selecionáveis pelo usuário.
      switch (item.getItemId())
      {
         case R.id.action_settings:
            abreConfiguracaoDoDispositivo();
            break;
      }
      
      return super.onOptionsItemSelected(item);
   }

   

}


O resultado final pode ser visto na tela abaixo:






Experimente usar este app na rua, à pé, ande alguns quarteirões. Depois faça o mesmo de dentro de um ônibus. Tente alternar entre o modo REDE e GPS, veja o que acontece. Desligue os provedores de localização, religue-os um a um. Alterne entre 3G e WiFi no modo REDE. Veja o que acontece!

Aos que preferirem, duas alternativas para experimentar a aplicação: Ou fazer o download do projeto completo ou ainda do APK ("executável") para instalação no celular.

Para instalar o APK, entretanto, primeiro é necessário configurar o celular para aceitar aplicativos de "fontes desconhecidas" (que não da Google Play Store). Então jogar o APK no aparelho e aí clicar sobre ele, mandando instalar.


Ficamos por aqui. Permaneço à disposição em caso de dúvidas ou sugestões.

Um abraço!



10 comentários:

  1. Não está funcionando... Você tem algum geolocalizador atualizado?

    ResponderExcluir
  2. Excelente trabalho! Parabens! Por favor, gostaria de saber qual a precisao dos GPS dos celulares em geral? Aproximadamente qual o raio (quantos metros) onde posso achar o celular com base na resposta do rastreamento feito quando, por exemplo, se perde o celualar? Muito obriagada pela atencao e ajuda!

    ResponderExcluir
  3. Prezada Maria, grato pelo comentário. Imagino que o raio dependa mais das condições do clima e localização do satélite no momento do uso. Teoricamente a precisão é de poucos metros, mas tudo depende das condições em dado momento. Hoje em dia há 3 formas de localizar: Por triangulação das antenas, por wifi ou por satélite.

    ResponderExcluir
  4. Bom dia!Prezado Luiz, gostaria de pegar os dados de localização que este app gera, e enviar para um banco de dados externo, ou por uma api, obrigado,

    ResponderExcluir
  5. Este comentário foi removido pelo autor.

    ResponderExcluir
  6. Amigo, parabéns pelo projeto.
    Gostaria de fazer uma pergunta : como posso usar somente a localizção por rede 3g/wifi, sem que o "android pergunte" se "deseja habilitar o gps para uma melhor precisão?"
    Obrigado

    ResponderExcluir
  7. Serei eternamente grato por esta colaboração brilhante. Perfeito Luiz Milfont!

    ResponderExcluir
    Respostas
    1. Prezado Edu, seu comentário me alegra. Muito agradecido. Espero ter ajudado!

      Excluir