Lezione 15 Location e mappe



Documenti analoghi
La geolocalizzazione

Sistemi Mobili e Wireless Android Localizzazione utente

Tale attività non è descritta in questa dispensa

Eclipse - Nozioni Base

Office 2007 Lezione 02. Le operazioni più

MOBILE WEB DESIGN TUTORIAL ANDROID METAIO AUGMENTED REALITY

Capitolo 3. L applicazione Java Diagrammi ER. 3.1 La finestra iniziale, il menu e la barra pulsanti

POSTA ELETTRONICA Per ricevere ed inviare posta occorrono:

PROGETTO PER LA TRASMISSIONE DOCUMENTI RELATIVI ALL APPROVAZIONE DELLE MANIFESTAZIONI IN FORMA DIGITALE

Android. Android03: Ciclo di vita di una Activity.

Visual basic base Lezione 01. L'ambiente di sviluppo

Guida all uso di Java Diagrammi ER

BDCC : Guida rapida all utilizzo

STAMPA UNIONE DI WORD

Utilizzo della Intranet, forum privati Soci e Staff

L ambiente di sviluppo Android Studio

FtpZone Guida all uso

Guida informatica per l associazione #IDEA

Per chi ha la Virtual Machine: avviare Grass da terminale, andando su Applicazioni Accessori Terminale e scrivere grass

Installazione e Configurazione della strumentazione necessaria. Antonio Gallo info@laboratoriolibero.com

Invio SMS. DM Board ICS Invio SMS

Guida alla configurazione della posta elettronica dell Ateneo di Ferrara sui più comuni programmi di posta

SOMMARIO... 3 INTRODUZIONE...

Il calendario di Windows Vista

Guida alla registrazione on-line di un DataLogger

COME FARE UNA RICHIESTA DI ASSISTENZA ON LINE (AOL)

Biblioteca di Cervia NOZIONI BASE DI INFORMATICA

STUDIUM.UniCT Tutorial per gli studenti

PROCEDURA INVENTARIO DI MAGAZZINO di FINE ESERCIZIO (dalla versione 3.2.0)

Product Shipping Cost Guida d'installazione ed Utilizzo

MOCA. Modulo Candidatura. [Manuale versione 1.0 marzo 2013]

Alla scoperta della nuova interfaccia di Office 2010

Sistemi Mobili e Wireless Android Primi passi

Integrazione InfiniteCRM - MailUp

Office 2007 Lezione 08

Esercizio data base "Biblioteca"

Airone Gestione Rifiuti Funzioni di Esportazione e Importazione

Progetto di Ingegneria del Software 2. SWIMv2

1.0 GUIDA PER L UTENTE

MANUALE DI GESTIONE BANCA DATI INTERNET ED AREA FTP PER ESPERTI DI RAZZA

Come masterizzare dischi con Nero 11

Guida all uso delle Web View su ios

CdL in Medicina Veterinaria - STPA AA

. A primi passi con microsoft a.ccepss SommarIo: i S 1. aprire e chiudere microsoft access Start (o avvio) l i b tutti i pro- grammi

Installazione & Configurazione Php e MySQL su Mac Os X. Php

Blue s Hotel Pro Il software che hai sempre desiderato per il tuo Hotel!

L amministratore di dominio

Q U E S T U R A di V A R E S E Ufficio di Gabinetto

LCMobile Restaurant. Guida su come usare il software per palmare LCMobile Restaurant.

Se avete domande scrivetemi a vtornar@libero.it

MANUALE PARCELLA FACILE PLUS INDICE

MANUALE D'USO DEL PROGRAMMA IMMOBIPHONE

- Il sito dedicato alle associazioni no-profit di Milano e provincia

Uso di base delle funzioni in Microsoft Excel

Configuration Managment Configurare EC2 su AWS. Tutorial. Configuration Managment. Configurare il servizio EC2 su AWS. Pagina 1

Come utilizzare il sito Verdeazzurroligure

Capitolo 20: Render. Avviate MasterChef dall icona presente sul vostro Desktop.

Utilizzo della APP IrriframeVoice. Versione 1.0 maggio 2015

File, Modifica, Visualizza, Strumenti, Messaggio

STAMPA DI UNA PAGINA SEMPLICE

Accise Settore Prodotti Alcolici Manuale d uso

GUIDA PER LA CONNESSIONE ALLA RETE WIRELESS E ALL USO DEL SERVIZIO BERGAMO Wi-Fi

PIANO DI TUTELA DELLE ACQUE DELLA SICILIA (di cui all'art. 121 del Decreto Legislativo 3 aprile 2006, n 152)

NOTE OPERATIVE. Prodotto Inaz Download Manager. Release 1.3.0

11/02/2015 MANUALE DI INSTALLAZIONE DELL APPLICAZIONE DESKTOP TELEMATICO VERSIONE 1.0

MANUALE D USO DELLA PIATTAFORMA ITCMS

Registratori di Cassa

Cominciamo dalla barra multifunzione, ossia la struttura a schede che ha sostituito la barra dei menu e la barra delle icone (Figura 1).

INTERNET EXPLORER Guida introduttiva CAPITOLO 1 Fig. 1

Uso dei modelli/template

NAVIGARE FRA LE PRATICHE...

Come utilizzare il nuovo HelpDesk Maggioli Informatica

NUOVA PROCEDURA COPIA ED INCOLLA PER L INSERIMENTO DELLE CLASSIFICHE NEL SISTEMA INFORMATICO KSPORT.

GHPPEditor è un software realizzato per produrre in modo rapido e guidato un part program per controlli numerici Heidenhain.

I M P O S T A R E U N A C C O U N T D I P O S T A C O N M O Z I L L A T H U N D E R B I R D

Tricks & Tips. [Access] Tutorial - ActiveX - Controllo Tree View. - Michele de Nittis - Versione: 1 Data Versione: venerdì 30 agosto 2002

GESCO MOBILE per ANDROID

Il web server Apache Lezione n. 3. Introduzione

GateManager. 1 Indice. tecnico@gate-manager.it

Identificare le diverse parti di una finestra: barra del titolo, barra dei menu, barra degli strumenti, barra di stato, barra di scorrimento.

Introduzione. Descrizione. FRITZ!APP Fon

Utilizzo del Terminalino

PSNET UC RUPAR PIEMONTE MANUALE OPERATIVO

HikVision. Creazione e gestione di collegamenti con sistemi TVCC HikVision DVR/Network Camera

PIATTAFORMA DOCUMENTALE CRG

FINE ANNO BOLLE / FATTURE PER E/SATTO

Manuale Operativo per l utilizzo della piattaforma E-Learning@AQ. Versione 1.1

Your Detecting Connection. Manuale utente.

MANUALE UTENTE INFOCAR REPAIR ACCESSO SMARTPHONE/TABLET

FASI DA ESEGUIRE ON-LINE

Moduli (schede compilabili) in Word Esempio: scheda di alimentazione per un degente

MANUALE EDICOLA 04.05

Manuale Operativo Beneficiario Sfinge2020

Inoltro telematico delle pratiche SUAP

Excel. A cura di Luigi Labonia. luigi.lab@libero.it

CARICAMENTO IN ASCOT DEL FASCICOLO ELETTORALE ELETTRONICO

Guida in linea di Websense Secure Messaging

GPS MANAGER Manuale Utente

Manuale Utente. Gestione Richieste supporto Data Warehouse. Della Ragioneria Generale dello Stato. Versione 1.0. Roma, Ottobre 2015

Transcript:

A cura di Carlo Pelliccia La diffusione delle applicazioni location-based è certamente uno dei maggiori contributi resi dalle piattaforme mobili alla storia dell informatica. Un applicazione o un servizio possono definirsi location-based quando lavorano con il posizionamento geografico dell utente e dei luoghi di suo interesse. I software di navigazione satellitare, ad esempio, sono delle applicazioni location-based, così come lo sono tutte quelle app che mostrano dove l utente si trova e cosa c è nei suoi paraggi. Sono location-based anche quelle applicazioni che permettono di interagire con i social network geolocalizzati, come Foursquare o il servizio Places di Facebook. Google è stato un pioniere dei servizi location-based: Google Maps e Google Earth hanno spianato la strada ad una nuova generazione di applicazioni basate sulla geografia e sul posizionamento. Con Android, naturalmente, Google non smette di innovare. È con l avvento dei dispositivi mobili, infatti, che le applicazioni location-based possono finalmente sfruttare a pieno tutte le potenzialità dei servizi geolocalizzati. In questa lezione scopriremo come è facile mostrare mappe, cercare luoghi ed interagire con il ricevitore GPS del telefono. Location manager e provider Gli smartphone implementano solitamente uno o più meccanismi di localizzazione dell utente. Il GPS è quello più noto ed utilizzato, ma non è l unico meccanismo disponibile. I dispositivi di ultima generazione, infatti, sono in grado di localizzare la propria posizione verificando le reti GSM e Wi-Fi disponibili nei paraggi (in questo caso si parla di localizzazione network-based). Si tratta di un meccanismo di localizzazione meno accurato rispetto al GPS, ma lo stesso affidabile quando è sufficiente conoscere l area dove si trova l utente, e non si ha bisogno di calcolare la sua posizione precisa. Android offre un interfaccia di programmazione che astrae dal meccanismo di localizzazione utilizzato in sottofondo. Tale interfaccia è offerta sotto forma di servizio di sistema. Dall interno di un attività i servizi di sistema possono essere recuperati usando il metodo getsystemservice(). Il metodo richiede in argomento l identificativo del servizio di sistema desiderato. Gli ID dei servizi di sistema sono conservati in alcune costanti. Quello per il servizio di localizzazione è riportato nella costante Global Positioning System GPS è una di quelle sigle che tutti conoscono ma pochi comprendono. GPS sta per Global Positioning System, ossia sistema di posizionamento globale. Si tratta di un sistema costituito da una serie di satelliti artificiali in orbita intorno al pianeta. Ciascun satellite trasmette ciclicamente dei messaggi verso la superficie. I messaggi contengono il segnale orario e delle informazioni sulle orbite percorse. Il ricevitore GPS ascolta questi messaggi e li elabora. In base al ritardo dei segnali e ai contenuti dei messaggi, il ricevitore è in grado di calcolare la propria distanza da ciascun satellite. Nel momento in cui il ricevitore riesce ad agganciare il segnale di quattro o più satelliti, diventa possibile applicare un calcolo matematico simile, nel principio, alla triangolazione. In questa maniera, il ricevitore può determinare la propria posizione sul globo terracqueo, esprimendola in termini di latitudine e longitudine. Più sono i satelliti di cui il dispositivo riceve il segnale, più è accurata la posizione calcolata. LOCATION_SERVICE. Il metodo getsystemservice(), una volta recuperato il servizio, lo restituisce sotto forma di semplice Object. È dunque necessario eseguire un casting verso la classe reale del servizio, che in questo caso è android.location.locationmanager. Riassumendo, dall interno di un attività, il servizio di localizzazione si recupera alla seguente maniera: LocationManager locationmanager = (LocationManager) getsystemservice(location_service); I meccanismi di localizzazione disponibili sono classificati come provider. I due provider discussi in precedenza sono identificati con due costanti:

LocationManager.GPS_PROVIDER Identifica il provider collegato al ricevitore GPS del telefono. LocationManager.NETWORK_PROVIDER Identifica il provider che localizza in maniera approssimativa il telefono basandosi sulle reti raggiungibili. Prima di usare uno di questi due provider, bisogna verificare che sia supportato dal telefono che esegue l applicazione. Per farlo si può richiamare il metodo getprovider() di LocationManager. Il metodo restituisce null se il provider non è disponibile, mentre restituisce un risultato di tipo android.location.locationprovider nel caso lo sia. Ad esempio: LocationProvider gpsprovider = locationmanager.getprovider(locationmanager.gps_provider); if (gpsprovider == null) { // GPS non disponibile else { // GPS disponibile Gli oggetti LocationProvider, quando disponibili, forniscono informazioni sul provider richiesto, come la sua accuratezza e le caratteristiche supportate. Dopo essersi accertati che un provider è disponibile, altrettanto importante è controllare che sia anche attivo. L utente, infatti, potrebbe averlo disabilitato dalle impostazioni del telefono. Figura 1 Dalle impostazioni di sistema è possibile abilitare o disabilitare i servizi di localizzazione integrati. Per questo bisogna sempre verificare che siano attivi, prima di utilizzarli. L abilitazione di un provider può essere controllata con il metodo isproviderenabled() di LocationManager. Ad esempio: boolean gpsenabled = locationmanager.isproviderenabled(locationmanager.gps_provider); Prima di usare uno dei due provider, quindi, è meglio controllarne lo stato, in modo da suggerire all utente di abilitarlo prima di procedere. Ancora un importante avvertimento: per utilizzare correttamente i servizi di localizzazione, è necessario che l applicazione, nel proprio manifest, richieda l uso dei permessi android.permission.access_coarse_location (per la localizzazione basata sui network) e/o android.permission.access_fine_location (per la localizzazione GPS): <?xml version="1.0" encoding="utf-8"?> <manifest...> Pagina 2

... <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_fine_location" />... <application...>... </application> </manifest> Dove mi trovo? Passiamo a vedere come è possibile recuperare la posizione fornita da uno dei provider previsti. Le misurazioni vengono rappresentate mediante oggetti di tipo android.location.location. I principali e più importanti metodi messi a disposizione da questa classe sono: public long gettime() Restituisce la data in cui l informazione è stata calcolata, come UNIX timestamp (il numero di millisecondi trascorsi dal 1 Gennaio 1970 alle ore 00:00:00 GMT) public double getlatitude() Restituisce la misura di latitudine. public double getlongitude() Restituisce la misura di longitudine. public boolean hasaltitude() Restituisce true se la misurazione comprende anche un dato di altitudine. public double getaltitude() Se disponibile, restituisce la misura di altitudine. public boolean hasspeed() Restituisce true se la misurazione comprende anche un dato di velocità. public float getspeed() Se disponibile, restituisce la misura di velocità. L unità di misura è m/s (metri al secondo). Una maniera semplice e diretta per ottenere una misurazione è domandarla al LocationManager, servendosi del metodo getlastknownlocation(). Il metodo richiede l ID del provider da interrogare e restituisce un oggetto Location. Ad esempio: Location location = locationmanager.getlastknownlocation(locationmanager.gps_provider); Si faccia attenzione al fatto che getlastknownlocation() non calcola la posizione del telefono nel momento in cui lo si richiama: il metodo si limita a restituire l ultima misurazione disponibile per il provider richiesto. Può accadere che un provider sia stato disabilitato in un posto e riabilitato poi a chilometri di distanza, e che quindi la sua ultima misurazione sia completamente inservibile. Per avere dati freschi da uno dei provider, gli si deve esplicitamente chiedere di inviarli non appena disponibili. Il metodo utile per farlo è: public void requestlocationupdates( String provider, long mintime, float mindistance, LocationListener listener) Pagina 3

Gli argomenti hanno il seguente scopo: provider è l ID del provider (ad esempio LocationManager.GPS_PROVIDER o LocationManager.NETWORK_PROVIDER). mintime è il numero di secondi minimo che deve intercorrere tra una misurazione e la successiva. Con questo parametro si può evitare che dal provider vengano troppe informazioni, chiedendo di non mandare una nuova lettura se non è passato almeno un certo numero di secondi. mindistance è la distanza minima, in metri, che deve esserci tra una misurazione e la successiva. Anche in questo caso l argomento serve per filtrare le letture del provider ed evitare che da questo vengano troppe informazioni, chiedendo di non mandare una nuova lettura se non si è riscontrato uno spostamento di un certo numero di metri. listener è l oggetto, di tipo android.location.locationlistener, su cui verranno notificate tutte le misurazioni effettuate e filtrate secondo i parametri precedenti. Ad esempio: locationmanager.requestlocationupdates(locationmanager.gps_provider, 5, 1, mylocationlistener); Con questa richiesta si sottoscrive il provider GPS e si ricevono le letture e gli eventi provenienti da questo. Le letture, in particolar modo, saranno filtrate: solo se lo spostamento equivale ad almeno un metro, e comunque non più di una notifica ogni cinque secondi. Letture ed eventi saranno segnalati sull oggetto mylocationlistener, che naturalmente deve implementare l interfaccia LocationListener. L implementazione di LocationListener richiede la definizione dei seguenti metodi: public void onstatuschanged(string provider, int status, Bundle extras) Notifica un cambio di stato nel provider in argomento. Il nuovo stato (argomento status) può essere: LocationProvider.OUT_OF_SERVICE, se il provider è andato fuori servizio; LocationProvider.TEMPORARILY_UNAVAILABLE, se il provider è diventato temporaneamente non disponibile; LocationProvider.AVAILABLE, se il provider è tornato disponibile. public void onproviderenabled(string provider) Notifica che il provider indicato in argomento è stato abilitato. public void onproviderdisabled(string provider) Notifica che il provider indicato in argomento è stato disabilitato. public void onlocationchanged(location location) Notifica la lettura di una nuova posizione. Una volta che non occorre più conoscere le misurazioni provenienti dal location provider selezionato, è meglio annullare la sottoscrizione svolta in precedenza, agendo sul LocationManager con il metodo removeupdates(): Pagina 4

locationmanager.removeupdates(mylocationlistener); Programmazione Android LocationDemo Forti delle nozioni appena acquisite, andiamo a realizzare un applicazione che le metta in pratica. Chiameremo l applicazione LocationDemo. Definiamone il layout nel file res/layout/main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content"> <TableLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <TableRow android:padding="5px"> <TextView android:text="provider" android:padding="5px" <TextView android:id="@+id/provider" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="disponibile" android:padding="5px" <TextView android:id="@+id/available" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="abilitato" android:padding="5px" <TextView android:id="@+id/enabled" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="timestamp" android:padding="5px" <TextView android:id="@+id/timestamp" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="latitudine" android:padding="5px" <TextView android:id="@+id/latitude" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="longitudine" android:padding="5px" <TextView android:id="@+id/longitude" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="altitudine" android:padding="5px" <TextView android:id="@+id/altitude" android:padding="5px" </TableRow> <TableRow android:padding="5px"> <TextView android:text="velocità" android:padding="5px" <TextView android:id="@+id/speed" android:padding="5px" </TableRow> </TableLayout> </ScrollView> </LinearLayout> Si tratta di un layout molto semplice, che realizza una tabella all interno della quale andremo ad annotare i dati provenienti dal provider GPS. Pagina 5

Figura 2 LocationDemo è un app che si collega al ricevitore GPS e ne mostra le letture sul display. Andiamo all attività LocationDemoActivity, che realizza la logica del progetto appena descritta: package example.locationdemo; import java.util.date; import android.app.activity; import android.location.location; import android.location.locationlistener; import android.location.locationmanager; import android.location.locationprovider; import android.os.bundle; import android.widget.textview; public class LocationDemoActivity extends Activity { private String providerid = LocationManager.GPS_PROVIDER; private LocationListener mylocationlistener = new LocationListener() { ; public void onstatuschanged(string provider, int status, Bundle extras) { if (status == LocationProvider.AVAILABLE) { settextviewvalue(r.id.available, "TRUE"); else { settextviewvalue(r.id.available, "FALSE"); public void onproviderenabled(string provider) { settextviewvalue(r.id.enabled, "TRUE"); public void onproviderdisabled(string provider) { settextviewvalue(r.id.enabled, "FALSE"); public void onlocationchanged(location location) { updatelocationdata(location); public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); Pagina 6

protected void onresume() { super.onresume(); settextviewvalue(r.id.provider, providerid); LocationManager locationmanager = (LocationManager) getsystemservice( LOCATION_SERVICE ); LocationProvider provider = locationmanager.getprovider(providerid); if (provider == null) { settextviewvalue(r.id.available, "FALSE"); else { settextviewvalue(r.id.available, "TRUE"); boolean gpsenabled = locationmanager.isproviderenabled(providerid); if (gpsenabled) { settextviewvalue(r.id.enabled, "TRUE"); else { settextviewvalue(r.id.enabled, "FALSE"); Location location = locationmanager.getlastknownlocation( LocationManager.GPS_PROVIDER ); if (location!= null) { updatelocationdata(location); locationmanager.requestlocationupdates(providerid, 5, 1, mylocationlistener); protected void onpause() { super.onpause(); LocationManager locationmanager = (LocationManager) getsystemservice( LOCATION_SERVICE ); locationmanager.removeupdates(mylocationlistener); private void settextviewvalue(int textviewid, String value) { TextView textview = (TextView) findviewbyid(textviewid); textview.settext(value); private void updatelocationdata(location location) { Date timestamp = new Date(location.getTime()); settextviewvalue(r.id.timestamp, timestamp.tostring()); double latitude = location.getlatitude(); settextviewvalue(r.id.latitude, String.valueOf(latitude)); double longitude = location.getlongitude(); settextviewvalue(r.id.longitude, String.valueOf(longitude)); if (location.hasaltitude()) { double altitude = location.getaltitude(); settextviewvalue(r.id.altitude, String.valueOf(altitude)); if (location.hasspeed()) { float speed = location.getspeed(); settextviewvalue(r.id.speed, String.valueOf(speed)); È importante osservare come l utilizzo del servizio di localizzazione sia stato collegato al ciclo di vita dell attività: si sono utilizzati i metodi onresume() e onpause(), rispettivamente, per avviare ed interrompere l utilizzo del servizio. In questa maniera il localizzatore viene invocato solo quando l attività sta occupando il display, e non quando gira in sottofondo. Non resta che mettere tutto insieme in AndroidManifest.xml: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versioncode="1" android:versionname="1.0" package="example.locationdemo"> <uses-permission android:name="android.permission.access_fine_location" /> Pagina 7

<application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".locationdemoactivity" 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> Emulare il GPS Quando si sviluppa un applicazione location-based, come l esempio appena illustrato, ci si scontra con il problema di come eseguirne il test ed il debug. Naturalmente è possibile installare l applicazione su uno smartphone ed andare a farsi un giro a piedi o in automobile, tuttavia questa non è la maniera migliore per test frequenti e debug efficaci. Per nostra fortuna è possibile impostare delle false coordinate geografiche sull emulatore fornito con l SDK. Con Eclipse lo si fa dalla scheda Emulator Control della prospettiva DDMS. È possibile fornire coordinate semplici, oppure caricarne una lista complessa da file di tipo GPX e KML. Figura 3 Con l Emulator Control di Eclipse DDMS è possibile inviare all emulatore false coordinate di localizzazione. Attenzione: se le coordinate inviate tramite l Emulator Control di Eclipse DDMS non funzionano correttamente, provate a chiudere l ambiente e a riavviarlo dopo aver aggiunto le seguenti righe al file eclipse.ini presente nella cartelle di installazione del vostro Eclipse: -Duser.country=US -Duser.language=en Coordinate GPS da riga di comando Se non utilizzate Eclipse, potete fornire false coordinate GPS all emulatore usando la riga di comando. Aprite il prompt dei comandi e connettetevi all emulatore via telnet: telnet localhost <porta> La porta usata dall emulatore è riportata nel titolo della finestra che lo contiene. In genere è 5554 o una cifra molto simile. Lanciate ora il comando: geo fix <longitude> <latitude> Ad esempio: Google Play services per Android geo fix 12.484564 41.91247 Finora abbiamo appreso come accedere al servizio di localizzazione di Android per conoscere la posizione dell utente, ma questo è soltanto l inizio. Una vera e propria applicazione location-based, infatti, fa anche uso di mappe e di altri servizi analoghi. Poiché questo è un terreno in cui Google gioca in casa, abbiamo a nostra disposizione un ottima libreria di classi per l accesso facilitato ai servizi location-based di Mountain View. L accesso a questi servizi è mediato da una serie di classi comprese all interno di una libreria extra chiamata Google Play services. Le libreria non è parte integrante del sistema, e per questo, prima di utilizzarla, è necessario scaricarla ed integrarla nel proprio Android SDK. Potete farlo avviando il Pagina 8

manager del vostro Android SDK ed individuando, nel gruppo Extras, la voce Google Play services. Figura 4 La libreria Google Play services può essere scaricata ed installata usando l Android SDK Manager. Se il pacchetto è Not installed, selezionato e procedete con il download e l installazione. Progetto libreria Dopo aver installato la libreria di Google Play services, tornate alla schermata principale di Eclipse, selezionate la voce di menù File» Import e scegliete l opzione Android» Existing Android Code into Workspace. Figura 5 Avviate la procedura di import di codice Android esistente, selezionando la voce Android» Existing Android Code into Workspace. Così facendo, sarà avviata la procedura di import di codice Android pronto all uso all interno del workspace di Eclipse. Al passo successivo vi sarà chiesto il percorso del progetto da importare. Specificate il percorso che corrisponde, nel vostro caso specifico, a questo pattern: <android sdk>/extras/google/google_play_services/libproject Verrà caricata la lista dei progetti Android riconosciuta al percorso indicato. Dovrebbe quindi comparire la voce google-play-services_lib. Selezionatela. Attivate anche l opzione Copy projects into workspace e confermate il tutto con il tasto Finish. Pagina 9

Figura 6 Come Root Directory, impostate il percorso /extras/google/google_play_services/libproject all interno della vostra installazione dell Android SDK, quindi selezionate il progetto google-play-services_lib ed attivate l opzione Copy projects into workspace. Appena importato, il progetto google-play-services_lib potrebbe presentare qualche errore di compilazione. Di solito avviene perché non è abbinato alla stessa versione di Android che state utilizzando per lo sviluppo delle vostre app. Non fatevi prendere dal panico: potete risolvere facilmente aprendo le proprietà del progetto, selezionando la scheda Android ed impostando nel riquadro Project Build Target la vostra immagine di riferimento del sistema operativo. Google Maps API Key Ancora un passo ci separa dal poter scrivere app capaci di mostrare una mappa: abbiamo bisogno di ottenere una chiave (API key) per l accesso al servizio Google Maps. Per farlo dobbiamo fornire a Google l impronta SHA1 del certificato che utilizziamo per firmare le nostre applicazioni. Eclipse ci può fornire la firma del certificato di debug. La troviamo in una maschera delle preferenze, al percorso Android» Build. Figura 7 Eclipse mostra la forma MD5 e SHA1 del certificato di debug. Pagina 10

Copiate negli appunti la firma SHA1 del certificato di debug. Con il browser, collegatevi ora all indirizzo: https://code.google.com/apis/console/ Autenticatevi con la vostra utenza Google (se non siete già autenticati) ed usate il menù sulla sinistra per creare un nuovo API Project. Figura 8 Create un nuovo API Project, da associare poi al vostro progetto Android. Chiamate il progetto come l applicazione che ci accingiamo a realizzare, cioè MapsDemo. Selezionate la voce Services. Vi sarà presentato il lunghissimo elenco dei servizi per i quali Google offre una API. Localizzate la voce Google Maps Android API v2 ed abilitatela. Dovrete accettare le condizioni del servizio. Figura 9 Nella sezione services abilitate la voce Google Maps Android API v2. Selezionate ora la voce di menù API Access. Da qui azionate il tasto Create new Android key. Nella maschera di creazione della chiave vi sarà richiesto di inserire una o più righe con la firma SHA1 del certificato ed il package delle app che volete abilitare all uso delle API. Usate il carattere punto e virgola per separare i due elementi, ad esempio: BF:4F:BB:40:3C:C9:16:DD:5C:98:2C:E5:36:B5:F8:AA:30:82:FF:48;example.mapsdemoì Pagina 11

Figura 10 Inserite il package dell app Android per la quale si sta generando la chiave. È possibile registrare più certificati o più app: basta usare più di una riga. Se avete un certificato di rilascio, ad esempio, inserite in una seconda riga anche la firma SHA1 di quest ultimo. Android ve la può visualizzare durante la procedura di export di un APK firmato con tale certificato. Ad operazione completata, avrete una nuova entry di tipo Key for Android apps nella lista API Access. Copiate e conservate il valore API key riportato al suo interno. Figura 11 La nuova API key è stata generata e può ora essere utilizzata con l app Android. Configurare l app Possiamo finalmente creare un applicazione Android capace di sfruttare la libreria di Google Maps. In Eclipse, create un nuovo progetto. Chiamatelo MapsDemo, e come package di riferimento mettete example.mapsdemo. Subito dopo averlo creato, visualizzatene le proprietà. Nella sezione Android aggiungete una dipendenza da libreria. Lo si può fare dalla porzione Library, con il tasto Add. Scegliete la libreria importata in precedenza e confermate. Figura 12 Un progetto Android, per sfruttare una libreria importata nel workspace, deve referenziarla esplicitamente nella sezione Android» Library delle proprie preferenze. Pagina 12

Prima di passare al codice XML e Java, dobbiamo adesso aggiungere un paio di cose al manifest dell applicazione. La prima aggiunta da fare riguarda i permessi. Per utilizzate le API di Google Maps dobbiamo creare un permesso apposito, e poi dichiararne esplicitamente l uso: <permission android:name="example.mapsdemo.permission.maps_receive" android:protectionlevel="signature" /> <uses-permission android:name="example.mapsdemo.permission.maps_receive" /> Il permesso creato ha un nome che segue la nomenclatura: <app package>.permission.maps_receive È importante creare ed utilizzare questo tipo di permesso, in quanto i Google Play services e le Google Maps API, per funzionare, si relazionano con le app Play Store e Google Maps (che, infatti, devono essere presenti nel sistema affinché tutto ciò funzioni). La dichiarazione di questo permesso aggiuntivo permette una corretta e sicura comunicazione tra la nostra app e quelle di Google. L accesso alle mappe di Google richiede poi i seguenti permessi: <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="com.google.android.providers.gsf.permission.read_gservices" /> <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_fine_location" /> Il rendering delle mappe richiede poi l uso di OpenGL ES versione 2, di cui non tutti i dispositivi Android sono dotati (alcuni vecchi telefoni potrebbero non supportare questa versione). Perciò aggiungiamo anche l elemento: <uses-feature android:glesversion="0x00020000" android:required="true" /> Ultima operazione da compiere sul manifest è l inserimento della API key generata pochi minuti fa. Va inserita come ultimo elemento della sezione <application> (subito prima di </application>), alla seguente maniera: <meta-data android:name="com.google.android.maps.v2.api_key" android:value="<api KEY QUI>" /> Ricapitoliamo l intero AndroidManifest.xml dell app MapsDemo, dove ogni cosa è stata sistemata al posto giusto: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="example.mapsdemo" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8" android:targetsdkversion="17" /> <permission android:name="example.mapsdemo.permission.maps_receive" android:protectionlevel="signature" /> Pagina 13

<uses-permission android:name="example.mapsdemo.permission.maps_receive" /> <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="com.google.android.providers.gsf.permission.read_gservices" /> <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_fine_location" /> <uses-feature android:glesversion="0x00020000" android:required="true" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name="example.mapsdemo.mainactivity" android:label="@string/app_name" > <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.maps.v2.api_key" android:value="your_api_key" /> </application> </manifest> MapView Siamo finalmente pronti a scrivere quel (poco) codice necessario per includere una mappa all interno della nostra app dimostrativa MapsDemo. A tal scopo, le Google Maps API per Android espongono un apposito widget MapView (nel package com.google.android.gms.maps), che può facilmente essere inserito in qualunque layout. Usando un layout XML, ad esempio il file activity_main.xml del nostro progetto, possiamo fare alla seguente maniera: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mainactivity" > <com.google.android.gms.maps.mapview android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> A questo punto, il layout può essere caricato all interno di una Activity, ad esempio la MainActivity del nostro progetto MapsDemo. Dopo averlo caricato, si deve sempre recuperare il riferimento all oggetto MapView contenuto al suo interno e conservarlo a livello di istanza. Affinché la mappa venga visualizzata correttamente, infatti, è necessario che l oggetto MapView venga messo a conoscenza degli eventi oncreate(), ondestroy(), onresume(), onpause() e opzionalmente anche onsaveinstancestate() previsti da Activity: package example.mapsdemo; import com.google.android.gms.maps.mapview; import android.app.activity; import android.os.bundle; Pagina 14

public class MainActivity extends Activity { private MapView mmapview; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); mmapview = (MapView) findviewbyid(r.id.map); mmapview.oncreate(savedinstancestate); protected void onresume() { super.onresume(); mmapview.onresume(); protected void onpause() { super.onpause(); mmapview.onpause(); MapFragment Un alternativa a MapView è MapFragment, che incorpora le mappe di Google all interno di un Fragment. Il vantaggio è che non c è bisogno di collegare il ciclo di vita della activity con quello della mappa: i fragment lo fanno già da soli. Lo svantaggio è che i fragment sono disponibili solo a partire da Android 3.0, e quindi usandoli si diminuisce la compatibilità dell applicazione. Esiste però un pacchetto JAR di compatibilità che permette di usare i fragment su qualunque versione di Android. Per saperne di più sui fragment: http://developer.android.com/guide/components/ fragments.html protected void ondestroy() { super.ondestroy(); mmapview.ondestroy(); protected void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); mmapview.onsaveinstancestate(outstate); Potete lanciare l applicazione: poche righe di codice (praticamente nessuna, abbiamo svolto quasi esclusivamente operazioni di configurazione e collegamento) sono bastate per avere Google Maps all interno dell app. Figura 13 La mappa è completamente funzionale, l utente può interagire con essa attraverso i comandi incorporati. Pagina 15

Configurare le mappe Lavorando sul tag XML che incorpora una MapView all interno di un layout, è possibile configurare numerosissimi aspetti della mappa che ci si accinge a visualizzare. Il tag MapView, infatti, prevede una serie di attributi aggiuntivi. Per averli a disposizione, bisogna anzitutto includere il namespace corrispondente, alla seguente maniera: <com.google.android.gms.maps.mapview xmlns:map="http://schemas.android.com/apk/res-auto" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" /> Così facendo, diventa possibile utilizzare gli attributi specifici di MapView, usando il prefisso map. Ad esempio: map:maptype="normal" Diamo un occhiata agli attributi aggiuntivi ora a disposizione: maptype. Stabilisce il tipo di mappa visualizzata. I valori validi sono: none (nessuna mappa), normal (mappa normale geometrica con scritte), hybrid (mappa satellitare con un layer di scritte), satellite (mappa satellitare senza scritte) e terrain (mappa dei rilievi). cameratargetlat, cameratargetlng, camerazoom, camerabearing, cameratilt. Questi attributi controllano la posizione iniziale della camera, determinando la porzioni di mappa visualizzata. uizoomcontrols, uicompass. Accettano valori booleani (true o false) che indicano, rispettivamente, se sulla mappa devono essere visualizzati i controlli per lo zoom e la bussola. uizoomgestures, uiscrollgestures, uirotategestures, uitiltgestures. Accettano valori booleani che indicano quali gesture sono abilitate. Ad esempio: <com.google.android.gms.maps.mapview xmlns:map="http://schemas.android.com/apk/res-auto" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" map:camerabearing="0" map:cameratargetlat="41.901766" map:cameratargetlng="12.491341" map:cameratilt="30" map:camerazoom="10" map:maptype="hybrid" map:uicompass="true" map:uirotategestures="false" map:uiscrollgestures="true" map:uitiltgestures="true" map:uizoomcontrols="false" map:uizoomgestures="true" /> Controllare le mappe Cerchiamo adesso di fare qualcosa in più, cioè controllare dinamicamente, da codice Java, quello che il componente di Google Maps mostra all utente. Per farlo, cominciamo dal riferimento di tipo Pagina 16

MapView già a nostra disposizione. Da esso, grazie al metodo getmap(), possiamo cavare fuori un oggetto com.google.android.gms.maps.googlemap: GoogleMap map = (GoogleMap) mmapview.getmap(); La classe GoogleMap permette un controllo molto fine della mappa visualizzata all interno del componente. Una prima cosa che possiamo farci, è accendere la visualizzazione della posizione attuale dell utente, grazie al metodo setmylocationenabled(): map.setmylocationenabled(true); Così facendo, la posizione dell utente verrà evidenziata sulla mappa, attraverso un apposito pallino di colore blu. Possiamo anche aggiungere dei marcatori in dei punti di interesse che vogliamo evidenziare all utente. Ad esempio: MarkerOptions marker = new MarkerOptions(); marker.position(new LatLng(41.853069, 12.605517)); marker.title("università"); marker.snippet("facoltà di informatica"); map.addmarker(marker); In questo modo, si aggiunge alla mappa un marker alla posizione (41,853069, 12,605517 ), con titolo Università e breve descrizione Facoltà di informatica. Figura 14 Mappa ibrida con un marker. Altri metodi consentono un controllo ancora più fine, ed un disegno di dettaglio. La documentazione completa è disponibile all indirizzo: https://developers.google.com/maps/documentation/android/ Pagina 17