Boteco Digital

Pegando a posição GPS no Android

Um recurso muito interessante de se manipular em um dispositivo mobile é o seu posicionamento GPS(Global Positioning System) que fornece coordenadas de Latitude e Longitude permitindo criar aplicações que com base onde você está se comporta de maneira diferente ou gera resultados diferentes.

Para começarmos devemos saber que um dispositivo Android possui uma classe para trabalharmos com localização, a classe LocationManager, esta classe não deve ser instanciada por nós, mas sim recuperada do sistema através do método:

	LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 

Para ela funcionar corretamente devemos adicionar no nosso AndroidManifest.xml as seguintes permissões

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Para acessar somente a localização pela Rede.

	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Para acessar a localização pela Rede e pelo GPS do dispositivo

Como vimos nas permissões acima podemos pegar a posição do dispositivo de diversas fontes, que chamamos de location provider, podemos listar todos os location provider através do siguinte método:

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
	
	for(String provider : locationManager.getAllProviders()){
		Toast.makeText(getApplicationContext(), provider, Toast.LENGTH_LONG).show();
	}

Normalmente deve retornar 3 tipos de location provider:

passive(CellID, WiFi MACID): Este provider utiliza a posição adquirida por outro programa ou serviço, sem propriamente pedir uma nova posição para o sistema. Pode ser representado pela constante LocationManager.PASSIVE_PROVIDER.

network (AGPS, CellID, WiFi MACID): Este provider utiliza a disponibilidade de torres de celular e pontos de acesso Wi-Fi para determinar uma posição. Pode ser representado pela constante LocationManager.NETWORK_PROVIDER.

gps (GPS, AGPS): Este provider utiliza os satélites GPS para determinar uma posição. Pode demorar um tempo para determinar a posição. Pode ser representado pela constate LocationManager.GPS_PROVIDER.

Precisão Uso de Energia Tecnologia
20ft ou 6m Alta GPS, Provider: gps

  • usa o chip GPS do dispositivo
  • linha de visão com os satélites
  • necessita cerca de 7 satélites para travar a prosição
  • leva muito tempo para travar uma posição
  • não funciona em torno de edifícios altos
200ft ou 60m Média Baixa GPS assistido (AGPS), Provider: network

  • usa o chip GPS do dispositivo, e também recebe dados de suporte da rede(celular) para travar a posição mais rapidamente
  • consumo de energia é baixa
  • muito preciso
  • funciona sem uma linha de visão para o céu
  • dependa da operadora de celular fornecer este recurso
5300ft ou 1.6km Baixa CellID lookup/WiFi MACID lookup, Provider: network or passive

  • trava a posição muito rapidamente e não necessita que o dispositivo tenha um chip GPS
  • precisão muito baixa
  • muito pouco preciso embora as possa ter uma precisão melhor em locais com muitos access point WIFI.
Pegando uma posição

Agora que já sabemos as características dos provideres de onde pegar a posição do dispositivo vamos fazer uma unica requisição:

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
		
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER , new LocationListener() {
			
	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		Toast.makeText(getApplicationContext(), &quot;Status alterado&quot;, Toast.LENGTH_LONG).show();				
	}
			
	@Override
		public void onProviderEnabled(String arg0) {
			Toast.makeText(getApplicationContext(), &quot;Provider Habilitado&quot;, Toast.LENGTH_LONG).show();
	}
			
	@Override
	public void onProviderDisabled(String arg0) {
		Toast.makeText(getApplicationContext(), &quot;Provider Desabilitado&quot;, Toast.LENGTH_LONG).show();				
	}
			
	@Override
	public void onLocationChanged(Location location) {
		TextView latitude = (TextView) findViewById( R.id.latitude);
		TextView longitude = (TextView) findViewById( R.id.longitude);
		TextView time = (TextView) findViewById( R.id.time);
		TextView acuracy = (TextView) findViewById( R.id.Acuracy);
		TextView provider = (TextView) findViewById( R.id.provider);
				
		if( location != null ){
			latitude.setText( &quot;Latitude: &quot;+location.getLatitude() );
			longitude.setText( &quot;Longitude: &quot;+location.getLongitude() );
			acuracy.setText( &quot;Precisão: &quot;+location.getAccuracy()+&quot;&quot; );
		
			SimpleDateFormat sdf = new SimpleDateFormat(&quot;dd/MM/yyyy HH:mm:ss&quot;);
			time.setText( &quot;Data:&quot;+sdf.format( location.getTime() ) );

			provider.setText( location.getProvider());			
		}
				
	}
}, null );
 

Como vemos na linha 3 chamamos o método requestSingleUpdate de nosso locationManager que recebe dois parâmetros, o primeiro é qual provider ele de deverá utiliza e o segundo parâmetro devera ser um objeto que implemente LocationListener do qual serão chamados certos métodos quando determinados eventos acontecerem.

A interface LocationListener nos obriga a implementar os seguintes métodos:

onProviderDisabled(String provider): será chamado quando o provider for desabilitado pelo usuário. Pode ser um bom lugar para iniciar uma nova requisição de posição por outro provider.

onProviderEnabled (String provider): será chamado quando o provider for habilitado pelo usuário.

onStatusChanged (String provider, int status, Bundle extras): será chamado quando o status do provider for alterado ou seja quando o provider for incapaz de travar uma posição ou se o ele foi recentemente disponível após um período de indisponibilidade. Como parâmetro status será passado uma das constantes LocationProvider.OUT_OF_SERVICE se o serviço está fora e não há previsão para voltar, LocationProvider.TEMPORARILY_UNAVAILABLE se o serviço está indisponível mas deve voltar em breve e LocationProvider.AVAILABLE se o serviço esta disponível agora.

onLocationChanged (Location location): será chamando quando uma posição for travada, passando como parâmetro para o método um objeto Location que representa a posição com todas as suas informações.

Location

O objeto Location que o método onLocationChanged recebe de parâmetro e representa a posição travada e podemos chamar os seguintes métodos para pegarmos as suas informações.

location.getLatitude(): Retorna a coordenada de latitude.

location.getLongitude(): Retorna a coordenada de longitude.

location.getTime(): Retorna o tempo UTC de quando a posição foi travada, em millisegundos desde Janeiro 1, 1970.(O mesmo modo de armazenamento de tempo da classe Date).

location.getAltitude(): Retorna a altitude em metros se disponível, senão retorna 0.0 .

getProvider() Retorna qual provider que gerou a posição. Útil quando utilizamos o provider passive.

getSpeed(): Retorna a velocidade de deslocamento em metros se disponível, senão 0.0 .

location.getAccuracy(): Retorna a precisão aproximada do ponto em metros. A precisão é dada traçando um circulo tendo como o centro a latitude e longitude e a accuracy como raio há a probabilidade de 68% da posição verdadeira esta dentro deste circulo.

Pegando sequencia de posições

Em alguns casos precisamos de posições periódicas, ou das posições de x em x metros para traçar uma rota por exemplo, para isso temos um outro método no objeto LocationManager o requestLocationUpdates.

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
		
long tempo = 1000 * 5; //5 minutos
float distancia = 30; // 30 metros
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER , tempo , distancia,  new LocationListener() {
			
	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		Toast.makeText(getApplicationContext(), &quot;Status alterado&quot;, Toast.LENGTH_LONG).show();				
	}
			
	@Override
	public void onProviderEnabled(String arg0) {
		Toast.makeText(getApplicationContext(), &quot;Provider Habilitado&quot;, Toast.LENGTH_LONG).show();
	}
			
	@Override
	public void onProviderDisabled(String arg0) {
		Toast.makeText(getApplicationContext(), &quot;Provider Desabilitado&quot;, Toast.LENGTH_LONG).show();				
	}
			
	@Override
	public void onLocationChanged(Location location) {
		TextView numero = (TextView) findViewById( R.id.numero);
		TextView latitude = (TextView) findViewById( R.id.latitude);
		TextView longitude = (TextView) findViewById( R.id.longitude);
		TextView time = (TextView) findViewById( R.id.time);
		TextView acuracy = (TextView) findViewById( R.id.Acuracy);
			
		if( location != null ){
			locs.add(location);
			numero.setText( &quot;Número de posições travadas: &quot;+locs.size() );
			latitude.setText( &quot;Latitude: &quot;+location.getLatitude() );
			longitude.setText( &quot;Longitude: &quot;+location.getLongitude() );
			acuracy.setText( &quot;Precisão: &quot;+location.getAccuracy()+&quot;&quot; );
				
			SimpleDateFormat sdf = new SimpleDateFormat(&quot;dd/MM/yyyy HH:mm:ss&quot;);
			time.setText( &quot;Data:&quot;+sdf.format( location.getTime() ) );
				
		}
	}
}, null );

Como podemos ver fizemos alteração em apenas uma linha onde trocamos o método chamado e passamos dois novos parâmetros:

requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)

minTime: tempo minimo entre as atualizações de posição, em milissegundos
minDistance: distância minima entre as atualizações, em metros

Neste ponto podemos acrescentar que será atualizada a posição se o tempo minimo for ultrapassado ou a distância o que vier primeiro.

Para pararmos de receber atualização de posições devemos chamar o método removeUpdates passando o LocationListener que utilizamos para pedir os updates:

locationManager.removeUpdates( listener );
Testando no Emulador

No emulador do SDK podemos para fim de teste enviar posições “fake” para testar nossa aplicação, para isso devemos ir perspectiva DDMS(se ela não está aparecendo vá em Windows -> Open Perspective -> Other… ) na aba Emulator Control rolando a janela verá a seguinte seção.

location

Basta inserir as coordenadas e clicar em send que elas serão enviadas pelo provider GPS para a aplicação.

Bom pessoal este é o básico, o resto é com vocês 🙂

baixar este exemplo

Referências

http://developer.android.com/guide/topics/location/strategies.html

http://developer.android.com/reference/android/location/LocationManager.html

http://developerlife.com/tutorials/?p=1375

Categorias Android
comments powered by Disqus