Android Programming
Android Programming
Android
PROGRAMMING
PROGRAMMARE
GOOGLE ANDROID
PRIMO APPUNTAMENTO ALLA SCOPERTA DI ANDROID. INSTALLEREMO GLI STRUMENTI
DI SVILUPPO NECESSARI E FAREMO LA CONOSCENZA DEI PRINCIPI DI BASE CHE REGOLANO
IL FUNZIONAMENTO DEL SISTEMA MOBILE REALIZZATO DA GOOGLE
M
eno di due anni fa Google ha rilasciato
una versione preliminare del kit di svi-
luppo di Android, il suo nuovo SO
dedicato agli smartphone. Futurologi e semplici
appassionati si divisero immediatamente tra
entusiasti e scettici. I detrattori, in particolar
modo, hanno sempre visto in Android un esperi-
mento, e non qualcosa di reale al quale i produt-
❑ CD ❑ WEB tori di dispositivi avrebbero creduto. A loro favo-
corsoandroid1.zip
re ha deposto il fatto che, per un periodo piutto-
cdrom.ioprogrammo.it
sto lungo, nessuno smartphone equipaggiato
con Android ha fatto capolino sul mercato, ben-
ché il sistema e i suoi strumenti di sviluppo fos-
sero ormai disponibili da parecchio tempo. La Fig. 1: L’architettura di Google Android
tecnica di Google, in realtà, era ed è ancora quel-
la di sempre: far venire l’acquolina in bocca (e far
parlare di sé) con versioni preliminari dei suoi
software e dei suoi servizi. COME È FATTO
Nel caso di Android, molti sviluppatori sono ANDROID
stati fidelizzati e fatti appassionare a un siste- Android, essendo un sistema operativo di
ma che, allora, non era ancora sul mercato. moderna fattura, è abbastanza complesso.
Nel frattempo le cose sono cambiate: Android Anche se il suo target sono i dispositivi mobi-
è stato consolidato, e molti produttori di li, l’architettura di Android ha poco da invi-
dispositivi mobili hanno aderito o stanno ade- diare a quelle dei comuni sistemi per desktop
rendo all’alleanza capeggiata da Google. o laptop. Tale architettura è presentata sche-
Grazie alle strategie di Google, esiste già una maticamente in Fig.1.
comunità molto ampia di sviluppatori, estre- Come si evince dalla figura, Google ha attinto
mamente produttiva, che altri sistemi mobili a piene mani dal mondo Open Source.
non possono vantare. Migliaia di applicazioni Il cuore di ogni sistema Android, tanto per
sono state già sviluppate, e molte altre lo cominciare, è un kernel Linux, versione 2.6.
saranno nei prossimi tempi. Direttamente nel kernel sono inseriti i driver
Il sistema appare inoltre stabile ed offre per il controllo dell’hardware del dispositivo:
REQUISITI
potenzialità molto ampie. Per questo motivo, driver per la tastiera, lo schermo, il touchpad,
a partire dal numero che state leggendo, il Wi-Fi, il Bluetooth, il controllo dell’audio e
Conoscenze richieste
Basi di Java ioProgrammo dedicherà ad Android un corso così via. Sopra il kernel poggiano le librerie
di programmazione a puntate. fondamentali, anche queste tutte mutuate dal
Software Si comincia, naturalmente, con lo studio del- mondo Open Source. Da citare sono senz’al-
Java SDK (JDK) 5+,
Eclipse 3.3 l’architettura del sistema, l’installazione e tro OpenGL, per la grafica, SQLite, per la
l’utilizzo degli strumenti di sviluppo, un gestione dei dati, e WebKit, per la visualizza-
Impegno primo compendio sui principi di base della zione delle pagine Web. Insomma, nei prossi-
¥ programmazione Android e lo sviluppo di una mi mesi avremo di che discutere!
Tempo di realizzazione prima semplice applicazione del tipo “Ciao L’architettura prevede poi una macchina vir-
Mondo”. tuale e una libreria fondamentale che, insie-
h t t p : / / w w w. i o p r o g r a m m o . i t
4 14 /Ottobre 2009
G And roi d pr o g r am m in g
GliGli strumenti
strumenti necessari
necessari per imparare
per imparare a programmare
a programmare Android Android Android
� COVER STORY
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Ottobre 2009/ 15 G
5
COVER
AndroidSTORY �
programming Gli strumenti necessari
Gli strumenti per imparare
necessari a programmare
per imparare a programmareAndroid
Android
Eclipse, che sono la 3.3, la 3.4 e anche la nuova equipaggiato con Android. Per sviluppare le
3.5. Può essere installato direttamente dall’in- applicazioni, quindi, dobbiamo imparare a
terno della piattaforma di sviluppo. interagire con questo emulatore. Il primo
Avviate Eclipse ed eseguite il wizard per concetto che si deve assimilare è quello che
l’installazione di nuovi componenti. In Eclipse ha nome Android Virtual Device (AVD), cioè
3.5 lo si fa con la voce di menu “Help » Install dispositivo virtuale Android. Nel nostro PC
New Software”. Nella 3.4 la voce di menu è “Help possiamo creare e configurare quanti disposi-
» Software Updates”, e poi si deve selezionare la tivi virtuali vogliamo. È come avere tanti diffe-
scheda “Available software”. In Eclipse 3.3, infine, renti smartphone da utilizzare per i propri
la voce di menu da richiamare è “Help » Softwa- test, solo che invece di dispositivi di plastica e
re Updates » Find and install”, scegliendo poi silicio si tratta di macchine virtuali, fatte cioè
“Search for new features to install”. Giunti a de- di puro software, da eseguire attraverso
stinazione, scegliete l’opzione per aggiungere l’emulatore. In questo modo è anche possibi-
un nuovo sito remoto alla lista delle fonti pre- le avviare contemporaneamente sullo stesso
sentate dal wizard (pulsante “Add”). L’indirizzo PC due o più dispositivi virtuali, ad esempio
da specificare è: per testare un’applicazione che fa interagire
https://dl-ssl.google.com/android/eclipse/r più smartphone, come una chat o un gioco
A questo punto selezionate la voce corrispondente multiplayer. Impariamo allora a gestire
alla nuova fonte e procedete attraverso i singo- l’elenco dei dispositivi virtuali configurati nel
li passi del wizard. Il plug-in per lo sviluppo del nostro Android SDK. È possibile gestirli da
software Android sarà automaticamente scari- riga di comando, usando il comando android
cato e installato. Dopo il riavvio di Eclipse, recatevi che è nella cartella tools del kit di sviluppo, ma
immediatamente nella schermata delle preferenze l’uso dell’interfaccia di gestione resa disponi-
dell’ambiente (voce di menu “Window » Prefe- bile da ADT in Eclipse ci renderà l’operazione
rences”). Qui troverete disponibile la nuova ca- senz’altro più agevole. Attivate la voce di
tegoria “Android”, nell’elenco sulla sinistra. menu “Window » Android AVD Manager”.
Selezionatela e impostate il percorso del vostro
Android SDK: è necessario affinché Eclipse pos-
sa agganciare il kit di sviluppo. Durante questa
fase dovreste anche ricevere un pop-up per
l’accettadella licenza del plug-in.
Per ora è possibile tralasciare le altre possibili • Name: il nome che si vuole attribuire al
impostazioni collegate al plug-in: imparere- dispositivo virtuale, ad esempio “Android1”.
mo ad usarle più avanti, quando avremo • Target: la tipologia del dispositivo. Sceglia
preso più confidenza con l’ambiente. mo Android 1.5. Creeremo così un disposi
tivo virtuale compatibile con la versione 1.5
delle specifiche di Android.
• SD Card: qui è possibile dotare il dispositi
GESTIONE DEGLI AVD vo virtuale di una scheda di memoria vir-
Il kit di sviluppo comprende un emulatore che tuale. È possibile specificare sia il percorso
ci consentirà di provare le nostre creazioni sul di un file di immagine di una scheda di me
PC, prima di installarle su un reale dispositivo moria, se si vuole riutilizzare una memoria
6 16 /Ottobre 2009
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
GliGli strumenti
strumenti necessari
necessari per imparare
per imparare a programmare
a programmare Android Android Android
� COVER STORY
programming
virtuale esi stente, sia una dimensione di sistema per un’interazione di più basso livello
spazio, per creare una nuova memoria con il dispositivo.
virtuale. Percorriamo quest’ultima strada e
specifi chiamo il valore “64M”. Verrà così
creata una scheda di memoria virtuale di 64
MB.
• Skin: dall’elenco è possibile scegliere la riso
luzione del dispositivo. Le scelte possibili
sono HVGA-P (equivalente a 480x320),HV
GA-L (320x480), QVGA-P (320x240) e QVGA-
L (240x320). C’è poi una scelta di default
chiamata semplicemente HVGA, che corri
sponde comunque a HVGA-P. Lascia mola
selezionata.
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Ottobre 2009/ 17 G
7
COVER
AndroidSTORY �
programming Gli strumenti necessari
Gli strumenti per imparare
necessari a programmare
per imparare a programmareAndroid
Android
h t t p : / / w w w. i o p r o g r a m m o . i t
8 18 /Ottobre 2009
G And roi d pr o g r am m in g
GliGli strumenti
strumenti necessari
necessari per imparare
per imparare a programmare
a programmare Android Android Android
� COVER STORY
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Ottobre 2009/ 19 G
9
COVER
AndroidSTORY �
programming Gli strumenti necessari
Gli strumenti per imparare
necessari a programmare
per imparare a programmareAndroid
Android
h t t p : / / w w w. i o p r o g r a m m o . i t
/Ottobre 2009
10 20
G And roi d pr o g r am m in g
GliGli strumenti
strumenti necessari
necessari per imparare
per imparare a programmare
a programmare Android Android Android
� COVER STORY
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Ottobre 2009/ 21 11
G
MOBILE
Android �
programming La gestione delle risorse
La gestione nei programmi
delle risorse Android
nei programmi Android
LE RISORSE ESTERNE
IN GOOGLE ANDROID
IN QUESTO SECONDO ARTICOLO IMPAREREMO A MANIPOLARE LE RISORSE ESTERNE.
SCOPRIREMO CHE ANDROID RENDE FACILE L’UTILIZZO DI TUTTO QUELLO CHE, PUR NON
ESSENDO CODICE, È INDISPENSABILE AL CORRETTO FUNZIONAMENTO DI UN’APPLICAZIONE
S
e c’è un aspetto di Android dal quale si
evince la modernità di questo sistema, è la
sua maniera di gestire le risorse e i dati.
Nelle piattaforme di sviluppo meno moderne,
spesso e volentieri, le risorse esterne come i dati
di configurazione, i messaggi di interfaccia, le
immagini o altro materiale simile, sono trattate
senza alcun riguardo speciale. Android, invece,
❑ CD ❑ WEB richiede che i progetti siano organizzati in una
Android144.zip
certa maniera. La corretta gestione delle risorse
cdrom.ioprogrammo.it
in questa piattaforma, è importante tanto quan-
to la stesura del codice. In un certo senso, con
Android non si può imparare a programmare se
prima non si apprende come organizzare e
richiamare le risorse. Perciò, dedichiamo all’ar-
gomento questo secondo articolo del corso.
h t t p : / / w w w. i o p r o g r a m m o . i t
12 58 / Novembre 2009
G And roi d pr o g r am m in g
La gestione
La gestione delle risorse
delle risorse nei programmi
nei programmi AndroidAndroid Android
� MOBILE
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Novembre 2009 / 59 13
G
MOBILE
Android �
programming La gestione delle risorse
La gestione nei programmi
delle risorse Android
nei programmi Android
zioni per richiamare le risorse dalle varie parti • @color, per i colori.
del software. Sostanzialmente un’applicazione • @dimen, per le dimensioni.
Android è costituita da file dichiarativi XML e da • @drawable, per i valori drawable, ma anche
classi Java. Sia in un caso sia nell’altro, ci sono per le immagini messe in res/drawable.
scorciatoie per richiamare le risorse incluse in • @layout, per richiamare i layout presenti nella
res. Cominciamo dal caso XML e prendiamo a cartella res/layout.
riferimento il più importante dei file di questo • @raw, per i file nella cartella res/raw (cfr. box
tipo: AndroidManifest.xml. Quando, al suo inter- laterale).
no, si dichiarano i dettagli dell’applicazione, è • @string, per le stringhe.
possibile scrivere qualcosa come: • @style, per gli stili.
14 60 / Novembre 2009
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
La gestione
La gestione delle risorse
delle risorse nei programmi
nei programmi AndroidAndroid Android
� MOBILE
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Novembre 2009 / 6115
G
MOBILE
Android �
programming Scopriamo cosa sono
Scopriamo e come
cosa sono si programmano
e come le le“Attività”
si programmano “Attività”
COME IL SISTEMA
GESTISCE LE ATTIVITÀ
TERZO APPUNTAMENTO. LE “ATTIVITÀ” SONO IL COMPONENTE SOFTWARE PIÙ UTILIZZATO
DAI PROGRAMMATORI ANDROID. IN QUESTO ARTICOLO IMPAREREMO COS’È UN’ATTIVITÀ,
COME VIENE GESTITA DAL SISTEMA E COME POSSIAMO REALIZZARNE DI NOSTRE
L
e applicazioni Android, come si è accennato che le attività sono quei componenti di un’applica-
durante la prima lezione di questo corso, si zione Android che fanno uso del display e che inte-
compongono di quattro mattoni fondamen- ragiscono con l’utente.
tali: le attività (activity), i servizi (service), i broadca- Dal punto di vista del programmatore, poi, possia-
st receiver e i content provider. Ogni applicazione è mo spingerci oltre e semplificare ulteriormente.
formata da uno o più di questi mattoni. Non è detto In maniera più pragmatica, un’attività è una classe
che li contenga tutti: ad esempio potrebbe essere che estende android.app.Activity. L’autore del codi-
costituita da due attività e da un servizio, senza ce, realizzando l’attività, si serve dei metodi eredi-
❑ CD ❑ WEB avere broadcast receiver né content provider. Nella tati da Activity per controllare cosa appare nel
corso_android_pt3.zip
stragrande maggioranza dei casi, comunque, le display, per assorbire gli input dell’utente, per
cdrom.ioprogrammo.it
applicazioni comprendono almeno un’attività. Le intercettare i cambi di stato e per interagire con il
attività, di conseguenza, sono il più fondamentale sistema sottostante.
dei componenti di base delle applicazioni Android.
CICLO DI VITA
COS’È UN’ATTIVITÀ DI UN’ATTIVITÀ
Stando alla documentazione ufficiale, un’attività è In un sistema desktop il monitor è sufficientemen-
“una singola e precisa cosa che l’utente può fare”. te spazioso da poter mostrare più finestre simulta-
Proviamo a indagare le implicazioni di questa affer- neamente. Perciò non è affatto raro lavorare con
mazione. Partiamo dal fatto che l’utente, per fare più programmi contemporaneamente attivi, le cui
qualcosa, deve interagire con il dispositivo. finestre vengono affiancate o sovrapposte. Gli
Domandiamoci come avvenga, nel caso di uno smartphone, invece, funzionano diversamente.
smartphone, l’interazione tra l’uomo e la macchi- Prima di tutto il display è piccolo, e pertanto ha
na. Un ruolo essenziale, naturalmente, è svolto dai poco senso affiancare due o più finestre di applica-
meccanismi di input, come la tastiera e il touch- zioni differenti. Poi non bisogna dimenticare che le
screen, che permettono all’utente di specificare il risorse di calcolo sono modeste, e perciò non è
proprio volere. Le periferiche di input, tuttavia, da buona cosa tenere simultaneamente in vita troppi
sole non bastano. Affinché l’utente sappia cosa può programmi. Per questi motivi le attività di Android
fare e come debba farlo, ma anche affinché il hanno carattere di esclusività. È possibile mandare
software possa mostrare all’utente il risultato ela- in esecuzione più attività simultaneamente, ma
REQUISITI
borato, è necessario un canale aggiuntivo. Nella soltanto un’attività alla volta può occupare il
maggior parte dei casi questo canale è il display. display. L’attività che occupa il display è in esecu-
Conoscenze richieste
Java Nella superficie dello schermo il software disegna zione e interagisce direttamente con l’utente.
tutti quegli oggetti con cui l’utente può interagire Le altre, invece, sono ibernate e tenute nascoste in
Software (bottoni, menu, campi di testo), e sempre sullo sottofondo, in modo da ridurre al minimo il consu-
Java SDK (JDK) 5+,
Eclipse 3.3+ schermo viene presentato il risultato dell’elabora- mo delle risorse di calcolo. L’utente, naturalmente,
zione richiesta. Il ragionamento ci porta alla con- può ripristinare un’attività ibernata e riprenderla
clusione che, per fare qualcosa con il dispositivo, è da dove l’aveva interrotta, riportandola in primo
necessario usare lo schermo. Esiste perciò un piano. L’attività dalla quale si sta allontanando,
Impegno
parallelo tra il concetto di attività, in Android, e invece, sarà ibernata e mandata in sottofondo al
¥ quello di finestra, in un sistema desktop, benché posto di quella ripristinata. Il cambio di attività può
Tempo di realizzazione
non siano esattamente la stessa cosa. In generale, anche avvenire a causa di un evento esterno. Il caso
ad ogni modo, possiamo assumere con tranquillità più ricorrente è quello della telefonata in arrivo: se
h t t p : / / w w w. i o p r o g r a m m o . i t
16 54 / Dicembre 2009
G And roi d pr o g r am m in g
Scopriamo
Scopriamo cosa
cosa sono
sono e come
e come si programmano
si programmano le “Attività” Android
le “Attività” � MOBILE
programming
il telefono squilla mentre si sta usando la calcolatri- permettono di killare le attività in sottofondo, ma
ce, quest’ultima sarà automaticamente ibernata e non sono previsti nel sistema di base.
mandata in sottofondo. L’utente, conclusa la chia- I differenti passaggi di stato di un’attività attraver-
mata, potrà richiamare l’attività interrotta e ripor- sano alcuni metodi della classe Activity che, come
tarla in vita, riprendendo i calcoli esattamente da programmatori, possiamo ridefinire per intercetta-
dove li aveva interrotti. re gli eventi di nostro interesse.
Visto che le attività ibernate, in termini di risorse di La Fig.1 illustra la sequenza di chiamate ai metodi
calcolo, non consumano nulla, in Android il con- di Activity eseguite durante i passaggi di stato del-
cetto di chiusura delle attività è secondario e tenu- l’attività. Entriamo nel dettaglio:
to nascosto all’utente. Ciò, di solito, spiazza chi è al
suo primo confronto con la programmazione dei • protected void onCreate(android.os.Bundle
dispositivi portatili. Le attività di Android non savedInstanceState)
dispongono di un bottone “x”, o di un tasto equiva- Richiamato non appena l’attività viene creata.
lente, con il quale è possibile terminarle. L’utente, L’argomento savedInstanceState serve per ripor- NOTA
di conseguenza, non può chiudere un’attività, ma tare un eventuale stato dell’attività salvato in pre-
può solo mandarla in sottofondo. Questo, comun- cedenza da un’altra istanza che è stata terminata. ANDROID SDK 1.6
que, non significa che le attività non muoiano mai, L’argomento è null nel caso in cui l’attività non È stata da poco rilasciata la
anzi! Per prima cosa le attività possono morire abbia uno stato salvato. versione 1.6 del kit di
spontaneamente, perché hanno terminato i loro • protected void onRestart() sviluppo per Android. Molte
compiti. Insomma, anche se il sistema non ci forni- Richiamato per segnalare che l’attività sta venen- sono le novità incluse nella
nuova versione: oltre ai
sce automaticamente un bottone “chiudi”, possia- do riavviata dopo essere stata precedentemente consueti bugfix e alle
mo sempre includerlo noi nelle nostre applicazio- arrestata. migliorie generali, il
ni. In alternativa, la distruzione delle attività è com- • protected void onStart() sistema comprende ora
pletamente demandata al sistema. I casi in cui Richiamato per segnalare che l’attività sta per delle nuove API per il
un’attività può terminare sono due: diventare visibile sullo schermo. supporto delle gesture
e del text-to-speech.
• protected void onResume() Se siete fermi alla versione
• L’attività è ibernata e il sistema, arbitrariamente, Richiamato per segnalare che l’attività sta per 1.5, potete aggiornarvi
decide che non è più utile e perciò la distrugge. iniziare l’interazione con l’utente. partendo dall’indirizzo:
• Il sistema è a corto di memoria, e per recuperare • protected void onPause() http://developer.android.c
spazio inizia a “uccidere” bruscamente le attività Richiamato per segnalare che l’attività non sta om/sdk/
Oltre all’SDK, bisogna
in sottofondo. più interagendo con l’utente. aggiornare anche l’ADT (il
Esistono poi dei task manager di terze parti che • protected void onStop() plug-in per Eclipse).
Richiamato per segnalare che l’attività non è più Farlo è molto semplice:
visibile sullo schermo. aprite Eclipse e selezionate
• protected void onDestroy() la voce di menu “Help »
Check for Updates”,
Richiamato per segnalare che l’applicazione sta
controllate gli
per essere terminata. aggiornamenti disponibili e
selezionate quelli relativi ai
La prassi richiede che, come prima riga di codice di componenti Android. Dopo
ciascuno di questi metodi, si richiami l’implemen- aver scaricato e installato
gli aggiornamenti, aprite la
tazione di base del metodo che si sta ridefinendo.
maschera della preferenze
Ad esempio: (voce di menu “Window »
Preferences”) e alla scheda
protected void onStart() { super.onStart(); // ...} “Android” provvedete ad
aggiornare il percorso
dell’SDK, in modo da
È importante non dimenticare questa regola: le puntare alla versione 1.6.
attività sviluppate potrebbero non funzionare! Con la voce di menu
“Window » Android SDK
and AVD Manager”, create
poi un AVD (Android Virtual
Device) compatibile con la
DESCRIVERE UN’ATTIVITÀ nuova versione del
Dopo che si è creata un’attività, la si deve registrare sistema.
all’interno del descrittore dell’applicazione (il file
AndroidManifest.xml), questo affinché il sistema
sappia della sua esistenza. Per farlo si usa un tag
<activity> all’interno del tag <application>:
Fig. 1: Ciclo di vita di un’attività. Sono illustrate le chia-
mate ai metodi che è possibile ridefinire per intercettare
i passaggi di stato <?xml version="1.0" encoding="utf-8"?>
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Dicembre 2009 / 55 17
G
MOBILE
Android �
programming Scopriamo cosa sono
Scopriamo e come
cosa sono si programmano
e come le le“Attività”
si programmano “Attività”
18 56 / Dicembre 2009
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
Scopriamo
Scopriamo cosa
cosa sono
sono e come
e come si programmano
si programmano le “Attività” Android
le “Attività” � MOBILE
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Dicembre 2009 / 5719
G
MOBILE
Android programming
� Scopriamo cosa sono
Scopriamo e come
cosa sono si programmano
e come le le“Attività”
si programmano “Attività”
20 58 / Dicembre 2009
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
MOBILE
Programmazione Programmazione
delle interfacce
� delle interfacce
utente con Android utente
Android con Android
programming
INTERFACCE: LAYOUT
E COMPONENTI
QUARTO APPUNTAMENTO. INIZIA LA TRATTAZIONE DEI CONCETTI E DEGLI STRUMENTI DI
ANDROID PER LA COSTRUZIONE E LA GESTIONE DELLE INTERFACCE UTENTE. SI COMINCIA
CON I WIDGET ED I LAYOUT DI BASE, INDISPENSABILI IN OGNI APPLICAZIONE
D
opo aver scoperto cosa sono e come fun- (come la documentazione). Se volete, potete
zionano le attività, studiamo ora come si anche selezionare tutto, in modo da disporre di
costruiscono e si gestiscono le interfacce più versioni del sistema per sviluppare e testare
utente in Android. Apprenderemo le pratiche le vostre applicazioni. Azionando il tasto “Install
utili per costruire oggetti grafici in grado di inte- Selected” vi verrà chiesto di accettare le licenze
ragire con chi impugna il device. Si tratta di un dei componenti selezionati. Usate l’opzione
passaggio cruciale del nostro percorso di “Accept All” e proseguite poi con il tasto “Install
apprendimento: tutti i dispositivi mobili di Accepted”. Il tool procederà al download e all’in-
❑ CD ❑ WEB nuova generazione puntano tantissimo sull’inte- stallazione dei componenti richiesti.
corso_android_pt3.zip
razione con l’utente. Naturalmente potrete ripetere questa operazio-
cdrom.ioprogrammo.it
ne in futuro, per controllare il rilascio di nuove
versioni del sistema e per configurarle nel vostro
SDK. Dopo aver concluso il download e l’installa-
ANDROID 2.0 zione, non dimenticatevi di creare uno o più
ED IL NUOVO SDK device virtuali (AVD) per i vostri sviluppi (voce
Collegatevi all’indirizzo di riferimento per il kit di “Virtual Devices” nel tool) compatibili con
sviluppo di Android, cioè: Android 2.0 e con le altre versioni che avete sca-
http://developer.android.com/sdk/ ricato. Se sviluppate con Eclipse, come suggerito
Da qui scaricare il più recente SDK disponibile in questo corso, dovrete anche aggiornare l’ADT
per la vostra piattaforma (al momento in cui e collegarlo alla nuova installazione dell’SDK.
questo articolo viene scritto, la versione più
recente è la r3). Estraete l’archivio scaricato sul
vostro disco rigido, al percorso che preferite. Con
la riga di comando, adesso, posizionatevi sulla VIEW E VIEWGROUP
directory tools del kit di sviluppo. Lanciate il Andiamo all’argomento del giorno, cioè alle
comando: interfacce grafiche e ai componenti che le attività
possono usare per interagire con l’utente. I primi
android due concetti che dobbiamo assorbire si chiama-
no View e ViewGroup, e corrispondono alla
Verrà caricata una GUI che vi permette di gestire maniera di Android di classificare ed organizzare
i device virtuali ed i componenti aggiuntivi. Il ciò che è sullo schermo. I bottoni, i campi di
REQUISITI
nuovo SDK, appena scaricato e installato, è prati- testo, le icone e tutti gli altri congegni di un’inter-
camente vuoto. Contiene solo gli strumenti di faccia grafica sono oggetti View. I ViewGroup,
Conoscenze richieste
Java sviluppo, e al suo interno non c’è traccia di alcu- invece, sono dei contenitori che possono mette-
na versione del sistema. La prima cosa da fare, re insieme più oggetti View. I ViewGroup, inoltre,
Software quindi, è selezionare la voce “Available Packages”, sono a loro volta degli oggetti View, e di conse-
Java SDK (JDK) 5+,
Eclipse 3.3+ che permette di visionare ed installare i compo- guenza un possono contenere altri ViewGroup.
nenti aggiuntivi, tra i quali ci sono anche le diffe- Grazie a questa intuizione è possibile organizza-
renti versioni della piattaforma. Una volta sele- re i componenti sullo schermo secondo uno
zionata la voce, espandete l’elenco dei compo- schema ad albero, come quello di Fig.2.
Impegno
nenti disponibili per l’unica fonte inizialmente I componenti View estendono tutti la classe base
¥ registrata. Selezionate le piattaforme con le quali android.view.View. Nella libreria standard di
Tempo di realizzazione
intendete sviluppare (sicuramente la nuova 2.0) Android ci sono già molti componenti di questo
ed i componenti aggiuntivi che giudicate utili tipo, soprattutto nel pacchetto android.widget.
h t t p : / / w w w. i o p r o g r a m m o . i t
G 50 / Gennaio 2010
A n d ro id p r o g r a m m ing 21
Programmazione delle interfacceProgrammazione
Android programming utente con Android � MOBILE
delle interfacce utente con Android
NOTA
ViewGroup è una classe astratta. Pertanto non
può essere istanziata direttamente. Come nel PROBLEMI SSL
caso di View, è possibile realizzare il proprio Se, nel tentativo di
ViewGroup custom, ma il più delle volte conviene scaricare gli aggiornamenti
scegliere fra le tante implementazioni messe a automatici dell’SDK, vi
disposizione dalla libreria Android. Queste doveste imbattere in un
errore SSL, potete
implementazioni differiscono nella maniera di risolverlo alla seguente
presentare i componenti che sono al loro inter- maniera: nell’elenco di
no: alcuni li mettono uno dopo l’altro, altri li sinistra scegliete la voce
Fig. 1: Dopo il download della nuova versione della organizzano in una griglia, altri ancora possono “Settings”, attivate la
piattaforma si deve configurare un device virtuale essere usati per avere una gestione a schede dello checkbox “Force https://...
che la installi, altrimenti non sarà possibile usarla sources to be fetched
per lo sviluppo schermo, e così via. Ovviamente conosceremo using http://…”,
presto tutte le principali implementazioni di confermate con il tasto
ViewGroup. “Save & Apply”. Adesso
re altre View. Per questo motivo gli oggetti Una volta che, combinando oggetti View e tornate sulla scheda
ViewGroup dispongono di diverse implementa- ViewGroup, si è ottenuta l’interfaccia utente che “Available Packages” e
tentate di nuovo il
zioni del metodo addView(), che permette pro- si desidera, è necessario che questa venga download degli
prio di aggiungere una nuova View al gruppo: mostrata sullo schermo. Come abbiamo scoper- aggiornamenti.
to mediante alcuni esempi preliminari, le attività
• public void addView(View child) (cioè gli oggetti android.app.Activity) mettono a
Aggiunge un oggetto View al gruppo. disposizione un metodo setContentView(), dispo-
nibile nelle seguenti forme:
• public void addView(View child, int index)
Aggiunge un oggetto View al gruppo, specifi- • public void setContentView(View view)
candone la posizione attraverso un indice Mostra sullo schermo l’oggetto View specifica-
(index). to.
• public void setContentView( View view,
• public void addView(View child, int width, ViewGroup.LayoutParams params)
int height) Aggiunge un oggetto View al grup- Mostra sullo schermo l’oggetto View specifica-
po, specificandone larghezza (width) ed altezza to, applicando una serie di parametri di visua-
(height). lizzazione ed organizzazione del componente
(params).
• public void addView( View child, View
Group.LayoutParams params)
Aggiunge un oggetto View al gruppo, applican-
do una serie di parametri di visualizzazione ed WIDGET
organizzazione del componente (params). Con il termine widget (congegno) si indicano quei
componenti di base per l’interazione con l’uten-
• public void addView(View child, int index, te, come i bottoni, le check box, le liste, i campi di
ViewGroup.LayoutParams params) testo e così via. I widget predefiniti di Android
Aggiunge un oggetto View al gruppo, specificando estendono tutti (direttamente o indirettamente)
la posizione attraverso un indice (index) ed appli- la classe View, e sono conservati nel package
cando una serie di parametri di visualizzazione ed android.widget. Esaminiamone alcuni in una
organizzazione del componente (params). veloce panoramica:
h t t p : / / w w w. i o p r o g r a m m o . i t
22 Gennaio And
2010/
roi d pr 51 G
o g r am m in g
MOBILE
Programmazione Programmazione
delle interfacce
� delle interfacce
utente con Android utente
Android con Android
programming
ANDROID.WIDGET.TEXTVIEW ANDROID.WIDGET.DATEPICKER
Permette di mostrare del testo all’utente. Il Un componente che permette di scegliere una data
messaggio da visualizzare può essere imposta- selezionando giorno, mese ed anno. La data impo-
to con il metodo setText(), che può accettare stata dall’utente può essere recuperata servendosi
come parametro sia una stringa sia un riferi- dei metodi getDayOfMonth(), getMonth() e getYear().
mento a risorsa preso dal gruppo R.string (cfr.
ioProgrammo 144). ANDROID.WIDGET.TIMEPICKER
Un componente che permette di scegliere un orario
ANDROID.WIDGET.EDITTEXT selezionando ora e minuto. L’orario impostato dal-
Estende TextView e permette all’utente di modifica- l’utente può essere recuperato servendosi dei meto-
re il testo mostrato. Il testo digitato può essere recu- di getCurrentHour() e getCurrent Minute().
perato con il metodo getText(), che restituisce un
Fig. 3: TextView
oggetto del tipo android.text.Editable. Gli oggetti ANDROID.WIDGET.ANALOGCLOCK
Editable sono simili alle stringhe, ed infatti imple- Un componente che mostra all’utente un orolo-
mentano l’interfaccia java.lang.Char Sequence. gio analogico.
ANDROID.WIDGET.BUTTON ANDROID.WIDGET.DIGITALCLOCK
Realizza un bottone che l’utente può premere o Un componente che mostra all’utente un orolo-
Fig. 4: EditText
cliccare. Il componente espande TextView, e per gio digitale.
questo è possibile impostare il testo mostrato al
suo interno con il metodo setText(), sia con para- Tutti gli oggetti discussi finora richiedono, nei
metro stringa sia con riferimento a risorsa del loro costruttori, un oggetto che estenda la classe
gruppo R.string. astratta android.content.Context. Si tratta di una
struttura che permette l’accesso al sistema e che
Fig. 5: Button ANDROID.WIDGET.IMAGEVIEW costituisce il contesto di esecuzione dell’applica-
Un componente che permette di mostrare un’im- zione. Non dovete preoccuparvi di come ottene-
magine. Metodi utili sono: setImage Bitmap(), che re oggetti di questo tipo: android.app.Activity
accetta un oggetto di tipo android.graphics.Bitmap; estende indirettamente Context, per cui dall’in-
setImageDrawable(), che accetta un argomento terno di un’attività, vi sarà sufficiente usare la
android. graphics. drawable. Drawable; setImage parola chiave this. Ad esempio:
Resource(), che accetta un riferimento a risorsa
drawable. Button b = new Button(this);
G 52 / Gennaio 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 23
Programmazione delle interfacceProgrammazione
Android programming utente con Android � MOBILE
delle interfacce utente con Android
h t t p : / / w w w. i o p r o g r a m m o . i t
24 GennaioAnd
2010/
roi d pr o 53
g r amG
m in g
MOBILE
Programmazione Programmazione
delle interfacce
� delle interfacce
utente con Android utente
Android con Android
programming
G 54 / Gennaio 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 25
MOBILE
Android �
programming Design Design
delle interfacce utenteutente
delle interfacce con Android (seconda
con Android parte)
(parte 2)
INTERFACCE IN XML
PER ANDROID
QUINTO APPUNTAMENTO. VI È SEMBRATO CHE IL DESIGN JAVA DI UN’INTERFACCIA UTENTE,
IN ANDROID, SIA LUNGO E NOIOSO? NESSUN PROBLEMA! OGGI IMPAREREMO A SERVIRCI
DELL’XML PER VELOCIZZARE E SEMPLIFICARE L’OPERAZIONE
L
o scorso mese abbiamo imparato a disporre menti; ora, invece, si assiste ad un’inversione di ten-
sullo schermo i principali widget messi a denza. La programmazione Web, ad esempio, ha
disposizione da Android: bottoni, caselle di dimostrato quanto sia più facile gestire un’interfac-
testo, check box e via discorrendo. La logica che per- cia utente descrivendone i componenti con un lin-
mea la loro creazione ed il loro utilizzo, come abbia- guaggio a marcatori, anziché con un linguaggio di
mo potuto osservare, non si discosta di molto da programmazione.
quella adottata da altre librerie Java per le interfacce I linguaggi a marcatori come HTML ed XML ben si
utente, come AWT e Swing. Questo modo di creare le prestano a questo genere di operazioni: sono più
❑ CD ❑ WEB GUI è potente, ma anche estremamente tedioso. facili da leggere e da scrivere, sia per l’uomo sia per
corso_android_pt5.zip
Ogni volta che si deve utilizzare un widget, lo si deve la macchina (cioè per gli editor visuali). Così oggi le
cdrom.ioprogrammo.it
creare, personalizzare ed inserire in un contenitore piattaforme moderne applicano alla programma-
predisposto in precedenza. Sin dalle origini delle zione di applicazioni native il medesimo principio,
interfacce basate sui widget, i creatori delle piat- fornendo agli sviluppatori framework ed editor
taforme di sviluppo hanno cercato di porre rimedio basati perlopiù su XML. Uno dei primi tentativi in tal
a questo difetto. Nella maggior parte dei casi si è senso ad aver avuto successo è stato XUL, nato in
fatto ricorso ad editor visuali: il programmatore, casa Mozilla ed impiegato per le GUI di Firefox e di
anziché scrivere codice, trascina i componenti sul- altre applicazioni della fondazione, poi importato
l’editor, dimensionandoli ad occhio ed impostando- anche in altri ambiti ed ambienti. Mi ricollego ora al
ne le caratteristiche salienti mediante delle proce- discorso precedente, ripetendo per l’ennesima volta
dure guidate. Il lavoro sporco lo fa l’editor in sot- che Android è un sistema operativo di moderna
tofondo, generando ed interpretando il codice di concezione. Come abbiamo imparato il mese scor-
programmazione necessario. Questo approccio è so, le GUI possono essere realizzate con un approc-
valido, ma da solo non costituisce una vera e propria cio classico, basato sul codice di programmazione.
soluzione al problema. Il codice prolisso e difficile Spesso e volentieri, però, è più semplice ricorrere
da gestire, infatti, è ancora lì: l’ambiente di sviluppo all’approccio moderno, basato su XML, che Android
non ha fatto altro che nascondere la sporcizia sotto rende disponibile nativamente.
il tappeto. Gli editor visuali, poi, sono molto difficili
da realizzare, perché devono interpretare e generare
del codice complesso, ed infatti ne esistono davvero
pochi di buona qualità. Il codice generato automati- LAYOUT XML
camente, infine, è spesso un obbrobrio. L’ambiente, Veniamo al dunque. Avrete sicuramente notato che
REQUISITI
infatti, non ha l’intelligenza sufficiente per scrivere e la struttura predefinita di un progetto Android crea-
mantenere un codice leggibile e performante. to in Eclipse contiene sempre la directory res/layout.
Conoscenze richieste
Java Con l’avvento dei browser moderni, di AJAX e degli Abbiamo già conosciuto alcune fra le sottodirectory
interpreti di nuova concezione, si sono portate sul di res e, in tutti i casi, abbiamo osservato come la
Software Web molte applicazioni che, fino a ieri, erano piattaforma di sviluppo gestisse in maniera speciale
Java SDK (JDK) 5+,
Eclipse 3.3+ appannaggio esclusivo degli ambienti desktop e dei le differenti categorie di risorse possibili. La cartella
linguaggi compilati. I client di posta elettronica, ad layout non fa eccezione. Al suo interno possono
esempio, stanno scomparendo a favore delle web- essere disposti dei file XML che il sistema interpre-
mail. Il proliferare delle applicazioni Web sta facen- terà come descrizioni dichiarative dei layout e dei
Impegno
do maturare velocemente gli strumenti di sviluppo widget che saranno poi usati in una o più attività
¥ propri di questo ambito. All’inizio la programmazio- dell’applicazione. Un esempio, in questo caso, vale
Tempo di realizzazione
ne Web sottraeva idee alla programmazione delle più di mille parole. Il mese scorso abbiamo chiuso
applicazioni native, emulandone approcci e stru- con questo codice:
h t t p : / / w w w. i o p r o g r a m m o . i t
26 50 / Febbraio 2010
G And roi d pr o g r am m in g
Design
Designdelle
delle interfacce
interfacce utente con Android (parte
(seconda
2) parte) Android
� MOBILE
programming
TextView label1 = new TextView(this); riporta il nome del file aperto. L’ambiente, anche in
label1.setText("Nome:"); questo caso, fornisce alcune utili agevolazioni, come
EditText edit1 = new EditText(this); l’auto-completamento dei tag, degli attributi e dei
TextView label2 = new TextView(this); valori, con tanto di aiuto in linea, come mostrato in
label2.setText("Cognome:"); figura.
...
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Febbraio 2010/ 51 27
G
MOBILE
Android �
programming Design Design
delle interfacce utenteutente
delle interfacce con Android (seconda
con Android parte)
(parte 2)
} <Button
android:text="@string/etichettaBottoneSalva" />
Sul CD-Rom allegato alla rivista trovate il proget-
to Android completo avviabile con l’emulatore. A patto, ovviamente, di aver creato in res/values
un file XML che definisca la risorsa stringa
NOTA
etichettaBottoneSalva, come ad esempio:
@tipo/nome
28 52 / Febbraio 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
Design
Designdelle
delle interfacce
interfacce utente con Android (parte
(seconda
2) parte) Android
� MOBILE
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Febbraio 2010/ 5329
G
MOBILE
Android programming
� DesignDesign
delle interfacce utenteutente
delle interfacce con Android (seconda
con Android parte)
(parte 2)
ereditati poi da tutti i widget e tutti i layout. Fra Permettono di stabilire una dimensione massima
questi si segnalano: del componente, attraverso una misura scritta let-
teralmente o riferita da res/values.
• minWidth e minHeight
Permettono di specificare una dimensione mini- • gravity
ma per il componente. La misura deve essere Stabilisce la gravità applicata al componente. I
espressa letteralmente, specificando l’unità di valori possibili sono: top, bottom, left, right, cen-
misura, oppure riferendo una dimensione defini- ter_vertical, center_horizontal, center, fill_horizon-
ta sotto res/values. (cfr. ioProgrammo 144). tal, fill_vertical, fill, clip_vertical e clip_horizontal.
• paddingLeft, paddingTop, paddingRight, I tanti componenti che derivano da TextView (tra cui
paddingBottom e padding i diversi tipi di bottoni) hanno a loro disposizione:
Permettono di specificare il padding (margine
interno) del componente (cfr. ioProgrammo 146). • text
I primi quattro attributi permettono di distingue- Permette di impostare il testo visualizzato, attra-
re la misura di padding assegnata in ogni direzio- verso un valore letterale o un riferimento a stringa
L’AUTORE ne, mentre il quinto permette di assegnare a tutte memorizzata sotto res/values.
e quattro le direzioni il medesimo padding con
Carlo Pelliccia lavora un’istruzione sola. I valori espressi devono essere Una particolare estensione di TextView è EditText.
presso 4IT (www.4it.it), Con EditText si realizza una casella di input, che per-
dotati di unità di misura, o in alternativa fare rife-
dove si occupa di analisi e
sviluppo software per rimento ad una dimensione nota in res/values. mette all’utente di immettere del testo. In questo
piattaforme Java. Nella sua caso possono tornare utili i seguenti attributi:
carriera di technical writer • visibility
ha pubblicato cinque Accetta tre possibili valori: 0 (visibile), 1 (invisibi- • hint
manuali ed oltre Un suggerimento da visualizzare quando non c’è
le), 2 (scomparso). Nel primo caso, che è quello di
centocinquanta articoli,
molti dei quali proprio tra le default, il componente è visibile. Nel secondo del testo visualizzato.
pagine di ioProgrammo. Il caso il componente non è visibile, ma lo spazio
suo sito, che ospita anche spettante viene riservato e mantenuto vuoto. Nel • password
diversi progetti Java Open terzo caso il componente è invisibile e nessuno Un booleano (true o false) che indica se il campo
Source, è disponibile contiene una password. In questo caso il testo
spazio gli viene assegnato durante il disegno del
all’indirizzo
www.sauronsoftware.it layout, proprio come non fosse mai esistito. La viene camuffato in modo da non risultare leggibi-
visibilità di un componente può essere poi mani- le ad un occhio indiscreto.
polata a runtime da codice, con il metodo
setVisibility(). • numeric
Rende il campo di tipo numerico. Si deve specifi-
Esistono poi dei tag non comuni a tutti i widget, ma care uno o più valori (separandoli con pipe) fra
molto diffusi. Tra questi: integer, signed e decimal. Il primo indica un valo-
re intero, il secondo un valore numerico con
• width e height segno, il terzo di un valore decimale.
Permettono di stabilire una dimensione precisa
del componente, attraverso una misura scritta let- • digits
teralmente o riferita da res/values. Da usare se il campo è numerico. Permette di spe-
cificare quali cifre è possibile utilizzare. Ad esem-
• maxWidth e maxHeight pio il valore “123” farà sì che l’utente possa inseri-
re nel campo sono le cifre “1”, “2” e “3”.
PROSSIMAMENTE
Il prossimo mese proseguiremo la nostra trattazione
Fig. 4: Dimensionare un componente rispetto al suo contenitore. Da sinistra a
delle interfacce utente, parlando di eventi.
destra: wrap_content su layout_width e layout_height; wrap_content su
layout_width e fill_parent su layout_height; fill_parent su layout_width e wrap_con-
tent su layout_height; fill_parent su layout_width e su layout_height. Carlo Pelliccia
30 54 / Febbraio 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
Android:Android:
MOBILE � tocco e tocco e digitazione Android programming
digitazione
GESTIRE IL TOUCH
SU ANDROID
SESTO APPUNTAMENTO. IN QUESTA PUNTATA DEL CORSO IMPAREREMO LE VARIE TECNICHE
PER INTERCETTARE LE AZIONI DI TOCCO E DIGITAZIONE ESEGUITE DALL’UTENTE SUI WIDGET
PRESENTI NEL DISPLAY, IN MODO DA REAGIRE DI CONSEGUENZA
N
ei due precedenti appuntamenti abbiamo super(context);
conosciuto i principali widget di Android e }
le tecniche utili per richiamarli e disporli
nel display dello smartphone. Oggi impareremo a @Override
raccogliere l’input dell’utente, e lo faremo intercet- public boolean onTouchEvent(MotionEvent event) {
tando gli eventi scatenati dai widget. super.onTouchEvent(event);
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
❑ CD ❑ WEB Toast toast = Toast.makeText(getContext(),
corso_android_pt6.zip
I METODI DI CALLBACK "Bottone cliccato!",
cdrom.ioprogrammo.it
Tutti i widget di Android dispongono di una serie di Toast.LENGTH_SHORT);
metodi di callback, con nomi del tipo onTipo toast.show();
Evento(). Questi metodi vengono richiamati auto- return true;
maticamente ogni volta che il corrispondente }
evento è riscontrato sul widget. Mi spiego meglio return false;
con un esempio concreto. La classe android.wid- }
get.Button, che abbiamo conosciuto nel corso delle }
due puntate precedenti, definisce uno speciale
metodo chiamato onTouchEvent(). Questo metodo Il metodo onTouchEvent() riceve in ingresso un
è eseguito automaticamente ogni volta che il botto- argomento di tipo android.view.MotionEvent, che
ne viene toccato dall’utente, attraverso il touch riporta tutte le informazioni relative all’evento di
screen del suo dispositivo. Sono molti i metodi di tocco riscontrato sul bottone. La versione superio-
questa categoria, ed ogni widget ha i propri. re del metodo (cioè quella definita in Button) viene
Ciascun metodo ha le sue regole e la sua firma: richiamata con la riga:
parametri e valore di ritorno, insomma, cambiano
di caso in caso. La documentazione ufficiale delle super.onTouchEvent(event);
API di Android, come sempre, presenta l’elenco
esaustivo (in inglese) per ciascun widget. Lo svilup- Questo, nel caso specifico, è necessario affinché l’e-
patore interessato alla gestione di uno specifico vento venga gestito graficamente: la definizione
evento deve individuare il metodo di suo interesse, base del metodo contenuta in Button fa sì che il
quindi estendere il widget e ridefinire il metodo bottone, quando sottoposto a pressione, cambi il
REQUISITI
individuato. Proviamo a farlo proprio con il meto- suo aspetto ed il suo colore, per mostrare reattività
do onTouchEvent() di Button, rendendo il bottone al tocco dell’utente (con il tema predefinito di
Conoscenze richieste
Java reattivo al singolo “clic da dito”: Android 2.0, il bottone cambia da grigio ad aran-
cione).
Software package it.ioprogrammo.buttonclickdemo1; Dopo aver eseguito la versione base del metodo, la
Java SDK (JDK) 5+,
Eclipse 3.3+ nostra versione ridefinita controlla i dettagli dell’e-
import android.content.Context; vento. Se si tratta del primo tocco riscontrato sul
import android.view.MotionEvent; bottone (ACTION_DOWN), viene mostrato all’u-
import android.widget.Button; tente un messaggio di notifica (“Bottone clicca-
Impegno
import android.widget.Toast; to!”). Altri filtri possono essere applicati per inter-
¥ cettare ulteriori varianti dell’evento di tocco, ad
Tempo di realizzazione
public class MyButton extends Button { esempio ACTION_MOVE per un trascinamento e
public MyButton(Context context) { ACTION_UP per l’azione di rilascio del pulsante
h t t p : / / w w w. i o p r o g r a m m o . i t
G 54 / Marzo 2010
A n d ro id p r o g r a m m ing 31
Android programming Android:Android:
tocco etocco
digitazione � MOBILE
e digitazione
h t t p : / / w w w. i o p r o g r a m m o . i t
32 Marzo And
2010/
roi d pr 55 G
o g r am m in g
Android:Android:
MOBILE � tocco etocco e digitazione Android programming
digitazione
Questa volta, invece di estendere Button e realiz- L’attività, di conseguenza, andrebbe riscritta alla
zare così un componente custom, abbiamo seguente maniera:
semplicemente implementato un’interfaccia.
Nel metodo onClick() abbiamo scritto il codice package it.ioprogrammo.buttonclickdemo3;
necessario per gestire l’evento di clic. Il parame-
tro ricevuto dal metodo, nel caso specifico, rap- import android.app.Activity;
presenta l’oggetto View o derivato sul quale l’e- import android.os.Bundle;
NOTA
vento è stato riscontrato. Affinché la classe import android.widget.Button;
MyClickListener venga utilizzata come gestore public class ButtonClickDemo3Activity extends Activity {
FOCUS dell’evento di clic su uno specifico widget, è ...
Un altro evento comune
definito in View è quello necessario registrarne un’istanza sul widget
relativo al focus. Quando stesso, servendosi del metodo setOnClick Dopo aver richiamato il layout definito nel file
un widget riceve il focus, Listener() citato in precedenza. Lo si può fare XML, non si deve far altro che recuperare il bottone
significa che è selezionato, quando si allestisce o si richiama il layout dalla al quale si vuole collegare l’evento e registrare su di
e che tutti gli eventi di
schermata. Ecco una Activity equivalente a quel- esso il proprio listener personalizzato.
digitazione saranno a esso
rivolti. È possibile sapere la del paragrafo precedente, ma che a differenza
quando un widget riceve o di quest’ultima utilizza un widget Button stan-
perde il focus. Il metodo dard insieme con l’event listener di poco sopra:
per registrare il listener sul COME SCRIVERE
widget è
setOnFocusChangeListener()
package it.ioprogrammo.buttonclickdemo2; MENO CODICE
, mentre l’interfaccia per Qualcuno potrebbe obiettare che, con gli event
implementarlo è import android.app.Activity; listener, è comunque necessario creare una clas-
View.OnFocusChangeListe import android.os.Bundle; se distinta per ciascun gestore previsto, con il
ner. L’interfaccia richiede il import android.view.Gravity; rischio di avere più codice dedicato alla cattura
metodo
import android.widget.Button; degli eventi che non alla loro gestione. Esistono
onFocusChange(View view,
boolean hasFocus). Il import android.widget.LinearLayout; diversi trucchi applicabili con gli event listener
parametro view è il widget che aiutano ad evitare le situazioni di questo tipo.
che ha subito l’evento, public class ButtonClickDemo2Activity extends Activity { Ve ne svelo un paio. Per realizzare un event liste-
mentre il booleano ... ner bisogna estendere un’interfaccia. Java non
hasFocus indica se il
supporta l’ereditarietà multipla, e quindi una
componente ha ricevuto il
focus (true) oppure se lo ha In questa maniera non è stato necessario creare classe può avere una sola super-classe. Questo
perso (false). un componente custom: è stato sufficiente regi- limite però non vale nel caso delle interfacce: una
strare sul Button l’event listener realizzato classe ne può implementare un numero qualsia-
pocanzi, con la riga: si. Ecco allora che, nel caso di GUI non troppo
complesse, si può fare che la Activity che control-
button.setOnClickListener(new MyClickListener()); la lo schermo sia essa stessa event listener di uno
o più eventi, per uno o più widget. Mi spiego
La tattica degli event listener, inoltre, si sposa meglio con un esempio. Prendiamo in considera-
meglio con la possibilità messa in campo da zione il seguente layout, come al solito da battez-
Android di definire risorse e layout attraverso dei zare main.xml:
file XML (cfr. numero precedente). Il layout realiz-
zato nell’attività mostrato poco sopra, ad esempio, <?xml version="1.0" encoding="utf-8"?>
potrebbe essere definito in un file XML indipen- <LinearLayout xmlns:android="http://schemas
dente. Chiamiamolo main.xml: .android.com/apk/res/android"
android:orientation="vertical"
<?xml version="1.0" encoding="utf-8"?> android:layout_width="fill_parent"
<LinearLayout xmlns:android="http://schemas. android:layout_height="fill_parent"
android.com/apk/res/android" android:gravity="center">
android:orientation="vertical" <Button android:id="@+id/bottone01"
G 56 / Marzo 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 33
Android programming Android: tocco etocco
Android: digitazione
e digitazione� MOBILE
L’esempio è lievemente più complesso del prece- Così facendo non c’è bisogno di far implementa-
dente: qui i bottoni sono diventati due. re alcuna interfaccia all’attività. La tecnica con-
Realizziamo un’attività che carichi questo layout e sente di scrivere davvero poco codice per inter-
gestisca gli eventi di clic su ambo i bottoni: cettare gli eventi, lasciando il programmatore NOTA
libero di concentrarsi sulla logica della loro
package it.ioprogrammo.buttonclickdemo4; gestione. Il più delle volte, è proprio quest’ultima MODIFICATORI
Quando si riceve un evento
la tecnica da preferirsi.
di digitazione, attraverso
import android.app.Activity; l’istanza di KeyEvent, è
import android.os.Bundle; possibile sapere se insieme
import android.view.View; al tasto principale che
import android.view.View.OnClickListener; PANORAMICA riguarda l’evento sono stati
import android.widget.Button; SUGLI EVENTI attivati anche uno o più
tasti modificatori. I tasti
import android.widget.Toast; Ora che abbiamo imparato ad utilizzare gli event modificatori, in Android,
listener, la prima cosa da fare è chiedersi: quanti e sono tre: ALT, SHIFT e SYM.
public class ButtonClickDemo4Activity extends Activity quali sono gli eventi che è possibile gestire? La KeyEvent permette di
implements OnClickListener { risposta non è semplice: ogni widget ha i suoi even- controllare lo stato dei tre
modificatori attraverso i
... ti e, di conseguenza, i suoi event listener. Anche in
metodi booleani
questo caso, quindi, la documentazione è una isAltPressed(),
In questo caso è la stessa attività a implementare risorsa fondamentale, che bisogna assolutamente isShiftPressed() e
l’interfaccia OnClickListener, definendo di con- imparare a leggere. Soprattutto nel caso dei widget isSymPressed().
seguenza il metodo onClick(). Non è stato dun- più particolari, quindi, dovrete cavarvela, altrimen-
que necessario creare una classe apposita. ti rischiamo di prolungare questo corso fino al
Inoltre l’event listener realizzato è stato adopera- 2020! Insieme, però, possiamo prendere in esame i
to su due bottoni differenti (bottone01 e bot- tipi di eventi più universali e diffusi, riconosciuti e
tone02). È stato possibile farlo servendosi degli id gestibili su qualsiasi widget. A definirli, tanto per
assegnati ai due bottoni: all’interno del codice cambiare, è la madre di tutti i widget: la classe
del solo metodo onClick() realizzato, si è mostra- android.view.View. Ecco una panoramica degli
to un messaggio differente a seconda della sor- eventi più importanti:
gente dell’evento. Un’altra tecnica per risparmia-
re codice consiste nell’adoperare le classi inne- • Click. Lo abbiamo usato in tutti gli esempi pre-
state anonime di Java. È possibile fare qualcosa cedenti. Il metodo sul widget è setOnClick
di questo tipo: Listener(), e l’interfaccia per il gestore da imple-
mentare è View.OnClickListener. Il metodo
button.setOnClickListener(new OnClickListener() { richiesto dall’interfaccia è onClick(View view),
@Override che in parametro riporta il widget che ha subi-
public void onClick(View view) { to l’evento.
// gestione evento Fig. 2: Questa volta
} • Click lungo. Un evento che accade quando si bisogna gestire i clic su
}); clicca su un widget e si mantiene la pressione due bottoni differenti
per qualche istante. Il metodo per registrare l’e-
Di fatto si crea e si registra allo stesso tempo il vent listener è setOnLongClickListener(), e l’in-
gestore dell’evento di clic. Ci pensa il compilatore a terfaccia per il gestore è View.OnLongClick
separare la classe anonima innestata su un file Listener. Il metodo da implementare è onLong
.class differente. Riscriviamo allora l’esempio pre- Click(View view). Il metodo, come nel caso pre-
cedente secondo quest’altra tecnica: cedente, riceve come parametro un riferimento
al widget su cui si è prodotto l’evento. In più, il
package it.ioprogrammo.buttonclickdemo5; metodo deve restituire un booleano per segna-
lare se l’evento è stato completamente gestito
import android.app.Activity; (true) oppure no (false).
h t t p : / / w w w. i o p r o g r a m m o . i t
34 MarzoAnd
2010/
roi d pr o g57
r amG
m in g
Android:Android:
MOBILE � tocco etocco e digitazione Android programming
digitazione
• Tocco. Un evento più generico dei due pre- <?xml version="1.0" encoding="utf-8"?>
cedenti: serve per rilevare un tocco qualsiasi <LinearLayout xmlns:android="http://schemas.
su un componente. Il metodo per registrare il android.com/apk/res/android"
listener sul widget è setOnTouchListener(), android:orientation="vertical"
mentre l’interfaccia per implementarlo è android:layout_width="fill_parent"
View.OnTouch Listener. L’interfaccia richiede android:layout_height="fill_parent"
il metodo onTouch(View view, MotionEvent android:gravity="center">
event). Come nei casi precedenti, view è il <EditText android:id="@+id/eventArea"
widget che ha subito l’evento. Il parametro di android:layout_width="wrap_content"
tipo MotionEvent riporta invece i dettagli android:layout_height="wrap_content"
dell’evento (tipo di azione, coordinate, dura- android:background="#990000"
ta ecc.), come nel caso documentato nel android:textColor="#FFFFFF"
primo esempio di oggi. Il metodo deve resti- android:width="200px"
tuire un booleano per segnalare se l’evento è android:height="200px" />
stato completamente gestito (true) oppure <TextView android:id="@+id/logArea"
no (false). android:layout_width="wrap_content"
L’AUTORE android:layout_height="wrap_content"
• Digitazione. Un evento usato per segnalare android:text="Compi un evento sull'area
Carlo Pelliccia lavora la pressione o il rilascio di un tasto della rossa qui sopra" />
presso 4IT (www.4it.it),
tastiera hardware. Il metodo per registrare il </LinearLayout>
dove si occupa di analisi e
sviluppo software per listener sul widget è setOnKeyListener(),
piattaforme Java. Nella sua mentre l’interfaccia per implementarlo è Il layout dispone, al centro del display, due compo-
carriera di technical writer View.OnKeyListener. L’interfaccia richiede il nenti. C’è un EditText con sfondo di colore rosso e
ha pubblicato cinque metodo onKey( View view, int keyCode, dimensioni 200 x 200 pixel, che useremo per far
manuali ed oltre
KeyEvent event). Come nei casi precedenti, compiere all’utente delle operazioni di digitazione
centocinquanta articoli,
molti dei quali proprio tra le view è il widget che ha subito l’evento. Il e di tocco. C’è poi un TextView, che useremo inve-
pagine di ioProgrammo. Il parametro keyCode riporta il codice associa- ce per descrivere ogni evento riscontrato sul com-
suo sito, che ospita anche to al tasto premuto, mentre quello di tipo ponente precedente, dimostrando così di averlo
diversi progetti Java Open KeyEvent riporta ulteriori dettagli (tasto intercettato correttamente.
Source, è disponibile
pigiato, tasto rilasciato, eventuali modifica- Andiamo ora a realizzare, mediante una Activity,
all’indirizzo
www.sauronsoftware.it tori e così via). Il metodo deve restituire un quanto proposto:
booleano per segnalare se l’evento è stato
completamente gestito (true) oppure no package it.ioprogrammo.eventdemo;
(false).
import android.app.Activity;
Siccome di esempi dedicati ai clic ne abbiamo già import android.os.Bundle;
visti diversi, proviamo ora a gestire i due eventi di import android.util.Log;
tocco e digitazione. Prepariamo il seguente layout, import android.view.KeyEvent;
da chiamare come al solito main.xml: import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.View.OnKeyListener;
import android.widget.TextView;
G 58 / Marzo 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 35
MOBILE
Android �
programming Android: corso di
Android: programmazione
corso di programmazione
ANDROID:
TUTTO SUI MENU
SETTIMO APPUNTAMENTO. ARGOMENTO DEL MESE SONO I MENU. LE APPLICAZIONI
ANDROID NE SUPPORTANO DIVERSI TIPI, CHE L’UTENTE PUÒ SFRUTTARE PER AZIONARE
COMANDI E IMPOSTARE LE OPZIONI. CONOSCIAMOLI E IMPARIAMO A PROGRAMMARLI
I
menu sono una parte importante di qualsiasi
applicazione. Gli utenti sono abituati ad avere a
che fare con il concetto di menu, al quale si rivol-
gono ogni volta che vogliono cercare i comandi o
modificare le opzioni delle loro applicazioni. Ciò
risulta vero tanto nell’ambito dei software desktop,
quanto in quello delle applicazioni mobili per cellu-
lari e smartphone. Con questo articolo impareremo
❑ CD ❑ WEB a conoscere i menu previsti da Android, ponendo
corso_android_pt7.zip
particolare attenzione alle regole per la costruzione
cdrom.ioprogrammo.it
di interfacce grafiche semplici ed efficaci, con menu
concisi e facili da raggiungere e navigare.
I MENU IN ANDROID
In Android esistono tre differenti tipi di menu, che lo
sviluppatore può collegare ad una Activity:
• Options menu
Sono i menu concepiti per raggruppare le opzioni
ed i comandi di un’applicazione. Si dividono in
due sotto-gruppi, icon menu ed expanded menu,
descritti di seguito.
h t t p : / / w w w. i o p r o g r a m m o . i t
36 50 / Aprile 2010
G And roi d pr o g r am m in g
Android:
Android: corso dicorso di programmazione Android
programmazione � MOBILE
programming
ne selezionata, come ad esempio i comandi per una risorsa di tipo stringa memorizzata su file XML
salvarla in locale e condividerla con gli amici. esterno, nel secondo caso. Un controllo più granula-
Come nel caso precedente, questo genere di re sugli elementi inseriti è reso possibile da queste
menu si presenta come una lista a tutto schermo, altre due varianti del metodo add():
che può contenere numerose opzioni.
public MenuItem add(int groupId, int itemId, int
• Submenu order, CharSequence title)
Le applicazioni che dispongono di molti comandi public MenuItem add(int groupId, int itemId, int
possono usufruire anche dei submenu. In pratica, order, int titleRes)
in uno qualsiasi dei menu descritti in precedenza,
è possibile inserire un elemento che, invece di In questo caso, oltre al titolo, è possibile specificare
compiere un’azione diretta, va ad aprire un sotto- altre tre proprietà di ciascun elemento del menu:
menu, nel quale si possono presentare ulteriori
possibilità di scelta. • groupId
Con questo valore è possibile assegnare l’elemen-
Nei prossimi paragrafi impareremo a programmare to ad un gruppo. Si può specificare un qualsiasi
tutti e tre i tipi di menu presentati. valore maggiore di zero (ovviamente deve essere
lo stesso per due o più elementi che si intende
assegnare al medesimo gruppo), oppure si può
usare lo zero o la costante Menu.NONE se non si
OPTIONS MENU vuole assegnare l’elemento ad alcun gruppo. Fig. 2: L’expanded menu
del browser di Android
Cominciamo dagli options menu che, come abbia-
mo detto, costituiscono il menu principale di qual- • itemId
siasi applicazione. Il menu delle opzioni è un con- Con questo valore si assegna un identificativo
cetto strettamente legato a quello di singola attività. all’elemento stesso. Questo identificativo torna
Ogni Activity, infatti, può avere un solo options utile in seguito, quando si vuole distinguere un
menu. La classe Activity dispone di un metodo defi- elemento da un altro. Come nel caso precedente,
nito al seguente modo: bisogna usare un valore maggiore di zero affinché
la caratteristica possa essere sfruttata. Se non si è
public boolean onCreateOptionsMenu(Menu menu) interessati all’assegnare un identificativo all’ele-
mento, è sufficiente usare il valore zero o la
Questo metodo, nel ciclo di vita dell’attività, viene costante Menu.NONE.
richiamato automaticamente dal sistema la prima
volta che l’utente preme il tasto “menu” del suo • order
dispositivo. L’argomento passato, un oggetto di tipo Se si vuole assegnare uno specifico ordine all’ele-
android.view.Menu, costituisce l’options menu ini- mento, è possibile in questo caso specificarlo
Fig. 3: Il context menu
zialmente vuoto. Ridefinendo il metodo è possibile esplicitamente con un valore da uno in su.
del browser di Android
intercettare queste chiamate e popolare così il menu Usando lo zero o la costante Menu.NONE si lascia visualizzato quando si
fornito con le voci utili alla propria applicazione. Il stabilire al sistema l’ordine dell’elemento nel tiene il tocco per qual-
metodo onCreateOptionsMenu(), al termine dei pro- menu di appartenenza. che secondo sopra ad
un’immagine contenuta
pri compiti, deve restituire un booleano: true per
in una pagina Web
rendere attivo il menu realizzato, false per dichiara- Sperimentiamo subito quanto descritto finora.
re che l’attività non dispone di un menu, e quindi Realizziamo un’attività dimostrativa così formulata:
alla pressione del tasto “menu” del dispositivo non si
deve mostrare nulla. Programmando nel corpo del package it.ioprogrammo.menudemo01;
metodo, il proprio options menu può essere assem- import android.app.Activity;
blato servendosi dei metodi messi a disposizione import android.view.Menu;
dagli oggetti di tipo android.view.Menu. Aggiungere public class MenuDemo01Activity extends Activity {
un elemento al menu è molto semplice, basta servir- ...
si dei metodi:
Abbiamo popolato il menu con sei semplici coman-
public MenuItem add(CharSequence title) di, etichettati rispettivamente “Comando 1”,
public MenuItem add(int titleRes) “Comando 2”, “Comando 3” e così via. Installate l’ap-
plicazione su un dispositivo e provate il suo menu.
Entrambi i metodi aggiungono un elemento al Dovreste ottenere un risultato simile a quello in fig.
menu. Il titolo dell’elemento (cioè la scritta che sarà 5. Come potete osservare, i sei elementi introdotti
mostrata per qualificarlo) può essere espressa con sono andati a costituire l’icon menu dell’attività. Fig. 4: Un submenu del
una stringa, nel primo caso, o con il riferimento ad Provate ora la seguente variante: browser di Android
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Aprile 2010/ 51 37
G
MOBILE
Android �
programming Android: corso di
Android: programmazione
corso di programmazione
In questo caso i comandi sono nove. Lanciate l’atti- Questo metodo viene richiamato automaticamente
vità e verificate cosa accade. Mentre nel caso prece- ogni volta che uno degli elementi dell’options menu
dente tutti e sei i comandi previsti sono diventati dell’attività viene selezionato dall’utente. Lo specifi-
NOTA
parte dell’icon menu dell’attività, ora le cose sono co elemento selezionato, naturalmente, è quello
andate diversamente. Come accennato in apertura, riportato in argomento, mentre il valore di ritorno
ANDROID un icon menu può contenere al massimo sei ele- serve per indicare al sistema se l’evento è stato gesti-
2.1 (API 7)
Anche questo mese c’è da menti, come nel caso del primo esempio. Ora che gli to (true) oppure no (false). Ridefinendo il metodo e
segnalare una nuova elementi sono diventati nove, il sistema ha posizio- applicando dei filtri sull’identificativo dell’elemento
release di Android, la 2.1. nato nell’icon menu solo i primi cinque del lotto. Il segnalato (è possibile recuperarlo con il metodo
Le API vengono avanzate al sesto spazio disponibile nell’icon menu è stato auto- getId() di MenuItem) è possibile riconoscere e gesti-
livello 7. Si tratta di una
maticamente occupato con un elemento di tipo re la specifica azione eseguita dall’utente. Ecco un
release minore, e le
modifiche per quel che “altro”, che lavora come pulsante d’accesso per l’ex- esempio che mostra un avviso differente in base alla
riguarda la panded menu dell’attività. In quest’ultimo sono voce di menu selezionata:
programmazione sono stati inseriti i restanti quattro comandi. Gli elementi
poche. Se volete dare che confluiscono nell’icon menu possono utilizzare package it.ioprogrammo.menudemo04;
un’occhiata al changelog:
delle icone al posto del testo. Usufruire di questa ...
http://developer.android.
com/sdk/android-2.1.html funzionalità è molto semplice. Per prima cosa dove- public class MenuDemo04Activity extends Activity {
te fare caso al fatto che i metodi add() di Menu resti- ...
tuiscono un oggetto di tipo android.view.MenuItem.
Come è facile intuire, l’oggetto restituito rappresen- Questo stralcio di codice mette in atto una tecnica
ta l’elemento appena introdotto nel menu. Questo consigliata: memorizzare gli identificativi degli ele-
genere di oggetti dispone di metodi che permettono menti del menu con delle costanti. In questo modo
il controllo dell’elemento. Fra questi segnaliamo i gli ID risultano più leggibili e si è meno inclini a
seguenti: commettere errori di battitura o distrazione. Una
seconda tecnica per la gestione degli eventi consiste
public MenuItem setIcon(Drawable icon) nell’utilizzare il seguente metodo di MenuItem:
public MenuItem setIcon(int iconRes)
public MenuItem setOnMenuItemClickListener
Ambo i metodi servono per aggiungere un’icona (MenuItem.OnMenuItemClickListener
all’elemento. Si può usare un oggetto graphics.draw- menuItemClickListener)
able.Drawable, caricato o realizzato in precedenza,
oppure il riferimento ad un’immagine conservata La tecnica richiama le logiche di gestione degli even-
Fig. 5: Un semplice nella directory res/drawable del progetto. Una volta ti che abbiamo conosciuto il mese scorso. L’interfac-
icon menu, con sei impostata un’icona su un elemento, questa sarà cia MenuItem.OnMenuItemClickListener richiede l’im-
comandi testuali mostrata solo se l’elemento è parte dell’icon menu. plementazione del metodo:
Ecco un esempio che dimostra la funzionalità:
public boolean onMenuItemClick(MenuItem item)
package it.ioprogrammo.menudemo03;
... Il metodo viene richiamato quando l’elemento è
public class MenuDemo03Activity extends Activity { selezionato dall’utente. Ecco un esempio analogo al
... precedente, ma basato su questa seconda tecnica di
gestione degli eventi:
Affinché l’esempio funzioni correttamente, è neces-
sario disporre delle immagini play, pause e stop nella package it.ioprogrammo.menudemo05;
directory res/drawable del progetto. Nel CD-Rom ...
Fig. 9: Sono stati
allegato alla rivista troverete tutto ciò di cui avrete public class MenuDemo05Activity extends Activity {
aggiunti nove comandi
al menu. I primi cinque bisogno. Una volta fatta funzionare l’attività, il suo ...
sono entrati a far parte icon menu sarà come quello mostrato in Fig. 7. Ora
dell’icon menu, mentre i che abbiamo imparato a disporre gli elementi nel- La classe Activity, infine, dispone di altri due metodi
restanti quattro sono
l’options menu, impariamo anche come gestire gli collegati alla gestione del suo options menu:
stati posizionati nell’ex-
panded menu dell’atti- eventi di attivazione di ciascuno degli elementi
vità introdotti. Esistono un paio di maniere per intercet- • public boolean onPrepareOptionsMenu(Menu menu)
38 52 / Aprile 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
Android:
Android: corso dicorso di programmazione Android
programmazione � MOBILE
programming
Viene richiamato quando l’options menu sta per gendo elementi al parametro menu. Il terzo argo-
essere visualizzato. Infatti il metodo mento, menuInfo, viene usato solo in alcuni casi
onCreateOptionsMenu(), usato in tutti gli esempi che esamineremo in futuro, come ad esempio
precedenti, viene richiamato solo la prima volta quando si ha a che fare con le liste.
che il menu deve essere mostrato. Se si intende
modificare il menu costruito in precedenza, si può • public boolean onContextItemSelected(MenuItem
ridefinire questo secondo metodo. Gli oggetti item)
Menu, a tal proposito, dispongono di una serie di Richiamato quando un elemento di un context
metodi che permettono di recuperare, modificare menu viene selezionato.
e rimuovere gli elementi introdotti al suo interno • public void onContextMenuClosed(Menu menu)
in precedenza. Anche se non è un caso molto Richiamato quando il menu contestuale viene
comune, quindi, Android permette lo sviluppo di chiuso.
options menu dinamici, che cambiano in base NOTA
allo stato dell’applicazione. Gli oggetti android.view.ContextMenu dispongo-
no di tutti i metodi già visti con gli oggetti Menu. LA REGOLA
• public void onOptionsMenuClosed(Menu menu) Fate però attenzione al fatto che gli elementi dei DEI TRE CLIC
Una vecchia regola di
Viene richiamato quando l’options menu, dopo menu contestuali non supportano né le icone né usabilità dice che l’utente
essere stato visualizzato, viene chiuso. le scorciatoie da tastiera (cfr. box laterale). deve sempre poter trovare
In compenso gli oggetti ContextMenu si specia- quel che cerca con al
• public void openOptionsMenu() lizzano attraverso i seguenti metodi: massimo tre clic. Se non ci
Apre il menu automaticamente, senza che sia riesce, l’utente inizia a
provare frustrazione.
necessario premere il tasto “menu” del dispositi- • public ContextMenu setHeaderTitle(CharSe- Questa regola è stata
vo. quence title) inizialmente concepita per
public ContextMenu setHeaderTitle(int titleRes) il Web ma, di fatto, oggi
Associa un titolo al menu contestuale, che sarà può essere applicata anche
mostrato nell’intestazione del menu. alle applicazioni mobili e
desktop di tipo non
CONTEXT MENU professionale e dedicate ad
I menu contestuali permettono di associare partico- • public ContextMenu setHeaderIcon(Drawable un pubblico quanto più
lari opzioni o comandi ai singoli widget di un’atti- icon) ampio possibile. I menu di
vità. La creazione e l’utilizzo dei context menu sono public ContextMenu setHeaderIcon(int icon- Android, è evidente, sono
molto simili a quelli dell’options menu. Res) stati concepiti tenendo a
mente la regola.
La prima cosa che si deve fare è dichiarare che uno o Associa un’icona al menu contestuale, che sarà Per approfondire:
più widget dell’attività devono disporre di un menu mostrata nell’intestazione del menu. http://en.wikipedia.org/wi
contestuale. Lo si può fare con il metodo ki/Three-click_rule
registerForContextMenu(View view) di Activity. • public ContextMenu setHeaderView(View view)
Ad esempio, per dotare un bottone di un menu con- Imposta l’oggetto view come intestazione del
testuale si deve fare così: menu, sostituendo l’icona ed il titolo dei meto-
di precedenti.
Button mioBottone = new Button(this);
// … • public void clearHeader()
registerForContextMenu(mioBottone); Ripulisce l’intestazione del menu.
Se il widget è stato dichiarato in un XML di layout, lo Realizziamo insieme il seguente esempio di codice:
si può caricare attraverso il suo identificativo:
package it.ioprogrammo.menudemo06;
View mioWidget = findViewById(R.id.mioWidgetId); ...
// ... public class MenuDemo06Activity extends Activity {
registerForContextMenu(mioBottone); ...
Fatto ciò, è possibile ridefinire uno o più metodi di Fig. 7: Le icone degli
Activity in modo da generare e gestire il menu con- Si tratta di un’attività che dispone di due bottoni, elementi vengono
testuale. Questi metodi sono: tutti e due collegati ad un menu contestuale. mostrate nell’icon
L’esempio mostra come registrare i widget per il menu.
• public void onCreateContextMenu(ContextMenu menu contestuale, come creare menu distinti per
menu,View v, ContextMenu.ContextMenuInfo men- widget differenti e come gestire gli eventi dei
uInfo) menu contestuali. A proposito di eventi: anche
Questo metodo viene richiamato ogni volta che il nel caso dei context menu è possibile sfruttare la
menu contestuale per il widget v deve essere tecnica di gestione alternativa basata sugli ogget-
mostrato. Il menu deve essere costruito aggiun- ti OnMenuItemClickListener.
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Aprile 2010/ 5339
G
MOBILE
Android programming
� Android: corso di
Android: programmazione
corso di programmazione
40 54 / Aprile 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
MOBILE � corsoAndroid:
Android: corso di programmazione
di programmazione Android programming
NOTIFICHE E FINESTRE
DI DIALOGO
OTTAVO APPUNTAMENTO. QUESTO MESE INCREMENTEREMO L’INTERATTIVITÀ
DELLE NOSTRE APPLICAZIONI, DOTANDOLE DELLA POSSIBILITÀ DI EMETTERE
DEGLI AVVISI E DI INTERROGARE L’UTENTE ATTRAVERSO LE FINESTRE DI DIALOGO
N
ei mesi passati abbiamo già appreso sa), il messaggio da mostrare (come stringa, nel
numerose tecniche per dialogare con chi primo caso, o come riferimento a risorsa esterna, nel
utilizza l’applicazione: tra widget, eventi e secondo) e la durata del messaggio. Non è possibile
menu siamo già in grado di costruire applicazioni specificare quanti secondi, esattamente, il messag-
interattive. Ci sono comunque altri due strumenti gio dovrà restare visibile. Si può soltanto dire se il
che non possono assolutamente mancare nel messaggio deve durare poco o tanto. Per farlo si deve
nostro armamentario: sono i cosiddetti toast e le usare come argomento duration una fra le due
finestre di dialogo. I primi servono per segnalare costanti Toast.LENGTH_SHORT (durata breve) o
❑ CD ❑ WEB delle notifiche, mentre le seconde possono essere Toast.LENGTH_ LONG (durata lunga). Ecco un
corso_android_pt7.zip
usate sia per emettere un output sia per ricevere esempio:
cdrom.ioprogrammo.it
un input.
Toast toast = Toast.makeText(this, "Questo è un toast",
Toast.LENGTH_LONG);
UN TOAST COME AVVISO Una volta creato, il toast può essere mostrato chia-
Un toast è un avviso mostrato per qualche istante in mandone il metodo show():
sovraimpressione sullo schermo. Le notifiche toast
vanno usate per brevi messaggi testuali. Insomma, toast.show();
informazioni del tipo “impostazioni salvate”, “opera-
zione eseguita” e simili. I messaggi toast rimangono Altri metodi degli oggetti Toast permettono di impo-
sullo schermo per qualche istante e poi il sistema li stare ulteriori proprietà dell’avviso. Si consideri ad
rimuove automaticamente: non c’è alcuna intera- esempio il metodo:
zione con l’utente. La classe di riferimento per la
gestione dei messaggi toast è android.widget.Toast. public void setGravity(int gravity, int xOffset, int
A disposizione ci sono i seguenti due metodi statici: yOffset)
● public static Toast makeText(Context context, Con questo metodo si può impostare in quale ango-
CharSequence text, int duration) lo dello schermo far apparire il messaggio (gravity,
● public static Toast makeText(Context context, int cfr. ioProgrammo 146), specificando anche il disco-
resId, int duration) stamento dai bordi laterali (xOffset) e da quelli verti-
cali (yOffset). Ad esempio:
REQUISITI
Entrambi i metodi costruiscono un messaggio toast
testuale. I parametri da fornire sono, rispettivamen- toast.setGravity(Gravity.TOP | Gravity.LEFT, 10, 10);
Conoscenze richieste
Java te, il contesto applicativo (ad esempio l’attività stes-
Questo avviso sarà mostrato in alto a sinistra, sco-
Software stato di 10 pixel dai bordi. Si possono anche creare
Java SDK (JDK) 5+,
Eclipse 3.3+ dei messaggi toast che, invece di mostrare del sem-
plice testo, facciano uso di immagini o di altri widget
al loro interno. In tal caso, invece di passare per i
metodi statici makeToast(), si usa il costruttore della
Impegno
classe, che vuole in argomento il contesto dell’appli-
¥ cazione:
Tempo di realizzazione Fig. 1: Ecco come appare un messaggio toast nell’in-
terfaccia di Android Toast toast = new Toast(this);
h t t p : / / w w w. i o p r o g r a m m o . i t
G 62 / Maggio 2010
A n d ro id p r o g r a m m ing 41
Android: corso
Android programming di programmazione
Android: � MOBILE
corso di programmazione
Questo significa che toast di maggiore complessità logo, e sulla maniera che dovremo adoperare per
possono essere creati con la più agevole sintassi di richiamarle e mostrarle.
XML, per essere poi caricati dinamicamente quando La classe Activity fornisce un metodo così definito:
occorre mostrarli.
Nel CD-Rom allegato alla rivista troverete degli public final void showDialog(int id)
esempi completi di utilizzo delle notifiche toast.
Possiamo richiamare questo metodo ogni volta che
dobbiamo aprire e mostrare una finestra di dialogo.
Il parametro id simboleggia quale specifica finestra
di dialogo l’attività deve mostrare. Il valore è arbitra-
rio, nel senso che è nostro compito creare le finestre
di dialogo ed assegnargli degli identificativi. La pras-
si consiglia di usare delle costanti interne alla classe
dell’attività.
Mi spiego meglio attraverso un esempio. Facciamo il
caso che la nostra attività faccia uso di due finestre
di dialogo, una per emettere un avviso di errore ed
una per richiedere una conferma. La miglior cosa da
Fig. 2: Un toast di maggiore complessità, con icona fare, in casi come questo, è aggiungere due costanti
e testo, costruito a partire da una definizione di all’attività, con nomi e valori arbitrari ma univoci. Ad
layout esterna, in formato XML
esempio:
h t t p : / / w w w. i o p r o g r a m m o . i t
42 Maggio And
2010/
roi d pr o63
g r amG
m in g
MOBILE � corsoAndroid:
Android: corso di programmazione
di programmazione Android programming
G 64 / Maggio 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 43
Android: corso
Android programming di programmazione
Android: � MOBILE
corso di programmazione
h t t p : / / w w w. i o p r o g r a m m o . i t
44 MaggioAnd
2010/
roi d pr o 65
g r amG
m in g
MOBILE � corsoAndroid:
Android: corso di programmazione
di programmazione Android programming
Fig. 5: Un avviso che può essere chiuso attraverso il Fig. 6: Una richiesta di conferma con due bottoni
suo stesso bottone “chiudi”
G 66 / Maggio 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 45
Android: corsoAndroid:
Android programming di programmazione � MOBILE
corso di programmazione
Il metodo crea e restituisce una finestra di attesa accetta un intero compreso tra 0 ed il valore massi-
indeterminata, quindi senza barra di progresso. mo previsto. Ad esempio:
Richiede come parametri il contesto dell’applicazio-
ne (tipicamente l’attività stessa che sta creando la progress.setSecondaryProgress(30);
finestra), il titolo da assegnare alla finestra ed il mes-
saggio da mostrare al suo interno. Le ProgressDialog
con barra di avanzamento sono leggermente più
complesse. L’oggetto, in questo caso, va costruito FINESTRE
manualmente richiamando il costruttore: DI DIALOGO CUSTOM
Se AlertDialog e ProgressDialog non dovessero anda-
ProgressDialog progress = new ProgressDialog(this); re bene per una vostra specifica esigenza, potete
sempre procedere alla costruzione e all’utilizzo di
Bisogna poi specificare che la barra che si sta crean- una finestra di dialog custom, cioè i cui contenuti
do non è indeterminata: sono stabiliti in tutto e per tutto da voi. Vediamo
insieme come procedere. Ancora una volta, la
progress.setIndeterminate(false); miglior cosa da farsi è realizzare un layout XML. Fig. 10: Una ProgressDialog
Realizziamo insieme il seguente: indeterminata (cioè senza
barra di avanzamento)
Adesso si deve indicare di usare la barra orizzontale:
<LinearLayout xmlns:android="http://schemas
progress.setProgressStyle(ProgressDialog.STYLE_HORIZ .android.com/apk/res/android"
ONTAL); ...
h t t p : / / w w w. i o p r o g r a m m o . i t
46 Maggio And
2010/ 67
roi d pr o g r am mG
in g
MOBILE
Liste, tabelle
� eListe, tabelle
gallerie e gallerie di immagini
di immagini Android programming
T
utti i layout dimostrati negli esempi dei
mesi precedenti sono dei layout “fissi”. I
widget di un layout fisso sono sempre gli
stessi e non cambiano ruolo nel corso del tempo:
ogni volta che si avvia l’attività, i componenti
mostrati sono sempre gli stessi e la schermata, di
conseguenza, appare sempre uguale. Ripensate,
ad esempio, a quando abbiamo dimostrato l’uso
❑ CD ❑ WEB di etichette, bottoni e caselle di testo realizzando
corso_android_9.rar
un form per l’immissione delle generalità ana-
cdrom.ioprogrammo.it
grafiche (nome, cognome, sesso) dell’utente. È
stato fatto nei numeri 146 e 147 della rivista.
Pensate ad un’applicazione come la rubrica del
telefono, oppure la galleria delle immagini. Si tratta Fig. 1: La galleria delle immagini di Android è il clas-
di attività il cui contenuto cambia di continuo. Se sico esempio di applicazione il cui layout non è fisso,
in quanto il numero dei widget presenti dipende da
aggiungo un contatto o se scatto una nuova foto, ad una fonte esterna
esempio, ecco che nelle corrispondenti applicazio-
ni apparirà un nuovo elemento.
In questo genere di applicazioni, quindi, il numero
ed il tipo dei widget presenti non è sempre lo stes- dati (nel caso specifico, le immagini lette dalla
so, ma dipende da una fonte di informazioni ester- memoria) con lo strato dell’interfaccia utente (con-
na. La galleria delle immagini, ad esempio, costrui- tenitori e widget). Ciò, secondo tutti i più moderni
sce e mostra tanti widget quanti sono quelli neces- paradigmi della programmazione orientata agli
sari per mostrare i file immagine presenti in oggetti, è male. Non vorrete mica cedere al lato
memoria. Con le nozioni acquisite finora siamo in oscuro della forza, vero? Per nostra fortuna la libre-
grado di costruire un adattatore di questo tipo. ria di Android mette a disposizione una serie di
Sarebbe sufficiente, all’interno di un’attività, scri- strumenti che permettono di ottenere layout dina-
vere un ciclo for o qualcosa di analogo che, per ogni mici, in maniera assolutamente semplice, corretta
elemento riscontrato nella fonte dei dati, vada ad e pulita. Basta solo imparare a utilizzarli.
aggiungere al contenitore corrente tutti i widget
necessari per mostrarlo. Qualcosa come:
REQUISITI
@Override ADAPTERVIEW
Conoscenze richieste
Basi di Java public void onCreate(Bundle savedInstanceState) { ... } E ADAPTER
Il primo componente che andiamo a svelare è la
Software Una tecnica come questa funziona (bisognerebbe classe astratta android.widget.AdapterView. La clas-
Java SDK (JDK) 5+,
Eclipse 3.3+ usare qualche altra accortezza in più, in verità, ma se estende ViewGroup e, pertanto, è un contenitore
l’esempio serve giusto per rendere il concetto), ma di altri widget. I suoi widget, però, non devono esse-
nell’ottica della programmazione Android non è il re aggiunti facendo uso esplicito dei metodi
massimo. I layout XML, ad esempio, in un caso addView() messi a disposizione dal contenitore. Le
Impegno
come questo non risultano facilmente applicabili. istanze di AdapterView, infatti, sono in grado di
¥ Se la schermata va costruita iterativamente, infatti, determinare da sole i loro contenuti, partendo da
Tempo di realizzazione
c’è poca speranza di farlo senza il supporto della una sorgente esterna di informazioni che gli sugge-
logica Java. La pratica, inoltre, tende a mischiare i risce quanti e quali sono gli elementi da mostrare.
h t t p : / / w w w. i o p r o g r a m m o . i t
G 64 / Giugno 2010
A n d ro id p r o g r a m m ing 47
Liste, tabelle eListe,
Android programming gallerie di immagini
tabelle � MOBILE
e gallerie di immagini
Questa sorgente deve una implementazione dell’in- derlo, e può farlo in XML. Si può usare un layout
terfaccia android.widget.Adapter. Sono le istanze di XML per dichiarare da quali widget sarà composto
Adapter a determinare gli elementi che devono esse- ciascun elemento della lista. L’unico vincolo è che
re mostrati, facendo da tramite tra l’attività e la fonte questo layout deve necessariamente contenere un
esterna. AdapterView risponderà ai comandi di widget TextView. Soddisfatto questo requisito, è suf-
Adapter, mostrando esattamente quanto richiesto. ficiente notificare all’ArrayAdapter quale è il layout
Per realizzare delle schermate di questo tipo potete XML e quale, al suo interno, è l’id del TextView da
estendere da voi AdapterView e implementare come utilizzare. Lo si può fare nel costruttore dell’adapter.
meglio credete l’interfaccia Adapter, ma in verità Partendo da un layout listitem.xml così definito:
molto raramente vi accadrà di farlo. Android dispo-
ne già di ottime implementazioni pronte all’uso, in <?xml version="1.0" encoding="utf-8"?>
grado di coprire la stragrande maggioranza delle esi- <LinearLayout xmlns:android="http://schemas.
genze di programmazione. Nei prossimi paragrafi android.com/apk/res/android"
conosceremo le implementazioni di Adapter, per android:layout_width="wrap_content"
poi applicarle insieme alle estensioni di android:layout_height="wrap_content">
AdapterView disponibili nella libreria di base. <TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5pt" NOTA
android:textSize="10pt"
ARRAYADAPTER android:id="@+id/listItemTextView" />
GENERICS
Un adattatore semplice e veloce da utilizzare è </LinearLayout> I generics sono una
costituito dalla classe android.widget.Array- caratteristica di Java
Adapter. Come il nome suggerisce, si tratta di un Si può fare: introdotta a partire dalla
adattatore che si comporta un po’ come un array, in versione 5 della
piattaforma. L’utilizzo più
quanto dispone di metodi utili per aggiungere, ArrayAdapter<String> arrayAdapter = new
comune che se ne fa è per
verificare e rimuovere gli elementi al suo interno. ArrayAdapter<String>(this, R.layout.listitem, qualificare il tipo di dato
La classe fa uso dei generics di Java per gestire R.id.listItemTextView); contenuto in un insieme o
meglio il tipo degli elementi al suo interno, proprio in una lista, evitando così la
come fanno anche java.util.ArrayList o Ora non resta che aggiungere gli elementi all’adap- necessità di casting
continuo. Prima di Java 5,
java.util.Vector. Quando si crea un oggetto di tipo ter. Il metodo suo add() è quel che ci vuole: infatti, un ArrayList di
ArrayAdapter, quindi, bisogna specificare il tipo stringhe si sarebbe dovuto
degli elementi che conterrà. Ad esempio: arrayAdapter.add("Carlo"); gestire alla seguente
arrayAdapter.add("Claudia"); maniera:
ArrayAdapter<String> arrayAdapter = new arrayAdapter.add("Silvia");
ArrayAdapter<String>(...); arrayAdapter.add("Alessandro"); ArrayList list = new
ArrayList();
In questo esempio gli elementi trattati dall’adattato- Ovviamente inserire gli elementi della lista in que- list.add("stringa");
re sono delle stringhe. Al posto delle stringhe, se sta maniera non è il massimo. Gli adattatori, infat- String str = (String)
necessario, potete utilizzare qualsiasi classe vi faccia ti, servono per assorbire elementi dall’esterno, ad list.get(i);
comodo per il caso specifico. Fate però attenzione al esempio dal file system o dal database del sistema.
fatto che gli ArrayAdapter sono stati concepiti per Di questo aspetto, naturalmente, ci occuperemo Con i generics, invece, è
possibile fare:
lavorare con il testo. Il loro scopo è iniettare dei wid- nei mesi a venire. Per ora continuiamo a concen-
get TextView all’interno dell’AdapterView che li uti- trarci sulla classe ArrayAdapter. Gli elementi al suo ArrayList<String> list =
lizza. I TextView, vi ricordo, sono dei widget testuali, interno possono essere recuperati con il metodo newArrayList<String>();
utili per mostrare una stringa a schermo. Nel caso di getItem(int position), rimossi uno ad uno con list.add("stringa");
un ArrayAdapter di stringhe, quindi, gli elementi remove(T item), ripuliti completamente con clear() String str = list.get(i);
aggiunti nell’adattatore saranno mostrati diretta- o conteggiati con getCount(). Da questo punto di
mente con delle etichette di testo. Se gli elementi vista, gestire un ArrayAdapter è proprio come gesti- Per approfondire:
gestiti, invece, non sono delle stringhe ma degli re un comune java.util.ArrayList, fatta salva qual- http://tinyurl.com/
oggetti qualsiasi, nei TextView generati sarà intro- che differenza nel nome dei metodi. jgenerics
dotta la rappresentazione testuale di ciascun ele-
mento, ottenuta richiamando il metodo toString()
dell’oggetto corrispondente. Oltre alla classe degli
elementi da gestire, ArrayAdapter vuole sapere IMPLEMENTARE
anche come rappresentarli. Come accennato, IL PROPRIO ADAPTER
ArrayAdapter userà una TextView per ciascun ele- Come abbiamo appena appreso, un ArrayAdapter è
mento previsto. Come questa TextView è fatta e in proprio quello che ci vuole quando i dati gestiti
che contesto è inserita spetta allo sviluppatore deci- sono una lista testuale o, comunque, rappresenta-
h t t p : / / w w w. i o p r o g r a m m o . i t
48 Giugno 2010
And roi d /
pr o65
g r amG
m in g
MOBILE
Liste, tabelle
� eListe, tabelle
gallerie e gallerie di immagini
di immagini Android programming
• public int getCount() Questo metodo restituisce Una volta creato l’oggetto, bisogna assegnargli un
il numero di elementi presenti nell’adattatore. Adapter affinché sia possibile caricare dei dati al
suo interno. Il metodo utile è setAdapter():
• public Object getItem(int position) Resttituisce
l’elemento alla posizione indicata. listView.setAdapter(mioAdapter);
Fig. 2: Un esempio di • public long getItemId(int position) Restituisce Che adattatore utilizzare? Un ArrayAdapter o un
ListView con un id per l’elemento alla posizione indicata. adattatore custom ottenuto per estensione di
ArrayAdapter BaseAdapter, come mostrato in precedenza,
• public View getView(int position, View andranno benissimo.
convertView, ViewGroup parent) Questo è il Gli eventi di tocco e tocco lungo su un oggetto della
metodo più importante del lotto. Deve restituire lista possono essere gestiti applicando degli appo-
il widget che rappresenterà l’elemento sullo siti listener all’oggetto ListView. Il tocco semplice
schermo. L’indice dell’elemento da rappresenta- può essere intercettato usando il metodo
NOTA re è dato dal parametro position. Il parametro setOnItemClickListener() e l’interfaccia android.
convertView costituisce il widget generato dall’a- widget.AdapterView.OnItemClickListener:
CURSORADAPTER dapter ad una sua precedente chiamata. Se pos-
Un altro Adapter di Android sibile, infatti, l’adattatore deve cercare di ricicla- listView.setOnItemClickListener(new
molto utilizzato è re i widget, per risparmiare memoria. Il parame- OnItemClickListener() {
android.widget.CursorAdap
tro parent, infine, è il contenitore che dovrà ospi- @Override
ter. Non è stato illustrato
nell’articolo in quanto per tare il widget generato o riciclato. public void onItemClick(AdapterView<?>
la sua comprensione è adapterView, View view, int position, long id) {
necessario conoscere cosa Ecco un esempio di implementazione che permet- // ...
sia e come si utilizza un te di gestire una lista di immagini (fornite sotto }
Cursor. Un cursore è
forma di oggetti android.graphics.drawable. });
l’oggetto che permette di
scorrere i risultati di una Drawable):
query svolta al sistema di Gli argomenti forniti al metodo onItemClick() sono:
database interno ad import android.content.Context;
Android, e dunque il ... • AdapterView<?> adapterView
CursorAdapter è un
public class ImageAdapter extends BaseAdapter {... } L’AdapterView che ha subito l’evento.
adattatore ideale per
impaginare e mostrare
all’utente i dati che • View view
provengono da un Il widget all’interno dell’AdapterView che ha
database. Ne riparleremo
in futuro.
LA CLASSE LISTVIEW subito l’evento.
La classe android.widget.ListView permette di rea-
lizzare delle liste di elementi con scrolling verticale. • int position
Le istanze di ListView, come quelle di ogni altro La posizione del widget all’interno
widget, possono essere costruite indifferentemente dell’AdapterView, come indice da zero in su.
con codice Java o XML. Nel primo caso, dall’inter-
no di un’attività, si farà qualcosa come: • long id
L’id della riga dell’AdapterView che ha subito l’e-
ListView listView = new ListView(this); vento.
Nel caso del codice XML, invece, sarà necessario Il tocco lungo richiede il metodo setOnItem
fare qualcosa del tipo: LongClickListener() e l’interfaccia android.wid-
G 66 / Giugno 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 49
Liste, tabelle eListe,
Android programming gallerie di immagini
tabelle � MOBILE
e gallerie di immagini
h t t p : / / w w w. i o p r o g r a m m o . i t
50 Giugno And
2010 /o g67
roi d pr r amG
m in g
MOBILE
Liste, tabelle
� eListe, tabelle
gallerie e gallerie di immagini
di immagini Android programming
G 68 / Giugno 2010
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 51
programming Android:
MOBILE
Android l’utilizzol’utilizzo
Android: di temidie temi
stili e stili
UN’APPLICAZIONE
CON STILE
IL DESIGN È UNO DEI FATTORI PIÙ IMPORTANTI IN AMBITO MOBILE. NON È SUFFICIENTE
CHE UN’APPLICAZIONE FUNZIONI: DEVE ANCHE ESSERE ELEGANTE E GRADEVOLE ALLA
VISTA. PER QUESTO OGGI SCOPRIREMO COME GESTIRE IL LOOK DELLE APPLICAZIONI
P
er tutta la durata di questo corso, abbiamo che il testo sia grassetto e corsivo (con la proprietà
più volte rimarcato come Android spicchi tra textStyle), di colore giallo (textColor), grande 20
gli altri sistemi mobili per la modernità dei punti (textSize), con un font a spaziatura fissa (type-
suoi concetti e per la tipologia dei suoi strumenti, face) e distanziato di 10 punti dai bordi del widget
soprattutto per quel che riguarda il design delle (padding). Tutte queste proprietà potrebbero essere
interfacce utente. Realizzare una UI per Android, espresse anche con del codice Java, ma natural-
infatti, è un’operazione che ricorda più il design di mente in XML è molto più semplice configurare
una pagina Web che non la costruzione di un’ap- lo stile di un widget. Utilizzando Eclipse, poi, lo è
plicazione a finestre su un sistema desktop. Grazie ancora di più, visto che si possono utilizzare le pro-
❑ CD ❑ WEB
android_10.rar al linguaggio di layout basato su XML, in Android cedure guidate messe a disposizione dal plug-in per
ogni widget dell’interfaccia può essere velocemen- lo sviluppo Android.
cdrom.ioprogrammo.it
te espresso e configurato. Tra le tante cose che
Android permette, c’è anche la possibilità di inter-
venire sull’aspetto di ciascun widget, modifican-
done ad esempio il colore, i bordi, lo stile del testo,
l’immagine di sfondo e così via. Oggi ci concen-
treremo proprio su questo aspetto, introducendo i
concetti di stile e tema. Fig. 1: Un componente TextView personalizzato nelle sue
proprietà di stile
potrebbe costarci parecchia fatica in futuro. Questo TextView, una volta caricato in un’attività,
Per questo motivo Android mette a disposizione apparirà identico a quello dimostrato in apertura
uno speciale costrutto XML che permette di definire di paragrafo. Adesso, però, è possibile realizzarne
gli stili come delle entità indipendenti, slegate cioè a iosa senza dover fare copia-incolla degli attributi
dal widget o dai widget cui sono applicate. Gli stili di stile: basterà applicare a tutti lo stile textViewSt-
possono essere definiti negli XML di tipo resources, yle01, e tutti i testi appariranno gialli e in grassetto.
come già siamo abituati a fare con le stringhe. La La richiesta del cliente di cambiare le dimensioni
cartella di progetto da utilizzare, quindi, è “res/ ed il colore del testo, adesso, potranno essere sod-
values” (o una delle sue varianti) e il modello da disfatte nel giro di un minuto, modificando un solo
seguire è il seguente: file XML, cioè quello che contiene la definizione
dello stile.
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
<style name=”textViewStyle01”>
<item name=”android:textStyle”>bold|italic</ EREDITÀ NEGLI STILI
item> Chi di voi conosce il Web design, l’HTML ed i CSS
si starà sicuramente trovando a proprio agio. Il NOTA
<item name=”android:textColor”>#FFFF00</item> modello di gestione degli stili di Android, infatti,
<item name=”android:textSize”>20sp</item> ha fatto tesoro dell’esperienza del Web. Dai fogli di
<item name=”android:typeface”>monospace</ stile CSS, infatti, riprende anche un’altra caratte- FILE CONSIGLIATI
item> ristica: l’ereditarietà. Cerchiamo di capire insieme Stili e temi, come si è
<item name=”android:padding”>10dp</item> cosa significhi e quali vantaggi comporti. visto, vanno definiti in file
</style> Torniamo all’esempio del cliente petulante del XML di tipo resources, da
</resources> posizionare al percorso
paragrafo precedente. Nell’applicazione che stiamo /res/values (o varianti). Non
realizzando per lui abbiamo fatto uso di numerosi ci sono vincoli sui nomi
I singoli <item> rappresentano le proprietà che oggetti TextView. Stando alla specifica iniziale del dei file XML posizionabili
entrano a far parte dello stile. Nomi e valori, come software, il testo in questi componenti deve appa- a questo percorso, e per-
è possibile osservare, devono essere ricavati dagli rire giallo e di una certa dimensione. Così abbiamo tanto potete crearne quanti
ne volete e con i nomi che
attributi dei widget e dai valori che è possibile attri- definito uno stile e lo abbiamo applicato ad ogni più desiderate. Potete met-
buire a questi ultimi. occorrenza del widget TextView. Il cliente, succes- tere uno stile in ogni file,
In un singolo file di risorse, naturalmente, posso- sivamente, ci ha chiesto delle modifiche, che noi oppure fare un solo file con
no essere definiti più stili, usando più occorrenze siamo stati in grado di apportare istantaneamente tutti gli stili della vostra
del tag <style>. Ciascuno stile deve avere un nome modificando lo stile applicato al testo. La soddi- applicazione. Per Android,
in fin dei conti, è la stessa
univoco. Il nome possiamo stabilirlo noi come sfazione del cliente è stata enorme nel constatare cosa. La maggior parte
meglio preferiamo, certamente facendo in modo quanto fossimo veloci ed efficienti nell’applicare la degli sviluppatori della
che sia significativo nel nostro caso specifico. Nel modifica richiesta. Per questo, il cliente ci ha preso comunità Android, ad ogni
caso appena mostrato, ad esempio, si sta preparan- gusto... Girovagando tra le schermate dell’applica- modo, preferisce usare un
do uno stile che si intende applicare a dei widget zione, adesso gli è venuto in mente che alcune delle unico file styles.xml per gli
stili ed un unico file the-
TextView. Per questo si è scelto di chiamarlo text- scritte che abbiamo modificato – solo alcune, però, mes.xml per i temi. Spesso
ViewStyle01. Il nome potrà successivamente essere non tutte – dovrebbero essere un po’ più piccole, ed risulta conveniente seguire
impiegato per richiamare lo stile. Il modello da inoltre andrebbero allineate al centro dello scher- questa convenzione.
seguire in Java sarà: mo invece che a sinistra. Contiamo fino a dieci,
sfoggiamo un sorriso compiacente, annuiamo, e
R.style.textViewStyle01 mettiamoci a lavoro.
Abbiamo diverse possibilità. Naturalmente non
Mentre in XML sarà: possiamo modificare lo stile textViewStyle01, perché
questo significherebbe modificare tutti i TextView
@style/textViewStyle01 che ne fanno uso, e non solo quelle poche unità
indicate dal cliente. Potremmo allora raggiungere
Una volta pronto, lo stile può essere applicato ad ogni occorrenza di TextView da modificare, sgan-
un widget qualsiasi attraverso il suo attributo style. ciarla dallo stile definito in precedenza, e definire
Ad esempio: su ciascuna di esse il nuovo stile usando gli attri-
buti di stile previsti da TextView. Come soluzione
<TextView funzionerebbe, ma sarebbe un passo indietro. La
android:layout_width=”fill_parent” cosa migliore da fare, invece, è definire un secondo
android:layout_height=”wrap_content” stile, da applicare poi in sostituzione del proce-
android:text=”@string/message” dente soltanto a quelle etichette che devono essere
style=”@style/textViewStyle01” /> modificate. La definizione degli stili, in questo caso,
http :/ id
A n d ro / www.
p r o gi or apm
r omg ing
r a m mo. it Luglio 2010 / 5553
programming Android:
MOBILE
Android l’utilizzol’utilizzo
Android: di temidie temi
stili e stili
http :/ id
A n d ro / www.
p r o gi or apm
r omg ing
r a m mo. it Luglio 2010 / 5755
programming Android:
MOBILE
Android l’utilizzol’utilizzo
Android: di temidie temi
stili e stili
Nel disco rigido del computer che state utilizzando allora realizzare un’attività che appaia all’utente
per sviluppare, localizzate dove avete installato come una finestra di dialogo, facendo così nell’An-
l’SDK di Android. Qui dovreste avere una directory droidManifest.xml:
chiamata “platforms”. Questa cartella contiene le
diverse versioni di Android che avete scaricato ed <activity android:theme=”@android:style/Theme.
Carlo Pelliccia
LO STORAGING
SECONDO ANDROID
LEGGERE E SCRIVERE FILE DAL DISCO DI UNO SMARTPHONE ANDROID È UN’OPERAZIONE
POSSIBILE MA SOGGETTA A RESTRIZIONI DI SICUREZZA E A NORME DI BUON USO.
OGGI IMPAREREMO COME UTILIZZARE CORRETTAMENTE IL FILE SYSTEM DI ANDROID
C
onclusa la panoramica dedicata alla rea- fortunatamente per noi, spendono molte risorse nella
lizzazione delle UI (interfacce utente) delle revisione del loro codice e nei test di sicurezza dello
applicazioni Android, andiamo da oggi a con- stesso. Significa che i sistemi operativi ed i software
centrarci su altri aspetti della piattaforma mobile di che girano al loro interno, oggi, sono molto meno
Google, egualmente indispensabili per applicazioni vulnerabili rispetto a qualche anno fa. Naturalmente
distribuibili e vendibili nel mondo reale. Cominciamo non esiste e non esisterà mai un sistema o un software
parlando di file system. Qualunque applicazio- sicuro al 100%, e per questo i produttori investono
ne Android, infatti, può leggere e scrivere file dalla anche nel correggere velocemente le falle che ven-
memoria interna del telefono o da una scheda esterna gono scoperte, distribuendo poi gli aggiornamenti in
❑ CD ❑ WEB
Android 153.rar inserita nel dispositivo. I principi da osservare per maniera rapida e trasparente.
compiere questo genere di operazioni differiscono Sul secondo fronte, quello cioè che fa leva sul fattore
cdrom.ioprogrammo.it
leggermente dalle normali pratiche Java adoperate umano, la battaglia è invece un po’ più complessa ed
negli applicativi desktop o server. Scopriamo insieme arretrata. C’è chi, come Apple, richiede di approvare
come fare per leggere e scrivere file dall’interno di preventivamente qualunque applicazione prodotta
un’applicazione Android. per le piattaforme iPhone, iPod e iPad. L’utente può
installare applicazioni solo se le preleva dallo store
di Apple, che ha verificato una ad una le applicazioni
disponibili, convalidandone sicurezza, attendibilità e
SICUREZZA funzionalità. L’utente, così, non rischia di cadere in
PRIMA DI TUTTO trappola. Da una parte questo approccio risolve quasi
Le piattaforme mobili di nuova generazione sono figlie completamente il problema del fattore umano della
di una ritrovata attenzione per la sicurezza dell’utente, sicurezza, ma dall’altro limita pesantemente la libertà
dei suoi dati e del suo dispositivo. I sistemi operativi dell’utente e dei produttori di software. Insomma,
per desktop, Windows in primis, sono continuamente la cura rischia di essere peggiore del male. Android,
vittima di virus e malware di ogni sorta. Questa piaga al contrario, è permeato da una filosofia più aperta,
è da sempre causa di grossa frustrazione per chi il e per questo lascia maggiore libertà ad utenti e pro-
computer lo utilizza per svago o per lavoro, pur non grammatori, senza costringerli ad un unico canale
essendone un esperto e non comprendendone i mec- di approvvigionamento delle applicazioni. Tutto ciò,
canismi interni. Siccome gli smartphone sono sempre però, deve essere conciliato con la necessità di non far
REQUISITI
più simili ai PC, sia come potenza di calcolo sia come proliferare il malware su questa piattaforma software.
possibilità dei loro software, i produttori di sistemi Nel caso di Android, quindi, non esiste un unico store
Conoscenze richieste mobili stanno facendo il possibile per evitare che delle applicazioni, ma ne esistono diversi. C’è quello
Basi di Java
anche le loro piattaforme possano diventare vittima principale, l’Android Market di Google, ma per il resto
di tale piaga. chiunque è libero di realizzare il proprio, ed infatti
Software
Java SDK (JDK) 5+, Il software malevolo può insediarsi in un sistema in diversi produttori lo hanno già fatto. In questo caso,
Android SDK, Eclipse due differenti maniere: sfruttando una vulnerabilità quindi, si può scegliere di chi fidarsi, godendo sia di
3.3+, ADT
interna del sistema operativo o di qualche software una maggiore libertà sia di un senso di sicurezza basa-
Impegno che vi è installato, oppure convincendo l’utente ad to sulla fiducia per lo store che si sta adoperando. Ad
eseguire un programma che all’apparenza è inno- ogni modo resta sempre viva la possibilità di installare
cuo, ma che in realtà nasconde qualcosa di losco. Sul applicazioni procurate anche senza la mediazione
Tempo di realizzazione
primo fronte si combatte una battaglia fatta di investi- di uno store. È dunque necessario che il sistema sia
menti sulla sicurezza del codice prodotto. I creatori di intrinsecamente sicuro, in modo che l’utente corra
Android e di tutti i sistemi operativi contemporanei, meno rischi possibile.
66 /Agosto 2010
A n d ro id p r o g r a m m ing 57
h ttp ://www.io pr o g r a m m o .i t
Android programming La gestione del filedel
La gestione system
file system MOBILE
58
http :/ / w ww. i o p r o g r a m m o. it Agosto And
2010 /o67
roi d pr g r am m in g
MOBILE La gestione
La gestione del filedel file system
system Android programming
68 /Agosto 2010
A n d ro id p r o g r a m m ing 59
h ttp ://www.io p r o g r a m m o .i t
Android programming La gestione del filedel
La gestione system
file system MOBILE
Una volta che ci si è accertati che sia possibile accedere ... Con la prospettiva DDMS
allo storage esterno, è possibile farlo recuperandone il public class FileDemo04Activity extends Activity { di Eclipse, inoltre, potrete
percorso attraverso il metodo statico di Environment: esplorare il file system
public void onCreate(Bundle savedInstanceState) { dell’emulatore o di un
dispositivo collegato,
public static File getExternalStorageDirectory() super.onCreate(savedInstanceState);
andando così a verificare
setContentView(R.layout.main); dove sono i file e di quale
Il metodo restituisce un oggetto java.io.File che rap- Drawable[] pictures; permessi dispongono.
presenta la radice dello storage esterno. Usando le if (canReadFromExternalStorage()) {
quelli esistenti e così via, senza alcuna limitazione. pictures = new Drawable[0];
come caso di studio nel paragrafo precedente. Questa ImageAdapter adapter = new ImageAdapter(this,
L’AUTORE
terza implementazione del software salva gli appunti pictures);
60
http :/ / w ww. i o p r o g r a m m o. it Agosto And
2010 /o69
roi d pr g r am m in g
MOBILE Android:
Android: l’accesso
l’accesso al DB
al DB Android programming
DATABASE
DA TASCHINO
UNA DELLE CARATTERISTICHE PIÙ INTERESSANTI DI ANDROID È IL DBMS INTEGRATO
NEL SISTEMA, CHE DOTA LE APPLICAZIONI DELLA CAPACITÀ DI ARCHIVIARE E RICERCARE
VELOCEMENTE I DATI. IN QUESTO ARTICOLO IMPAREREMO COME APPROFITTARNE
D
BMS, ossia Database Management a coSa SeRVe?
System, è un termine caro agli svilup- È lecito chiedersi che ruolo possa avere un
patori di applicazioni server-side e di DBMS installato in un telefono cellulare. Le
impresa. La maggior parte delle applicazioni applicazioni mobili, infatti, non gestiscono
Web, ad esempio, si appoggiano ad un databa- grandi quantità di dati, e nemmeno devono
se, e lo utilizzano per organizzare e ricercare soddisfare il requisito dell’accesso contem-
velocemente dati di ogni tipo. È naturale che poraneo da parte di un elevato numero di
le applicazioni server-side abbiano bisogno di utenti. I DBMS, invece, servono proprio per
un DBMS, visto che devono gestire grosse moli soddisfare la necessità di scrivere e leggere
❑ cd ❑ Web
NotePad.rar di dati, come l’elenco degli utenti iscritti ad un molti dati, e soprattutto lo possono fare in tante
sito, o gli articoli pubblicati in un blog, i com- sessioni simultanee (si pensi a quante visite
cdrom.ioprogrammo.it
menti dei visitatori, le statistiche di accesso e contemporanee può raggiungere un sito Web).
così via. Insomma, anche le più semplici appli- Un’applicazione mobile, da questo punto di
cazioni server fanno solitamente uso intensivo vista, potrebbe tranquillamente accontentarsi
dei database. di salvare le proprie informazioni in uno o più
Le applicazioni client-side per desktop, diver- file di testo, come d’altronde è stato già spie-
samente, usano i DBMS assai meno di frequen- gato nel numero precedente. Perché allora si
te. Esistono dei DBMS specifici per personal dovrebbe usare un DBMS?
computer, come Access di Microsoft, ed alcuni Tanto per cominciare, lo si fa perché con un
di quelli usati lato server si comportano bene DBMS è tutto più facile. In un database, infat-
anche se installati su un desktop o un laptop ti, i dati possono essere strutturati e tipizzati.
(MySQL, ad esempio). In questo caso i DBMS Immaginiamo di dover realizzare un’applica-
vengono utilizzati soprattutto in applicazioni zione che gestisca una lista di contatti, tipo
specifiche, spesso realizzate ad hoc per par- un’agenda. Ogni contatto è caratterizzato da
ticolari situazioni ed utenti. Ad esempio un un identificativo (ID), un nome, un cognome
gestionale per un libero professionista, o qual- e un indirizzo. Se dovessimo salvare queste
che altro software del genere, può fare ricorso informazioni su un file di testo, dovremmo
ad un DBMS locale. inventare un formato e programmare poi le
Passando al mondo mobile, invece, “DBMS” e classi in grado di gestirlo. La soluzione più
REQUISITI
“database” sono parole dal suono alieno e fuori classica consiste nell’organizzare un contatto
contesto. Almeno fino a ieri. per ciascuna riga, separando poi i campi con
Conoscenze richieste Gli smartphone di nuova generazione, infatti, una virgola. Ad esempio:
Basi di Java
hanno raggiunto potenza di calcolo e com-
plessità software sufficienti per l’esecuzione 1,Mario,Rossi,061299178
Software
Java SDK (JDK) 5+, di un DBMS di piccole dimensioni, ottimiz- 2,Antonio,Verdi,028667661
Android SDK, Eclipse zato appositamente per un ambito peculia-
3.3+, ADT
re e ristretto. Android comprende un piccolo I dati di un contatto, inoltre, non sono soltanto
Impegno DBMS, che gli sviluppatori possono richiamare di natura testuale: nome, cognome, e numero di
per salvare ed organizzare i dati delle loro telefono sono delle stringhe, ma l’identificativo
applicazioni. In questo articolo scopriremo del contatto è certamente un intero, e va gesti-
Tempo di realizzazione
come funziona questo DBMS. Vedremo come to come tale. Nel leggere e nel salvare i dati,
utilizzarne i benefici per rendere migliori e più quindi, bisognerebbe fare un sacco di lavoro di
complete le nostre applicazioni. codifica e decodifica, sia per gestire la struttura
54 / Settembre 2010
A n d ro id p r o g r a m m ing 61
h ttp ://www.io p r o g r a m m o .i t
Android programming Android: l’accesso
Android: al DB
l’accesso al DB MOBILE
nel sistema operativo stesso. Gli sviluppatori public void onUpgrade(SQLiteDatabase db,
di Google, come vedremo tra poco, hanno int oldVersion, int newVersion) {
62
h ttp :/ / www. i o p r o g r a m m o. it Settembre And
2010 /o g55
roi d pr r am m in g
MOBILE Android:
Android: l’accesso
l’accesso al DB
al DB Android programming
base di una stessa applicazione deve avere un popolati automaticamente quando si aggiunge
nome differente, così come differente deve un nuovo record, con una sequenza progressi-
essere il nome della classe helper) e la sua va di interi, funzionando quindi da contatore.
versione. Il numero di versione è un intero che Lo speciale nome _id, poi, serve ad Android
va incrementato ogni volta che, in un nuovo per capire quale è il campo identificativo di
rilascio del software, il database viene modifi- ciascun record.
cato nella struttura. In questa maniera, quando Seguendo questa prassi, le vostre tabelle saran-
l’utente aggiorna la propria applicazione, la no perfettamente integrate nella gestione auto-
classe riesce a capire se il database della ver- matica offerta dal sistema.
sione precedentemente installata deve essere Una volta completato lo sviluppo della classe
aggiornato oppure no. helper, è possibile sfruttarla in qualsiasi punto
I due metodi onCreate() e onUpdate() devono dell’applicazione. Tipicamente, nello sviluppo
necessariamente essere implementati. Il primo di una activity, si tende a conservare l’helper
viene richiamato quando il database deve esse- a livello di istanza, avendo cura di istanziarlo
re creato per la prima volta. Il parametro db, di la prima volta in risposta all’evento onCreate()
tipo android.database.sqlite.SQLiteDatabase, dell’attività. Il modello è il seguente:
serve per poter manipolare il database appe-
na creato. Tra poco vedremo come. Il metodo package mia.applicazione;
56 / Settembre 2010
A n d ro id p r o g r a m m ing 63
h ttp ://www.io p r o g r a m m o .i t
Android programming Android: l’accesso
Android: al DB
l’accesso al DB MOBILE
L’argomento table è il nome della tabella in cui ContentValues values = new ContentValues();
suoi valori iniziali; values è la mappa dei valori int r = db.update(“agenda”, values, whereClause,
public int update(String table, ContentValues L’utilizzo di delete() è simile ad update(), con la
values, String whereClause, String[] whereArgs) sola differenza che in questo caso non ci sono
nuovi valori da sovrascrivere ai precedenti,
Come nel caso precedente, table è il nome visto che si tratta di un’operazione di cancella-
della tabella e values è la mappa dei campi da zione e non di aggiornamento.
aggiornare con i nuovi valori da assegnare. Gli Ad esempio:
argomenti whereClause e whereArgs servono
per selezionare il record o i record da aggiorna- SQLiteDatabase db = mioDatabaseHelper.
64
h ttp :/ / www. i o p r o g r a m m o. it Settembre And
2010 /o g57
roi d pr r am m in g
MOBILE Android:
Android: l’accesso
l’accesso al DB
al DB Android programming
db.query(“agenda”, null, null, null, null, null, null); int count = cursor.getCount();
58 / Settembre 2010
A n d ro id p r o g r a m m ing 65
h ttp ://www.io pr o g r a m m o .i t
Android programming Android: l’accesso
Android: al DB
l’accesso al DB MOBILE
ritornerà false per indicare che non ci sono String orderBy = “_id ASC”;
ulteriori risultati su cui muoversi. Attraverso Cursor cursor = db.query(“agenda”, columns, null, null,
66
h ttp :/ / www. i o p r o g r a m m o. it Settembre And
2010 /o g59
roi d pr r am m in g
Condividere
MOBILE Condividere i dati in iAndroid
dati in Android Android programming
GESTIONE DEI
CONTENT PROVIDER
I CONTENT PROVIDER COSTITUISCONO LA MANIERA DI ANDROID PER CONDIVIDERE DATI
FRA LE APPLICAZIONI. IN QUESTO ARTICOLO IMPAREREMO A CONSULTARE I PROVIDER
PREDEFINITI E VEDREMO ANCHE COME COSTRUIRE UN FORNITORE DI CONTENUTI CUSTOM
N
ei due numeri precedenti abbiamo imparato quella che fa da ponte per l’accesso al provider dei
ad interagire con il file system ed il DBMS. contatti in rubrica. Al suo interno c’è la costante statica
Come abbiamo visto, secondo i meccanismi CONTENT_URI, di tipo android.net.Uri, che riporta
di gestione della sicurezza di Android, sia i file che l’URI che identifica univocamente il provider.
i database sono solitamente di esclusiva proprietà Una volta che si conosce l’URI di una tipologia di
dell’applicazione che li genera. Come fare, allora, contenuto, interagire con il provider che la eroga è
per condividere dati strutturati tra più applicazioni più o meno come fare delle interrogazioni ad un data-
Android? La risposta è: mediante i Content Provider. base. Per prima cosa si deve recuperare un’istanza
❑ CD ❑ WEB Un Content Provider è una parte di un’applicazione dell’oggetto android.content.ContentResolver. Stando
AndroidCP.rar Android che si occupa di rendere disponibili dei dati all’interno di una Activity (o avendo a disposizione un
alle altre applicazioni installate nel sistema. Ogni oggetto android.app.Context) si può usare il metodo
cdrom.ioprogrammo.it
applicazione, pertanto, può definire una o più tipolo- getContentResolver(). Ad esempio:
gie di dati e rendere poi disponibili tali informazioni
esponendo uno o più Content Provider. Nell’ordine ContentResolver cr = getContentResolver();
60 / Ottobre 2010
A n d ro id p r o g r a m m ing 67
h ttp ://www.io p r o g r a m m o .i t
Android programming Condividere i dati ini Android
Condividere dati in Android MOBILE
solamente attenzione al fatto che il cursore restituito, public void onCreate(Bundle savedInstanceState) {
scere il nome ed il tipo delle colonne che costituiscono String[] selectionArgs = null;
lo specifico tipo di dato richiesto. Anche in questo caso String sortOrder = Contacts.DISPLAY_NAME + “
costanti statiche di una classe. Nel caso della rubrica Cursor cursor = managedQuery(uri, projection,
68
h ttp :/ / w ww. i o p r o g r a m m o. it Ottobre And roi d pr/o g61
2010 r am m in g
Condividere
MOBILE Condividere i dati ini Android
dati in Android Android programming
ricerca per iD Aggiorna uno o più record del tipo specificato Activity {
Tutti i contenuti esposti mediante il parametro uri. La selezione avviene private static final int DELETE_DIALOG = 1;
mediante provider dovreb- attraverso l’uso combinato dei parametri where private Gallery gallery = null;
bero avere una colonna e selectionArgs. I nuovi valori da assegnare ai private int selectedImageId;
chiamata _ID, con l’iden-
tificativo numerico del record selezionati devono essere specificati attra-
verso la mappa values, di tipo android.content. @Override
record, univoco nella sua
categoria. Se si conosce ContentValues. Il metodo restituisce il numero dei public void onCreate(Bundle savedInstanceState) {
l’ID di un record e lo si record aggiornati. super.onCreate(savedInstanceState);
vuole estrarre diretta- gallery = new Gallery(this);
mente dal suo provider,
si può fare ricorso alla • public int delete(Uri uri, String where, String[] Uri uri = MediaStore.Images.Media.EXTERNAL_
selectionArgs) CONTENT_URI;
classe android.content.
ContentUris e al suo meto- Cancella uno o più record del tipo specificato ...
do statico withAppende- mediante il parametro uri. La selezione avviene
dId(): Uri uri = ContentUris. attraverso l’uso combinato dei parametri where e
withAppendedId(uri_di_
base_del_contenuto, selectionArgs. Il metodo restituisce il numero dei
id_del_contenuto); record cancellati. creare uN coNteNt
Cursor c = cr.query(uri, Provider
null, null, null, null); Implementiamo un esempio pratico. Questa volta Se volete condividere i dati della vostra applicazio-
lavoreremo con la lista delle immagini memorizzate ne con gli altri software installati nel telefono, pote-
nella galleria del telefono. L’URI di base per l’accesso te implementare il vostro Content Provider. Farlo è
alle immagini che sono nello storage esterno viene molto semplice: bisogna estendere la classe android.
riportato nella proprietà: content.ContentProvider, che richiede l’implementa-
zione dei seguenti metodi:
android.provider.MediaStore.Images.Media.EXTERNAL_
CONTENT_URI • public boolean onCreate()
Il codice da eseguirsi alla creazione del provider.
Tutte le immagini recuperate mediante l’apposito Il metodo deve restituire un booleano: true, per
provider dispongono di una colonna “_ID”, in cui segnalare che la creazione del provider è andata a
viene riportato il loro identificativo numerico univoco. buon fine; false, in caso contrario.
Come indicato nel box laterale, dato l’ID di un conte- • public String getType(Uri uri)
nuto, è possibile avere un suo URI specifico facendo: Dato un URI di gestione del provider, questo meto-
do deve restituire il tipo MIME del contenuto cor-
Uri uri = ContentUris.withAppendedId(uri_generico, id); rispondente. Solitamente, con tipi di dati perso-
nalizzati, non bisogna far altro che inventare il
Dato l’URI puntuale di un contenuto-immagine, è nome della tipologia, seguendo però alcuni criteri.
possibile caricare l’immagine (sotto forma di oggetto Se l’URI specificato corrisponde ad un contenuto
android.graphics.Bitmap) facendo: specifico (in genere avviene quando l’URI contiene
l’ID del contenuto), allora bisogna restituire un tipo
ContentResolver cr = new ContentResolver(this); MIME del tipo:
Bitmap image = MediaStore.Images.Media.getBitmap(cr,
uri); vnd.android.cursor.item/vnd.il_nome_del_tipo
Sfruttando queste conoscenze, andiamo a realizzare Per gli URI che corrispondono a gruppi di contenuti
un’attività in grado di svolgere i seguenti compiti: (senza ID, quindi), la formula è del tipo:
62 / Ottobre 2010
A n d ro id p r o g r a m m ing 69
h ttp ://www.io p r o g r a m m o .i t
Android programming Condividere i dati ini Android
Condividere dati in Android MOBILE
• public Cursor query(Uri uri, String[] projec- authorities, invece, definisce la parte fondamen-
tion, String selection, String[] selectionArgs, tale dell’URI gestito dal provider, cioè quello che
String sortOrder) dovranno utilizzare le altre applicazioni per inte-
Il metodo richiamato per eseguire una ricerca tra i ragire con il nostro Content Provider. Ad esempio,
dati gestiti dal provider. facciamo il caso che autorities sia:
70
h ttp :/ / www. i o p r o g r a m m o. it Ottobre And
2010 /o g63
roi d pr r am m in g
MultitaskingMultitasking
MOBILE con i servizi Android
con i servizi Android Android programming
LE APPLICAZIONI
GIRANO IN PARALLELO
I SERVIZI SONO QUELLA FUNZIONALITÀ DI ANDROID CHE PERMETTE DI ESEGUIRE
OPERAZIONI IN SOTTOFONDO, ANCHE QUANDO L’APPLICAZIONE CHE LE HA AVVIATE
NON È PIÙ ATTIVA. INSOMMA: MULTITASKING ALLO STATO PURO, ANCHE IN MOBILITÀ!
N
ella prima puntata di questo corso (appar- mediale possa essere rimossa dallo schermo. Lo si può
sa su ioProgrammo 143) si è subito spiega- fare, naturalmente, con un servizio.
to come le applicazioni Android contenga- Ecco un altro esempio, per chiarire ancora meglio il
no sempre uno o più componenti scelti fra i quattro concetto: immaginiamo di dover realizzare un’appli-
tipi fondamentali: le attività, i servizi, i broadcast cazione che, di tanto in tanto, si colleghi ad Internet per
receiver e i content provider. Delle attività ci siamo scaricare via Web delle notizie. L’utente ha imposto un
occupati a lungo, e continueremo a farlo in futuro. filtro sulle notizie di suo interesse, specificando delle
Nel numero precedente, invece, sono stati intro- parole chiave: solo le news che contengono le keyword
❑ CD ❑ WEB dotti i content provider, oggetti indispensabili per specificate gli devono essere notificate. È possibile farlo
Android14.rar la condivisione dei dati fra più applicazioni. Oggi ci avviando un servizio che, in sottofondo, si colleghi alla
occuperemo dei servizi. rete e analizzi le notizie di volta in volta disponibili.
cdrom.ioprogrammo.it
Quando si incontra una notizia in grado di soddisfare
il filtro impostato, il servizio non deve far altro che lan-
ciare un’attività per notificare l’evento all’utente. Con i
COS’È UN SERVIZIO servizi di Android è possibile fare anche questo.
Un servizio, nel gergo di Android, è una parte di una
applicazione che gira in background. A differenza
delle attività, i servizi non dispongono di un’interfaccia
grafica attraverso la quale interagire con l’utente. Allo CREARE UN SERVIZIO
stesso tempo, però, i servizi non vanno confusi né con La prima cosa da farsi per realizzare un servizio è
i processi né con i thread, che sono cose distinte e ben estendere la classe android.app.Service:
diverse. Un servizio, infatti, è gestito direttamente da
Android, e per questo possiede un proprio peculiare import android.app.Service;
ciclo di vita. In più i servizi si avvantaggiano delle public class MioServizio extends Service {
60 / Novembre 2010
A n d ro id p r o g r a m m ing 71
h ttp ://www.io pr o g r a m m o .i t
MultitaskingMultitasking
Android programming con i servizi Android MOBILE
con i servizi Android
72
h ttp :/ / www. i o p r o g r a m m o. it Novembre And
2010 /o g61
roi d pr r am m in g
MultitaskingMultitasking
MOBILE con i servizi con i servizi Android
Android Android programming
62 / Novembre 2010
A n d ro id p r o g r a m m ing 73
h ttp ://www.io pr o g r a m m o .i t
Multitasking Multitasking
Android programming con i servizi Android MOBILE
con i servizi Android
da mostrare, viene caricato servendosi della classe di public class WallpaperChangerActivity extends Activity
oggetto Bitmap come wallpaper è davvero molto sem- private Button bStartService;
plice in Android: basta servirsi del singleton android. private Button bStopService;
prietà statica STARTED, che ci tornerà utile a breve. Ora public void onCreate(Bundle savedInstanceState) {
NOTA
che il servizio è pronto ci serve un’attività per coman- ...
74
http :/ / www. i o p r o g r a m m o. it Novembre And
2010 / o63
roi d pr g r am m in g
Applicazioni
MOBILE location-based
Applicazioni conlocation-based
Android conAndroid
Androidprogramming
TU SEI QUI!
TE LO DICE ANDROID
I SERVIZI LOCATION-BASED SONO UNA DELLE CARATTERISTICHE PIÙ ATTRAENTI DI
ANDROID. IMPARIAMO A REALIZZARE APPLICAZIONI IN GRADO DI LOCALIZZARE L’UTENTE
VIA GPS E DI DISEGNARE LA SUA POSIZIONE IN UNA MAPPA
U
n’applicazione o un servizio possono definirsi è android.location.LocationManager. Riassumendo,
location-based quando lavorano con il posi- dall’interno di un’attività, il servizio di localizzazione
zionamento geografico dell’utente. Google è si recupera alla seguente maniera:
stato un pioniere dei servizi location-based: Google
Maps e Google Earth hanno spianato la strada ad LocationManager locationManager = (LocationManager)
56 / Dicembre 2010
A n d ro id p r o g r a m m ing 75
h ttp ://www.io p r o g r a m m o .i t
Applicazioni location-based
Android programming con location-based
Applicazioni Android MOBILE
con Android
76
http :/ / w ww. i o p r o g r a m m o. it Dicembre And
2010 /o g57
roi d pr r am m in g
Applicazioni
MOBILE location-based
Applicazioni con location-based
Android conAndroid
Androidprogramming
abilitato.
• public void onProviderDisabled(String provider)
Notifica che il provider indicato in argomento è stato
disabilitato. EMULARE IL GPS
• public void onLocationChanged(Location location) Quando si sviluppa un’applicazione location-based,
Notifica la lettura di una nuova posizione. come l’esempio appena illustrato, ci si scontra con il pro-
blema di come eseguirne il test ed il debug. Naturalmente
NOTA Una volta che non occorre più conoscere le misurazioni è possibile installare l’applicazione su uno smartphone
provenienti dal location provider selezionato, è meglio ed andare a farsi un giro a piedi o in automobile, tuttavia
COORDINATE annullare la sottoscrizione svolta in precedenza, agendo questa non è la maniera migliore per test frequenti e
GPS DA RIGA sul LocationManager con il metodo removeUpdates(): debug efficaci. Per nostra fortuna è possibile impostare
DI COMANDO delle false coordinate geografiche sull’emulatore fornito
Se non utilizzate Eclipse, locationManager.removeUpdates(myLocationListener); con l’SDK. Con Eclipse lo si fa dalla scheda “Emulator
potete fornire false coor- Control” della prospettiva “DDMS”. È possibile fornire
dinate GPS all’emulatore coordinate semplici, oppure caricarne una lista comples-
usando la riga di coman-
do. Aprite il prompt dei sa da file di tipo GPX e KML. Attenzione: se le coordinate
comandi e connettetevi LOCATIONDEMO inviate tramite l’Emulator Control di Eclipse DDMS non
all’emulatore via telnet: Forti delle nozioni appena acquisite, andiamo a realizza- funzionano correttamente, provate a chiudere l’ambien-
re un’applicazione che le metta in pratica. Chiameremo te e a riavviarlo dopo aver aggiunto le seguenti righe al
telnet localhost <porta> l’applicazione LocationDemo. Definiamone il layout nel file eclipse.ini presente nella cartelle di installazione del
La porta usata dall’emu- file res/layout/main.xml: vostro Eclipse:
latore è riportata nel titolo
della finestra che lo contie- <?xml version=”1.0” encoding=”utf-8”?> -Duser.country=US
ne. In genere è 5554 o una <LinearLayout xmlns:android=”http://schemas.android. -Duser.language=en
cifra molto simile. Lanciate com/apk/res/android”
ora il comando: android:orientation=”vertical” android:layout_
width=”fill_parent”
geo fix <longitude> <lati-
tude> android:layout_height=”fill_parent”> GOOGLE APIS
… PER ANDROID
Ad esempio: Finora abbiamo appreso come accedere al servizio di
geo fix 12.484564 Si tratta di un layout molto semplice, che realizza una localizzazione di Android per conoscere la posizione
41.91247 tabella all’interno della quale andremo ad annotare i dati dell’utente, ma questo è soltanto l’inizio. Una vera e pro-
provenienti dal provider GPS. pria applicazione location-based, infatti, fa anche uso di
Andiamo all’attività LocationDemoActivity, che realizza mappe e di altri servizi analoghi. Poiché questo è un ter-
la logica del progetto appena descritta: reno in cui Google gioca in casa, abbiamo a nostra dispo-
sizione un’ottima libreria di classi per l’accesso facilitato
package it.ioprogrammo.locationdemo; ai servizi location-based di Mountain View. Purtroppo
import java.util.Date; tale libreria, per motivi di licensing, viene fornita sepa-
... ratamente dal sistema, e per questo richiede del lavoro
public class LocationDemoActivity extends Activity { preparatorio aggiuntivo. Per prima cosa è necessario
… aver scaricato e integrato la libreria nel proprio Android
SDK. Potete verificarlo avviando il manager dei disposi-
Notate come l’utilizzo del servizio di localizzazione è tivi virtuali e controllando che nell’elenco dei pacchetti
stato collegato al ciclo di vita dell’attività: si sono utilizzati installati (“Installed Packages”) sia presente un pacchetto
i metodi onResume() e onPause(), rispettivamente, per del tipo “Google APIs by Google Inc.”, associato alla ver-
Fig.2: LocationDemo è avviare ed interrompere l’utilizzo del servizio. In que- sione di Android per la quale state sviluppando. Se non
un’app che si collega al ri- sta maniera il localizzatore viene invocato solo quando lo trovate, muovetevi nella scheda “Available Packages” e
cevitore GPS e ne mostra
l’attività sta occupando il display, e non quando gira scaricatelo. Ad operazione completata create un disposi-
le letture sul display
in background.Non resta che mettere tutto insieme in tivo virtuale che supporti le Google API appena installate
AndroidManifest.xml: (lo potete fare dalla scheda “Virtual Devices”). In Eclipse,
quando creerete una nuova applicazione che usa le
<?xml version=”1.0” encoding=”utf-8”?> mappe di Google, ricordatevi di indicare esplicitamente
<manifest xmlns:android=”http://schemas.android.com/ l’utilizzo della libreria nel target del progetto. L’ambiente,
apk/res/android” creando il nuovo progetto, aggiungerà la libreria al build
android:versionCode=”1” path dell’applicazione. Se non utilizzate Eclipse dovrete
58 / Dicembre 2010
A n d ro id p r o g r a m m ing 77
h ttp ://www.io p r o g r a m m o .i t
Applicazioni location-based
Android programming conlocation-based
Applicazioni Android MOBILE
con Android
svolgere questo compito a mano. I JAR delle Google API e per ognuno di essi vi fornirà l’impronta MD5. Con il
li trovate a partire dal percorso <android-sdk-directory>/ browser, recatevi ora all’indirizzo: http://code.google.
add-ons. Accertatevi, infine, che nel manifest della vostre com/android/add-ons/google-apis/maps-api-signup.
applicazioni location-based siano comprese la dichiara- html
zione di utilizzo della libreria Google Maps e le clausole
di utilizzo dei permessi per l’accesso al location manager Accettate le condizioni proposte e inserite l’MD5 del cer-
e ad Internet. Solitamente lo scheletro del manifest di tificato per il quale volete ottenere una chiave di utilizzo
un’app location-based assomiglia al seguente: di Google Maps. È fatta! Salvate la pagina Web con la
chiave generata per il vostro certificato.
<?xml version=”1.0” encoding=”utf-8”?> SUL WEB
<manifest ...>
<application ...> GOOGLE MAPS API
<uses-library android:name=”com.google.android. MAPACTIVITY REFERENCE
maps” /> E MAPVIEW La reference guide per
... Il pacchetto di riferimento per le API Android di Google le Google Maps API di
</application> Maps è com.google.android.maps. All’interno vi trovate Android è all’indirizzo:
<uses-permission android:name=”android.permission. MapActivity, che è la classe da estendere nel caso in cui si http://code.google.com/
ACCESS_FINE_LOCATION” /> voglia realizzare un’attività che mostri delle mappe sullo android/add-ons/google-
<uses-permission android:name=”android.permission. schermo. Estendere MapActivity è esattamente come apis/reference/index.html
ACCESS_COARSE_LOCATION” /> estendere Activity, con l’unica differenza che si deve
<uses-permission android:name=”android.permission. implementare il metodo:
INTERNET”/>
</manifest> protected boolean isRouteDisplayed()
keystore che trovate ad uno dei seguenti percorsi: android:apiKey=”CHIAVE GOOGLE MAPS QUI”
android:id=”@+id/mapView”
In Eclipse potete verificare il percorso del keystore di MapView mapView = (MapView) findViewById(R.
debug aprendo le preferenze dell’ambiente ed entrando
nella voce “Android » Build”.
L’impronta MD5 di un certificato può essere calcolata
usando l’utility keytool, compresa in ogni Java SDK. Con il
prompt dei comandi posizionatevi all’interno della direc- Fig.5: L’utilizzo delle
tory bin del vostro JDK, in modo che il comando keytool Google API va indicato
come target del nuovo
sia a portata di lancio. Quindi eseguite il comando:
progetto Android che si
sta creando in Eclipse
keytool -keystore <percorso-keystore> -list
78
http :/ / w ww. i o p r o g r a m m o. it Dicembre And
2010 /o g59
roi d pr r am m in g
Applicazioni
MOBILE location-based
Applicazioni conlocation-based
Android conAndroid
Androidprogramming
60 / Dicembre 2010
A n d ro id p r o g r a m m ing 79
h ttp ://www.io p r o g r a m m o .i t
Applicazioni location-based
Android programming conlocation-based
Applicazioni Android MOBILE
con Android
80
http :/ / w ww. i o p r o g r a m m o. it Dicembre And
2010 /o g61
roi d pr r am m in g
COVER
Applicazioni AndroidSTORY Applicazioni
senza scrivere codice con AppAndroid
Inventorsenza scrivere codice
Android con App Inventor
programming
L
e applicazioni contano. Questa è la conclu- e vendere (o regalare) delle applicazioni Android
sione alla quale sono finalmente giunti tutti competitive. Insomma, basta l’idea.
i produttori di smartphone di ultima genera-
zione. Non basta più proporre un hardware poten-
te, un design accattivante e un sistema facile da
utilizzare: ci vuole anche un ampio parco di appli- PREREQUISITI
cazioni, possibilmente di alta qualità. Non si fanno App Inventor è un’applicazione web online, come
discriminazioni per genere, utilità o complessità: GMail o Facebook per intenderci, e perciò per
l’utente moderno, sul market del suo smartphone, accedere all’applicazione bastano un computer ed
❑ CD ❑ WEB
appinv.zip vuole trovare di tutto: dallo strumento di lavoro al un browser di comune fattura. Più nello specifico, i
passatempo, dall’applicazione per interagire con il sistemi attualmente supportati sono:
cdrom.ioprogrammo.it
suo social network preferito a quella utile per risol-
vere una piccola faccenda di tutti i giorni. • Windows: XP, Vista, 7
Google tutto ciò l’ha capito benissimo e per questo • Mac OS X: 10.5, 10.6
la mamma di Android coccola ed incentiva chiun- • GNU/Linux: Ubuntu 8+, Debian 5+
que abbia nuove idee per applicazioni di successo.
Gli sviluppatori che hanno scelto Android, infatti, I browser compatibili, invece, sono:
hanno vita facile: hanno a disposizione un lin-
guaggio di programmazione facile ed espressivo, • Mozilla Firefox 3.6 o successivo
una libreria di funzionalità potenti e complete, un • Apple Safari 5.0 o successivo
ambiente di sviluppo aperto e flessibile. La docu- • Google Chrome 4.0 o successivo
mentazione e gli articoli tecnici non mancano, così • Microsoft Internet Explorer 7 o successivo
come abbondanti sono le comunità online dove gli
sviluppatori Android si radunano e si danno aiuto È poi importante che il sistema ed il browser instal-
a vicenda. Programmare applicazioni per Android, lino Java 6. Per verificare ed eventualmente soddi-
insomma, è facile e divertente. A Google, però, sfare questo ulteriore requisito, è sufficiente colle-
questo non basta. La programmazione, infatti, è garsi a questa pagina www.java.com. Per verificare
molto importante per avere buone applicazioni, e il vostro sistema seguite il link “Io ho Java?”. In caso
per questo va incentivata, ma allo stesso tempo la di esito negativo, procedete al download e all’instal-
necessità di scrivere del codice è un limite per chi lazione dal sito stesso.
non ha studiato informatica. Insomma, per quanto
REQUISITI
facile e divertente possa essere lo sviluppo delle
applicazioni Android, la capacità di scrivere del
Conoscenze richieste
-
buon codice resta sempre appannaggio degli addet- SETUP DEL SOFTWARE
ti ai lavori o di chi studia per diventarlo. Benché l’App Inventor in sé, essendo un’applica-
Software Per questo motivo Google sta gradualmente intro- zione online, non necessiti dell’installazione di
Java 6 ducendo App Inventor, un sistema alternativo per ulteriore software per lo sviluppo delle applica-
creare applicazioni Android senza scrivere una sola zioni Android, conviene comunque scaricare ed
Impegno riga di codice. Grazie ad App Inventor le applica- installare un package aggiuntivo, chiamato App
zioni possono essere letteralmente disegnate sullo Inventor Setup Software. Il pacchetto contiene degli
Tempo di realizzazione schermo del proprio computer. Apprendendo alcu- strumenti aggiuntivi per la verifica ed il confezio-
ni principi di base, tra l’altro molto semplici, si namento delle applicazioni e serve soprattutto per
diventa velocemente in grado di creare, verificare verificare le applicazioni realizzate su un dispositi-
12 / Gennaio 2011
A n d ro id p r o g r a m m ing 81
h ttp ://www.io pr o g r a m m o .i t
Applicazioni Android
Android senza scrivere codice
programming con AppAndroid
Applicazioni Inventor
senza scrivereCOVER
codice STORY
con App Inventor
CREARE UN NUOVO
PROGETTO
Iniziamo ad imparare come funziona App Inventor.
La piattaforma è organizzata per progetti. Ogni
applicazione Android che vogliamo realizzare fa
parte di un progetto differente. Per questo, non
Fig. 1: L’emulatore Android compreso nell’App Inventor appena si accede ad App Inventor, la prima cosa
Setup Software che viene visualizzata è l’elenco dei progetti sui
82
h ttp :/ / www. i o p r o g r a m m o. it Gennaio And
2011 /o g13
roi d pr r am m in g
COVER
Applicazioni AndroidSTORY Applicazioni
senza scrivere codice con AppAndroid
Inventor senza scrivere codice
Android con App Inventor
programming
14 / Gennaio 2011
A n d ro id p r o g r a m m ing 83
h ttp ://www.io p r o g r a m m o .i t
Applicazioni Android
Android senza scrivere codice
programming con AppAndroid
Applicazioni Inventor
senza scrivereCOVER
codice STORY
con App Inventor
BLOCKS EDITOR
L’interfaccia dell’applicazione, a questo punto, è
pronta: non ci sono né altri componenti da aggiun-
Fig. 7: Le aree “Components”, “Media” e “Properties” gere né altri file multimediali da caricare. Manca
permettono di gestire ciascun componente presente però qualcosa. Dobbiamo ancora fare in modo NOTA
nell’applicazione
che quando l’utente aziona il bottone, il rombo del
SCARICARE
I SORGENTI
tati tutti i componenti usati nell’applicazione. Volete condividere con
altre persone il sorgente
• Il componente di base, che si chiama “Screen1”, delle vostre applicazio-
ni realizzate con l’App
rappresenta la finestra principale dell’applica- Inventor? Andate nella
zione. Al suo interno ci sono tutti i componen- lista dei progetti, selezio-
ti trascinati nella schermata (nel nostro caso nate uno, quindi dalla lista
saranno “Image1”, “Button1” e “Sound1”). “More actions” selezio-
Selezionando uno dei componenti è possibi- Fig. 8: L’anteprima dell’interfaccia realizzata
nate la voce “Download
Source”. Scaricherete così
le rinominarlo (tasto “Rename”) o eliminarlo un archivio ZIP che contie-
definitivamente dalla schermata (“Delete”). ne il progetto selezionato.
motore venga effettivamente riprodotto. Ci manca, Un’altra persona potrà
• Properties. Contiene gli strumenti utili per insomma, quello che è il cuore di ogni applicazio- importarlo nel suo account
modificare le proprietà di ciascun elemen- ne: la logica, cioè la sequenza di indicazioni di tipo su App Inventor, selezio-
nando questa volta la voce
to dell’applicazione. Per modificare l’aspetto causa-effetto che sono il cuore di ogni applicazione. “Upload Source”.
di un componente è anzitutto necessario sele- Descrivere una logica è ciò per cui i linguaggi di In questa maniera potrà
zionarlo nell’anteprima o dall’elenco presen- programmazione sono nati. Il codice serve proprio anche lui lavorare sul
te nell’area “Components”. Fatto ciò, la scheda per gestire il legame tra le cause e gli effetti, ed vostro progetto.
“Properties” riporterà tutti i dettagli del compo- infatti ogni codice suona sempre come «se accade
nente selezionato che è possibile modificare. questo, allora fai quest’altro». Come è possibile,
Quali siano le proprietà modificabi- quindi, stabilire queste sequenze di azioni di questo
li dipende dalla natura del componente. genere se App Inventor, come si è detto in apertura,
non richiede la conoscenza di un linguaggio di pro-
• Media. Qui vengono riportati tutti i file multime- grammazione?
diali (immagini, audio, video) necessari all’appli- La risposta è: attraverso il Blocks Editor. Si tratta di
cazione. Con il tasto “Add” è possibile avviare la un editor visuale che sostituisce completamente la
procedura di upload di un nuovo file. necessità di scrivere codice, e lo fa attraverso delle
rappresentazioni grafiche dei flussi causa-effetto.
Utilizziamo questi strumenti. Per prima cosa, usia- Spiegarlo è molto più difficile che provarlo, andia-
mo l’area “Media” per caricare l’immagine e l’audio mo dunque a sperimentarlo in prima persona.
di cui si è detto in precedenza. In alto a destra, l’App Inventor presenta il tasto
Andiamo poi su “Components”. Selezioniamo “Open the Blocks Editor”. Premiamolo.
“Screen1”, che corrisponde alla finestra principa- Il Blocks Editor è un applicativo esterno realizzato
le dell’applicazione, e modifichiamo alcune sue in Java. Premendo sul tasto, il software sarà sca-
caratteristiche nell’area “Properties”. Cambiamo il ricato ed eseguito. Per questo è molto probabile
colore di sfondo impostandolo su nero, e modifi- che vi venga richiesto il consenso per l’esecuzio-
chiamo il titolo della finestra in modo che diventi ne. Naturalmente bisogna acconsentire. Alla prima
“Automobile”. esecuzione, inoltre, il Blocks Editor vi chiederà pro-
Passiamo ora a “Image1”. Impostiamo l’immagine babilmente di digitare il percorso del comando adb,
da mostrare, alterando la proprietà “Picture”. che è una delle utilità installate in precedenza con il
Associamogli l’immagine dell’automobile caricata pacchetto App Inventor Setup Software, e che serve
poco prima nella sezione “Media”. Modifichiamo per connettersi all’emulatore o ad un dispositivo
anche le proprietà del componente “Button1”. reale. Andate quindi sul vostro disco a trovare il per-
In particolare, cambiamo il testo contenuto al suo corso del comando adb.exe (Windows) o adb (Linux
interno, impostando la proprietà “Text” sul valo- e Mac). Fornite tale percorso in maniera completa,
re “Metti in moto”. Finiamo modificando anche ad esempio (Windows):
84
h ttp :/ / www. i o p r o g r a m m o. it Gennaio And
2011 /o g15
roi d pr r am m in g
COVER
Applicazioni AndroidSTORY Applicazioni
senza scrivere codice con AppAndroid
Inventorsenza scrivere codice
Android con App Inventor
programming
16 / Gennaio 2011
A n d ro id p r o g r a m m ing 85
h ttp ://www.io pr o g r a m m o .i t
Applicazioni Android
Android senza scrivere codice
programming con AppAndroid
Applicazioni Inventor
senza scrivereCOVER
codice STORY
con App Inventor
86
h ttp :/ / www. i o p r o g r a m m o. it Gennaio And
2011 /o g17
roi d pr r am m in g
COVER
Applicazioni AndroidSTORY Applicazioni
senza scrivere codice con AppAndroid
Inventorsenza scrivere codice
Android con App Inventor
programming
Fig. 16: La logica per la gestione dei quattro pulsanti Carlo Pelliccia
18 / Gennaio 2011
A n d ro id p r o g r a m m ing 87
h ttp ://www.io pr o g r a m m o .i t
Android programming API e librerie
COVER STORY� per interagire
API e librerie con Twitter
per interagire da Android
con Twitter da Android
PORTA TWITTER
SU GOOGLE ANDROID
IN QUESTO ARTICOLO VEDREMO COME SVILUPPARE UN’APPLICAZIONE PER ANDROID,
CAPACE DI DIALOGARE CON IL SERVIZIO DI SOCIAL NETWORKING TWITTER. A TAL SCOPO
MOSTREREMO COME UTILIZZARE LA LIBRERIA TWITTER4J
C
osa stai facendo? Basta rispondere a que- 1 – molte testate di giornali, o di news in genera-
sta semplicissima domanda per comin- le, (specialmente quelle americane e inglesi)
ciare a utilizzare uno dei servizi di social usano Twitter come mezzo per diffondere le
network che sta esponenzialmente aumentando ultime notizie. Avendo a disposizione sola-
le registrazioni e sta prepotentemente imponen- mente 140 caratteri compongono un Tweet di
dosi come una delle più importanti piattaforme pochissime parole seguito da un link all'artico-
in questo campo. Una delle tante definizioni lo vero e proprio. Naturalmente un URL può
possibili per twitter ce la dà Wikipedia: “Twitter è essere relativamente lungo, soprattutto se
un servizio di social network e microblogging che paragonato alla limitata disponibilità di testo
❑ CD ❑ WEB
twitterAndroid.zip fornisce agli utenti una pagina personale aggior- di Twitter. Per questo si utilizza solitamente
nabile tramite messaggi di testo con una lunghez- degli strumenti tipo TinyURL; questo è un ulte-
cdrom.ioprogrammo.it
za massima di 140 caratteri. riore esempio di come possano nascere siner-
Gli aggiornamenti possono essere effettuati trami- gie tra strumenti e servizi fra loro eterogenei.
te il sito stesso, via SMS, con programmi di mes- 2 – una cosa che mancava a Twitter era proprio la
saggistica istantanea, e-mail, oppure tramite possibilità di ricercare tutti quei Tweet che ver-
varie applicazioni basate sulle API di Twitter”. tessero sullo stesso argomento. A tale lacuna
Un concetto centrale nel funzionamento di sono stati gli stessi utenti a porre rimedio;
Twitter è quello del following e dei follower. infatti si è utilizzato il vecchio sistema dei tag.
Il primo sta a indicare gli utenti che abbiamo Quando si scrive qualcosa che si reputa essere
deciso di seguire, ossia quegli utenti i cui tweet di interesse generale, lo si termina con un tag
(leggi nota) ci verranno notificati e andranno a del tipo #topic, in questo modo, chiunque
costituire la nostra friend timeline. voglia rispondere o dire qualcosa sull'argo-
Simmetricamente a quanto appena detto, i fol- mento, potrà farlo terminando a sua volta il
lower costituiscono la lista di tutti quegli utenti Tweet con il medesimo tag. Un esempio cele-
che hanno deciso di seguirci. Naturalmente non bre di questo tipo di utilizzo lo si è avuto a
è assolutamente obbligatorio seguire uno dei seguito delle elezioni in Iran, dove grazie a
propri follower e viceversa. Uno dei punti di Twitter e al tag #iranelection i manifestanti riu-
forza di Twitter è proprio quello di consentire scivano in qualche modo a tenere informata
una lunghezza massima di 140 caratteri per ogni l'opinione pubblica su ciò che stava accaden-
post, anzi, per usare il gergo di Twitter, per ogni do nel proprio paese.
REQUISITI
Tweet. Anche se a prima vista ciò possa apparire
come una grossa limitazione rispetto ad altri Adesso che abbiamo dato una brevissima intro-
Conoscenze richieste
Java strumenti come i normali blog o Facebook, gra- duzione su cosa sia Twitter veniamo alla parte
zie a ciò è possibile utilizzarlo con un gran nume- maggiormente vicina ai nostri interessi, cioè lo
Software ro di strumenti (PC, telefonini, palmari etc...) e di sviluppo di applicazioni.
Twitter4J, Eclipse.
Android SDK applicazioni (vedi definizione di Wikipedia).
Inoltre questa estrema necessità di sintesi nel
comunicare ha fatto sì che l'utilizzo di questo
servizio sia andato al di là di quello inizialmente API PER I WEB SERVICE
Impegno
previsto dagli stessi ideatori. Ne faremo breve- DI TWITTER
¥ mente due esempi, ma se ne potrebbero elenca- In un precedente articolo abbiamo già parlato
Tempo di realizzazione
re molti altri, giusto per cercare di capire in che dei Web Service REST-style, in particolare di cosa
direzione si sta muovendo la Rete. siano, a cosa servano e come vadano utilizzati.
h t t p : / / w w w. i o p r o g r a m m o . i t
88 22 /Ottobre 2009
G And roi d pr o g r am m in g
API eper
API e librerie librerie per interagire
interagire con da
con Twitter Twitter da Android Android
Android � COVER STORY
programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Ottobre 2009/ 2389G
Android programming API e librerie
COVER STORY� per interagire
API e librerie con Twitter
per interagire da Android
con Twitter da Android
90 24 /Ottobre 2009
h t t p : / / w w w. i o p r o g r a m m o . i t
G And roi d pr o g r am m in g
API e per
API e librerie librerie per interagire
interagire con da
con Twitter Twitter da Android Android
Android � COVER STORY
programming
stampare l'id, lo user e il testo di ogni status della piedi un ambiente che ci permetta di sviluppare
FriendsTimeline. Con il mio account ho ottene- e debugare la nostra applicazione. Dopo aver
nuto il seguente output sulla console: installato e scaricato Android, una delle parti più
importanti è quella della creazione del Virtual
2691267627 - TIME.com - For #ff, add @time_live. Device. Infatti è proprio grazie a questo punto
Starting Monday, it's the best way for you to che saremo in grado di emulare un generico
communicate 1-on-1 with our newsroom. And we'll dispositivo sul nostro PC. Per fare ciò basta lan-
follow you back! ciare da prompt il comando Android create avd -
2691154798 - developerworks - Learn how to create -target 2 --name my_avd. La prima parte del
drag-and-drop code that is modular, and easier to comando (create avd) indica che vogliamo creare
write and maintain > http://su.pr/6bXlqP un nuovo Android Virtual Device, la seconda (--
2690818806 - Andrea Galeazzi - I'm watching rock & target 2) fa sì che tale device possa girare sull'e-
roll circus...amazing! mulatore, mentre la terza (--name my_avd)
2690608685 - TIME.com - Why girls have BFFs and imposta semplicemente il nome del device che
boys hang out in packs | http://su.pr/92EuL5 andremo a creare. A questo punto, una volta lan-
2690262831 - developerworks - Parallel development ciato tale comando, vi verrà chiesto se volete
for mere mortals - Step through Subversion version- creare un profilo hardware personalizzato; noi NOTA
control > http://su.pr/2leWWm possiamo tranquillamente accettare quello di
2689450274 - developerworks - Writing great code default e quindi premere invio. Ora il nostro SMARTPHONE
with FileNet P8 APIs - Reliable-Scalable-Highly- device è pronto per essere fatto girare sotto ANDROID
HTC è stata la prima
Available content management > http://su.pr/19PsCq l'emulatore.
azienda al mondo a
….... mettere in vendita uno
smartphone con installato il
Vediamo invece come inviare i nostri tweet uti- sistema operativo Android.
lizzando la libreria Twitter4j: in questo caso la L'AMBIENTE Dopo aver lanciato sul
mercato i vari HTC Dream,
procedura è anche più semplice di quella vista DI SVILUPPO HTC Magic e l’ultimissimo
poco fa. Infatti, una volta istanziato l'oggetto Quando parliamo di programmazione in Java, HTC Hero, ora l’azienda di
twitter che si occupa della connessione e dell'au- indipendentemente da ciò che stiamo svilup- Taiwan vorrebbe arrivare
tenticazione, basta invocare il metodo pando, difficilmente possiamo fare a meno di sul mercato con un nuovo
updateStatus come segue: Eclipse ed anche questo caso non fa eccezione. smartphone Android: l’HTC
Click.
Per sviluppare sulla piattaforma Android con
Status status = twitter.updateStatus("That's an Eclipse è necessario installare il relativo plug-in e
example about how to tweet by Twitter4j"); configurarlo opportunamente.
System.out.println("Successfully Utilizzando l'ultima versione di Eclipse al
updated the status to [" + status.getText() + "]."); momento, Galileo, basta che andiate su Help
Install New Software e clicchiate sul bottone
Tale codice produce il seguente output: Add. Inserite poi nel campo Location https://dl-
ssl.google.com/android/eclipse/ e scegliete il
Successfully updated the status to [That's an nome che preferite nel campo Name, premete
example about how to tweet by Twitter4j] poi OK. Così facendo dovrebbe apparire una
check box con il nome "Developer Tools", sele-
zionatela e premete Next e poi Finish. Se tutto
procede correttamente alla fine vi verrà chiesto
ANDROID di riavviare Eclipse. Una volta riavviato andate
E IL SUO EMULATORE su Window Preferences e selezionate Android
Potremmo continuare a esporre ulteriori funzio- sulla parte destra.
nalità della libreria Twitter4j, ma non dobbiamo Ciò che è necessario impostare è la location di
dimenticare che il nostro scopo è quello di dove abbiamo posizionato l'SDK di Android
implementare un client di Twitter che giri sulla (nel nostro caso D:\Program Files (x86)\
piattaforma Android. È quindi opportuno, a que- android-sdk-windows-1.5_r2\).
sto punto, iniziare a introdurre i concetti base su Una volta selezionato correttamente il percor-
cui si fonda il sistema operativo di Google. so dovreste ritrovarvi in una situazione del
Android è una piattaforma per dispositivi mobili tutto simile a quella riportata in Fig. 4. Anche se
che include sistema operativo, middleware e quest'ultima parte può risultare tediosa è fonda-
applicazioni di base. Maggiori informazioni, mentale che venga correttamente eseguita in
comunque, sono reperibili nel precedenti artico- modo tale da evitare che durante la fase di svi-
lo di questa cover story). Per essere quanto più luppo qualcosa non funzioni senza capirne il
pratici possibile, vediamo subito di mettere in motivo.
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Ottobre 2009/ 2591G
Android programming API e librerie
COVER STORY� per interagire
API e librerie con Twitter
per interagire da Android
con Twitter da Android
CONCLUSIONI
In questo articolo abbiamo presentato Twitter e
utilizzato le API Java Twitter4j per usufruire dei
servizi messi a disposizione. Nella seconda parte
abbiamo invece iniziato a presentare il nuovo OS
di Google. Nel prossimo metteremo assieme
questi due aspetti per realizzare il nostro client
Twitter su Android!
h t t p : / / w w w. i o p r o g r a m m o . i t
92 26 /Ottobre 2009
G And roi d pr o g r am m in g
La classe ActivityMOBILE
e il disegno La classe con
� dell’interfaccia Activity e il disegnoAndroid
Android dell’interfaccia con Android
programming
UN CLIENT TWITTER
SU ANDROID
CONTINUIAMO E COMPLETIAMO IL NOSTRO PROGETTO PER IMPLEMENTARE UN CLIENT
PARTE 2
TWITTER SULLA PIATTAFORMA ANDROID. L’OCCASIONE CI PERMETTERÀ DI APPROFONDIRE
MOLTI ASPETTI SUL FUNZIONAMENTO DEL SISTEMA OPERATIVO CREATO DA GOOGLE
C
hi lavora nel campo del software ormai lo public void onCreate(Bundle savedInstanceState) {
sa benissimo: le cose cambiano con una super.onCreate(savedInstanceState);
velocità elevatissima, magari un fra- TextView tv = new TextView(this);
mework o una piattaforma che avevamo impara- tv.setText("Hello, Android");
to a conoscere e utilizzare meno di un anno fa, è setContentView(tv);
già parte della storia dell'informatica. }
In questo articolo proveremo a mettere assieme }
due grosse novità di quest'anno (benché entram-
❑ CD ❑ WEB be hanno avuto origine uno o due anni prima): La prima cosa importante da notare è che la nostra
twitterclient144.zip
Twitter e Android. classe eredita dalla classe Activity. Possiamo pensa-
cdrom.ioprogrammo.it
Visto che nello scorso articolo abbiamo dedicato re alla classe Activity (o meglio alla classe che la
maggior spazio al funzionamento di Twitter, sia estende) come una classe che funge da “entry
come social network che come set di API, questa point” per l'applicazione che vogliamo realizzare.
volta ci occuperemo prima di Android descriven- A mio avviso, quando si sviluppa un'applicazione
do i suoi meccanismi di funzionamento e come per Android, è molto semplice adottare questo tipo
implementare un'applicazione che si colleghi a di visione: Android è un host all'interno del quale
Internet e sia interagibile per mezzo di un touch- possono girare più Activity. Di conseguenza un'ac-
screen. tivity verrà “pilotata” da Android che gli comuni-
cherà quando viene avviata, messa in pausa, riav-
viata o distrutta. La Fig. 1 illustra i vari stati in cui
un'activity può venirsi a trovare e anche in che
CREARE APPLICAZIONI
PER ANDROID
Abbiamo già dedicato una parte dello scorso arti-
colo alla discussione dell'installazione di un envi-
ronment che ci permetta di sviluppare delle appli-
cazioni in Java ed emularle su un virtual device di
Android. Si rimanda quindi al precedente numero
di ioProgrammo per la messa in piedi di tale
ambiente; in questa sede ci limitiamo a ricordare
che è necessario scaricare e installare lo SDK di
Android, reperibile all'indirizzo http://developer.
android.com/sdk/1.5r3/index.html ed è fortemente
REQUISITI
consigliato utilizzare anche il relativo plug-in per
Conoscenze richieste
Eclipse. Proprio al termine di quest'ultimo aveva-
Java mo iniziato a scrivere la nostra prima applicazione
Hello World. Ripartiamo quindi da dove ci siamo
Software lasciati la volta scorsa. Benché il codice sia abba-
Eclipse, Android SDK
1.5 stanza semplice già contiene vari aspetti che meri-
tano di essere approfonditi:
Impegno
h t t p : / / w w w. i o p r o g r a m m o . i t
G 62 / Novembre 2009
A n d ro id p r o g r a m m ing 93
La classe Activity
Android e il disegno dell’interfaccia
programming La classe con Android
Activity MOBILE
e il disegno�dell’interfaccia con Android
modo può arrivarci. Lo state diagramm in questio- un'applicazione per Android senza aver conoscen-
ne è già abbastanza esplicativo di per sé, vale za della gestione del life-cycle di un'activity.
comunque la pena spendere alcune parole al Un altro “mattoncino fondamentale” è quello dello
riguardo. Come potete notare, appena viene crea- sviluppo dell'interfaccia grafica. Nell'esempio pre-
ta un'activity su di essa, vengono anche invocati cedente abbiamo semplicemente creato una
nell'ordine i seguenti metodi: onCreate, onStart e textView tramite una new, scritto su di essa il testo
onResume. Al termine dell'invocazione di quest'ul- "Hello, Android" e posta la textView sul display.
timo metodo possiamo dire che l'applicazione sta Potete facilmente intuire che se il layuot si comin-
girando. In particolare, nel metodo onCreate, ven- cia a complicare un po' diventerebbe veramente
gono tipicamente creati quei componenti grafici difficoltoso creare delle GUI questo modo.
che andranno a costituire l'interfaccia grafica. Tale Esiste però anche un altro modo per definire il
interfaccia viene poi infatti settata mediante il layuot di un'applicazione, ed è tramite un file XML;
metodo setContentView. Quando e se un'activity cominciamo quindi subito con l'analizzare come è
viene sospesa, solitamente perché ne viene avviata strutturato quello che definisce il layuot della
un'altra, è invocato il metodo onPause. In questo nostra applicazione:
punto è opportuno salvare, qualora ce ne fosse
bisogno, tutti i dati che costituiscono lo stato in cui <?xml version="1.0" encoding="utf-8"?>
si trova l'activity. <AbsoluteLayout android:id="@+id/widget38"
Una volta che quest'ultima è posta nello stato pau- android:layout_width="fill_parent"
sed, abbiamo tre possibili stati successivi in cui sarà android:layout_height="fill_parent" xmlns:android=
consentito andare:Destroyed, Stopped, Running. "http://schemas.android.com/apk/res/android">
Sul primo stato c'è abbastanza poco da dire, l'ap- <ListView android:id="@+id/list"
plicazione viene killata (ad esempio a seguito di android:layout_width="319px" android:layout_height="356px"
una chiusura), e qui è necessario rilasciare tutte le android:layout_x="1px"android:layout_y="0px">
risorse eventualmente allocate all'inizio, più preci- </ListView>
sante nel metodo onDestroy. I restanti due casi <EditText NOTA
sono invece quelli più interessanti. android:id="@+id/text" android:layout_width="259px"
Cerchiamo di comprendere come mai siamo obbli- android:layout_height="50px"android:background="#ffffffff" TOOL PER
gati a implementare un'applicazione che sia in android:textSize="12sp" android:textColor="#ff666666"
DISEGNARE
grado di gestire il proprio stato corrente mediante android:layout_x="1px" android:layout_y="383px">
L’INTERFACCIA
la ricezione delle callback da parte del sistema ope- </EditText>
GRAFICA
In realtà scrivere il file XML
rativo, che ci informa su quale sarà il prossimo <Button android:id="@+id/button" per la definizione della GUI
stato nel quale la nostra activity andrà a trovarsi. android:layout_width="wrap_content" dall'inizio alla fine può
Dobbiamo infatti tenere a mente che Android è android:layout_height="52px" android:text="Send" risultare un compito noioso
stato progettato per girare su piattaforme hardwa- android:layout_x="260px" android:layout_y="383px">
ed alcune volte anche poco
praticabile. Esiste a tal
re limitate e ciò comporta un'oculata gestione delle </Button>
proposito un tool RAD di
sue risorse, specialmente la memoria. Per questo </AbsoluteLayout> nome AnDroidDraw
motivo Android gestisce le varie Activity come uno (http://www.droiddraw.or
stack. In testa si trova quella attualmente in primo Un client per Twitter è concettualmente molto g/androiddraw.html) che
piano sul display; immediatamente dopo si troverà semplice, deve solamente assolvere a due compiti: permette di definire
un'interfaccia grafica in
la penultima Activity, quella che come già accenna- mostrarci la nostra friends-timeline e permetterci maniera visuale.
to prima, è stata messa in stato Paused. Tutte le di inviare i nostri Tweet. Per fare ciò abbiamo quin-
altre sotto quest'ultima vengono messe nello stato di bisogno di solo tre componenti:
stopped dopo la chiamata ad onStopped. Se poi
l'activity viene richiamata in primo piano, a secon- 1. Una ListView in cui visualizzare i vari Tweet della
da della memoria richiesta nei momenti preceden- friends-timeline;
ti, possiamo ritrovarci in due situazioni differenti: o 2. Una TextView in cui inserire ciò che vogliamo
la memoria a disposizione era sufficiente e quindi “tweetare”;
verrà invocato il metodo onRestart, che alla fine ci 3. Un bottone per inviare effettivamente quanto
riporterà nello stato di Running, oppure è stato scritto nel controllo sopra citato.
necessario uccidere l'Activity e quindi ricominciare
tutto ripartendo da onCreate. In Fig. 2 potete vedere come si presenta grafica-
mente l'XML appena riportato.
Notiamo che come layout di root abbiamo scelto
un AbsoluteLayout all'interno del quale abbiamo
DEFINIRE UNA posto i nostri controlli; gli attributi associati a que-
GUI SU ANDROID st'ultimi sono talmente palesi che approfondire il
Sicuramente non è possibile tentare di scrivere loro significato non sarebbe di alcuna utilità.
h t t p : / / w w w. i o p r o g r a m m o . i t
94 Novembre 2009
And roi d/pr63
o g r amG
m in g
La classe ActivityMOBILE
e il disegno La classecon
� dell’interfaccia Activity e il disegnoAndroid
Android dell’interfaccia con Android
programming
tale libreria. In particolare a struttura predefinita che, ad esempio, affianca alla btn.setOnClickListener(this);
noi interessa che sia scritta directory src, dove sono contenuti i sorgenti, un'al- try {
al 100% in Java e che sia tra chiamata res contenente a sua volta altre tre twitter = new Twitter("name","password");
compatibile con Android sotto directory: drawable, layout e strings. adapter = new TwitterAdapter
Senza addentrarci nei dettagli di ognuna di esse, (twitter,this,android.R.layout.simple_list_item_1);
concentriamoci ad esempio sulla directory layout lv.setAdapter(adapter);
dato che è quella che ci riguarda più da vicino. } catch (TwitterException e) {}
Il file main.xml in essa contenuto è proprio quello }
riportato sopra. Il plug-in di Eclipse genera auto-
maticamente una costante numerica per ogni Si ha ora la necessità di recuperare i componenti
entità contenuta nella directory res: definiti nell'XML come classi Java. A differenza del
primo esempio, Hello Android, in cui facevamo
/* AUTO-GENERATED FILE. DO NOT MODIFY. esplicitamente delle new per i componenti che ci
package it.galeazzi.andrea; servivano, in questo caso dobbiamo utilizzare il
public final class R { metodo findViewById, che restituisce il componen-
public static final class attr {} te a partire da un dato id, che, come al solito, ci
public static final class drawable { viene fornito dalla classe R. Visto poi che tale meto-
public static final int icon=0x7f020000; do restituisce una generica View (classe base), è
G 64 / Novembre 2009
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing 95
La classe Activity
Android e il disegno dell’interfaccia
programming La classe con Android
Activity MOBILE
e il disegno�dell’interfaccia con Android
public class TwitterAdapter implements ListAdapter { Al costruttore tale classe riceve tre parametri: il
private Twitter twitter; primo è l'oggetto twitter che ci permette di colle-
PATTERN MVC
È un pattern architetturale
private ArrayAdapter<String> adapter; garci al web service, mentre gli altri due vengono molto diffuso nello sviluppo
public TwitterAdapter(Twitter twitter,Context passati direttamente all'oggetto adapter. Inoltre, è di interfacce grafiche di
context, int viewId) throws TwitterException { stato aggiunto il metodo refresh, non previsto dal- sistemi software object-
super(); l'interfaccia ListAdapter. È forse questo il metodo oriented. Originariamente
impiegato dal linguaggio
this.twitter = twitter; più interessante, poiché è colui il quale si occupa di
Smalltalk, il pattern è stato
adapter = new ArrayAdapter<String>(context, viewId); riempire l'oggetto adapter con i tweet che recupe- esplicitamente o
refresh(); riamo tramite la libreria Twitter4j (più precisamen- implicitamente integrato da
} te per mezzo dell'oggetto twitter passato al costrut- numerose tecnologie
tore). Si è infatti scelto di preferire l'incapsulamen- moderne, come framework
basati su PHP, su Ruby
public boolean hasStableIds() { to all'ereditarietà. Per essere più chiari abbiamo
(Ruby on Rails), su Python
return adapter.hasStableIds(); fatto questo: dovevamo implementare un'interfac- (Django), su Java (Swing,
} cia (ListAdapter) ed esiste una classe (Array JSF e Struts), su Objective C
public boolean areAllItemsEnabled() { Adapter) che, oltre a fornire una implementazione e su .NET.
return adapter.areAllItemsEnabled(); per tale interfaccia, ha un comportamento molto
} simile a quello che vogliamo ottenere. Abbiamo
public int getCount() { così dichiarato un membro privato (ossia abbiamo
return adapter.getCount(); incapsulato) di tale classe e abbiamo definito una
} serie di metodi delegate che rigirano la chiamata
public String getItem(int position) { sulla classe incapsulata, che perciò svolge effettiva-
return adapter.getItem(position); mente il lavoro per conto della classe contenitrice.
} In questo modo, l'unico metodo suppletivo che
public long getItemId(int position) { abbiamo avuto veramente la necessità di imple-
return adapter.getItemId(position); mentare, è stato, come già accennato, il metodo
} refresh.
public int getItemViewType(int position) {
return adapter.getItemViewType(position);
}
public View getView(int position, View CATTURARE GLI EVENTI
convertView, ViewGroup parent) { DEL DISPLAY
return adapter.getView(position, convertView, parent); Rifacendoci al pattern MVC, possiamo affermare
} che fin qui abbiamo discusso e analizzato le parti
public int getViewTypeCount() { View (ossia i componenti grafici) e Model (vale a
return adapter.getViewTypeCount(); dire TwitterAdapter); non ci rimane, quindi, che
} occuparci del Controller.
public boolean isEmpty() { In precedenza è già stato anticipato che avremmo
h t t p : / / w w w. i o p r o g r a m m o . i t
96 Novembre 2009
And roi d/pr65 G
o g r am m in g
La classe ActivityMOBILE
e il disegno La classecon
� dell’interfaccia Activity e il disegnoAndroid
Android dell’interfaccia con Android
programming
avuto la necessità di recuperare dei componenti sorgenti. Essendo Twitter4j una libreria open sour-
definiti nell'XML. Uno dei motivi è quello di riusci- ce, possiamo tranquillamente prelevare i sorgenti
re a intercettare l'evento di pressione del bottone ed inserirli come package nel nostro progetto.
send; per ottenere ciò si è proceduto come segue: Sfortunatamente ciò non è ancora sufficiente.
Infatti, in alcune limitate porzioni del codice, tale
btn =(Button)findViewById(R.id.button); libreria fa uso delle librerie DOM per l'XML.
btn.setOnClickListener(this); Per ovvie ragioni di occupazione in memoria di un
….. oggetto DOM, Android, essendo progettato per
@Override architetture embedded, non fornisce una completa
public void onClick(View v) interfaccia di questo tipo per il parsing di un XML
{ bensì solo una di tipo SAX. D'altro canto i punti
try dove viene utilizzata sono ben localizzati e non
{ sono così vitali per il funzionamento complessivo
String txt = text.getText().toString(); della libreria stessa.
twitter.updateStatus(txt); Per ragioni di spazio non riporteremo le piccole
adapter.refresh(); modifiche apportate alla libreria, ad ogni modo, il
} catch (TwitterException e) codice nel CD allegato contiene già la libreria
{ modificata per essere compilata per Android.
text.setText(e.getMessage()); Ci rimane un'ultima cosa da fare affinché la nostra
} applicazione sia completamente funzionante su
} Android: concedere i permessi di connessione a
Internet.
Niente di più semplice: la nostra Actvity implemen- Per fare ciò aprite il file AndroidManifest.xml e clic-
ta anche l'interfaccia OnClickListener e ne imple- cate su Add e selezionate Uses Permession; dalla
menta perciò il metodo onClick. La logica in esso combo box selezionate poi android.permission.
contenuta è estremamente lineare: INTERNET. Dovreste così ritrovarvi in una soluzio-
ne analoga a quella riportata in Fig. 3.
1. si recupera il testo da inviare dalla TextView;
2. si spedisce tale testo al web service tramite la
libreria Twitter4j;
3. infine si aggiorna l'adapter poiché è sicuramente
entrato un altro tweet nella nostra time-line.
L’AUTORE
Impostata l'Activity come listener del bottone, ogni
Laureato in ingegneria volta che quest'ultimo verrà premuto, sarà invoca-
elettronica presso
to il metodo appena descritto.
l'università Politecnica
delle Marche, lavora presso
il reparto R&D della Korg
S.p.A. Nei limiti della
disponibilità di tempo IMPORTARE LA LIBRERIA
risponde all'indirizzo
[email protected]
TWITTER4J SU ANDROID
Fin qui abbiamo sempre dato per scontato che nel Fig. 3: Editor di Android Manifest in cui sono stati
nostro progetto fosse presente la libreria Twitter4j aggiunti i permessi di accesso a Internet
che abbiamo utilizzato basandoci sull'esperienza
fatta nell'articolo precedente. È anche vero che,
sempre nello scorso articolo, avevamo accennato
al fatto che Android non implementa una Java VM CONCLUSIONI
classica, bensì la Dalvik virtual machine. Molto sin- Abbiamo così ultimato un client Twitter per
teticamente diciamo che essa è ottimizzata per Android, che ci ha permesso di acquisire un discre-
sfruttare la poca memoria presente nei dispositivi to know-how sia riguardo il sistema operativo di
mobili, consente di far girare diverse istanze della Google, sia riguardo la nuova piattaforma di social
macchina virtuale contemporaneamente e network che sta vedendo tassi di crescita enormi.
nasconde al sistema operativo sottostante la Naturalmente il client qui sviluppato implementa
gestione della memoria e dei thread. Ciò che inte- solamente le funzionalità base di Twitter. Avete
ressa noi come sviluppatori è il fatto che il byteco- ormai però tutte le conoscenze necessarie per
de con cui lavora non è Java. Ne consegue che non estenderle.
è possibile referenziare direttamente i jar tipica-
mente distribuiti, ma è necessario ricompilare i Andrea Galeazzi
h t t p : / / w w w. i o p r o g r a m m o . i t
G 66 / Novembre 2009
A n d ro id p r o g r a m m ing 97
MOBILE
Android �
programming Il framework Funambol
Il framework per sincronizzare
Funambol i datii personali
per sincronizzare dati personali
ANDROID DIALOGA
CON OUTLOOK
IL PARADIGMA DEL “DATA ON THE CLOUD” RISULTA COMODO QUANDO SI VOGLIONO GESTIRE
LE STESSE INFORMAZIONI DA DIVERSI CLIENT, ETEROGENEI TRA LORO. IN QUESTO ARTICOLO
LO ADOPEREREMO PER TENERE SINCRONIZZATE DELLE NOTE TRA ANDROID E OUTLOOK
I
cellulari di ultima generazione hanno portato 3. Un client per Android e uno per Outlook che per-
la gestione dei dati in mobilità a livelli mai mettano di gestire e sincronizzare in locale que-
sperimentati fino ad oggi: si possono consul- ste informazioni, nel nostro caso le note di
tare mappe satellitari che mostrano la nostra Outlook.
posizione, visionare documenti e condividerli
con i collaboratori, raccontare in tempo reale ciò È chiaro che realizzare tutto da zero risulterebbe
che ci accade con foto e video. In tutti questi sce- oltremodo oneroso, ma per fortuna tante tessere di
nari le informazioni sono memorizzate in un ser- questo mosaico esistono già. Partiamo dal proto-
❑ CD ❑ WEB ver, con i client che possono leggerle, modificar- collo: invece di inventarcene uno, con un grande
FunambolSyncNotepad.zip le, crearne di nuove. In casi particolari i client dispendio di tempo, possiamo usare qualcosa di
cdrom.ioprogrammo.it memorizzano in locale una copia di quanto pre- già esistente, con il vantaggio di avere alle spalle
sente sul server e, grazie ad apposite procedure anni di utilizzo e librerie già pronte: stiamo parlan-
di sincronia, questa viene tenuta coerente con i do di SyncML. Questo protocollo nasce proprio allo
dati originali. Lo scopo di questo articolo è quel- scopo di gestire le operazioni di sincronizzazione
lo di realizzare un sistema in grado di gestire e dei dati tra server e smart device, conservando la
sincronizzare delle note tra Outlook e un disposi- massima libertà sul tipo di dato scambiato. Nelle
tivo Android. Costruiremo prima di tutto un ser- sue specifiche, vengono definiti i tipi di sincronia
ver dove memorizzare le nostre note, configure- possibili, i flussi di ognuna di queste, codici di erro-
remo Outlook per accedervi ed estenderemo re, formato dei messaggi che si possono scambiare
un'applicazione Android già esistente, aggiun- in ogni fase, casistiche ed esempi di utilizzo.
gendo la capacità di sincronizzare le note che Anche per quanto riguarda la parte server possia-
questa già gestisce con il nostro server. Una volta mo risparmiare tempo sfruttando qualcosa di già
capito il meccanismo di base, si potranno aggan- esistente, come il software realizzato da Funambol.
ciare ulteriori applicazioni, come Thunderbird, Funambol Community Edition è la versione open
un programma desktop o un sito web. source di una piattaforma per la sincronia “on the
cloud” di dati personali come contatti, calendario,
note. Con un'approssimazione riduttiva possiamo
dire che realizza i primi due punti dell'elenco pre-
REQUISITI
ARCHITETTURA cedente e utilizza, per lo scambio dei dati con i
Conoscenze richieste
DELL'APPLICAZIONE client, proprio il protocollo SyncML. Laddove non
Java Partendo da una panoramica di massima, un'infra- supportato nativamente, vengono messi a disposi-
struttura in grado di gestire la sincronizzazione dei zione dei plug-in per effettuare la sincronia: ne esi-
dati tra diversi client deve essere composta, alme- stono per la maggior parte dei sistemi operativi
no, dai seguenti elementi: mobile, da Symbian ad iPhone, troviamo plugin
Software
Java SDK (JDK) 5+, per Outlook e Thunderbird, sono stati realizzati
Eclipse 3.3+
1. Un server “on the cloud” dove memorizzare i connettori per eGroupware del calibro di Exchange
dati. e Zimbra. Esistono SDK per Java, J2ME e C++, per
2. Un motore di sincronia che sappia tenerli alli- aggiungere capacità di sincronia con un server
Impegno neati tra diversi client, capace di eseguire opera- Funambol all'interno di tutte le applicazioni che
zioni di creazione, aggiornamento, cancellazio- ancora non la supportano. Rimane scoperta solo la
ne, risoluzione dei duplicati e notifica dei cam- parte riguardante il client per Android. Su questo
Tempo di realizzazione
biamentiun protocollo con cui scambiare i dati aspetto, terminata la creazione dell'infrastruttura,
tra i client e il motore. andremo a focalizzare la nostra attenzione.
h t t p : / / w w w. i o p r o g r a m m o . i t
98 44 / Marzo 2010
G And roi d pr o g r am m in g
Il framework
Il framework Funambol
Funambol per sincronizzare
per sincronizzare i dati personali
i dati personali � MOBILE
Android programming
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Marzo 2010 / 45 99
G
MOBILE
Android �
programming Il framework Funambol
Il framework per sincronizzare
Funambol i datii personali
per sincronizzare dati personali
ti con cui sincronizzarsi, timestamp dell'ultima abbiamo inserito nel menu principale una nuova
sicronia effettuata ecc). voce in grado di richiamarla e abbiamo modificato
lo strato di accesso ai dati per gestire più agevol-
• Viene chiamanto il metodo SyncManager.sync mente le informazioni racchiuse nella classe Note.
passandogli NotesSyncSource come SyncSource.
Se non viene specificato diversamente, la prima Fig. 2: L'Activity principale dell'applicazione Notepad...
tentata è una TWO_WAY_SYNC. A secondo del tipo
di sincronia, il SyncManager trasmette al server
Funambol i dati sugli elementi aggiunti, modificati Come dicevamo prima, il protocollo SyncML si
e cancellati nel client, ricavati grazie ai metodi della occupa solo dello strato di trasporto, lasciando
SyncSource e ai paramentri LastAnchor e piena libertà sui dati trasportati. Per questo il ser-
NextAnchor, che indicano l'intervallo di tempo ver Funambol definisce un formato, il SIF-N, per
all'interno del quale considerare le modifiche inserire oggetti di tipo note dentro ai messaggi
NOTA richieste. Il server Funambol analizza quanto otte- SyncML, in modo da essere indipendente da come
nuto, aggiorna i suoi dati e trasmette le sue modifi- ogni client le persiste nel suo storage locale. Per i
FUNAMBOL che al SyncManager, che le persiste sul client grazie contatti e per gli appuntamenti, invece, viene usato
Nata circa 10 anni fa dalla ai metodi addItem, deleteItem e removeItem della lo standard VCard. Occorrerà quindi serializzare in
visione di un ingegnere SyncSource. SIF-N le note ed inserirle in dei SyncItem prima di
italiano, Fabrizio
Capobianco, Funambol Al termine della sincronia, vengono aggiornati mandarle al server, mentre, per ogni SyncItem
oggi offre un prodotto di LastAnchor e NextAnchor della SyncSource. inviato da quest'ultimo al client, verrà estratto il
sincronia dati “on the Funambol mette a disposizione un progetto chia- contenuto, deserializzato dal SIF-N e convertito in
cloud” sotto licenza Affero mato client-sdk, sempre reperibile nella sezione un oggetto Note. I due helper che si occupano di
GPL2, comprensivo di download della Forge, contenente librerie e docu- queste operazioni sono, rispettivamente,
client ed estensioni per
moltissime piattaforme mentazione per usare i suoi servizi con diverse tec- NoteToSIFN e SIFNParser, utilizzati nei metodi di
mobili e non. Data la nologie: Java, C++ e J2ME. Al momento della scrit- NoteDao. Non occorre scendere nel dettaglio di
natura totalmente open tura di questo articolo, inoltre, è in fase sviluppo
source del prodotto, tutto il anche l'SDK per Android, presente per ora solo
codice sorgente è all'interno del progetto android-client e in grado di
liberamente disponibile e,
grazie a ciò, nel tempo si è sincronizzare contatti e appuntamenti (https://
creata una community android-client.forge.funambol.org). Per maggiori
intorno al progetto, che ha informazioni, rimandiamo al box laterare con un
sviluppato connettori ed elenco di link a diversi documenti informativi.
estensioni per ulteriori
ambienti, oltre a quelli già
supportati. Per maggiori
informazioni
www.funambol.org CLIENT ANDROID:
GESTIONE DATI
Allo scopo di semplificare il processo di sviluppo,
minimizzare il codice da scrivere e concentrarsi
unicamente sulle funzionalità di sincronia, abbia-
mo modificato ed esteso un'applicazione Android
già esistente, il famoso Notepad presente nel tuto-
rial online introduttivo alla piattaforma
(http://developer.android.com/guide/tutorials/notep-
ad). Sono state incluse le librerie del funambol-sdk
per android e, direttamente dal Funambol Java
SDK, sono state aggiunte alcune classi presenti nei
package com.funambol.*, che implementano l'og-
getto Note e i metodi per la sua conversione.
Successivamente, abbiamo creato una nuova atti-
vità per i impostare le configurazioni necessarie ad Fig. 3: … e quella per la creazione e la modifica
usare il server Funambol e lanciare una sincronia, di una nota
h t t p : / / w w w. i o p r o g r a m m o . i t
10046 / Marzo 2010
G And roi d pr o g r am m in g
Il framework
Il framework Funambol
Funambol per sincronizzare
per sincronizzare i dati personali
i dati personali � MOBILE
Android programming
queste due classi, dato che sono prese direttamen- riquadro che la contiene, categorie di appartenen-
te dal client-sdk e possono funzionare per noi za e folder in cui è inserita. Attualmente il nostro
come una black-box. L'appena citato NotesDao è il client non fa uso queste informazioni, ma dato che
nostro Data Access Object, una classe che fa da sono tutte incluse nel processo di sincronia, future
ponte tra i SyncItem e le informazioni grezze pro- implementazioni non avrebbero difficoltà a farlo.
venienti da NotesDbAdapter, occupandosi delle Inoltre Outlook permette di modificare solo il
operazioni di conversione, gestione dei timestamp corpo della nota, e non il titolo. La query per crea-
e degli status. Il metodo getNoteFromSyncItem re la tabella, dentro la classe NotesDbAdapter,
viene usato per convertire il contenuto di un diventa quindi la seguente:
SyncItem in un oggetto Note: prima viene istanzia-
to un parser passandogli il contenuto preso dal private static final String DATABASE_CREATE =
SyncItem, poi viene invocato il suo metodo parse "create table notes (" +
per ottenere la Note. Tra le due chiamate, c'è la "_id integer primary key autoincrement, " +
gestione delle possibili eccezioni generate. ...
SIFNParser parser = null; Come si può notare, sono stati aggiunti anche due
InputStream is = new campi per le informazioni funzionali al processo di NOTA
ByteArrayInputStream(syncItemData.getContent()); sincronia: status dell'elemento e data di ultimo
try { aggiornamento. Tra i diversi valori che lo status FUNAMBOL FORGE
parser = new SIFNParser(is); può assumere, ci sono quelli di NEW, UPDATED e Funambol Forge è un
} catch (SAXException e) { DELETED, mentre last_update contiene il time- repository di progetti in
... stamp di questo cambio di status. NoteSyncSource stile SourceForge che
ospita sia i progetti
deve infatti sapere quali sono le note nuove, modi- sviluppati e manutenuti da
La conversione opposta, da Note a SIF-N, avviene ficate o cancellate in un range temporale, general- Funambol, sia quelli creati
nel metodo getSyncItemFromNote, che passa al mente dall'ultima sincronia al momento corrente, e gestiti dalla community.
costruttore del converter fuso orario e codifica con e per farlo si appoggia NoteDao, sfruttando questi La home page contiene
cui l'oggetto Note verrà convertito, inserendo il due campi. La seguente query, ad esempio, per- informazioni generali su
Funambol con accesso
risultato di questa operazione all'interno di un mette di trovare le note create successivamente diretto alle pagine di
SyncItem, settandone anche il tipo all'ultima operazione di sincronia andata a buon download dei vari
(NOTE_ITEM_TYPE) e la chiave (il progessivo della fine: componenti, server e
nota). client, documentazione e
StringBuilder where = new StringBuilder();
altro. Il progetto Core e i
sottoprogetti contengono
NoteToSIFN converter; where.append(KEY_LASTUPDATED).append(">").appe
la maggior parte del
String convertedContent; nd(since) codice di Funambol
TimeZone tz = .append(" AND ") Community Edition. Sul
Calendar.getInstance().getTimeZone(); .append(KEY_LASTUPDATED).append("<").append(to Forge sono anche ospitate
converter = new NoteToSIFN(tz, "UTF-8"); );
le pagine per i programmi
di partecipazione alla
try { .append(" AND ")
community Funambol,
convertedContent = .append(KEY_STATUS).append("='").append(status).a come i Code Sniper, Phone
converter.convert(noteToConvert); ppend("'"); Sniper e L10n Sniper:
} catch (ConverterException e) { occasioni per entrare in
Log.e("getSyncItemFromNote", e.getMessage()); Cursor mCursor =
contatto con questo
mondo, con la sicurezza di
return null; mDb.query(DATABASE_TABLE,
essere retribuiti per il
} ALL_TABLE_COLUMNS, lavoro fatto.
Log.i("getSyncItemFromNote", convertedContent); where.toString(),
SyncItem item = new SyncItem(noteToConvert. null, null, null, null);
getUid().getPropertyValueAsString()); return mCursor;
item.setContent(convertedContent.getBytes());
item.setType(NOTE_ITEM_TYPE); status contiene il valore SyncItemState.NEW, che
item.setKey(noteToConvert.getUid().getPropertyValue indica una nuova nota, mentre le variabili since e to
AsString()); contengono due timestamp, rispettivamente quello
return item; della data dell'ultima sincronia e quello del momen-
to corrente. Sono entrambi memorizzati nel client
Rispetto all'originale del tutorial, nel database grazie alla classe NotePreferences come campi
usato per contenere i dati del client sono stati LastAnchor e NextAnchor. La seconda viene inviata
aggiunti tutti gli ulteriori campi che Outlook dal server all'inizio di ogni operazione di sincronia
memorizza per ogni nota: una data ad essa asso- e, se questa va a buon fine, viene memorizzata in
ciata, colore, coordinate X, Y, larghezza e altezza del LastAnchor al suo termine. Allo scopo di mettere in
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Marzo 2010 / 47 G
101
MOBILE
Android �
programming Il framework Funambol
Il framework per sincronizzare
Funambol i datii personali
per sincronizzare dati personali
grado la SyncSource di conoscere le note rimosse sul nota arrivata dal server chiamerà il metodo
client dall'ultima sincronia, abbiamo scelto di elimi- NoteSyncSource.addItem
narle in modalità soft-deletion, cioè senza cancellare
fisicamente il record corrispondente alla nota, ma @Override
impostando a 'D' il suo status e aggiornando il time- public int addItem(SyncItem item)
stamp presente in last_update. Coerentemente con throws SyncException
questa politica di soft-deletion, modifichiamo il { ... }
metodo NoteDbAdapter.fetchAllNotes, introducendo
il seguente controllo sullo status di un record del DB: A sua volta, superato il controllo della possibilità di
aggiungere un elemento per il tipo di sincronia cor-
public Cursor fetchAllNotes() rente, NoteSyncSource.addItem chiama il medoto
{ NoteDao.addNote
return mDb.query(DATABASE_TABLE,
new String[] {KEY_ROWID, KEY_TITLE, public int addNote(SyncItem item, int key) {... }
KEY_BODY},
NOTA KEY_STATUS + "<>'D'", Come si legge dal codice, il valore di ritorno del
null, null, null, null); metodo NoteSyncItem.addItem viene impostato su
MYFUNAMBOL } 200 quando un'operazione va a buon fine, secondo
MyFunambol quanto dettato dallo standard SyncML. Valori come
(http://my.funambol.com) Ricordiamoci comunque che, forzando nel 500, ad esempio, indicano invece diversi tipi di erro-
è il portale, liberamente NoteSyncSourceConfig una sincronia di tipo ri. Rispetto al programma Notepad originale, è stata
utilizzabile, per provare le REFRESH_FROM_SERVER, tutte le note presenti aggiunta nella nostra applicazione una nuova
funzionalità offerte dalla
piattaforma Funambol. sul client vengono fisicamente cancellate. Questo Activity, FunambolSettings, che permette di specifi-
Una volta registrati, si può tipo di sincronia va usato per riportare sul client care username, password e server sul quale effettua-
scaricare il client adatto al quanto contenuto sul server, senza che il primo re la sincronia, oltre che ad esporre una TextView
tipo di smartphone possa trasmettere le ultime modifiche a quest'ulti- contenente i messaggi. Il log delle singole operazio-
posseduto e lanciare la mo. Si può anche impropriamente usare una ni della sincronia è reso possibile da NoteListerner,
prima sincronia. Oltre alla
possibilità di gestire i REFRESH_FROM_SERVER per fare un po' di pulizia una classe derivante da SyncListener che viene
contatti, note e e liberare risorse sul client, sempre preziose, se si agganciata a NoteSyncSource in fase di creazione di
appuntamenti via web, il creano e cancellano note in modo intensivo. quest'ultima. Il meccanismo di funzionamento è
portale può essere usato semplice, dato che la SyncSource chiama i diversi
come semplice backup dei
dati del propro dispositivo,
funzionalità utile in caso di
perdita o sostituzione del CLIENT ANDROID:
device. Se si è sempre alla LA SINCRONIA DATI
ricerca di funzionalità Passiamo ora alla creazione dell'elemento più
borderline, all'indirizzo importante della sincronia: la classe NoteSync-
http://dogfood.funambol
.com è raggiungibile la Source. In fase di inizializzazione, le viene passata
versione di beta-testing un'ulteriore classe, NoteSyncSourceConfig, che con-
dello stesso portale, con tiene le configurazioni minime di cui la SyncSource
implementate le necessita:
ultimissime funzionalità da
sperimentare. Attualmente,
public NoteSyncSourceConfig(Activity a) {...}
ad esempio, è possibile
assegnare ai propri
contatti la foto del loro Sono fondamentali la RemoteUri, che indica il data-
profilo su Facebook. base su server Funambol da utilizzare per sincroniz-
zare i dati, quello delle note appunto, e il Type dei
dati contenuti all'interno del SyncItem gestito dalla
SyncSource. Nel nostro caso, come avevamo spiega-
to, viene usato il SIFN, mentre per i contatti avrem-
mo trovato un Type uguale a text/x-vcard. Non viene
applicato nessun tipo di Encoding al contenuto del
SyncItem. Troviamo anche l'Activity che serve per
ottenere l'Application Context necessario alla
SyncSource per molte delle sue operazioni. Gli altri
medoti di NoteSyncSource sono abbastanza sempli- Fig. 4: L'Activity che abiamo aggiunto ci consente di
ci e quasi sempre corrispondenti ad un metodo su impostare username, password e server da usare
per sincronizzare le nostre note...
NoteDao. Ad esempio, l'inserimento di una nuova
h t t p : / / w w w. i o p r o g r a m m o . i t
10248 / Marzo 2010
G And roi d pr o g r am m in g
Il framework
Il framework Funambol
Funambol per sincronizzare
per sincronizzare i dati personali
i dati personali � MOBILE
Android programming
metodi del listener in base alla tipologia di operazio- valori (l’oggetto SharedPreferences) per poi chiamare
ne svolta. Questi metodi, implementati nel nostro i metodi del Context che permettono di caricarlo e di
NoteListerner, non fanno altro che aggiornare la persisterlo per mezzo dell'oggetto SharedPre-
TextView con i log, accodando il nuovo messaggio. ferences.Editor. Ogni Context può contenere molte-
plici oggetti SharedPreferences, ognuno di essi iden-
tificato da un nome univoco. Nella nostra applica-
zione, abbiamo usato l'identificativo fnblPref. Di
seguito un classico esempio di creazione di un con-
tainer per le preferenze: memorizzazione di un valo-
re di tipo stringa facente capo alla chiave “syncUrl” e
lettura di quest'ultimo.
h t t p : / / w w w. i o p r o g r a m m o . i t
A n d ro id p r o g r a m m ing Marzo 2010 / 49 G
103
Questo approfondimento tematico è pensato per chi vuol imparare a programmare e creare
software per gli smartphone con sistema operativo Google Android. La prima parte del testo
guida il lettore alla conoscenza degli strumenti necessari per sviluppare sulla piattaforma
mobile di Mountain View (installazione SDK, librerie e tool di supporto allo sviluppo).
Le sezioni successive sono pensate per un apprendimento pratico basato su esempi di
progetto: dialogo e interazione con l’ambiente operativo del telefonino, interazione con gli
utenti, componenti di un widget, interfacce in XML, gestione del touch, progettazione dei
menu e via dicendo.
Una serie di esempi pratici da seguire passo passo che spingono il lettore a sperimentare sul
campo il proprio livello di apprendimento e lo invitano a imparare divertendosi.
www.punto-informatico.it