Dopo aver visto come mostrare una mappa android, ora il prossimo passo è posizionarci con la mappa sulle coordinate gps ricevute dall’app.
In questa lezione vedremo come rilevare la posizione geografica del telefonino, sfruttando il sensore gps. Per fare ciò occorrerá:
- Aggiornare il file manifest con i permessi per acceere ai sensori di posizione
- Abilitare e gestire l’evento di ricezione delle coordinate gps.
Inoltre vedremo come inviare coordinate gps all’emultore, per simulane un cambiamento di posizione.
Le classi necessarie per l’utilizzo degli strumenti GPS sono principalmente due:
- LocationManager
- LocationProvider
Come per tutti i sensori e altri servizi di android, per accedere al sensore gps, dobbiamo dichiarare una serie di permessi nel manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> |
Dove:
- ACCESS_FINE_LOCATION permette di accedere alle informazioni di locazione più precise, fornite dal sensore GPS.
- ACCESS_COARSE_LOCATION permette di avere indicazioni di posizione più approssimate.
In questo articolo, non andremo a spiegare quali sono le best practices per la selezione delle più accurate sulla posizione, ma semplicemente come ricevere queste informazioni. Per maggiori informazioni su quali tecniche adottare vi rimando a questo articolo: http://developer.android.com/guide/topics/location/strategies.html
La classe LocationManager fornisce accesso a tutti i servizi relativi alla posizione. Quale per esempio, quello che notifica l’applicazione notificati ogni qualvolta cambia la posizione geografica, che è anche quello che andremo ad utilizzare.
Mentre la classe LocationProvider è una classe astratta, per i vari provider di servizi di posizionamento.
In questo articolo vedremo come creare una applicazione, che ad ogni aggiornamento di posizione da parte dei servizi gps, aggiornerá due caselle di testo relative alla latitude e longitudine.
Ad alto livello ecco cosá dovremo fare nella nostra applicazione:
1. Ottenere dal sistema operativo una istanza della classe LocationManager
2. Verificare che l’oggetto ritornato non sia null.
3. Registrare un listener di tipo OnLocationChangedListener per ricevere gli aggiornamenti delle coordinate gps.
4. Ad ogni aggiornamento di posizione dobbiamo gestire la nuova richiesta.
In questo modo, ogni qual volta si verifica un aggiornamento nelle coordinate geografiche, il listener verrá chiamato, e noi potremo elaborare i dati ricevuti.
L’istanza della classe LocationManager la otteniamo grazie al metodo getSystemService. Questo metodo prende in input una stringa, che identifica il nome del servizio di sistema e ritorna, se disponibile un istanza del gestore per quel servizio (nel nostro caso appunto un oggetto di tipo LocationManager). I nomi dei servizi sono definiti come costanti nella classe Context (maggiori info le trovate qua: http://developer.android.com/reference/android/content/Context.html) nel nostro caso il servizio richiesto è
Context.LOCATION_SERVICE |
Il codice per ottenere l’istanza di LocationManager sará quindi:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); |
Ricordate sempre di Castare l’oggetto ritorno da getSystemService, in quanto ogni servizio richiesto ritorna un oggetto diverso.
Per iniziare a ricevere gli aggiornamenti di posizione, si utilizza il metodo (meglio uno dei metodi) requestLocationUpdates. Ne esistono diverse specializzazioni, in quanto si possono passare alcuni parametri per configurare queste richieste, com per esempio:
- Minimo intervallo di tempo fra una richiesta e l’altra
- Minima distanza
- Criteri specifici
- Intent da chiamare al verificarsi dell’update
- Listener che si occupa di gestire l’aggiornamento.
Nell’eventualitá che vogliamo invece ricevere degli aggiornamenti singoli, invece che periodici, abbiamo a disposizione il metodo requestSingleUpdate.
In questo esempio useremo il seguente metodo dell’oggetto LocationManager:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100,1000, this) |
Gli argomenti passati sono:
- Il tipo di provider da utilizzare
- La distanza minima in metri prima di lanciare un nuovo aggiornamento
- Il minimo intervallo di tempo in millisecondi
- Il LocationListener (in questo caso la classe sará la stessa dell’activity principale)
Vediamo la classe MainActivity implementata fino a questo punto:
public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100,1000, this); } } |
In questa lezione verrá utilizzato il metodo requestLocationUpdates, con la gestione degli aggiornamenti delegata ad un Listener, in questo caso si tratta dell’interfaccia LocationListener. Quindi se per esempio si vuole far gestire questi eventi direttamente all’activity che utilizza il servizio, ci basta implementare tale interfaccia:
public class MainActivity extends Activity implements LocationListener { ... @Override public void onLocationChanged(Location location) {...} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} } |
Ecco brevemente a cosa servono questi metodi:
- Il metodo onLocationChanged viene chiamato ogni qualvolta cambia la posizione dell’utente.
- Il metodo onStatusChanged viene chiamato quando cambia lo stato del provider (il sensore GPS che ci da le coordinate per esempio)
- onProviderDisabled viene invocato quando l’utente disabilita manualmente i servizi di posizionamento.
- Alla stessa maniera onProviderEnabled viene invocato quando l’utente abilita manualmente i servizi di posizionamento.
Nell’esempio di questa lezione ci limiteremo a lavorare sul metodo onLocationChanged, che viene chiamato ogni volat che la posizione cambia, e l’oggetto Location passato come argomento contiene le informazioni sulle coordinate appena ricevute (insieme anche ad altre informazioni, quali per esempio il provider che le ha generate, l’altitudine se disponibile, la velocitá se disponibile, e alcuni metodi come il calcolo della distanza verso un altra coordinata, etc…). Molto intuitivamente i metodi per ottenere latitudine e longitudine sono getLatitude() e getLongitude(), cominciamo subito a sviluppare la callback onLocationChanged:
@Override public void onLocationChanged(Location location) { double latitude = location.getLatitude(); double longitude = location.getLongitude(); Toast.makeToast(this, "Lat: " + latitude + " Long: " + longitude, Toast.LENGTH_SHORT).show(); } |
Con l’ultima riga semplicemente mostriamo su schermo il contenuto delle variabili appena lette.
Ora se si usa un telefonino reale, possiamo testare senza problemi questo programma, ma nel caso non abbiamo a disposizione un dispositivo e dobbiamo affidarci all’emulatore, niente paura, possiamo inviare manualmente delle coordinate gps all’emulatore via telnet. Per farlo, avviare un emulatore, e da linea di comando digitare:
telnet localhost debugport |
Dove debugport è il numero di porta che compare sull’emulatore. Se la connessione è andata a buon fine ci basta digitare il seguente comando:
geo fix longitude, latitude |
Quindi se per esempio vogliamo inserire le coordinate di dublino, digiteremo il seguente comando:
geo fix -6.245704,53.32432 |
Un altro modo per inserire le coordinate gps con Eclipse è andare su Window -> Show Perspective -> DDMS, selezionare il tab emulator control e cercare per i due campi ove inserire latitudine e longitudine.
Bene con questo è tutto, i sorgenti di questa lezione li trovate disponibilisu github, al seguente indirizzo: https://github.com/inuyasha82/ItalialinuxExample/tree/master/LezioniAndroid
Un libro sullo sviluppo android: https://amzn.to/2WIIiVl