Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Google Maps

Come integrare una mappa interattiva all'interno di un'app Android, sfruttando le API fornite da Google ed i servizi di Google Maps.
Come integrare una mappa interattiva all'interno di un'app Android, sfruttando le API fornite da Google ed i servizi di Google Maps.
Link copiato negli appunti

Le mappe di Google sono diventate il linguaggio visivo universale per descrivere aree geografiche. Tracciano luoghi di ogni parte del mondo, sia nelle
caratteristiche fisiche del territorio che in quelle urbanistiche, con la ricchezza di tantissime informazioni stradali e di interesse economico e
socio-culturale. Nel Web sono onnipresenti, ed anche le app Android sembrano spesso non poterne fare a meno.

Questo articolo vuole guidare il programmatore in tutte le fasi del processo di integrazione di una GoogleMap all’interno un layout,
culminando in un esempio che visualizza una mappa con immagini satellitari centrata attorno al Duomo di Milano.

Il risultato che otterremo è visibile in figura:

Il monumento è indicato da un marker, il segnaposto a goccia di colore rosso che è talmente diffuso e caratteristico da far parte del logo
ufficiale di Google Maps.

Nozioni preliminari

Noteremo presto che il processo di integrazione ed utilizzo delle Google Maps sarà relativamente semplice: basterà infatti predisporre un layout e
richiamarlo dal codice Java aggiungendo alcune configurazioni.

Il motivo di questa facilità è il supporto offerto dai Google Play Services. Per seguire bene quanto illustrato sarà necessario
capitalizzare i concetti spiegati nelle lezioni precedenti di questa guida.

Pertanto, per iniziare la sperimentazione delle GoogleMaps il programmatore dovrà trovarsi in possesso dei seguenti prerequisiti:

  • libreria dei Google Play Services già installata nel progetto Android;
  • un progetto Google già disponibile, creato tramite la Google Developers Console;
  • una chiave Public Access generata nel proprio progetto Google e riferita al package Java che verrà utilizzato per realizzare l'app. Al
    momento, quindi, non sarà necessaria alcuna autorizzazione OAuth.

AndroidManifest.xml, le configurazioni necessarie

Sarà fondamentale configurazione configurare correttamente il file manifest. In questo paragrafo, vedremo punto per punto tutto ciò di cui abbiamo bisogno.

Come ogni forma di comunicazione particolare, avremo bisogno di aggiungere le opportune permission.

Tre sono assolutamente necessarie:

  • android.permission.INTERNET: indispensabile per ricevere i dati dai server di Google;
  • android.permission.ACCESS_NETWORK_STATE: servirà per controllare lo stato della Rete ed appurare la presenza di una connessione Internet prima di inviare
    richieste;
  • android.permission.WRITE_EXTERNAL_STORAGE
    : necessaria per permettere la cache di dati nello storage esterno del dispositivo.

Non formalmente obbligatorie ma fortemente consigliate sono le permission relative alla geolocalizzazione. Servono nel caso in cui si vogliano utilizzare le
funzionalità di rilevamento della posizione incluse nelle mappe o implementate dal programmatore. Le alternative sono due:

  • android.permission.ACCESS_COARSE_LOCATION: per la localizzazione mediante reti mobili e WiFi (meno precisa, ma col vantaggio di non richiedere l'attivazione del GPS);
  • android.permission.ACCESS_FINE_LOCATION: utilizzando il GPS (più accurata, ma che spesso può richiedere un eccessivo consumo della batteria).

Lee mappe di Google sfruttano la libreria grafica OpenGL ES version 2, in assenza della quale non possono essere visualizzate. Per rendere limitare la compatibilità dell'app ai soli
dispositivi che ne sono dotati (che oggi sono la maggior parte), dobbiamo inserire nel manifest il seguente nodo:

<uses-feature
	android:glEsVersion="0x00020000"
	android:required="true"/>

In questo modo, quando pubblicheremo l'app su Google Play Store, essa non sarà mostrata nei risultati di ricerca di dispositivi che non possiedono la versione 2 di OpenGL.

Infine aggiungeremo ancora due nodi <metadata>. Il primo riguarderà la versione di Google Play Services, il secondo servirà per
contenere la chiave prodotta nella Google Developers Console.

<meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
<meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="WSzaSyDYCb9QTCpAI8qENOouBlqNjpH7xABtUn6" />

Riepilogando, quello che segue è un file manifest completo. Lo si può utilizzare come template, a patto di modificare:

  • l'attributo package del nodo manifest;
  • la propria API KEY nel metadata opportuno.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="it.html.googleservices.maps" >
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="INSERISCI QUI LA TUA API KEY" />
    </application>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Inserire una mappa in un layout

Dopo le fasi di configurazione fin qui descritte (integrazione dei GooglePlayServices, configurazione del progetto Google con relativa creazione della chiave
e definizione dei parametri opportuni nel file manifest), l'inserimento di una GoogleMap in un layout sarà pressochè immediato.

Useremo un particolare tipo di Fragment che presenta già una mappa integrata: il MapFragment.

Sarà sufficiente inserirlo nel layout che utilizzeremo (assumiamo il file /res/layout/activity_maps.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

A questo punto non resta che richiamare il layout ed associarlo ad una Activity, all'interno del metodo onCreate:

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

Così facendo, vedremo apparirire una mappa all'interno della nostra interfaccia. Non avendo specificato una configurazione particolare, inizialmente sarà mostrata una panoramica generale del mondo; la mappa potrà comunque essere utilizzata in ogni aspetto, con gesture e rotazioni per la navigazione.

L'oggetto GoogleMap

Un'operazione che comunque si rende necessaria è la configurazione a runtime della mappa. Ciò viene effettuato in Java e si basa sull'invocazione di metodi
della classe GoogleMap.

Nel seguente codice vediamo che, oltre al metodo onCreate, sono presenti:

  • un membro privato di classe GoogleMap;
  • un metodo privato, initMap, in cui viene recuperato un riferimento alla mappa da conservare per configurazioni future.

public class MapsActivity extends Activity {
    private GoogleMap googleMap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
    }
    private void initMap() {
        if (googleMap == null) {
            googleMap = ((MapFragment) getFragmentManager().findFragmentById(
                    R.id.map)).getMap();
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        initMap();
    }
}

GoogleMap è la classe centrale per l'interazione con una mappa. Possiede molti metodi, tramite i quali assegneremo configurazioni ed innescheremo azioni.
Eccone alcuni tra i più utili:

  • setMapType: specifica la tipologia di mappa. Google ne offre vari tipi, alcuni rivolti alle caratteristiche del territorio, altri orientati agli
    aspetti urbani e logistici;
  • animateCamera e movecamera: entrambi permettono di muovere l'inquadratura sulla mappa orientandola su altre collocazioni geografiche specificate mediante
    le coordinate di latitudine e longitudine;
  • setMyPositionEnabled: abilita un pulsante sullo schermo che, se premuto, ordina alla mappa di inquadrare il punto in cui si trova l'utente. Per la
    localizzazione saranno sfruttate funzionalità interne alla mappa ed occorreranno le necessarie permission;
  • addMarker: colloca un Marker in una determinata posizione.

Tipi di mappa

Le GoogleMap possono essere visualizzate in diversi modi. Possiamo decidere quale utilizzare tramite il metodo setMapType, cui passeremo il
valore di una costante specifica inclusa sempre nella classe GoogleMap:

  • MAP_TYPE_NORMAL: è la tipica mappa stradale. Mostra informazioni sulle vie nonché alcune costruzioni umane ed elementi naturali significativi (fiumi,
    alture, etc...);
  • MAP_TYPE_SATELLITE: mostra foto satellitari escludendo qualunque altra indicazione;
  • MAP_TYPE_HYBRID: rappresenta una via di mezzo tra le due precedenti opzioni. Visualizza immagini satellitari arricchite da annotazioni stradali;
  • MAP_TYPE_TERRAIN: mappa topografica, focalizzata principalmente sulle caratteristiche fisiche del territorio;
  • MAP_TYPE_NONE: non mostra alcuna mappa, solo una griglia vuota.

La figura che segue, tratta dalla documentazione ufficiale Google, mostra un confronto tra tre tipi di mappe, rispettivamente da sinistra: normal, hybrid e
terrain.

Per esempio, il seguente codice Java recupera il riferimento alla mappa Google, e ne imposta il tipo:

GoogleMap googleMap = ...;
...
...
googleMap.setMapType(MAP_TYPE_HYBRID);

Cambiare la posizione ed aggiungere Markers

Molto spesso risulta utile centrare una mappa in un luogo specifico, individuato mediante le coordinate terrestri, e magari marcarlo con un apposito
segnaposto (marker).

Esiste una classe apposita per definire una posizione, ovvero LatLng. Il suo costruttore accetta due numeri double, che definiscono le coordinate.

A titolo di esempio, proviamo ad inserire un membro privato di questo tipo nell'Activity:

private LatLng DUOMO_DI_MILANO=new LatLng(45.464143, 9.191910);

Avremo così definito un oggetto LatLng che localizza il Duomo di Milano.

Il metodo initMap può essere così modificato:

private void initMap() {
        if (googleMap == null) {
            googleMap = ((MapFragment) getFragmentManager().findFragmentById(
                    R.id.map)).getMap();
            googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
            }
            CameraPosition posizioneDelDuomo = new CameraPosition.Builder().target(
                    DUOMO_DI_MILANO).zoom(16).build();
            googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(posizioneDelDuomo));
            MarkerOptions marker = new MarkerOptions().position(DUOMO_DI_MILANO);
            googleMap.addMarker(marker);
    }

La mappa viene ricollocata con il metodo moveCamera, che chiede in input un oggetto CameraUpdate prodotto tramite apposita Factory. E' interessante che la vera
configurazione della camera venga effettuata a mezzo di un Builder, che costruisce un oggetto CameraPosition richiedendo il target (impostato con il membro
DUOMO_DI_MILANO) ed un valore di zoom pari a 16.

Il Marker, analogamente, viene prima definito mediante un oggetto MarkerOptions, e successivamente assegnato alla mappa sfruttando il metodo addMarker.

Il risultato di tale configurazione è quello mostrato nella figura all'inizio dell'articolo.

Ti consigliamo anche