Android e GeoLocalizzazione con latitudine e longitudine

La Geolocalizzazione consiste nel rilevare la posizione geografica di un dispositivo, esprimendola nelle coordinate bidimensionali denominate latitudine e longitudine. In questo minitutorial vedremo come realizzare una semplice app, per il recupero di questi due dati.

tempo tutorial Ti servono: 25 minuti

Geolocalizzazione

La geolocalizzazione è uno degli elementi che contraddistingue totalmente le applicazioni mobili da quelle tradizionali. Questo permette di dare vita a programmi di grandissima utilità in svariati settori (software commerciali, sportivi, multimediali ed altro ancora) conferendo a semplici numeri (latitudine e longitudine), solitamente dall'aria così "astratta", un'associazione con luoghi appartenenti al mondo reale.

La Geolocalizzazione consiste nel rilevare la posizione geografica di un dispositivo esprimendola nelle coordinate denominate latitudine e longitudine, le quali non sono altro che dei numeri frazionari che indicano un punto preciso sulla superficie terrestre, ipotizzando che questa sia piatta ossia bidimensionale, altrimenti dovremmo considerare anche l'altezza.

In questo tutorial vedremo:

  • i concetti basilari della geolocalizzazione in Android;
  • la conoscenza degli strumenti messi a disposizione in Visual Studio SDK
  • la dimestichezza con l'integrazione pratica di informazioni geografiche reali nella propria app

Tipi di localizzazione e quali permessi servono

Esistono due tipi di localizzazione comunemente usati nelle applicazioni Android:

  • localizzazione network-based: sfrutta dati provenienti da reti mobili locali per ottenere informazioni geografiche. Non è particolarmente accurata ma disponibile su praticamente tutti i dispositivi, a patto di avere una connessione dati attiva, abilitata tramite il proprio gestore di telefonia;
  • GPS: sistema leader nella geolocalizzazione basato su informazioni provenienti da una rete di satelliti. Molto accurato e comunque disponibile sulla maggior parte dei dispositivi Android, e senza dover usare una connessione dati.

Abbiamo imparato che quando la nostra applicazione ha bisogno di effettuare comunicazioni di carattere particolare o accedere a determinati sottosistemi hardware, deve presentare gli opportuni permessi che dovranno essere inseriti all'interno del file manifest, AndroidManifest.xml.

La localizzazione rientra in queste casistiche pertanto esistono appositi permessi:

  • per la localizzazione network-based si richiederà la permission COARSE. Il nodo XML corrispondente è:
          <uses-permission andorid:name="android.permission.ACCESS_COARSE_LOCATION"/>
        
  • per la localizzazione tramite GPS, sarà necessario richiedere i seguenti permessi:
          <uses-permission andorid:name="android.permission.ACCESS_FINE_LOCATION"/>
        

Trattandosi di un livello di accuratezza maggiore, i permessi per l'uso del GPS includono di default anche i permessi COARSE.

I "protagonisti" software

Essenzialmente, sfruttare la localizzazione in Android significa gestire un dialogo tra due entità: il LocationManager ed il LocationListener.

Il primo, il LocationManager, è un servizio di sistema, rintracciabile mediante Context, che svolge il ruolo di gestore unico dei sistemi di localizzazione. Che si voglia sfruttare il GPS piuttosto che la localizzazione Network-based, dovremo sempre interagire con il LocationManager. Questo il modo per reperirlo:

mLocationManager=this.getSystemService(LOCATION_SERVICE);

Il riferimento this equivale al Context, è stato usato immaginando di trovarci all'interno di un'Activity. Quello di LocationListener è il ruolo svolto dall'elemento della nostra applicazione che desidera ricevere informazioni sulla posizione del dispositivo. Tipicamente - così sarà per l'esempio che seguirà - tale ruolo viene svolto dall'Activity che pertanto dovrà implementare l'interfaccia LocationListener.

Tale operazione comporterà l'implementazione obbligatoria di quattro metodi astratti:

  • onStatusChanged: riferisce lo stato del provider di localizzazione che stiamo utilizzando. Gli stati possibili sono tre, identificati da apposite costanti intere: TEMPORARILY_UNAVAILABLE (temporaneamente non disposnibile), OUT_OF_SERVICE (fuori servizio), AVAILABLE (disponibile);
  • onProviderDisabled: notifica che il provider è stato disabilitato. Esempio comune: la disattivazione del GPS sul proprio device;
  • onProviderEnabled: notifica opposta alla precedente: il provider è stato appena abilitato dall'utente sul dispositivo;
  • onLocationChanged è invece il metodo centrale del listener, quello che riceve le informazioni di localizzazione reperite sotto forma di un oggetto di classe Location

Il modo in cui la localizzazione entrerà nel nostro progetto Android seguirà dei passi ben precisi. In sostanza, recupereremo un riferimento del LocationManager e gli chiederemo di fornirci aggiornamenti periodici (in base alle condizioni da noi dettate) sulla posizione del dispositivo. Tutte le informazioni che recupereremo saranno impacchettate all'interno di un oggetto Location.

La classe Location rappresenta il tipo di nodo informativo centrale al sistema di localizzazione Android. Contiene necessariamente latitudine e longitudine, reperibili mediante i metodi getLatitude e getLongitude. Opzionalmente, può contenere altre informazioni come la velocità (getSpeed), informazione oraria (getTime), orientamento (getBearing), l'accuratezza in metri (getAccuracy).

Inoltre contiene un paio di metodi utili per calcolare le distanze:

  • distanceTo : calcola la distanza tra l'oggetto ed un altro passato come parametro
  • distanceBetween :  è un metodo statico utilizzabile per calcolare la distanza tra due coppie di valori latitudine/longitudine.

Ulteriori informazioni su metodi, proprietà e tipologia dei parametri coinvolti in merito alla classe Location sono reperibili sulla documentazione ufficiale Android.

Uno sguardo all'applicazione d'esempio

L'esempio è molto semplice. Nella sua semplicità riesce però a mostrare l'applicazione dei concetti espressi sinora, in un'Activity che localizza effettivamente, a livello geografico, la posizione del dispositivo.

Nel layout vedremo apparire una semplice stringa che ci comunicherà la nostra latitudine e longitudine con una frase di questo tipo: "Ci troviamo in coordinate (41.885567, 12.566800)".

I metodi che troveremo all'interno dell'Activity sono di due tipologie:

  • metodi del ciclo di vita dell'Activity. Vedremo onCreate, onResume, onPause il cui compito sarà attivare e disattivare l'interazione con il LocationManager;
  • metodi obbligatori per l'implementazione dell'interfaccia LocationListener. Tra questi, in particolare in onLocationChanged, sarà mostrato l'utilizzo dei dati offerti dai meccanismi di localizzazione.

Questo il codice dei metodi che gestiscono il ciclo di vita:

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

    @Override
    protected void onResume()
    {
        super.onResume();
        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
       if (!locationManager.isProviderEnabled(providerId))
       {
           Intent gpsOptionsIntent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
           startActivity(gpsOptionsIntent);
       }
        else
            locationManager.requestLocationUpdates(providerId, MIN_PERIOD, MIN_DIST, this);
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        locationManager.removeUpdates(this);
    }

Il metodo onCreate non fa nulla di speciale. Indica solo all'Activity il layout da utilizzare. L'aspetto grafico dell'activity è peraltro semplicissimo, contiene solo una TextView in cui verranno riportate le coordinate individuate. Il file del layout è /res/layout/activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="In attesa di essere localizzati..."
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="25sp"
        android:id="@+id/locationText"/>

</RelativeLayout>

I metodi onResume e onPause fanno qualcosa di più interessante. La nostra Activity ha la necessità di registrarsi presso il LocationManager per richiedere aggiornamenti periodici sulla posizione. Il momento migliore per farlo è il metodo onResume in quanto individua l'istante in cui l'Activity sta iniziando ad interagire con l'utente.

Quando ciò non serve più, quindi al momento in cui l'Activity viene messa a riposo (metodo onPause), è il caso di annullare la registrazione per gli aggiornamenti presso il LocationManager. L'attivazione degli aggiornamenti avviene con la seguente riga di codice (presente in onResume):

locationManager.requestLocationUpdates(providerId, MIN_PERIOD, MIN_DIST, this);

I valori passati al metodo rappresentano rispettivamente: la stringa indicante il tipo di provider (nel nostro esempio è il GPS), MIN_PERIOD rappresenta il tempo minimo in millisecondi che deve intercorrere tra due aggiornamenti, MIN_DIST invece indica la distanza in metri minima che deve essere percorsa affinchè si abbia un nuovo aggiornamento.

Il quarto elemento, qui valorizzato a this, indica quale oggetto svolge il ruolo di LocationListener, in questo caso è l'Activity stessa.

I parametri passati a requestLocationUpdates derivano dai membri privati definiti nell'Activity, la cui definizione è questa:

public class MainActivity extends AppCompactActivity implements LocationListener
{
    private String providerId = LocationManager.GPS_PROVIDER;
    private LocationManager locationManager=null;
    private static final int MIN_DIST=20;
    private static final int MIN_PERIOD=30000;
    ...
}

Sempre in onResume si nota che prima di richiedere gli aggiornamenti periodici si controlla lo stato del provider. Qualora il GPS fosse disattivato non possiamo abilitarlo noi di iniziativa ma dobbiamo chiedere all'utente di farlo. A ciò serve l'Intent che apre la pagina delle Settings del dispositivo alla pagina della localizzazione:

if (!locationManager.isProviderEnabled(providerId))
       {
           Intent gpsOptionsIntent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
           startActivity(gpsOptionsIntent);
       }

La disattivazione degli aggiornamenti viene mostrata in onPause e lo si fa richiedendolo al LocationManager:

locationManager.removeUpdates(this);

L'implementazione dell'interfaccia LocationListener richiede l'implementazione dei quattro metodi:

    @Override
    public void onLocationChanged(Location location)
    {
        updateGUI(location);
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle)
    { }

    @Override
    public void onProviderEnabled(String s)
    { }

    @Override
    public void onProviderDisabled(String s)
    {  }

L'unico a cui si è dato un corpo significativo è onLocationChanged all'interno del quale viene richiamato un metodo privato, updateGUI, che aggiorna l'interfaccia utente:

private void updateGUI(Location location)
    {
        double latitude=location.getLatitude();
        double longitude=location.getLongitude();
        String msg="Ci troviamo in coordinate ("+latitude+","+longitude+")";
        TextView txt= (TextView) findViewById(R.id.locationText);
        txt.setText(msg);
    }

Dell'oggetto Location usiamo solo i due metodi più importanti, getLatitude e getLongitude. Si potrebbero ricavare molte informazioni ancora ma ci accontentiamo della posizione per poter indicare all'utente "dove si trova" nel mondo.

E poi?

Quanto visto e sperimentato in questo tutorial non è che l'inizio dello studio della localizzazione su dispositivi Android. Molti sono gli argomenti direttamente e indirettamente collegati, tra i quali alcuni rivestono probabilmente una maggiore rilevanza tanto da poter essere consigliati come immediati approfondimenti:

  • il geocoding rappresenta il meccanismo di conversione tra indirizzi e coordinate geografiche o viceversa (quest'ultimo detto reverse geocoding). E' una necessità, oltre che una curiosità, che si manifesta abbastanza presto nel programmatore. Nel framework Android esiste una classe apposita, Geocoder, che si occupa di realizzare questo processo;
  • le Location API, fornite da Google, come alternativa a quello che abbiamo visto sinora per creare applicazioni location-aware. Prima di avventurarci nel tema però è opportuno che si abbia almeno un'infarinatura su come si interagisce con i servizi Google e cosa sono i Google Play Services;
  • altro argomento fortemente collegato alla localizzazione e che interessa molto programmatori e utenti sono le mappe di Google, conosciutissime. Anche lo studio di questo argomento richiede però come prerequisito la dimestichezza con i Google Play Services.

--

Autore: Giuseppe Maggi
Ingegnere Informatico e docente, da diversi anni, di informatica professionale in centri di formazione torinesi. Nonostante le necessità portino a trattare varie tecnologie, dal C/C++ al .NET, dal web in HTML/CSS/jQuery a Linux, la predilezione resta sempre per il mondo Java ed i suoi vari ambiti di utilizzo, tra cui, ovviamente, Android. 

Tipo/Autore: Pubblicato da: CorsoAndroid.it

© 2011-2024 CorsoAndroid.it - Tutti i diritti riservati. Corso Base Android per rompere il ghiaccio Creare app per android
NB: Tutti i marchi citati sono di proprietą dei rispettivi proprietari. Android is a trademark of Google Inc.