Sei sulla pagina 1di 46

La visualizzazione: View

Android fornisce una collezione di controlli studiati e progettati appositamente per i device mobili: il cuore di questi controlli rappresentato principalmente da due classi,android.view.View e android.view.ViewGroup. Una View sostanzialmente unarea rettangolare nello schermo responsabile del disegno degli elementi grafici e della cattura e gestione degli eventi generati dallutente. Un oggettoViewGroup anchesso una View, ma che contiene altre View. Nella piattaforma Android si utilizza il concetto di layout per gestire limpaginazione dei controlli allinterno di un contenitore di oggetti View. Utilizzare i layout facilita la progettazione delle interfacce perch pi semplice orientare e posizionare i controlli che le compongono. Possiamo considerare una View come un widget: bottoni, etichette, caselle di testo, tabelle, sono tutti esempi di controlli e widget che possiamo utilizzare per comporre le interfacce grafiche delle nostre applicazioni. Come vedremo pi in dettaglio nel tutorial passo per passo che concluder questa guidapossiamo scegliere approcci diversi per la costruzione delle interfacce in ambiente Android: la prima possibilit quella di definire linterfaccia interamente da codice, altrimenti possiamo scegliere di costruire le interfacce attraverso delle configurazione XML, oppure ancora possiamo scegliere un approccio ibrido, definire le interfacce in XML e poi, attraverso un riferimento, modificarle e gestirle da codice.

Le attivit: Activity
La classe Activity uno degli elementi centrali di ogni applicazione Android. LActivity un concetto legato allo sviluppo delle interfacce grafiche: normalmente una Activityrappresenta una singola schermata della nostra applicazione. Le applicazioni possono definire una o pi Activity per trattare diverse fasi del software: ogni Activity responsabile del salvataggio del proprio stato in modo da poterlo ristabilire successivamente come parte del ciclo di vita dellapplicazione. Generalmente una Activity corrisponde ad un'azione specifica che lutente pu fare: essendo una delle componenti principali nel ciclo di vita di ogni applicazione Android, il modo in cui le Activity sono lanciate e in cui interagiscono tra loro una parte fondamentale nello sviluppo con la piattaforma Android. Ci pu essere solo una Activity attiva per volta, quindi una sola Activity per volta pu essere in primo piano (foreground) nello stesso tempo: una Activity che in un determinato momento non si trova nello stato attivo e quindi non si trova in foreground (in questo caso si dice che lActivity si trova in backgroud) potrebbe essere terminata dal sistema operativo ad esempio perch la memoria diventa insufficiente. Questo significa che ogni applicazione Android pu cambiare lo stato in ogni momento e deve essere pronta ad essere interrotta e chiusa in ogni istante. Come vedremo la classe Activity dispone di un numero notevole di callback che permettono ad una Activity di rispondere agli eventi come la sospensione e la ripresa.

Le azioni: Intent
Un Intent un meccanismo che descrive unazione specifica, come ad esempio chiamare a casa o inviare un sms: in Android praticamente ogni cosa passa attraverso un Intent, e lo sviluppatore li pu utilizzare per riusare o sostituire diversi componenti software. Ad esempio disponibile un Intent inviare una email: se nella nostra applicazione abbiamo la necessit di gestire linvio di email possiamo invocare lIntent che il sistema ci mette a disposizione, oppure possiamo scriverne uno nuovo e utilizzare questultimo nelle nostreActivity sostituendo lIntent di default con quello implementato da noi. Possiamo immaginare un Intent come unazione che possiamo far invocare ad Android: un Intent pu essere molto specifico ed essere richiamabile da una specifica Activity oppure pu essere generico e disponibile per qualsiasi Activity che rispetta determinati criteri. Schematizzando, un Intent pu essere utilizzato per: trasmettere linformazione per cui un particolare evento (o azione) si verificato;

esplicitare unintenzione che una Activity o un Service possono sfruttare per eseguire un determinato compito o
azione, solitamente con o su un particolare insieme di dati;

lanciare una particolare Activity o Service; supportare linterazione tra qualsiasi applicazione installata sul dispositivo Android, senza doversi preoccupare
di che tipo di applicazione sia o di quale componente software gli Intentfacciano parte. LIntent uno dei concetti e dei meccanismi fondamentali di Android: la sua implementazione trasforma ogni dispositivo Android in una collezione di componenti indipendenti ma facenti parte di un singolo sistema interconnesso.

La condivisione dei dati con i Content Provider


Un Content Provider un contenitore di dati e rappresenta uno dei modi migliori per condividere informazioni globali tra applicazioni. Nel modello di sicurezza implementato in Android, i file scritti da una applicazione non possono essere letti o scritti da unaltra. Android un sistema Linux-based in cui ogni applicativo ha il suo userid Linux, la sua directory data (/data/data/nome_pacchetto) e il suo spazio di memoria dedicato e protetto. Questo il motivo per cui gli applicativi Android necessitano dei Content Provider per comunicare tra loro. I processi possono segnalare se stessi al sistema come Content Provider di un insieme particolare di dati: quando queste informazioni sono richieste vengono richiamate da Android grazie ad un insieme specifico di API che permettono di agire sul contenuto secondo le specifiche definite. Alcuni Content Provider, ad esempio, forniscono laccesso ai proprio dati solo in lettura, mentre altri permettono alle applicazioni di creare, aggiornare, modificare o cancellare record, come nel caso di quella che gestisce i contatti.

Un database SQLite in un device Android un esempio di sorgente di dati che possiamo incapsulare allinterno di un Content Provider: Chiaramente Android provvisto di un insieme di Content Provider nativi, documentati nel package android.provider dellSDK. Possiamo vedere la lista di questi Content Provider sul sito degli svilupppatori Android. Per accedere alle risorse fornite da un Content Provider utilizziamo un insieme di URL caratterizzati dallo schema content:// con un modello che ricorda molto da vicino le chiamate REST. Diversi database nativi, come ad esempio quello dei contatti, sono disponibili come Content Provider rendendosi accessibili anche ad applicativi di terze parti.

Lavoriamo in backgroud con i Service


Un Service un processo che gira in background senza la diretta interazione con lutente (un concetto molto simile al deamon in ambiente Unix). La classe Service viene utilizzata per creare componenti software che possono svolgere attivit in modo invisibile, senza interfaccia utente. Un esempio tipico di Service lo vediamo implementato nel player di musica, che continua a riprodurre canzoni anche quando non in primo piano (foreground) e stiamo utilizzando altri programmi. Il codice responsabile di questa attivit sar implementato in un Service, al quale successivamente unaltra Activity potr ordinare di cambiare traccia o di fermare la musica. Utilizzando i Service possiamo far girare le nostre applicazioni e farle reagire ad eventianche quando non sono in primo piano: un Service pu essere avviato, fermato e controllato da altri componenti dellapplicazione, inclusi altri Service e Activity. Se la nostra applicazione deve svolgere attivit che non dipendono direttamente dallinput inserito dallutente, allora implementare un Service potrebbe essere la risposta alle nostre necessit: applicazioni che si aggiornano regolarmente ma che raramente o ad intermittenza interagiscono con lutente sono buone candidate ad essere implementate come Service. Un Service avviato ha una priorit pi alta rispetto ad Activity in stato di inattivit, in questo modo vi minore probabilit per un Service di essere terminato dal gestore delle risorse di runtime. Lunica ragione per cui Android potrebbe fermare un Serviceprematuramente per fornire risorse addizionali al componente software in primo piano (normalmente una Activity). Quando questo si verifica il Service fermato sar riavviato automaticamente non appena le risorse diventano nuovamente disponibili. Nel caso in cui il Service debba interagire direttamente con lutente potrebbe essere necessario incrementare la sua priorit come quella di unActivity in foreground. Questo ci assicura che i nostri Service non vengano terminati se non in circostanze estreme, chiaramente per a scapito della gestione delle risorse a tempo di esecuzione, potenzialmente con un conseguente degrado generale dellesperienza utente.

Il cuore di unapplicazione Android: AndroidManifest.xml


LAndroidManifest.xml il file che definisce i contenuti e il comportamento della nostra applicazione: allinterno di questo file sono elencate le Activity e i Service dellapplicazione, con i permessi che necessita per funzionare correttamente. Ogni progetto Android include un AndroidManifest.xml memorizzato nella directory principale del progetto: in questo file XML si possono inserire nodi per ogni elemento (Activity, Service,Content Provider e cos via) che compone la nostra applicazione, impostando i permessi per determinare come questi interagiscono lun laltro e con le altre applicazioni. Come abbiamo visto ogni applicazione gira allinterno di un proprio processo Linux, per cui ci sono delle restrizioni ben specifiche: ogni processo non pu accedere alla memoria di un altro processo, e ad ogni applicazione assegnato uno specifico identificatore utente. Inoltre i file di un applicativo non possono essere letti o scritti da altri applicativi: anche laccesso a diverse operazioni critiche sono protette, e dobbiamo specificatamente chiedere i permessi per utilizzarle. Questo tipo di richieste vanno impostate nellAndroidManifest.xml . Quando lapplicazione viene installata il gestore dei pacchetti concede o non concede i privilegi a seconda di come li abbiamo configurati nellAndroidManifest.xml. Tra i principali permessi che possiamo richiedere ci sono i seguenti:

READ_CONTACTS: leggere (ma non scrivere) i dati dei contatti dellutente. WRITE_CONTACTS: scrivere (ma non leggere) i dati dei contatti dellutente RECEIVE_SMS: monitorare larrivo di messaggi SMS INTERNET: accedere ed utilizzare la connessione Internet ACCESS_FINE_LOCATION: utilizzare un accurato sistema di localizzazione come il GPS
La radice di ogni AndroidManifest.xml il tag <manifest>: questo tag include i nodi che definiscono i componenti dellapplicazione, lambiente di sicurezza, e tutto ci che fa parte dellapplicazione. Nelle lezioni successive vedremo come si configura correttamente questo importante file e quali strumenti possiamo utilizzare per facilitare il nostro lavoro.

Android Virtual Device: virtualizziamo i dispositivi


LAndroid Virtual Device (AVD) permette agli sviluppatori di testare le loro applicazionisenza dover per forza possedere e collegare al PC uno smartphone Android vero e proprio. Gli AVD possono essere creati con differenti configurazioni per emulare differenti tipi di smartphone reali. LSDK di Android non include alcun

AVD pre-installato, dunque necessario creare almeno un device virtuale prima di poter testare le nostre applicazioni in un emulatore. Come vedremo in dettaglio nelle lezioni successive, ogni AVD configurato almeno con un nome, una versione di SDK supportata (Android 1.6, Android 2.1 e cos via), un valore che indica la quantit di memoria da riservare per la scheda SD e una risoluzione per lo schermo. Il plugin ADT di Eclipse (nelle lezioni precedenti abbiamo visto come installarlo e come integrarlo allinterno dellIDE) permette di gestire come facilit gli AVD e gli emulatori. In particolare permette di lanciare automaticamente lemulatore allinterno dellAVD selezionato per testare o effettuare il debug dei nostri progetti. Ovviamente chi non volesse utilizzare Eclipse e il plugin corrispondente pu controllare lemulatore attraverso la linea di comando (il terminale).

Resource : la gestione delle risorse in Android


Una Resource pu essere un'immagine bitmap, una stringa di testo che valorizza una etichetta o un bottone, o pu essere qualsiasi altra informazione che non sia codice e che necessaria per il corretto funzionamento dellapplicazione Android. Tutte le Resource vengono compilate allinterno dellapplicazione: questo molto utile per implementare linternazionalizzazione o per supportare diversi tipi di device. Le Resourcesono memorizzate e create all'interno di una directory specifica, la directory res del nostro progetto: il compilatore delle risorse di Android processa le risorse in base alle sotto-directory in cui sono memorizzate e in base al formato dei file. Ad esempio i file immagine JPG o PNG dovrebbero essere memorizzati in una directory all'interno del percorso res/drawable mentre i file XML che descrivono e configurano i layout delle schermate dovrebbero essere memorizzate in una directory all'interno del percorsores/layout. Possiamo aggiungere alle directory suffissi specifici per indicare una particolare lingua, un determinato orientamento dello schermo, la densit dei pixel e molto altro ancora. Il compilatore delle risorse comprime e impacchetta le risorse delle nostre applicazioni, e successivamente genera una classe chiamata R che contiene tutti gli identificatori che possiamo utilizzare per riferirci alle risorse del programma. Questa tecnica assicura che tutte le referenze delle Resource siano valide e permette di risparmiare spazio non dovendo memorizzare anche le stringhe di referenza come avviene in ambiente Java standard.

Creazione di unapplicazione
Ora siamo pronti per implementare la nostra prima applicazione Android: iniziamo con il classico esempio Hello Word. Prima di creare un nuovo progetto per dobbiamo installare alcuni componenti aggiuntivinell'SDK di Android, componenti che ci permetteranno, in fase di creazione del progetto, di selezionare un target di riferimento per il progetto stesso. Per fare questo, come vedremo dettagliatamente nelle lezioni successive,

apriamo l' Android SDK and AVD Manager seguendo questo percorso dal menu di Eclipse: Window / Android SDK and AVD Manager(per installare Eclipse e l'SDK di Android si veda la lezione I software necessari). Nota: se Eclipse dovesse restituire un errore si torni nel menu Windows / Preferences / Android e si verifichi che alla voce SDK Location sia indicato effettivamente il percorso dell'SDK di Android. Se non lo fosse, lo si cambi. Se lo fosse, si prema OK per confermare la scelta e si riapra l'Android SDK and AVD Manager come descritto sopra. Nella finestra che compare selezioniamo la voce Available packages del menu di sinistra, poi la voce Android Repository nel pannello di destra e selezioniamo i componenti che vogliamo installare (per questo e per i prossimi esempi che vedremo possiamo installare anche solo il pacchetto SDK Platform Android 2.1, API7). Facciamo clic su Install selected e poi, nella finestra successiva, su Install. Il sistema installer automaticamente anche gli Android SDK Platform-tools. Ad installazione conclusa possiamo proseguire. Figura 2: L'installazione dei componenti aggiuntivi di Android (clic per ingrandire)

Dal menu File di Eclipse selezioniamo New / Project. Nella finestra che compare selezioniamoAndroid / Android Project e poi clicchiamo su Next. A questo punto appare la finestra di dialog New Android Project: con questo wizard configureremo il nuovo progetto. Inseriamo la stringa HelloWord come nome del progetto, HelloWordApp come nome dellapplicazione, com.html_it.examples come nome del pacchetto, HelloWordActivity come nome dellActivity. La stringa che inseriamo come nome dellapplicazione quella che comparir nella barra del titolo dellapplicazione, dunque in una implementazione reale bisogna avere qualche accortezza per la scelta di questo nome. Figura 3: La finestra di configurazione dell'applicazione

Rimane da selezionare il build target per lapplicazione, scegliamo per il nostro esempio il target Android 2.1 (API level 7), e il Min SDK (nel nostro caso 7), ovvero la versione minima di Android richiesta per la nostra applicazione. A questo punto clicchiamo su Finish, e lADT generer la struttura rappresentata nella Figura 4: questa struttura rimane molto simile anche per applicazioni pi complesse e di maggiori dimensioni rispetto allesempio HelloWord. La struttura la vedremo in dettaglio nella lezione successiva. Figura 4: La struttura di un'applicazione Android

Struttura di unapplicazione
Riproponiamo, per comodit, la Figura 4 gi vista nella lezione precedente e ne descriveremo in dettaglio le varie componenti. Figura 4: La struttura di unapplicazione Android

Unapplicazione Android deve avere almeno tre componenti per poter funzionare:

1.Il file AndroidManifest.xml, che come abbiamo visto nelle lezioni precedenti si trova nella directory principale
del progetto ed responsabile della configurazione e del comportamento della nostra applicazione. 2.La cartella src che contiene il codice sorgente 3.La cartella resource che contiene le risorse necessarie alla nostra applicazione per un corretto funzionamento: questa cartella pu contenere sottocartelle per lorganizzazione delle risorse, come ad esempio drawable, raw, layout, anim e cos via Abbiamo gi introdotto il file AndroidManifest.xml, mentre il codice sorgente inizieremo a vederlo nelle lezioni successive. Puntualizziamo invece alcune caratteristiche della gestione delle risorse in ambiente Android: innanzitutto dobbiamo sottolineare che Android supporta una organizzazione lineare per la cartella res. Questo significa che non sono supportate sottocartelle oltre il secondo livello, ad esempio allinterno della directory layout (e ovviamente allinterno delle altre sottocartelle dirette della directory res) il sistema non riconosce le sottocartelle create. Unaltra puntualizzazione necessaria riguarda le cartelle raw e assets, che se necessarie creeremo nella cartella res. Queste due directory possono contenere la stessa tipologia di file, solo che quelli contenuti nella cartella raw sono considerati delle risorse a tutti gli effetti, mentre i file contenuti in assets

no. I file contenuti in raw saranno localizzati e accessibili attraverso gli ID autogenerati, mentre il contenuto della cartella assets considerato come contenuto generico: questo significa per esempio che nella cartella assets possiamo organizzare arbitrariamente la gerarchia di cartelle e sottocartelle, cosa che come abbiamo visto non permessa quando ci occupiamo delle risorse. La cartella layout contiene invece alcune View della nostra applicazione: in questa cartella che mettiamo i file XML che definiscono le interfacce della app (invece che definirle da codice). Le cartelle drawable-ldpi, drawable-hdpi, drawable-mdpi contengono immagini ed altre risorse grafiche per differenti risoluzioni e densit degli schermi, mentre nella cartella anim possiamo mettere le animazioni eventualmente utilizzate dalle nostre applicazioni. In menu ci saranno i descrittori XML che definiscono la struttura dei vari menu e in values possiamo mettere altre risorse utilizzate dallapplicazione, come ad esempio stili, stringhe e definizioni di colori (sempre sottoforma di descrittori XML).

Creare un dispositivo di emulazione


Per eseguire il building e il debugging di una applicazione Android dobbiamo prima completare i seguenti passi: 1.Configurare un Android Virtual Device (AVD) per lemultatore 2.Creare una configurazione di debug per il progetto (lo vedremo nella lezione successiva) Per completare queste procedure possiamo utilizzare il plugin ADT di Eclipse: lIDE collegher il debugger allemulatore Android (o allo smartphone che usiamo per sviluppare) cos potremo liberamente eseguire il debug delle applicazione in maniera comoda e precisa.

Android Virtual Device


LAndroid Virtual Device descrive il tipo di device che lemulatore pu simulare, includendo la piattaforma Android supportata (Android 1.6, Android 2.1 e cos via). La configurazione dellAVD comprende la scelta della dimensione dello schermo, la possibilit di utilizzare una SD card e la sua dimensione. Per creare un AVD necessario seguire questa procedura:

1.Lanciare lAndroid SDK e AVD Manager da Eclipse cliccando sullicona dedicata che troviamo nella toolbar
(Figura 5) oppure seguendo il percorso di menu Window / Android SDK and AVD Manager; Figura 5: Il pulsante di accesso all'Android SDK in Eclipse

2.Comparir un dialog diviso in due parti: il menu e il pannello gestionale. Clicchiamo sulla voceVirtual Devices
visibile nel box di sinistra: nella parte destra del dialog comparir lelenco degli AVD finora creati (se il primo AVD che creiamo chiaramente la lista sar vuota);

3.Cliccare sul pulsante New per creare un nuovo AVD;


4.A questo punto dobbiamo compilare i campi richiesti (Figura 6). Scegliamo un nome per lAVD; Selezioniamo il target: ad esempio per il supporto ad Android 2.1 scegliamo la voce Android 2.1-update API Level 7. Ricordiamo che i target disponibili si installano seguendo la voce Available packages del menu di sinistra, e selezionando le piattaforme disponibili che compaiono cliccando sulla voce Android Repository del pannello destro; 5.Scegliamo la capacit della card SD: limmagine che verr creata prender spazio nel nostro disco fisso, pertanto scegliamo un valore ragionevole, ad esempio 1024 Mib (il valore minimo di 9 MiB);

6.Il passo successivo la scelta di una skin, ovvero la modalit di visualizzazione dellemulatore. Selezioniamo
la skin (HVGA), che rappresenta la visualizzazione in modalit portrait; 7.Clicchiamo sul pulsante Create AVD e attendiamo la fine del processo di creazione. Figura 6: La creazione di un nuovo Android Virtual Device (AVD)

Finito il processo di creazione potremo vedere lAVD che abbiamo creato nel pannello di destra List of existing Android Virtual Device located at . Se volete testare il vostro emulatore sufficiente selezionarlo e cliccare sul pulsante Start sulla destra della finestra dialog.

Configurare lesecuzione e il debug


Prima di lanciare la nostra applicazione HelloWord necessario creare una configurazione di Run o di Debug per il progetto. Vediamo i passi da completare per creare una configurazione di Debug, quella che useremo di pi in fase di sviluppo:

1.Sempre in Eclipse, nel menu principale selezioniamo il percorso Run / Debug Configurations;
2.Nellelenco disponibile sulla parte sinistra della finestra di dialog che si apre eseguiamo un doppio click sulla voce Android Application per creare una nuova configurazione; 3.Cambiamo il nome della configurazione appena create da New_configuration a Android Debug (o altro nome);

4.Clicchiamo sul pulsante Browse e scegliamo il progetto che vogliamo debuggare, nel nostro caso HelloWord; 5.Spostiamoci sulla scheda Target e controlliamo il target associato al nostro progetto. Se lasciamo la spunta
su Automatic verr scelto in automatico il target adatto al progetto lanciato, altrimenti possiamo scegliere di spuntare la voce Manual: scegliendo questa opzione ogni volta che lanciamo un progetto con la configurazione

Android Debug ci verr chiesto di selezionare un target. Questa opzione molto utile e comoda quando dobbiamo testare la nostra app su differenti smartphone o emulatori;

6.Clicchiamo sul pulsante Apply per confermare le modifiche.


Figura 7: La configurazione del debug di un'applicazione Android

La creazione di una configurazione per il running delle app un processo molto simile a quello che abbiamo appena visto per la creazione della configurazione di debugging. Da un punto di vista pratico ci che cambia al punto 1 della precedente lista, dove al posto della voce Run / Debug configurations dovremmo seguire il percorso Run / Run Configurations. Da un punto di vista funzionale invece ci che cambia principalmente nellutilizzare una configurazione di running piuttosto che una di debugging che se usiamo quella di debugging il debugger di Eclipse sar collegato alla nostra applicazione, facilitando il debug del nostro codice anche grazie allutilizzo dei breakpoint. Utilizzando il plugin ADT di Eclipse, quando eseguiamo il running o il debugging della nostra applicazione succede quanto segue: 1.Viene compilato il progetto corrente e convertito in un eseguibile Android (.dex); 2.Gli eseguibili e le risorse esterne della applicazione vengono organizzate in un package Android (.apk); 3.Il device virtuale selezionato viene fatto partire (se non gi stato fatto partire prima, altrimenti questo punto non viene eseguito); 4.Lapplicazione viene installata nel device vituale selezionato; 5.Lapplicazione viene fatta partire nel device vituale.

Eseguire test sullemulatore e sullo smartphone


Vediamo dunque come eseguire il debug della nostra applicazione di prova usando, prima, l'emulatore di Eclipse e, dopo, su un terminale reale.

Test nell'emulatore
Siamo pronti per lanciare e testare la nostra app nell'emulatore precedentemente configurato. Tutto quello che dobbiamo fare cliccare sul pulsante Debug ( ) che troviamo nella toolbar di Eclipse; oppure

premere il tasto F11 o scegliere la voce Debug dal menu Run. Una volta cliccato sul pulsante Debug verr lanciato il lemulatore: al primo lancio necessario aspettare un po di tempo prima di poter interagire con il device virtuale, dunque aspettiamo con calma che lo startup si concluda (anche alcuni minuti su computer meno potenti). Quando lemulatore pronto per linterazione possiamo premere e trascinare il pulsante di sblocco con il lucchetto verde finch non sblocchiamo il device virtuale, come possiamo vedere nellimmagine seguente: Figura 8: L'emulatore prima di essere sbloccato

Se abbiamo fatto tutto correttamente nel nostro emulatore vedremo una schermata molto simile a quella seguente: Figura 9: L'emulatore con la nostra applicazione di prova

Come possiamo vedere nella Figura 9, lapplicazione molto semplice: viene visualizzato un controllo di tipo TextView con una linea di stato, Hello Word, Helloword!. Abbiamo creato e testato la nostra prima applicazione Android!

Test nello smartphone


Facciamo un ulteriore passo in avanti: dopo aver testato la nostra semplice applicazione del device virtuale, vediamo come si comporta su un device reale. Per procedere abbiamo bisogno di un cavo USB per collegare il nostro smartphone al PC e completare la seguente procedura:

1.In Eclipse selezioniamo Run / Debug Configurations; 2.Clicchiamo due volte su Android Debug; 3.Clicchiamo sulla scheda Target e impostiamo Deployment Target Selection Mode suManuale. Selezionare la
voce Manual che ci permetter di scegliere se eseguire il debug nellemulatore o nel device;

4. Clicchiamo sul pulsante Apply;


5.Colleghiamo attraverso una porta e un cavo USB il nostro smartphone al PC. Nel caso in cui stessimo lavorando in ambiente Linux (es. Ubuntu) necessario eseguire qualche passaggio ulteriore:

Accedere alla directory platform-tools: la troviamo nella directory in cui abbiamo installato lSDK di
Android;

Eseguiamo il kill del server adb lanciando il comando sudo ./adb kill-server; Riavviamo il server adb con il comando sudo ./adb start-server. In questo modo il server avr i
permessi necessari per accedere al device collegato al Pc;

6.Facciamo clic sul pulsante Debug per concludere la configurazione.

A questo punto comparir la finestra Android Device Chooser, in cui vengono visualizzati i device, virtuali e/o reali, di cui possiamo disporre nel nostro PC e che possiamo scegliere per eseguire il debug dellapplicazione. Il nostro device deve essere abilitato per il debug attraverso la connessione USB. Per attivare questa configurazione, selezioniamo il menuImpostazioni dello smartphone, poi la voce Applicazioni e qui impostiamo la seguente configurazione:

1.Attiviamo l'opzione Origini sconosciute; 2.Selezioniamo la voce Sviluppo; 3.Nelle opzioni disponibili in questa sezione attiviamo le voci Debug USB e Rimani attivo: questultima opzione
disabilita il controllo sullattivazione dello schermo, lasciandolo sempre attivo. Per concludere il processo sufficiente fare doppio clic sul device in cui si vuole eseguire l'applicativo nella finestra Android Device Chooser. Eseguito lultimo passaggio, Eclipse installer lapplicazione Android nel device che abbiamo selezionato dallelenco dei device disponibili (reali o virtuali) e la eseguir. Se abbiamo eseguito questa procedura per lapplicazione Hello Word vista nella lezione precedente, nel nostro smartphone comparir una schermata molto simile a quella rappresentata dalla figura 9. Rimane da sottolineare ancora una questione: ogni volta che finiamo di lavorare sullo smartphone dobbiamo ricordarci di disabilitare le impostazioni attivate sopra. Lattivazione permanente dello schermo, se non disabilitata, ovviamente porta ad un rapido scaricamento della batteria, mentre lattivazione delle altre opzioni al di fuori del contesto di sviluppo lascia aperte notevoli falle per la sicurezza del nostro device.

Definire caratteristiche e interfaccia grafica


Sviluppare software unattivit complessa perch richiede diverse fasi da completare in modo attento e preciso per raggiungere pienamente il proprio obiettivo. Nel contesto dello sviluppo mobile questo concetto ancora pi radicato: sviluppare un applicativo mobile unattivit che richiede particolari attenzioni perch ci muoviamo in un ambiente in cui le risorse sono limitate, i monitor sono di piccole dimensioni e lefficienza diventa una delle componenti fondamentali per la buona riuscita del nostro lavoro. In questa e nelle seguenti lezioni vedremo alcune tecniche e best practise per scrivere codice Android efficiente e professionale e alcune linee guida per la progettazione degli applicativi. Partiamo dalle caratteristiche e dall'interfaccia grafica.

Le caratteristiche
Supponiamo di voler sviluppare un applicativo che implementi il famoso gioco del Tris: lo chiameremo MyTris. La struttura di questa applicazione molto semplice, infatti possiamo immaginarla composta di cinque elementi:

Splash: lo splash rappresenta limmagine visualizzata quando lapplicazione in fase di caricamento, in cui

normalmente vengono rappresentati il logo del gioco o dellapplicativo e il numero di versione. anche molto comune la presenza di una musica di sottofondo;

Menu: il menu permette allutente di scegliere tra diverse opzioni, come ad esempio configurare lapplicativo,
avviare il gioco, vedere i punteggi, accedere ai credits, visualizzare lhelp e cos via ;

Avvio: questa schermata quella che compare una volta avviato il gioco o lapplicativo; Help: il compito dellhelp quello di visualizzare le istruzioni di utilizzo del gioco o dellapplicativo, descrivendo i
controlli disponibili, gli obiettivi, e nel caso dei giochi anche come si vince e il metodo con cui si calcolano i punteggi;

Credits: in questa schermata vi saranno le informazioni sullazienda o su chi si occupato dello sviluppo o

della distribuzione dellapplicativo: queste informazioni sono molto importanti perch ci permettono di essere contattati; La struttura proposta per il gioco MyTris in realt una struttura molto tipica che ritroviamo implementata sia in giochi sia in applicativi di altro genere, indipendentemente dalla piattaforma di sviluppo. Questo perch un valido modello che permette di avere una buona usabilit, una facilit duso ma anche flessibilit e chiarezza.

L'interfaccia grafica
Le interfacce utente in Android possono essere create in modo procedurale o dichiarativo. Nel primo caso si intende limplementazione dellinterfaccia grafica nel codice: ad esempio, in unapplicazione Swing scriviamo il codice Java per creare e manipolare tutti gli oggetti dellinterfaccia utente, come JButton, JFrame e cos via. La creazione dichiarativa non richiede la scrittura di codice: lesempio tipico del metodo dichiarativo rappresentato dalla creazione di una pagina web statica, in cui utilizziamo lHTML per descrivere cosa vogliamo vedere nella pagina. LHTML dunque dichiarativo. Android permette la creazione di interfacce sia procedurali sia dichiarative: possiamo creare uninterfaccia utente completamente in codice Java (metodo procedurale) oppure possiamo creare linterfaccia utente attraverso un descrittore XML (metodo dichiarativo). Android inoltre permette anche un approccio ibrido, in cui si crea uninterfaccia in modo dichiarativo e la si controlla e specifica in modo procedurale (si richiama il descrittore XML da codice e si continua a lavorare da l). Se guardiamo nella documentazione Android per i componenti delle interfacce utente vedremo che gli attributi presenti nelle API Java e quelli utilizzabili negli XML dichiarativi sono gli stessi: questo dimostra che in entrambi i casi abbiamo a disposizione le medesime possibilit. Dunque quale metodo meglio utilizzare? Entrambi i metodi sono soluzioni valide, anche se Google suggerisce nella maggior parte dei casi di usare la metodologia dichiarativa perch spesso il codice XML pi corto e semplice da leggere e capire rispetto al corrispondente codice Java, ed inoltre molto meno probabile che cambi nelle versioni future della piattaforma.

Specificare le attivit dellapplicazione


Abbiamo quindi ragionato sulla struttura base del nostro applicativo MyTris ed abbiamo analizzato e tracciato le linee guida per la progettazione delle interfacce che potremo implementare. Il passo successivo quello di ragionare sul core del nostro gioco: leActivity. MyTris necessiter almeno di cinque Activity, una per ogni caratteristica del gioco:

1.SplashActivity: questa sar lActivity lanciata di default che svolger il semplice compito di mostrare un layout
composto molto probabilmente da una immagine, una musica di sottofondo suonata fino al caricamento della MenuActivity;

2.MenuActivity: questa Activity mette a disposizione il menu del gioco, proponendo un layout composto da
diversi pulsanti, uno per ogni feature dellapplicazione. Inoltre ad ogni pulsante assoceremo un gestore per l'evento clic pulsante, in modo tale che una volta premuto venga lanciata lActivity legata al pulsante stesso;

3.PlayActivity: questa Activity sar la reale implementazione del gioco; sar responsabile di gestire gli input
dellutente, di tenere i punteggi della partita e di gestire tutte le dinamiche del gioco che implementeremo;

4.HelpActivity: visualizzer un testo con le spiegazioni sul funzionamento del gioco e sul calcolo dei punteggi; 5.CreditsActivity: visualizzer un testo con le informazioni su chi ha sviluppato il prodotto e su come sia
possibile contattarlo. Avr un layout molto simile alla HelpAcvitity: probabilmente visualizzeremo il testo servendoci di un controllo TextView scrollabile; Ogni Activity avr la propria classe e il proprio layout memorizzato nella directoryresources: in alcuni casi, come per le activity ScoreActivity e HelpActivity, visto che i loro compiti sono molto simili, si potrebbe pensare di condividere uno stesso layout e di impostare il testo da visualizzare a tempo di esecuzione invece che allinterno del layout stesso. Possiamo inoltre servirci di schemi e wireframe per analizzare e studiare la navigabilit e lusabilit del gioco, per verificare eventuali problematiche e criticit e trovare le soluzioni che pi si addicono alle caratteristiche del nostro gioco.

Implementare le funzionalit
Ora che abbiamo visto come progettare una tipica applicazione Android possiamo passare allimplementazione. Tenendo presenti le caratteristiche del nostro gioco teorico MyTris, vedremo in questa lezione alcuni dettagli e principi che sono alla base dello sviluppo di unapplicazione Android. Vedremo poi come metterli in pratica. Il primo elemento che vedremo pi in dettaglio lapplication context. Lapplication context un elemento centrale e importante per tutte le funzionalit disponibili al pi alto livello applicativo: possiamo utilizzare lapplication context per accedere alle risorse e alle impostazioni condivise tra istanze di diverse Activity. Una volta recuperato lapplication context, ad esempio con il seguente codice:

Context context = getApplicationContext();


possiamo utilizzarlo per accedere ad un ampio insieme di caratteristiche e servizi a disposizione dellapplicazione. Ad esempio possiamo richiamare il metodogetSharedPreferences() dellapplication context per recuperare le preferenze condivide dellapplicazione, oppure possiamo richiamare il metodo getResources() per recuperare le risorse dellapplicazione:

String hello =

context.getResources().getString(R.string.hello);
Visto che la classe Activity deriva dalla classe Context possiamo utilizzare il riferimentothis oppure richiamare esplicitamente lapplication context. Potremmo dunque riscrivere lesempio precedente come segue:

String hello = getResources().getString(R.string.hello);


Lapplication context lo utilizziamo anche per:

1.Lanciare istanze di Activity.


2.Gestire le directory, i database e i file protetti dellapplicazione. 3.Richiamare i gestori di servizi di sistema (e.g. servizio di localizzazione). 4.Applicare e controllare i permessi a livello applicativo. 5.Richiamare gli asset dellapplicazione. Possiamo dunque utilizzare lapplication context per lanciare istanze delle Activity. Per il nostro gioco di esempio MyTris, dovremmo implementare, ad esempio, cinque Activity, una per ogni schermata. Oltre allapplication context abbiamo a disposizione altre due opzioni per richiamare e lanciare istanze di Activity: implementare il lancio di una Activity nel file manifest oppure lanciare unActivity figlia da una Activity padre per riceverne un risultato. Per ogni applicazione Android dobbiamo definire nel file manifest una Activity di default: nel nostro caso potrebbe essere SplashActivity, che come abbiamo visto nelle lezioni precedenti avr il compito di visualizzare unimmagine e di riprodurre una musica come introduzione al gioco. Nelle prossime lezioni vedremo una serie di tutorial che ci guideranno nello sviluppo di piccole funzionalit come la definizione dei layout, la gestione dei menu, la gestione con i form dellinput dellutente, e molto altro ancora.

Running sullemulatore
Durante limplementazione possiamo servirci dellemulatore per testare il nostro lavoro: questo strumento molto comodo perch ci fornisce un preciso feedback sullandamento del progetto. Bisogna per tenere presente che questo strumento ha dei grossi limiti: mentre possiamo testare e verificare ad esempio la visualizzazione dei layout portrait (versione verticale) elandascape (versione orizzontale), la navigabilit e i menu, attualmente lemulatore non implementa tutte le caratteristiche hardware supportate da Android, come la fotocamera, la vibrazione, i LED, laccelerometro, e molto altro ancora. In tutti quei casi in cui lapplicativo che dobbiamo sviluppare ha bisogno di queste caratteristiche hardware non ci rimane altra scelta che testare il nostro lavoro direttamente su uno smartphone (la procedura completa per testare le app su un device reale la trovate nella lezione 15).

Dopo aver opportunamente configurato il device reale potremo installare e testare la nostra applicazione studiandone il comportamento in un contesto reale: in questo modo verifichiamo che il software risponda effettivamente a quello che abbiamo programmato.

Lavoriamo con i Layout


Iniziamo le lezioni pratiche con lo studio dei layout. I layout sono estensioni della classeViewGroup usati per posizionare i controlli delle nostre UI (User Interface): i layout possono essere nidificati permettendoci in questo modo di creare interfacce complesse usando anche combinazioni tra queste. Android mette a disposizione dello sviluppatore alcuni semplici modelli di layout che semplificano notevolmente la creazione delle interfacce: possiamo creare combinazioni di questi tipi per rendere le nostre interfacce semplici da utilizzare e capire. Vediamo alcune delle principali classi layout che la piattaforma ci mette a disposizione:

TableLayout: questo tipo di layout ci permette di disporre gli oggetti View usando una griglia composta da righe
e colonne, proprio come una tabella;

LinearLayout: il LinearLayout allinea ogni View figlia sia in senso verticale sia in senso orizzontale (un layout RelativeLayout: questo il layout pi flessibile tra quelli nativi perch permette di definire le posizioni di ogni
oggetto View in relazione agli altri oggetti View presenti;

orizzontale ha una riga di oggetti View, mentre un layout verticale composto da una colonna di oggetti View);

FrameLayout: questa la tipologia pi semplice di layout, perch non fa altro che posizionare in ordine di

inserimento tutti gli oggetti View partendo dallangolo in alto a sinistra dello schermo. molto comodo quando implementiamo degli swticher di immagini o delle interfacce a tab. Vediamo come utilizzare i layout. Creiamo un progetto che chiamiamo HelloLinear (vedere le lezioni precedenti per le istruzioni sulla creazione di un nuovo progetto Android). Una volta completato il processo di creazione apriamo il file /res/layout/main.xml, che dovrebbe presentarsi pi o meno come segue:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
Questo file XML definisce un layout di tipo LinearLayout verticale, come indica lattributoorientation impostato a vertical. Il layout contiene un widget figlio di tipo TextView, sostanzialmente un oggetto che visualizza del testo (quello contenuto dalla risorsa indicata nellattributo text che in questo caso impostato su @string/hello). Il risultato di questo layout molto simile a quello rappresentato dalla seguente figura: Figura 10: L'emulatore di Android con unapplicazione di prova

Iniziamo a modificare questo layout: la prima cosa che facciamo creare una nuova risorsa di tipo stringa. Per fare questo apriamo il file /res/values/string.xml ovvero il file che contiene le definizioni di tutte le risorse stringa. Quando lavoriamo con i file descrittori Eclipse ci fornisce, attraverso il plugin ADT, due modalit di visualizzazione e utilizzo: una testuale e una visuale. Nella figura seguente potete vedere la modalit visuale (la modalit testuale si attiva selezionando il tab string.xml e visualizza appunto un semplice XML modificabile): Figura 11: La modalit visuale delle risorse (clic per ingrandire)

Come mostra limmagine, selezionata la risorsa stringa identificata dal nome hello che ha il valore Hello Word, HelloLinear!. Questa proprio la stringa che attualmente viene richiamata nel layout attraverso lidentificatore-nome hello: questo il motivo per cui quando lanciamo il test di questa applicazione vediamo il seguente risultato: Figura 12: Linterfaccia con le nuove stringhe (clic per ingrandire)

dove il cerchio in verde evidenzia il valore stampato a video della risorsa stringa che contiene il nome dellapplicazione (nella figura 6 la seconda risorsa in elenco denominata app_name ) mentre il cerchio rosso evidenzia il valore stampata a video della stringa hello vista pocanzi. Quindi evidente che possiamo modificare questi valori a nostro piacimento, anche dopo la creazione del progetto Android. Utilizzando la modalit visuale aggiungiamo una risorsa di tipo stringa: clicchiamo dunque sul pulsante Add (v. Figura 13 qui sotto) e nella finestra che compare verifichiamo che sia selezionato il tipo di risorsa string e clicchiamo su Ok. Concluso il processo di creazione delle risorsa possiamo procedere con limpostazione dei valori come rappresentato nella figura seguente: Figura 13: Le impostazioni dei valori della nuova risorsa (clic per ingrandire)

Salviamo il file: abbiamo cos creato una nuova risorsa stringa identificata da name impostata sul valore Inserisci il tuo nome. Torniamo sul layout ed in particolare sul file /res/layout/main.xml e modifichiamolo come segue:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/name" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" /> </LinearLayout>
Abbiamo eliminato dal layout la visualizzazione della stringa identificata da hello, abbiamo inserito la visualizzazione della risorsa stringa creata da noi pocanzi identificata da name e abbiamo aggiunto un altro widget, un oggetto EditText, ovvero un elemento molto simile ad una casella di testo HTML. Il risultato finale sar simile al seguente: Figura 14: Linterfaccia con loggetto EditText (clic per ingrandire)

La figura 14 mostra un layout molto diverso dalla versione precedente (v. figura 12). Abbiamo modificato anche il nome dellapplicazione: come possiamo notare osservando pi attentamente la figura nella barra grigia posta nella zona superiore della schermata rappresentata non compare pi la stringa Hello Linear ma HTML.IT Applicazione 1.

Possiamo eseguire questo tipo di esperimento con le principali tipologie di layout per vedere come si comportano gli oggetti che inseriamo e per imparare a disporre i widget per comporre interfacce pi complesse e funzionali. Nella prossima lezione modificheremo questo layout di esempio per implementare linterfaccia di un semplice form e gestirne linvio dei dati.

Gestione dellinput: lavoriamo con i form


5.2 Gestione dellinput: lavoriamo con i form
Aggiungiamo alla nostra applicazione Android di esempio dei moduli per gestire le interazioni con lutente Proseguiamo lo studio della piattaforma Android ed introduciamo la gestione dei form e dellinput utente. In questa lezione riprenderemo il progetto introdotto nelle lezioni precedenti: modificheremo il layout per creare un form ed impareremo a gestire linvio dei dati inseriti. La prima cosa da fare modificare il layout /res/layout/main.xml come segue:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/form_intro" android:layout_marginTop="15dip" android:layout_marginBottom="25dip" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/name" /> <EditText android:id="@+id/edit_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/lastname"

android:layout_marginTop="15dip" /> <EditText android:id="@+id/edit_lastname" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" /> <Button android:id="@+id/form_button" android:layout_height="wrap_content" android:text="@string/form_button_label" android:layout_marginTop="15dip" android:layout_marginLeft="90dip" android:layout_width="130dip" /> </LinearLayout>
Lasciamo invariata la tipologia del layout: utilizzeremo nuovamente il LinearLayout. La primaTextView inserita visualizza semplicemente un messaggio informativo che, come vedremo tra poco, imposteremo nel file string.xml . Successivamente creiamo due coppie di widget costituite ognuna da un controllo TextView e da un controllo EditText (righe 16-39), per finire con un oggetto Button (righe 41-48) che attiver linvio del form. Il risultato che otteniamo sar simile al seguente: Figura 15: Interfaccia con moduli e il bottone di invio (clic per ingrandire)

Come mostrato nella figura 15, ci che otteniamo simile ad un classico form in HTML: vi sono due caselle di testo e un bottone per linvio del form. Prima di vedere il dettaglio del file risorse

stringa /res/values/string.xml aggiornato, soffermiamoci ancora qualche istante sul nuovo layout e sul codice che lo gestisce. Abbiamo introdotto alcune direttive per gestire gli spazi e i margini tra i widget, come ad esempio: android:layout_marginTop="15dip" eandroid:layout_marginBottom="25dip" che aggiungono, rispettivamente, un margine superiore di 15dip ed uno inferiore di 25dip (dove dip sta per density-independent pixels, ununit di misura astratta basata sulla densit fisica dello schermo dello smartphone). Inoltre abbiamo aggiunto gli attributi id ai controlli EditText e al Button:

android:id="@+id/edit_name" android:id="@+id/edit_lastname" android:id="@+id/form_button"


Questi valori ci serviranno pi avanti per identificare e richiamare questi widget da codice e poterne gestire i valori e le azioni ad essi associate. Abbiamo introdotto nuovi widget ai quali abbiamo dovuto associare alcune risorse stringa. Vediamo allora il file delle risorse stringa (il file /res/values/string.xml) aggiornato:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">HTML.IT - Applicazione 1</string> <string name="form_intro">Invia il form premendo sul pulsante di invio.</string> <string name="name">Inserisci il tuo nome</string> <string name="lastname">Inserisci il tuo cognome</string> <string name="form_button_label">Invia</string> <string name="label_form_name">Nome Inserito:</string> <string name="label_form_lastname">Cognome Inserito:</string> </resources>
In questo caso non dovrebbe esserci nulla di nuovo o inaspettato: abbiamo definito delle risorse stringa identificate dallattributo name il cui valore contenuto allinterno dei tag<string></string> e verr visualizzato l dove la risorsa sar richiamata. Prima di analizzare il restante codice anticipiamo cosa vogliamo ottenere. Abbiamo unActivitydi default che crea linterfaccia vista pocanzi e che, attraverso il clic del pulsante Invia invier ad unaltra Activity i dati che lutente inserir nelle opportune caselle di testo, la quale li visualizzer con unaltra opportuna interfaccia. Passiamo dunque ad analizzare il codice della prima Activity, quella lanciata di default. Nella cartella /src/html/it/examples/com troviamo il file HelloLinear.java ovvero il file in cui implementiamo lActivity di default. Analizziamo in dettaglio il codice di questo file:

package html.it.examples.com; import android.app.Activity; import android.content.Intent;

import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class HelloLinear extends Activity implements OnClickListener { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button button = (Button) findViewById(R.id.form_button); button.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch ( v.getId() ) { case R.id.form_button: final EditText edit_name = (EditText)findViewById(R.id.edit_name); final EditText edit_lastname = (EditText)findViewById(R.id.edit_lastname); Bundle bundle = new Bundle(); bundle.putString("name", edit_name.getText().toString()); bundle.putString("lastname", edit_lastname.getText().toString()); Intent form_intent = new Intent(getApplicationContext(), Form.class); form_intent.putExtras(bundle); startActivity(form_intent); break; } } }
Il metodo onCreate() (rigo 12) chiamato quando lActivity viene creata e lanciata. Qui impostiamo il layout di default setContentView(R.layout.main); e attiviamo la gestione del clic sul widget Button visto precedentemente, impostando un listener sulla Activity stessa (che infatti implementa linterfaccia OnClickListener). Una classe che implementa linterfaccia OnClickListener deve obbligatoriamente implementare il metodo OnClick(), metodo in cui si gestisce lazione eseguita, in questo caso il clic sul Button Invia: soffermiamoci dunque sulla gestione dellevento. La prima cosa da fare (righe 23-24) recuperare i riferimenti dei controlli EditText definiti precedentemente e che serviranno per salvare i dati inseriti dallutente, in questo caso il nome ed il cognome:

final EditText edit_name = (EditText)findViewById(R.id.edit_name);

final EditText edit_lastname = (EditText)findViewById(R.id.edit_lastname);


A questo punto (righe 25-27) creiamo un oggetto Bundle che utilizziamo per salvare i dati inseriti dallutente:

Bundle bundle = new Bundle(); bundle.putString("name", edit_name.getText().toString()); bundle.putString("lastname", edit_lastname.getText().toString());


Utilizziamo il metodo putString() delloggetto bundle per salvare i dati inseriti, recuperati poi con il metodo getText() del widget EditText. Con i dati memorizzati nel Bundle creiamo lIntent per la chiamata dellActivity alla quale li vogliamo passare (righe 28-30), nel nostro caso Form.class, associamo allIntent il Bundle ed infine lanciamo lActivity :

Intent form_intent = new Intent(getApplicationContext(), Form.class); form_intent.putExtras(bundle);


A questo punto lapplicativo passer la palla ad una nuova Activity chiamata Form. Vediamo allora com definita questa Activity:

package html.it.examples.com; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class Form extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.form); final TextView text_name = (TextView) findViewById(R.id.view_name); final TextView text_lastname = (TextView) findViewById(R.id.view_lastname); Bundle bundle = this.getIntent().getExtras(); text_name.setText(bundle.getString("name")); text_lastname.setText(bundle.getString("lastname")); } }
Questa Activity molto semplice: dopo aver impostato un nuovo layout (che vedremo in dettaglio a breve) richiama nel codice i due controlli TextView in cui visualizzeremo i dati inseriti dallutente ed inviati dallActivity di default attraverso il Bundle. Quindi recuperiamo i valori dal Bundle tramite il metodo getString() e li impostiamo rispettivamente negli oggettiTextView text_name e text_lastname. Il risultato sar simile al seguente: Figura 16: Interfaccia con la risposta allinvio del modulo (clic per ingrandire)

Il layout rappresentato nella figura 11 definito nel descrittore /res/layout/form.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/label_form_name" android:layout_marginTop="15dip" android:layout_marginBottom="10dip" /> <TextView android:id="@+id/view_name" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/label_form_lastname" android:layout_marginTop="15dip" android:layout_marginBottom="10dip" /> <TextView android:id="@+id/view_lastname" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>

Come abbiamo visto nelle lezioni teoriche ogni volta che scriviamo una nuova Activitydobbiamo definirla nel file AndroidManifest.xml, il file principale per la configurazione di ogni applicazione Android. Prima di lanciare lapplicazione vediamo dunque come modificare lAndroidManifest.xml per evitare di incorrere in un errore:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="html.it.examples.com" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="7" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".HelloLinear" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" />
Il codice aggiunto, che appunto dichiara lesistenza di una nuova Activity, quello evidenziato.

Menu e dialog
In questa lezione estenderemo ulteriormente le funzionalit della nostra applicazione Android dotandola con un classico menu per la gestione delle impostazioni. Android supporta due tipi di menu: quelli che si attivano quando premiamo lapposito pulsante fisico dello smartphone e i menu di contesto, quelli che si attivano tenendo premuto il dito sullo schermo. Noi implementeremo un esempio di menu del primo tipo, come quello rappresentato nella seguente figura: Figura 17: Interfaccia con un pulsante Impostazioni (clic per ingrandire)

Il menu Impostazioni si attiva premendo il pulsante Menu dellemulatore o il corrispettivo pulsante fisico dello smartphone. Selezionando il menu si apriranno le opzioni disponibili, rappresentate nella seguente figura: Figura 18: Le due opzioni del menu Impostazioni (clic per ingrandire)

Vediamo i passaggi necessari per implementare questo menu. La prima cosa che dobbiamo fare creare una nuova cartella risorse: /res/menu/. In questa cartella creiamo un file XML menu.xml in cui definiamo il menu:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/settings" android:title="@string/settings_label" android:alphabeticShortcut="@string/settin gs_shortcut" /> </menu>
Con questo nuovo descrittore XML definiamo un menu composto da un item con identificatore uguale a settings e valorizzato con due stringhe, una per il testo che comparir nella voce di menu (Impostazioni, cfr. figura 17) e una che possiamo utilizzare come shortcut. Aggiorniamo anche il file delle risorse stringa /res/values/string.xml inserendo le nuove risorse necessarie:

<string name="settings_label">Impostazioni</string> <string name="settings_title">Impostazioni</string> <string name="settings_shortcut">i</string>


A questo punto dobbiamo modificare il file HelloLinear.java per legare il menu che abbiamo appena creato allActivity di default, in modo che quando premiamo il tasto fisico di menu dellemulatore o dello smartphone lActivity di default sappia come gestire tale evento. Per fare questo aggiungiamo le seguenti direttive import:

import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem;


e implementiamo loverride del metodo onCreateOptionsMenu():

@Override
Il metodo getMenuInflater() restituisce unistanza di MenuInflater che utilizziamo per leggere la definizione del menu dallXML vista pocanzi e trasformarla in una View effettiva. Ogni volta che viene selezionata una voce di menu viene richiamato il metodoonOptionsItemSelected() di cui implementiamo loverride sempre nella stessa classe, proprio per gestire la selezione della voce di menu Impostazioni:

@Override public boolean onOptionsItemSelected(MenuItem item) { switch ( item.getItemId() ) { case R.id.settings: startActivity(new Intent(this, Settings.class)); return true; } return false; }
Riassumiamo quanto fatto finora: abbiamo creato il menu principale e labbiamo associato allActivity di default. Questo elemento ha una voce di menu che si chiama Impostazioni: per gestire la selezione di questa voce di menu abbiamo implementato il metodoonOptionsItemSelected() che dopo aver verificato quale voce di menu stata selezionata (nel nostro caso quella con identificatore uguale a R.id.settings) svolge lazione corrispondente, nel nostro caso lanciare lActivity Settings che vedremo tra poco. Android mette a disposizione degli strumenti che semplificano molto la definizione di tutte le preferenze dellapplicativo e la visualizzazione di queste utilizzando pochissime linee di codice. Questo perch nella maggior parte della applicazioni che svilupperemo sar presente un menu Impostazioni o Preferenze, cio un menu con il quale lutente pu personalizzare alcuni comportamenti dellapplicazione. Definiamo dunque le preferenze in un nuovo file risorsa /res/xml/settings.xml:

<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <CheckBoxPreference android:key="item1" android:title="@string/menu_item_1" android:summary="@string/item1_summary" android:defaultValue="true" /> <CheckBoxPreference android:key="item2" android:title="@string/menu_item_2" android:summary="@string/item2_summary" android:defaultValue="true" /> </PreferenceScreen>
Come mostrato nella figura 13, lutente pu scegliere di attivare/disattivare due impostazioni,Item1 e Item2, entrambe sono due controlli di tipo CheckBoxPreference (in sostanza due widget molto simili alle checkbox dellHTML). Anche in questo caso dobbiamo aggiornare il file risorsa /res/values/string.xml per le valorizzazioni delle voci di menu delle preferenze:

<string name="menu_item_1">Item 1</string> <string name="menu_item_2">Item 2</string> <string name="item1_summary">Summary Item 1</string> <string name="item2_summary">Summary Item 2</string>
Rimane da vedere la definizione della classe Settings.java:

package html.it.examples.com; import android.os.Bundle; import android.preference.PreferenceActivity; public class Settings extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings); } }
Questa Activity estende PreferenceActivity e richiama il metodo addPreferencesFromResource(): questo legge le definizioni delle preferenze dallXML passato come parametro (R.xml.settings) e permette di creare le viste corrispondenti nellActivity corrente. Non dobbiamo dimenticare di inserire la nuova Activity nel file di configurazioneAndroidManifest.xml, nel quale aggiungiamo il seguente codice:

<activity android:name=<code>".Settings"</code> android:label=<code>"@string/settings_title"</code>></activity>


Lanciamo nuovamente lapplicazione, premiamo il pulsante del menu, selezioniamoImpostazioni e cambiamo i valori delle voci Item1 e Item2: se proviamo ad uscire dal programma e poi a rientrarci, vedremo che le voci di menu delle preferenze sono nuovamente entrambe attive, indifferentemente dalle nostre scelte precedenti. Questo succede perch non abbiamo gestito e memorizzati i valori delle scelte effettuate dallutente: questo argomento esula dal carattere introduttivo di queste lezioni, ma per ora possiamo considera che questi valori potrebbero essere memorizzati come dati locali dellapplicativo.

Gestione della localizzazione


I servizi di localizzazione in Android si basano su due API: quella del mapping e quella dellalocation. Queste API sono divise in due pacchetti separati ed indipendenti, rispettivamentecom.google.android.maps e android.location: lAPI del mapping fornisce strumenti che facilitano la visualizzazione e la manipolazione di una mappa, come ad esempio la gestione dello zoom e cambiare la modalit di visualizzazione (vista satellite, street view, ecc.), mentre lAPI location mette a disposizione strumenti per la gestione del GPS (Global Position System) e dei dati di localizzazione in tempo reale. In questa lezione implementeremo un semplice servizio che visualizzer alcune informazioni circa le coordinate geografiche che simuleremo ed invieremo allemulatore.

Modifichiamo il file /res/menu/menu.xml aggiungendo il codice seguente:

<item android:id="@+id/where_am_i" android:title="@string/where_am_i_label" android:alphabeticShortcut="@string/where_am_i_sho rtcut" />


con il quale inseriamo una nuova voce di menu per accedere allActivity che implementeremo tra poco. Chiaramente dobbiamo anche aggiornare il file delle risorse stringa/res/values/string.xml:

<string name="where_am_i_label">Dove Sono? </string> <string name="where_am_i_title">Dove Sono</string> <string name="where_am_i_shortcut">w</string>


A questo punto creaimo un nuovo file descrittore XML /res/layout/where.xml per la generazione del layout della nuova Activity:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_height="wrap_content" android:text="La locazione rilevata :" android:layout_width="fill_parent" android:textSize="16px" android:textStyle="bold" android:gravity="center_horizontal" android:layout_marginTop="10dip" android:layout_marginBottom="10dip" /> <EditText android:layout_height="wrap_content" android:text="" android:layout_width="fill_parent" android:id="@+id/editTextShowLocation" android:lines="10" android:gravity="top"/> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/buttonGetLocation" android:text="Carica Locazione" android:textSize="15px" android:textStyle="bold" android:layout_marginTop="10dip" /> </LinearLayout>
Il layout molto semplice: composto da una posto da una TextView per la visualizzazione di un testo introduttivo, un widget EditText per la visualizzazione dei dati e un Button per il caricamento dei dati. Il risultato sar simile al seguente:

Figura 19: Interfaccia con i dati di localizzazione (clic per ingrandire)

Come rappresentato nella figura 19, nel widget EditText visualizziamo la data odierna, lo strumento che ci fornisce i dati (GPS) e alcune informazioni relative alla posizione rilevata: longitudine, latitudine, altitudine, accuratezza. Vediamo in dettaglio il codice della classe Where.java che implementa lActivity:

package html.it.examples.com; import import import import import import import import import import import android.app.Activity; android.content.Context; android.location.Location; android.location.LocationListener; android.location.LocationManager; android.os.Bundle; android.text.format.DateFormat; android.view.View; android.view.View.OnClickListener; android.widget.Button; android.widget.EditText;

public class Where extends Activity { private EditText editText; private Button buttonLoad; private LocationManager lManager; private LocationListener lListener; private Location location; @Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); setContentView(R.layout.where); editText = (EditText) findViewById(R.id.editText); buttonLoad = (Button) findViewById(R.id.buttonLoad); buttonLoad.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonLoadClick(); } }); } private void getCurrentLocation() { lManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); lListener = new LocationListener() { @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public void onLocationChanged(Location loc) { // TODO Auto-generated method stub location = loc; } }; lManager.requestLocationUpdates(LocationManager.GPS_PROVID ER, 0, 0, lListener); }

private void buttonLoadClick() { this.getCurrentLocation(); if ( location != null ) {

lManager.removeUpdates(lListener); String provider = location.getProvider(); String data = DateFormat.format("dd/MM/yyyy", location.getTime()).toString(); String longitude = "Longitudine: " + location.getLongitude(); String latitude = "Latitudine: " + location.getLatitude(); String altitudine = "Altitudine: " + location.getAltitude(); String accuracy = "Precisione: " + location.getAccuracy(); editText.setText("Oggi il " + data + "nn" + "Informazioni fornite da: " + provider + "nn" + longitude + "n" + latitude + "n" + altitudine + "n" + accuracy + "n"); } else { editText.setText("Impossibile determinare la locazione!"); } } }
Recuperiamo i riferimenti delle risorse EditText e Button, ed impostiamo su questultima unlistener per gestire lazione associata al clic del bottone:

editText = (EditText) findViewById(R.id.editText); buttonLoad = (Button) findViewById(R.id.buttonLoad); buttonLoad.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonLoadClick(); } });
Ogni volta che premiamo il bottone Carica Locazione vengono caricati i dati che simuliamo ed inviamo attraverso la scheda di Eclipse per la gestione dei controlli dellemulatore, chiamata appunto Emulator Control. Per aprire la vista Emulator Control entriamo nella perspective DDMS (Dalvik Debug Monitor Server) che fornisce strumenti utili per il debugging delle applicazioni Android. Per selezionare la perspective DDMS dobbiamo seguire dal menu di Eclipse il percorso Window / Open Perspective / Other / DDMS. Il risultato sar simile al seguente: Figura 20: La perspective DDMS e i controlli di location (clic per ingrandire)

Come mostrato in figura 20, nella scheda Devices selezioniamo lemulatore al quale vogliamo inviare i dati GPS simulati (chiaramente nel caso in cui fosse collegato e opportunamente configurato un device reale potremmo anche selezionare questo). Una volta selezionato il device si attiveranno i controlli di locazione per linserimento dei dati: nella scheda a tab denominata appunto Emulator Control selezioniamo lopzione Decimal, inseriamo le coordinate per la longitudine, quella per la latitudine, e premiamo il pulsante Send per inviare i dati appena inseriti nel device selezionato precedentemente. A questo punto torniamo sullemulatore: premiamo il pulsante Carica Locazione. Il risultato sar molto simile a quanto rappresentato in figura 20. Ogni volta che premiamo e attiviamo il pulsante Carica Locazione viene richiamata la funzionebuttonLoadClick(). Questa funzione utilizza i metodi messi a disposizione dalla classeLocation per recuperare le informazioni che rappresentiamo nel widget EditText:

String provider = location.getProvider(); String data = DateFormat.format("dd/MM/yyyy", location.getTime()).toString(); String longitude = "Longitudine: " + location.getLongitude(); String latitude = "Latitudine: " + location.getLatitude(); String altitudine = "Altitudine: " + location.getAltitude(); String accuracy = "Precisione: " + location.getAccuracy(); editText.setText("Oggi il " + data + "nn" + "Informazioni fornite da: " + provider + "nn" + longitude + "n" + latitude + "n" + altitudine + "n" + accuracy + "n");
Richiamiamo il metodo setText() del controllo EditText al quale passiamo i dati raccolti, come ad esempio location.getLongitudine() e location.getLatitudine(), che sono proprio le coordinate che abbiamo inserito nella scheda Emulator Control.

Android e le applicazioni di rete


Le applicazioni che svilupperemo in ambito mobile saranno quasi sempre dotate di accesso ad Internet: per consultare notizie, per informarsi sul tempo atmosferico, per leggere le email, per rimanere in contatto con i proprio amici attraverso i social network o effettuare chiamate VoIP per risparmiare sulle telefonate.

In questa lezione vedremo come fornire alla nostra applicazione desempio la connettivit ad Internet e come sfruttare la piattaforma Android per implementare un semplice lettore di feed RSS (Really Simple Syndication). Per accedere ai servizi di rete su un device Android dobbiamo avere i permessi appropriati. Una app Android infatti pu utilizzare la maggior parte dei servizi di rete solo se nel proprio file di configurazioni AndroidManifest.xml vi sono le appropriate impostazioni. La prima cosa che facciamo dunque modificare il file AndroidManifest.xml della nostra applicazione desempio aggiungendo i permessi per lutilizzo di Internet:

<uses-permission android:name="android.permission.INTERNET"
Aggiungiamo una voce di menu al menu principale dellapplicazione per poter accedere al servizio RSS. Modifichiamo quindi il file /res/menu/menu.xml aggiungendo il seguente codice:

<item android:id="@+id/rss" android:title="@string/rss_label" android:alphabeticShortcut="@string/rss_shortcut " />


Aggiungiamo le nuove risorse stringa nel file /res/values/strings.xml per la voce di menu appena inserita:

<string name="rss_label">RSS</string> <string name="rss_title">RSS Feed</string> <string name="rss_shortcut">r</string>


Il risultato che otterremo sar simile a quanta rappresentato in figura 16: Figura 21: Lapplicazione con un pulsante per leggere gli RSS (clic per ingrandire)

Limplementazione del lettore di RSS divisa in due Activity diverse: la prima (RSS.java) quella in cui impostiamo il feed da leggere e il layout principale, la seconda (RSSItem.java) quella che genera la lista di elementi pubblicati nel feed con il relativo layout. Vediamo in dettaglio il codice della prima Activity RSS.java:

package html.it.examples.com; import import import import import android.app.Activity; android.os.Bundle; java.util.ArrayList; android.widget.ArrayAdapter; android.widget.ListView; {

public class RSS extends Activity

String feedUrl = ""; ListView rssListView = null; ArrayList<RSSItem> RSSItems = new ArrayList<RSSItem>(); ArrayAdapter<RSSItem> array_adapter = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.rssmain); feedUrl = "http://feeds.feedburner.com/Blogrammazione/"; refreshRSSList(); rssListView = (ListView) findViewById(R.id.rssListView); array_adapter = new ArrayAdapter<RSSItem>(this, R.layout.list_item, RSSItems); rssListView.setAdapter(array_adapter); refreshRSSList(); } private void refreshRSSList() { ArrayList<RSSItem> newItems = RSSItem.getRSSItems(feedUrl); RSSItems.clear(); RSSItems.addAll(newItems); } }
Inizialmente definiamo nella classe alcune variabili:

String feedUrl = ""; ListView rssListView = null; ArrayList<RSSItem> RSSItems = new ArrayList<RSSItem>(); ArrayAdapter<RSSItem> array_adapter = null;
La variabile feedUrl di tipo stringa ci servir per memorizzare lURL del feed da leggere;rssListView la variabile che conterr il riferimento al widget di tipo ListView contenuto nel descrittore XML che definisce il layout della lista di elementi letti dal feed; RSSItems una struttura di tipo ArrayList che conterr la lista degli elementi del feed (ognuno caratterizzato da un titolo, una descrizione, una data di pubblicazione e un link); array_adapter una variabile che conterr un oggetto di tipo ArrayAdapter che, come vedremo pi in dettaglio tra qualche istante, permette di legare degli oggetti anche di tipo arbitrario contenuti in un array con un determinato layout pi o meno complesso. Allinterno del metodo principale dellActivity onCreate(), impostiamo il feed che leggeremo, richiamiamo il metodo refreshRSSList() e creiamo lArray Adapter passando come parametri il contesto attuale (mediante il riferimento this), il file descrittore XML per il layout della lista (R.layout.list_item) ed infine il riferimento che conterr la lista di oggettiRSSItem:

feedUrl = "http://feeds.feedburner.com/Blogrammazione/"; refressRssList(); rssListView = (ListView) findViewById(R.id.rssListView); array_adapter = new ArrayAdapter<RSSItem>(this, R.layout.list_item, RSSItems); rssListView.setAdapter(array_adapter); refreshRSSList();
La funzione refreshRSSList recupera e aggiorna la lista di item letti dal feed e aggiunge questi elementi allArrayList che contiene tutte le voci del feed:

private void refreshRSSList() { ArrayList<RSSItem> newItems = RSSItem.getRSSItems(feedUrl); RSSItems.clear(); RSSItems.addAll(newItems); }


Il file descrittore XML /res/layout/rssitem.xml per il layout di questa Activity davvero molto semplice, visto che contiene solo un widget di tipo ListView:

<?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">

<ListView android:id="@+id/rssListView" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>


La seconda Activity, RSSItem.java, legge ogni elemento del feed e costruisce la lista di itemche vengono visualizzati nella precedente RSS.java:

package html.it.examples.com; import import import import import import java.io.InputStream; java.net.HttpURLConnection; java.net.URL; java.text.SimpleDateFormat; java.util.ArrayList; java.util.Date;

import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public class RSSItem { private private private private String title; String description; Date date; String link;

public RSSItem(String title, String description, Date pubDate, String link) { this.title = title; this.description = description; this.date = pubDate; this.link = link; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description;

} public Date getPubDate() { return date; } public void setPubDate(Date pubDate) { this.date = pubDate; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } @Override public String toString() { SimpleDateFormat sdf = new SimpleDateFormat("hh:mm MM/dd/yy"); String result = getTitle() + " sdf.format(this.getPubDate()) + " )"; return result; } ( " +

public static ArrayList<RSSItem> getRSSItems(String feedUrl) { ArrayList<RSSItem> rssItems = new ArrayList<RSSItem>(); try { URL url = new URL(feedUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStream is = conn.getInputStream(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(is); Element element = document.getDocumentElement();

NodeList nodeList = element.getElementsByTagName("item"); if (nodeList.getLength() > 0) { for (int i = 0; i < nodeList.getLength(); i++) { Element entry = (Element) nodeList.item(i); Element _titleE = (Element)entry.getElementsByTagName("title").item(0); Element _descriptionE = (Element)entry.getElementsByTagName("description").item(0); Element _pubDateE = (Element) entry.getElementsByTagName("pubDate").item(0); Element _linkE = (Element) entry.getElementsByTagName("link").item(0); String _title = _titleE.getFirstChild().getNodeValue(); String _description = _descriptionE.getFirstChild().getNodeValue(); Date _pubDate = new Date(_pubDateE.getFirstChild().getNodeValue()); String _link = _linkE.getFirstChild().getNodeValue(); RSSItem rssItem = new RSSItem(_title, _description, _pubDate, _link); rssItems.add(rssItem); } } } } catch (Exception e) { e.printStackTrace(); } return rssItems; } }
Questa Activity genera gli item dellRSS impostato precedentemente: ogni oggetto RSSItem ha un titolo, una descrizione, una data di pubblicazione e un link; per ogni attributo sono inoltre disponibili i classici metodi setter e getter.

Il cuore dellActivity il metodo getRSSItem(): qui apriamo una connessione URL con il server e recuperiamo i dati dellRSS. Se la connessione andata a buon fine allora utilizziamo il DocumentBuilderFactory e il DocumentBuilder per effettuare il parsing dellXML:

URL url = new URL(feedUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStream is = conn.getInputStream(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(is); Element element = document.getDocumentElement();
Con il metodo getElementsByTagName() della classe Element recuperiamo tutti gli elementiitem contenuti nellRSS (corrispondenti ai tag <item></item> nei dati XML) e li salviamo in un oggetto di tipo NodeList. Effettuiamo un ciclo for su tutti i nodi delloggetto NodeListcreando un oggetto RSSItem per ogni elemento presente, recuperiamo le informazioni dellitem (titolo, descrizione, data di pubblicazione e link) e lo aggiungiamo allArrayList:

NodeList nodeList = element.getElementsByTagName("item"); if ( nodeList.getLength() > 0 ) { for ( int i = 0; i < nodeList.getLength(); i++ ) {

Element entry = (Element) nodeList.item(i); Element _titleE = (Element)entry.getElementsByTagName("title").item(0); Element _descriptionE = (Element)entry.getElementsByTagName("description").item(0); Element _pubDateE = (Element) entry.getElementsByTagName("pubDate").item(0); Element _linkE = (Element) entry.getElementsByTagName("link").item(0); String _title = _titleE.getFirstChild().getNodeValue(); String _description = _descriptionE.getFirstChild().getNodeValue(); Date _pubDate = new Date(_pubDateE.getFirstChild().getNodeValue()); String _link = _linkE.getFirstChild().getNodeValue(); RSSItem rssItem = new RSSItem(_title, _description, _pubDate, _link); rssItems.add(rssItem); } }

Infine viene restituito loggetto ArrayList con tutti gli item del feed RSS analizzati e memorizzati. Anche il file descrittore XML per il layout da utilizzare per ogni item dellRSS molto semplice:

<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" android:textSize="13sp" android:autoLink="all" >
Utilizziamo solo un widget TextView per la visualizzazione dei dati di ogni item dellRSS. A questo proposito possiamo notare che abbiamo sovrascritto il metodo toString() per gli oggetti RSSItem, in modo che la stampa di un elemento di questo tipo permetta di visualizzarne il titolo e la data di pubblicazione, come mostrato nella figura seguente: Figura 22: Lapplicazione che legge i feed RSS (clic per ingrandire)