Android Manuale

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 un’area rettangolare nello schermo responsabile del disegno degli elementi grafici e della cattura e gestione degli eventi generati dall’utente. Un oggettoViewGroup è anch’esso una View, ma che contiene altre View. Nella piattaforma Android si utilizza il concetto di “layout” per gestire l’impaginazione dei controlli all’interno 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 guida possiamo scegliere approcci diversi per la costruzione delle interfacce in ambiente Android: la prima possibilità è quella di definire l’interfaccia 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. L’Activity è 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 dell’applicazione. Generalmente una Activity corrisponde ad un'azione specifica che l’utente 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 l’Activity 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.

description

manuale utente android in italiano

Transcript of Android Manuale

Page 1: Android Manuale

La visualizzazione: ViewAndroid 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 un’area rettangolare nello schermo responsabile del disegno degli

elementi grafici e della cattura e gestione degli eventi generati dall’utente. Un oggettoViewGroup è

anch’esso una View, ma che contiene altre View.

Nella piattaforma Android si utilizza il concetto di “layout” per gestire l’impaginazione dei controlli

all’interno 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 l’interfaccia 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à: ActivityLa classe Activity è uno degli elementi centrali di ogni applicazione Android. L’Activity è 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 dell’applicazione.

Generalmente una Activity corrisponde ad un'azione specifica che l’utente 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 l’Activity 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.

Page 2: Android Manuale

Le azioni: IntentUn Intent è un meccanismo che descrive un’azione 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 l’invio di email possiamo invocare l’Intent che il sistema ci mette a disposizione, oppure possiamo

scriverne uno nuovo e utilizzare quest’ultimo nelle nostreActivity sostituendo l’Intent di default con quello

implementato da noi.

Possiamo immaginare un Intent come un’azione 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 l’informazione per cui un particolare evento (o azione) si è verificato;

•esplicitare un’intenzione 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 l’interazione tra qualsiasi applicazione installata sul dispositivo Android, senza doversi preoccupare di che tipo di applicazione sia o di quale componente software gli Intentfacciano parte.

L’Intent è 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 ProviderUn 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 un’altra. 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 l’accesso 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.

Page 3: Android Manuale

Un database SQLite in un device Android è un esempio di sorgente di dati che possiamo incapsulare

all’interno di un Content Provider: Chiaramente Android è provvisto di un insieme di Content Provider nativi,

documentati nel package “android.provider” dell’SDK. 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 ServiceUn Service è un processo che gira in background senza la diretta interazione con l’utente (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

un’altra 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

dell’applicazione, inclusi altri Service e Activity. Se la nostra applicazione deve svolgere attività che non

dipendono direttamente dall’input inserito dall’utente, allora implementare un Service potrebbe essere la

risposta alle nostre necessità: applicazioni che si aggiornano regolarmente ma che raramente o ad

intermittenza interagiscono con l’utente 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. L’unica 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 l’utente potrebbe essere necessario

incrementare la sua priorità come quella di un’Activity 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

dell’esperienza utente.

Page 4: Android Manuale

Il cuore di un’applicazione Android: AndroidManifest.xmlL’AndroidManifest.xml è il file che definisce i contenuti e il comportamento della nostra applicazione:

all’interno di questo file sono elencate le Activity e i Service dell’applicazione, 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 l’un l’altro

e con le altre applicazioni.

Come abbiamo visto ogni applicazione gira all’interno 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 l’accesso a diverse operazioni critiche sono protette, e dobbiamo

specificatamente chiedere i permessi per utilizzarle. Questo tipo di richieste vanno impostate

nell’AndroidManifest.xml .

Quando l’applicazione viene installata il gestore dei pacchetti concede o non concede i privilegi a seconda di

come li abbiamo configurati nell’AndroidManifest.xml.

Tra i principali permessi che possiamo richiedere ci sono i seguenti:

•READ_CONTACTS: leggere (ma non scrivere) i dati dei contatti dell’utente.

•WRITE_CONTACTS: scrivere (ma non leggere) i dati dei contatti dell’utente

•RECEIVE_SMS: monitorare l’arrivo 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 dell’applicazione, l’ambiente di sicurezza, e tutto ciò che fa parte dell’applicazione. 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 dispositiviL’Android 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. L’SDK di Android non include alcun

Page 5: Android Manuale

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 all’interno

dell’IDE) permette di gestire come facilità gli AVD e gli emulatori. In particolare permette di lanciare

automaticamente l’emulatore all’interno dell’AVD selezionato per testare o effettuare il debug dei nostri

progetti. Ovviamente chi non volesse utilizzare Eclipse e il plugin corrispondente può controllare l’emulatore

attraverso la linea di comando (il terminale).

Resource : la gestione delle risorse in AndroidUna 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 dell’applicazione Android.

Tutte le Resource vengono compilate all’interno dell’applicazione: questo è molto utile per implementare

l’internazionalizzazione 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 un’applicazioneOra 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,

Page 6: Android Manuale

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 dell’applicazione,

“com.html_it.examples” come nome del pacchetto, “HelloWordActivity” come nome dell’Activity. La stringa

che inseriamo come nome dell’applicazione è quella che comparirà nella barra del titolo dell’applicazione,

dunque in una implementazione reale bisogna avere qualche accortezza per la scelta di questo nome.

Figura 3: La finestra di configurazione dell'applicazione

Page 7: Android Manuale

Rimane da selezionare il build target per l’applicazione, 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 l’ADT genererà la struttura rappresentata nella Figura 4: questa

struttura rimane molto simile anche per applicazioni più complesse e di maggiori dimensioni rispetto

all’esempio “HelloWord”. La struttura la vedremo in dettaglio nella lezione successiva.

Figura 4: La struttura di un'applicazione Android

Page 8: Android Manuale

Struttura di un’applicazioneRiproponiamo, per comodità, la Figura 4 già vista nella lezione precedente e ne descriveremo in dettaglio le varie componenti.

Figura 4: La struttura di un’applicazione Android

Page 9: Android Manuale

Un’applicazione 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 l’organizzazione 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 all’interno della directory “layout” (e

ovviamente all’interno delle altre sottocartelle dirette della directory “res”) il sistema non riconosce le

sottocartelle create.

Un’altra 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”

Page 10: Android Manuale

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 dall’applicazione,

come ad esempio stili, stringhe e definizioni di colori (sempre sottoforma di descrittori XML).

Creare un dispositivo di emulazionePer eseguire il building e il debugging di una applicazione Android dobbiamo prima completare i seguenti passi:

1.Configurare un Android Virtual Device (AVD) per l’emultatore

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: l’IDE collegherà il debugger

all’emulatore Android (o allo smartphone che usiamo per sviluppare) così potremo liberamente eseguire il

debug delle applicazione in maniera comoda e precisa.

Android Virtual Device

L’Android Virtual Device descrive il tipo di device che l’emulatore può simulare, includendo la piattaforma

Android supportata (Android 1.6, Android 2.1 e così via). La configurazione dell’AVD 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 l’Android SDK e AVD Manager da Eclipse cliccando sull’icona 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

Page 11: Android Manuale

2.Comparirà un dialog diviso in due parti: il menu e il pannello gestionale. Clicchiamo sulla voce“Virtual Devices” visibile nel box di sinistra: nella parte destra del dialog comparirà l’elenco 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 l’AVD; 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: l’immagine 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 dell’emulatore. 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)

Page 12: Android Manuale

Finito il processo di creazione potremo vedere l’AVD 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 l’esecuzione e il debugPrima 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.Nell’elenco 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

Page 13: Android Manuale

“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 nell’utilizzare 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 all’utilizzo 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.L’applicazione viene installata nel device vituale selezionato;

5.L’applicazione viene fatta partire nel device vituale.

Page 14: Android Manuale

Eseguire test sull’emulatore e sullo smartphoneVediamo 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 l’emulatore: 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 l’emulatore è pronto per l’interazione

possiamo premere e trascinare il pulsante di sblocco con il lucchetto verde finché non sblocchiamo il device

virtuale, come possiamo vedere nell’immagine 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

Page 15: Android Manuale

Come possiamo vedere nella Figura 9, l’applicazione è 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 nell’emulatore 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 l’SDK 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.

Page 16: Android Manuale

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

dell’applicazione. 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: quest’ultima opzione disabilita il controllo sull’attivazione 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 l’ultimo passaggio, Eclipse installerà l’applicazione Android nel device che abbiamo selezionato

dall’elenco dei device disponibili (reali o virtuali) e la eseguirà. Se abbiamo eseguito questa procedura per

l’applicazione “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. L’attivazione permanente dello schermo, se non

disabilitata, ovviamente porta ad un rapido scaricamento della batteria, mentre l’attivazione delle altre opzioni

al di fuori del contesto di sviluppo lascia aperte notevoli falle per la sicurezza del nostro device.

Definire caratteristiche e interfaccia graficaSviluppare software è un’attività 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 è

un’attività che richiede particolari attenzioni perché ci muoviamo in un ambiente in cui le risorse sono limitate,

i monitor sono di piccole dimensioni e l’efficienza 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:

Page 17: Android Manuale

•Splash: lo splash rappresenta l’immagine visualizzata quando l’applicazione è in fase di caricamento, in cui normalmente vengono rappresentati il logo del gioco o dell’applicativo e il numero di versione. È anche molto comune la presenza di una musica di sottofondo;

•Menu: il menu permette all’utente di scegliere tra diverse opzioni, come ad esempio configurare l’applicativo, avviare il gioco, vedere i punteggi, accedere ai credits, visualizzare l’help e così via ;

•Avvio: questa schermata è quella che compare una volta avviato il gioco o l’applicativo;

•Help: il compito dell’help è quello di visualizzare le istruzioni di utilizzo del gioco o dell’applicativo, 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 sull’azienda o su chi si è occupato dello sviluppo o della distribuzione dell’applicativo: 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à d’uso 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 l’implementazione dell’interfaccia grafica nel codice: ad esempio, in un’applicazione Swing

scriviamo il codice Java per creare e manipolare tutti gli oggetti dell’interfaccia utente, come JButton, JFrame

e così via.

La creazione dichiarativa non richiede la scrittura di codice: l’esempio tipico del metodo dichiarativo è

rappresentato dalla creazione di una pagina web statica, in cui utilizziamo l’HTML per descrivere cosa

vogliamo vedere nella pagina. L’HTML è dunque dichiarativo.

Android permette la creazione di interfacce sia procedurali sia dichiarative: possiamo creare un’interfaccia

utente completamente in codice Java (metodo procedurale) oppure possiamo creare l’interfaccia utente

attraverso un descrittore XML (metodo dichiarativo). Android inoltre permette anche un approccio ibrido, in

cui si crea un’interfaccia 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.

Page 18: Android Manuale

Specificare le attività dell’applicazioneAbbiamo 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à l’Activity 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 dell’applicazione. Inoltre ad ogni pulsante assoceremo un gestore per l'evento “clic pulsante”, in modo tale che una volta premuto venga lanciata l’Activity legata al pulsante stesso;

3.PlayActivity: questa Activity sarà la reale implementazione del gioco; sarà responsabile di gestire gli input dell’utente, 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 all’interno del layout stesso.

Possiamo inoltre servirci di schemi e wireframe per analizzare e studiare la navigabilità e l’usabilità 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 all’implementazione. Tenendo presenti le caratteristiche del nostro gioco teorico MyTris, vedremo in questa lezione alcuni dettagli e principi che sono alla base dello sviluppo di un’applicazione Android. Vedremo poi come metterli in pratica.

Il primo elemento che vedremo più in dettaglio è l’application context. L’application context è un elemento

centrale e importante per tutte le funzionalità disponibili al più alto livello applicativo: possiamo utilizzare

l’application context per accedere alle risorse e alle impostazioni condivise tra istanze di diverse Activity.

Una volta recuperato l’application context, ad esempio con il seguente codice:

Context context = getApplicationContext();

possiamo utilizzarlo per accedere ad un ampio insieme di caratteristiche e servizi a disposizione

dell’applicazione. Ad esempio possiamo richiamare il metodogetSharedPreferences() dell’application

context per recuperare le preferenze condivide dell’applicazione, oppure possiamo richiamare il

metodo getResources() per recuperare le risorse dell’applicazione:

String hello =

Page 19: Android Manuale

context.getResources().getString(R.string.hello);

Visto che la classe Activity deriva dalla classe Context possiamo utilizzare il riferimentothis oppure

richiamare esplicitamente l’application context.

Potremmo dunque riscrivere l’esempio precedente come segue:

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

L’application context lo utilizziamo anche per:

1.Lanciare istanze di Activity.

2.Gestire le directory, i database e i file protetti dell’applicazione.

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 dell’applicazione.

Possiamo dunque utilizzare l’application context per lanciare istanze delle Activity. Per il nostro gioco di

esempio MyTris, dovremmo implementare, ad esempio, cinque Activity, una per ogni schermata.

Oltre all’application 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 un’Activity 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 un’immagine 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 dell’input dell’utente, e molto altro

ancora.

Running sull’emulatoreDurante l’implementazione possiamo servirci dell’emulatore per testare il nostro lavoro: questo strumento è molto comodo perché ci fornisce un preciso feedback sull’andamento 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 l’emulatore non implementa tutte le caratteristiche hardware

supportate da Android, come la fotocamera, la vibrazione, i LED, l’accelerometro, e molto altro ancora.

In tutti quei casi in cui l’applicativo 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).

Page 20: Android Manuale

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 LayoutIniziamo 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 orizzontale ha una riga di oggetti View, mentre un layout verticale è composto da una colonna di oggetti View);

•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;

•FrameLayout: questa è la tipologia più semplice di layout, perché non fa altro che posizionare in ordine di inserimento tutti gli oggetti View partendo dall’angolo 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 l’attributoorientation impostato

a vertical. Il layout contiene un widget figlio di tipo TextView, sostanzialmente un oggetto che visualizza del

testo (quello contenuto dalla risorsa indicata nell’attributo 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 un’applicazione di prova

Page 21: Android Manuale

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 l’immagine, è 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

l’identificatore-nome “hello”: questo è il motivo per cui quando lanciamo il test di questa applicazione vediamo

il seguente risultato:

Figura 12: L’interfaccia con le nuove stringhe

(clic per ingrandire)

Page 22: Android Manuale

dove il cerchio in verde evidenzia il valore stampato a video della risorsa stringa che contiene il nome

dell’applicazione (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 poc’anzi. 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

l’impostazione 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"

Page 23: Android Manuale

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 poc’anzi 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: L’interfaccia con l’oggetto EditText

(clic per ingrandire)

La figura 14 mostra un layout molto diverso dalla versione precedente (v. figura 12). Abbiamo modificato

anche il nome dell’applicazione: 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”.

Page 24: Android Manuale

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 l’interfaccia di un semplice

form e gestirne l’invio dei dati.

Gestione dell’input: lavoriamo con i form5.2 Gestione dell’input: lavoriamo con i formAggiungiamo alla nostra applicazione Android di esempio dei moduli per gestire le interazioni con l’utente

Proseguiamo lo studio della piattaforma Android ed introduciamo la gestione dei form e dell’input utente. In

questa lezione riprenderemo il progetto introdotto nelle lezioni precedenti: modificheremo il layout per creare

un form ed impareremo a gestire l’invio 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"

Page 25: Android Manuale

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à l’invio 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 l’invio del form. Prima di vedere il dettaglio del file risorse

Page 26: Android Manuale

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, un’unità 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 dall’attributo name il cui valore è contenuto all’interno dei tag<string></string> e verrà

visualizzato lì dove la risorsa sarà richiamata.

Prima di analizzare il restante codice anticipiamo cosa vogliamo ottenere. Abbiamo un’Activitydi default che

crea l’interfaccia vista poc’anzi e che, attraverso il clic del pulsante Invia invierà ad un’altra Activity i dati che

l’utente inserirà nelle opportune caselle di testo, la quale li visualizzerà con un’altra 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

l’Activity di default. Analizziamo in dettaglio il codice di questo file:

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

Page 27: Android Manuale

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 l’Activity 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

l’interfaccia OnClickListener).

Una classe che implementa l’interfaccia OnClickListener deve obbligatoriamente implementare il

metodo OnClick(), metodo in cui si gestisce l’azione eseguita, in questo caso il clic sul Button Invia:

soffermiamoci dunque sulla gestione dell’evento.

La prima cosa da fare (righe 23-24) è recuperare i riferimenti dei controlli EditText definiti precedentemente e

che serviranno per salvare i dati inseriti dall’utente, in questo caso il nome ed il cognome:

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

Page 28: Android Manuale

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 dall’utente:

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

Utilizziamo il metodo putString() dell’oggetto bundle per salvare i dati inseriti, recuperati poi con il

metodo getText() del widget EditText.

Con i dati memorizzati nel Bundle creiamo l’Intent per la chiamata dell’Activity alla quale li vogliamo passare

(righe 28-30), nel nostro caso Form.class, associamo all’Intent il Bundle ed infine lanciamo l’Activity :

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

A questo punto l’applicativo “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 dall’utente ed inviati

dall’Activity 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 all’invio del modulo

(clic per ingrandire)

Page 29: Android Manuale

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>

Page 30: Android Manuale

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

l’applicazione vediamo dunque come modificare l’AndroidManifest.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 l’esistenza di una nuova Activity, è quello evidenziato.

Menu e dialogIn 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 l’apposito 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)

Page 31: Android Manuale

Il menu Impostazioni si attiva premendo il pulsante Menu dell’emulatore 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/settings_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

all’Activity di default, in modo che quando premiamo il tasto fisico di menu dell’emulatore o dello smartphone

l’Activity di default sappia come gestire tale evento. Per fare questo aggiungiamo le seguenti

direttive import:

Page 32: Android Manuale

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

e implementiamo l’override del metodo onCreateOptionsMenu():

@Override

Il metodo getMenuInflater() restituisce un’istanza di MenuInflater che utilizziamo per leggere la

definizione del menu dall’XML vista poc’anzi e trasformarla in una View effettiva. Ogni volta che viene

selezionata una voce di menu viene richiamato il metodoonOptionsItemSelected() di cui implementiamo

l’override sempre nella stessa classe, proprio per gestire la selezione della voce di menu Impostazioni:

@Overridepublic 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 l’abbiamo associato all’Activity 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

l’azione corrispondente, nel nostro caso lanciare l’Activity Settings che vedremo tra poco.

Android mette a disposizione degli strumenti che semplificano molto la definizione di tutte le preferenze

dell’applicativo 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 l’utente può personalizzare alcuni comportamenti dell’applicazione.

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, l’utente 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 dell’HTML). Anche in questo caso dobbiamo aggiornare il file risorsa /res/values/string.xml per le

valorizzazioni delle voci di menu delle preferenze:

Page 33: Android Manuale

<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 dall’XML passato come parametro (R.xml.settings) e

permette di creare le viste corrispondenti nell’Activity 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 l’applicazione, 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 dall’utente: questo

argomento esula dal carattere introduttivo di queste lezioni, ma per ora possiamo considera che questi valori

potrebbero essere memorizzati come dati locali dell’applicativo.

Gestione della localizzazioneI 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: l’API 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 l’API 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 all’emulatore.

Page 34: Android Manuale

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_shortcut" />

con il quale inseriamo una nuova voce di menu per accedere all’Activity 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:

Page 35: Android Manuale

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 l’Activity:

package html.it.examples.com; import android.app.Activity;import android.content.Context;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.os.Bundle;import android.text.format.DateFormat;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import 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) {

Page 36: Android Manuale

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_PROVIDER, 0, 0, lListener); } private void buttonLoadClick() { this.getCurrentLocation(); if ( location != null ) {

Page 37: Android Manuale

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 quest’ultima unlistener per

gestire l’azione 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 dell’emulatore, 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)

Page 38: Android Manuale

Come mostrato in figura 20, nella scheda Devices selezioniamo l’emulatore 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

l’inserimento dei dati: nella scheda a tab denominata appunto Emulator Control selezioniamo

l’opzione 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 sull’emulatore: 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 reteLe 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.

Page 39: Android Manuale

In questa lezione vedremo come fornire alla nostra applicazione d’esempio 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

d’esempio aggiungendo i permessi per l’utilizzo di Internet:

<uses-permission android:name="android.permission.INTERNET"

Aggiungiamo una voce di menu al menu principale dell’applicazione 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: L’applicazione con un pulsante per leggere gli RSS

(clic per ingrandire)

Page 40: Android Manuale

L’implementazione 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 android.app.Activity;import android.os.Bundle;import java.util.ArrayList;import android.widget.ArrayAdapter;import 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:

Page 41: Android Manuale

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 l’URL 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.

All’interno del metodo principale dell’Activity onCreate(), impostiamo il feed che leggeremo, richiamiamo il

metodo refreshRSSList() e creiamo l’Array 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

all’ArrayList 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">

Page 42: Android Manuale

<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 java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.text.SimpleDateFormat;import java.util.ArrayList;import 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 String title; private String description; private Date date; private 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;

Page 43: Android Manuale

} 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();

Page 44: Android Manuale

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 dell’RSS 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.

Page 45: Android Manuale

Il cuore dell’Activity è il metodo getRSSItem(): qui apriamo una connessione URL con il server e

recuperiamo i dati dell’RSS. Se la connessione è andata a buon fine allora utilizziamo

il DocumentBuilderFactory e il DocumentBuilder per effettuare il parsing dell’XML:

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 nell’RSS (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 dell’oggetto NodeListcreando un

oggetto RSSItem per ogni elemento presente, recuperiamo le informazioni dell’item (titolo, descrizione, data

di pubblicazione e link) e lo aggiungiamo all’ArrayList:

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); }}

Page 46: Android Manuale

Infine viene restituito l’oggetto ArrayList con tutti gli item del feed RSS analizzati e memorizzati.

Anche il file descrittore XML per il layout da utilizzare per ogni item dell’RSS è 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 dell’RSS. 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: L’applicazione che legge i feed RSS

(clic per ingrandire)