quinta-feira, 18 de julho de 2013

Android – Implementando o uso do GPS na api Google Maps


A capacidade de usar recursos do Google através do Android é excelente e a cada dia que passa se torna mais expansível no mundo dos programadores. Antes de iniciarmos este artigo, recomendo a leitura do artigo do mês passado que explica os primeiros passos para obter e trabalhar com a API do Google Mapas. Vou explicar o uso de algumas classes e controles para dominar o uso do GPS, simulando várias situações localizadas por coordenadas. O emulador do eclipse demonstrou ser uma poderosa ferramenta para o uso destes recursos.

Principais Classes

1-) MyLocationOverlay

É esta classe que irá implementar automaticamente a localidade desejada. É uma classe utilizada para mostrar uma esfera para indicar a latitude e a longitude da localização do GPS ativo, tendo dois principais parâmetro, o contexto da aplicação e o próprio “MapView”.

2-) LocationManager

Esta classe fornece acesso aos serviços de localização do sistema. Estes serviços permitem que aplicativos obtenham atualizações periódicas de localização geográfica do dispositivo. Esta classe não permite instanciá-la diretamente, ao invés disto para recuperar o valor é necessário utilizar através do método “getSystemService” passando como parâmetro o contexto de localização (Context.LOCATION_SERVICE). Outro método importante desta classe é o getLastKnownLocation”, o mesmo devolve uma localização que indica os dados da última localização obtida. Já o método “requestlocationUpdates” resgata as atualizações das localizações,  possuindo várias sobrescritas. Neste exemplo utilizaremos especificamente os parâmetros: Provedor de localização, tempo, distância e a classe de Atualização de nova localidade.

3-) LocationListener

Usada para receber notificações do “LocationManager” quando sofrer alguma alteração no local. Possui vários métodos públicos abstratos:

OnLocationChanged: Invocado quando o local mudou.
OnProviderDisabled: Invocado quando o provedor é desativado pelo usuário.
OnProviderEnabled: Invocado quando o provedor é ativado pelo usuário.
OnStatusChanged: Invocado quando existirem alterações de status de provedor.

Criando um Exemplo

No exemplo do artigo deste mês vou envolver todos os conceitos aprendidos anteriormente. Inicie uma aplicação do Zero clicando em “File/New/Android Project...” e faremos as configurações a seguir.

Habilitando o Emulador do GPS - “Emulator Control”

Com este emulador na IDE do eclipse podemos simular diversas tarefas como Chamadas recebidas, Mensagens (SMS) e no nosso caso a localização por GPS utilizando coordenadas, tanto para o dispositivo quanto para o próprio emulador durante o desenvolvimento. Por padrão este controle vem como desabilitado, podemos habilitá-lo clicando no menu “ItemShow View/Other...” Ele estará presente na pasta “Android”.

Figura 01: Selecionado o “Emulator Control”.

Selecione o Emulador de Controle e clique em “Ok”. Por padrão ele estará disponível na região inferior da IDE do Eclipse, Ver Imagem 02.

Figura 02: “Emulator Control”.

O que nos interessa para este artigo é a parte chamada “Location Controls”, é ali onde iremos inserir dados para localização do GPS.

Configurações no “AndroidManifest.xml”

Deveremos dar permissões ao aplicativo para acesso à internet e ao local utilizando fontes de localizações como, por exemplo, o GPS. Ambas são utilizadas a tag “uses-permission”. Daremos também permissão para acesso a biblioteca “com.google.android.maps” fazendo o uso da tag “uses library”.
Para Acesso a internet:


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


Para Uso de fontes de localizações:


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


Para permitir acesso a biblioteca do Google Maps:


<uses-library android:name="com.google.android.maps" />


Segue em seguida a listagem completa:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="pct.Google_maps"
      android:versionCode="1"
      android:versionName="1.0">
   <uses-sdk android:minSdkVersion="8" />
   <uses-permission android:name="android.permission.INTERNET" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <application android:icon="@drawable/icon" android:label="@string/app_name">
   <uses-library android:name="com.google.android.maps" />
        <activity android:name=".Google_mapsActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Criando o “Lay-Out”

A tela de lay-out será bem simplificada, possuindo apenas um “MapView”, Ver Imagem 03.

Figura 03: Lay-Out de exemplo.

O XML correspondente:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <LinearLayout android:id="@+id/linearLayout4"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:weightSum="1">
    </LinearLayout>
     <com.google.android.maps.MapView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mapview"
    android:layout_width="fill_parent"
    android:clickable="true"
    android:apiKey="0AOvUFOH7B4e1mBLmq1cEkgCMwk_YYYYY_XXXXX"
    android:layout_height="500dp"/>   
 </LinearLayout>


Codificando o exemplo

Explicarei detalhadamente todas as etapas efetuadas, sendo que o primeiro passo seria importar as bibliotecas necessárias.

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class Google_mapsActivity extends MapActivity
{   
     private GeoPoint geoPoint;
     private MapView  mapView;
     private MapController mapController;
     private MyLocationOverlay myLocationOverlay;
     private LocationManager locationManager;
     private LocationListener locationListener;
     
A classe principal herdará da classe “MapActivity”. Definimos alguns objetos para uso privado, sendo a “geoPoint” para atribuição das coordenadas do mapa, a “mapView” e “MapController” para referência e controle do Mapa. O objeto MyLocationOverlay servirá para trabalharmos com nossa localização e o “LocationManager” e “LocationListener” para acesso e controle dos métodos utilizados.      

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         mapView = (MapView) findViewById(R.id.mapview);
         mapController = mapView.getController();
myLocationOverlay = new MyLocationOverlay(this,  mapView);
         mapView.getOverlays().add(myLocationOverlay);
locationManager = (LocationManager)    getSystemService(Context.LOCATION_SERVICE);
Location localizacao =   locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
   
No evento OnCreate() é onde focamos o desenvolvimento do exemplo, atribuindo a referencia criada do “MapView” e obtendo os controles necessários usando o método “getController”. A classe “MyLocationOverlay” é a mais importante, pois é com ela que conseguimos automaticamente atribuir a localização desejada atribuindo o “Overlay” para o “Mapview”. O “LocationManager” fornece acesso aos serviços de localizações finalizando com a classe “Location”, tendo como último ponto de acesso utilizando o método “getLastKnowLocation”.

      if (localizacao != null)
      {
Toast.makeText(Google_mapsActivity.this,"lat: "+localizacao.getLatitude() + " Lon: "+localizacao.getLongitude(), Toast.LENGTH_LONG).show();
geoPoint = new GeoPoint((int)(localizacao.getLatitude() * 1e6), (int)(localizacao.getLongitude() * 1e6));
         mapController.setCenter(geoPoint);
      }
        
Realizamos uma condição para analisar se foi ou não encontrado algum dado, caso positivo informamos com uma mensagem informativa a Latitude e Longitude localizando e centralizando no mapa estas informações.

     locationListener = new Minhalocalizacao();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

    }
   
Foi necessário criar uma classe chamada “MinhaLocalizacao” para implementar os métodos da classe abstrata “LocationListener”. Os métodos presentes serão invocados conforme comportamento do GPS. Utilizaremos o “OnLocationChanged” que servirá para indicar quando o local será mudado.

Observação Importante
Fica a critério de o desenvolvedor criar a classe “MinhaLocalizacao” dentro da classe principal. Poderíamos também ter criado um arquivo a parte.

    class Minhalocalizacao implements LocationListener
    {
         @Override
         public void onLocationChanged(Location location)
         {
Toast.makeText(Google_mapsActivity.this,"lat: "+location.getLatitude() + " Lon: "+location.getLongitude(), Toast.LENGTH_LONG).show();
geoPoint = new GeoPoint((int)(location.getLatitude() * 1e6), (int)(location.getLongitude() * 1e6));
             mapController.setCenter(geoPoint);
         }

         @Override
         public void onProviderDisabled(String provider)
         {
// TODO Auto-generated method stub
}

         @Override
         public void onProviderEnabled(String provider)
         {
              // TODO Auto-generated method stub
            }

         @Override
public void onStatusChanged(String provider, int status, Bundle extras)
         {
              // TODO Auto-generated method stub
         }
    }

É necessário programar todos os métodos, mesmo não utilizados. No método “onLocationChanged” o código será o mesmo que foi proposto acima, a única diferença é que temos como parâmetro a variável “Location”.

    @Override
    protected boolean isRouteDisplayed()
    {
         // TODO Auto-generated method stub
         return false;
    }

O método sobrescrito “isRouteDisplayed()” que retorna um booleano para informar se algum tipo de rota está sendo visualizada. Este método é obrigatório em se tratando da classe “MapActivity”.

  
    @Override
    protected void onResume()
    {
         super.onResume();
         myLocationOverlay.enableMyLocation();
    }
   
    @Override
    protected void onPause()
    {
         super.onPause();
         myLocationOverlay.enableMyLocation();
    }

Para habilitar o objeto “MyLocationOverlay” foi necessário sobrescrever dois métodos da Atividade Principal, o “OnResume” (iniciar) e o “OnPause” (Pausar). Usamos em ambos os casos o método “enableMyLocation”.
     
}
Exemplo em “Run-Time”

Rode a aplicação e teremos um resultado idêntico ao da figura 04.

Figura 04: Aplicação em “Run-time”.

Para simular o uso do GPS abra o Eclipse em “Emulator Control” na aba Manual insira a latitude e a longitude. Recomendo entrar no próprio site do “Google Maps” indicando um local, no meu caso informei o nome de minha cidade (Avaré – São Paulo)
Clique no local encontrado e com o botão direito escolha “O que há aqui?” para obter as coordenadas solicitadas. Ver Imagem 05.

Figura 05: Coordenadas.

Os valores aparecerão na barra de pesquisa, Ver Imagem 06.

Figura 06: Latitude e Longitude.

Pronto, agora é só informar estes dados no Eclipse (troque os pontos por vírgula) e clicar no botão “Send” para atualizar o 
Mapa. Ver Imagem 07.

Figura 07: Informando os dados necessários.

O resultado ficará idêntico ao da imagem 08.

Figura 08: Usando o GPS.

A classe “MyLocationOverlay” implementa automaticamente uma esfera que irá ficar piscando como localização do ponto das coordenadas indicadas, economizando e muito a implementação de “Overlays” próprios para este processo.

Conclusão

Este artigo procurei demonstrar de uma forma rápida e prática o uso de recursos de GPS com a API do Google mapas. Com a implementação da classe “MyLocationOverlay” economizamos  muitas linhas de codificação, pois com ela conseguimos automatizar praticamente todo o processo para construção e uso de recursos para se localizar por coordenadas no “MapView”. Espero que este artigo possa abrir portas para os senhores desenvolver aplicações ricas de recursos.
Abraços e até o mês que vem!

Referências


Nenhum comentário:

Postar um comentário