Realizzazione di un sistema di rubrica telefonica in - SCoPE

Università degli Studi di Napoli Federico II
Facoltà di Scienze MM.FF.NN.
Corso di Laurea in Informatica
Tesi sperimentale di Laurea Triennale
Realizzazione di un sistema di rubrica
telefonica in ambiente Android
Relatori
Candidato
Prof. Guido Russo
Dr. Filippo Cestari
Anastasia Kokonozi
matr. 566/201
Anno Accademico 2011-2012
Indicegenerale
Prefazione....................................................................................................................4
CAPITOLO I...............................................................................................................6
Dispositivi mobile e software.....................................................................................6
1.1
Smartphone....................................................................................................6
1.2 Tablet.............................................................................................................7
1.3 Diffusione dei dispositivi e sistemi operativi................................................7
CAPITOLO II...........................................................................................................10
Stato dell'arte.............................................................................................................10
2.1
Premessa......................................................................................................10
2.2 Applicazioni delle università estere.............................................................11
2.3 Applicazioni delle università italiane...........................................................17
2.4 Analisi comparativa.....................................................................................22
CAPITOLO III..........................................................................................................25
Modello di programmazione.....................................................................................25
3.1 App native vs Web app................................................................................25
3.2 Sviluppo nativo............................................................................................28
3.3 PhoneGap: il framework..............................................................................31
3.4 Compatibilità...............................................................................................33
CAPITOLO IV..........................................................................................................34
L'implementazione....................................................................................................34
4.1 Ambiente di sviluppo: Server......................................................................34
4.1.1 Installazione e configurazione di LDAP..............................................34
4.1.2
Importazione dei dati su LDAP............................................................37
Anastasia Kokonozi 566/201
Pagina 2 di 117
4.1.3 WebService/API...................................................................................38
4.2 Ambiente di sviluppo: Android....................................................................44
4.2.1
Installazione e configurazione di Android SDK...................................45
4.2.2
Installazione di Eclipse ed ADT Plugin................................................47
4.2.3
Creazione di un nuovo progetto con PhoneGap...................................48
4.3 Struttura del progetto...................................................................................49
4.3.1 AndroidManifest...................................................................................50
4.3.2
HTML5.................................................................................................53
4.3.3
CSS – Responsive design.....................................................................55
4.3.4
JavaScript – jQuery Mobile..................................................................59
4.3.5
JavaScript – PhoneGap.........................................................................65
CAPITOLO V...........................................................................................................69
La sperimentazione...................................................................................................69
Conclusioni...............................................................................................................76
APPENDICE.............................................................................................................77
A.
Installazione dell'applicazione......................................................................77
B. Porting dell'applicazione...............................................................................79
C. Testare l'applicazione con l'emulatore...........................................................81
D. Pubblicazione dell'applicazione....................................................................94
E. Codice dell'applicazione................................................................................97
Bibliografia..............................................................................................................117
Anastasia Kokonozi 566/201
Pagina 3 di 117
Prefazione
Nel corso degli ultimi anni la grande diffusione di smartphone e tablet ha
portato una parte dell’informatica a focalizzarsi sullo sviluppo di applicazioni per
questi dispositivi. I programmatori quindi si sono dovuti scontrare su diverse
problematiche come: l’enorme differenza di prestazioni fra questi dispositivi ed i
personal computer. Diversi sistemi operativi mobili che permettono di sviluppare
nuove app solamente mediante delle proprie SDK (Software Development Kit),
frammentazione dei dispositivi anche nel caso in cui sfruttano un sistema operativo
identico (risoluzione del display differente, presenza o meno di un monitor
touchscreen, etc).
Tutte queste problematiche hanno portato le software house, che vogliono
intraprendere lo sviluppo di applicativi per smartphone e tablet, a fare diverse scelte
ovvero: sviluppare per una sola tipologia di piattaforma, oppure creare diversi team
di sviluppo ognuno dei quali specializzato sulla programmazione su un tipo di
sistema operativo mobile, oppure usare delle tecnologie innovative che permettono
di sviluppare un app per più piattaforme.
All’interno di questo elaborato verrà mostrato lo sviluppo per dispositivi
Android di un’applicazione chiamata Rubrica Unina usando il framework
PhoneGap. La scelta è ricaduta su questo framework perché è uno dei primi che
permette di creare applicazioni native per i vari dispositivi che supporta, partendo
da un codice comune scritto in JavaScript.
Il presente lavoro di tesi consiste nel progettare quest'applicazione con
funzionalità di rubrica telefonica per la ricerca dei recapiti dei docenti
dell'Università degli Studi di Napoli Federico II.
Più precisamente lo scopo della tesi è quello di realizzare un prototipo che
possa essere utilizzato dagli studenti o da chiunque altro necessiti di mettersi in
Anastasia Kokonozi 566/201
Pagina 4 di 117
contatto con un docente, fornendogli un ulteriore mezzo per effettuare delle ricerche
in modo immediato dei recapiti del docente, quali numero di telefono, indirizzo
email, struttura di afferenza, etc.
L'applicazione si baserà sul funzionamento del sistema web FastGuttel, che
permette la ricerca di un contatto per nome, cognome, struttura e numero telefonico.
Dispone inoltre di un'area riservata, che non sarà presa in considerazione per
quest'applicazione, dove i docenti possono visualizzare i dati relativi al loro interno
telefonico.
Viene ora esposta la struttura secondo la quale è organizzato il seguente
elaborato di laurea.
Nel Capitolo 1 si presenta una breve introduzione al mondo delle applicazioni
mobile, dei dispositivi mobile e della loro attuale diffusione.
Nel Capitolo 2 vengono passate in rassegna alcune applicazioni utilizzate dalle
università italiane ed estere, che integrano funzionalità di rubrica telefonica, al fine
di effettuare un'analisi comparativa per evidenziare le funzionalità più utilizzate in
quest'ambito.
Nel Capitolo 3 viene analizzato il modello di programmazione e le differenze
tra lo sviluppo nativo di un'applicazione e lo sviluppo di una web app, con
particolare attenzione al framework PhoneGap.
Nel Capitolo 4 è descritto il processo di preparazione dell'ambiente di
sviluppo, sia della parte server che della parte relativa allo sviluppo per Android. E'
inoltre descritta la base dati con cui l'integrazione interagisce e sono illustrati
dettagliatamente tutti gli strumenti utilizzati, con alcuni frammenti di codice.
Il lavoro si conclude illustrando il funzionamento dell'applicazione realizzata ,
nel Capitolo 5.
In
Appendice
vengono
illustrate
le
procedure
per
l'installazione
dell'applicazione su un dispositivo Android, il porting dell'applicazione su altre
piattaforme ed il testing dell'applicazione tramite l'emulatore messo a disposizione
dall'SDK di Android.
Anastasia Kokonozi 566/201
Pagina 5 di 117
CAPITOLO I
Dispositivi mobile e software
Un dispositivo mobile (anche conosciuto come dispositivo portatile, palmare)
è semplicemente un dispositivo di piccole dimensioni che implementa funzionalità
uguali o simili a quelle dei personal computer.
A causa delle loro dimensioni ridotte la comunicazione tra utente e dispositivo
avviene tramite monitor touchscreen e/o mini tastiere; inoltre possiedono
caratteristiche hardware e prestazionali inferiori rispetto i personal computer,
presupposto significativo da considerare durante la fase di sviluppo di un software.
1.1
Smartphone
Uno smartphone è un dispositivo portatile che abbina le funzionalità di un
telefono cellulare a quelle di gestione dei dati personali, può derivare
dall'evoluzione di un palmare a cui si aggiungono funzioni di telefono o viceversa,
di un telefono mobile a cui si aggiungono funzioni di palmare.
La caratteristica più interessante degli smartphone è la possibilità di installarvi
ulteriori applicazioni (app), che incrementano le funzionalità del dispositivo. Queste
app possono essere sviluppate dal produttore del telefono, dallo stesso utilizzatore, o
da terze parti.
Attualmente gli smartphone vengono venduti con diversi accessori hardware
come fotocamera, GPS, componenti che permettono di connettere il dispositivo con
il web piuttosto che con tecnologie come il bluetooth e il WiFi che permettono la
comunicazione con altri apparecchi. Inoltre vengono anche preinstallati programmi
Anastasia Kokonozi 566/201
Pagina 6 di 117
per l’accesso a internet, la gestione delle email, la pianificazione delle attività e per
la compatibilità con i più comuni formati di file come PDF e quelli della suite
Microsoft Office.
1.2 Tablet
Un tablet è un computer di dimensioni compatte che come principale sistema
di input utilizza uno schermo touchscreen controllato da una penna o tramite le dita.
Il nome deriva dalla forma del dispositivo che ricorda una tavoletta utilizzata per la
scrittura. Questi dispositivi non sono dotati di tastiera sebbene questa spesso possa
essere simulata sullo schermo. Nel 2010 Apple ha presentato l'iPad un tablet
computer che ha rilanciato il mercato di questi dispositivi difatti le vendite nel 2010
oscillano intorno ai 19,5 milioni.
I vantaggi di questi tipi di dispositivi sono altamente soggettivi, tuttavia un
indubbio vantaggio risiede nel fatto che gli utenti trovano più intuitivo premere
sull'immagine che rappresenta un oggetto piuttosto che guidare un dispositivo di
puntamento come un mouse per selezionare un oggetto.
1.3 Diffusione dei dispositivi e sistemi operativi
Audiweb è un organismo che rileva i dati audience di internet in Italia,
offrendo al mercato dati obiettivi, di carattere quantitativo e qualitativo, sulla
fruizione del mezzo.
Di recente Audiweb ha pubblicato i risultati della ricerca sulla diffusione di
internet e della connessione alla rete relative al mese di dicembre 2012. I dati
impressionano e ci fanno realizzare che l'informatizzazione di massa, anche nel
nostro paese, è pressoché compiuta, infatti sono ben 38,4 milioni gli Italiani che
accedono a internet (da casa, ufficio, da luogo di studio o altri luoghi), pari al 79,6%
Anastasia Kokonozi 566/201
Pagina 7 di 117
della popolazione tra gli 11 e i 74 anni di età.
Più in dettaglio, emerge una maggiore disponibilità di accesso da casa
attraverso computer (35,8 milioni di individui tra gli 11 e i 74 anni), mentre
l’accesso da luogo di lavoro è indicato dal 48,2% degli occupati (10,9 milioni di
individui) e l’accesso da luogo di studio è indicato dal 7,7% dei casi (3,7 milioni).
Il 34,8% degli individui ha dichiarato di avere un cellulare con accesso a
internet (16,8 milioni) e il 5,6% (2,7 milioni) da tablet. E’ interessante soprattutto
quest’ultimo dato decisamente in crescita, la penetrazione degli smartphone oggi
raggiunge il 50% di chi possiede un telefono cellulare, la più alta in Europa, e
cresce rapidamente anche la diffusione dei tablet: oggi i dati ci confermano come
entrambe queste tipologie di dispositivo mobile abbiano un ruolo fondamentale
nelle scelte di acquisto di tutti i giorni.
Dati confermati anche dall'analisi di Nielsen sull'utilizzo del mobile in Italia
nell'ultimo trimestre del 2012. Nielsen è leader mondiale nelle informazioni di
marketing e nella rilevazione di dati sui consumi e sull’utilizzo dei media.
Anastasia Kokonozi 566/201
Pagina 8 di 117
Confermata ancora una volta la crescita degli smartphone, un trend che
continua ormai da più di due anni e che coinvolge oltre la metà dei possessori di
cellulari, ovvero il 56% degli utenti italiani di telefonia mobile.
La vera novità però non è la crescita dei possessori di smartphone, bensì
l’andamento dei principali attori all’interno del segmento. Symbian, leader
indiscusso con oltre il 70% di quota nel 2010, ha registrato trimestre dopo trimeste
un graduale calo, imputabile anche al passaggio di Nokia a Windows, arrivando nel
terzo trimestre del 2012 a dover cedere la posizione di leadership ad Android, che,
con una crescita senza precedenti, arriva al 36% di quota di mercato, superando
ogni altro sistema operativo.
La diffusione dei dispositivi mobile e delle connessioni alla rete da questi
dispositivi, piuttosto che dai classici pc desktop, giustifica l'interesse nella
realizzazione dell'applicazione oggetto di questo lavoro di tesi, come supporto
innovativo e avanzato al servizio web FastGuttel.
Anastasia Kokonozi 566/201
Pagina 9 di 117
CAPITOLO II
Stato dell'arte
2.1
Premessa
Nonostante il crescente interesse per lo sviluppo di applicazioni per dispositivi
mobile quali smartphone e tablet, la produzione di lavori inerenti a ciò nell'ambito
dell'istruzione è piuttosto scarna, almeno in Italia.
Analizzando lo stato dell’arte nella letteratura scientifica è evidente che la
maggior parte delle università americane, invece, possiedono una propria
applicazione. Queste possono essere distinte in tre principali categorie:
1. Applicazioni per iOS: disponibili per dispositivi Apple con sistema
operativo iOS, quali iPhone, iPad e iPod, scaricabili dall'Apple Store
2. Applicazioni per Android: disponibili per dispositivi con sistema
operativo Android, quali smartphone e tablet di varie marche
3. Applicazioni web-based: fruibili attraverso l'uso di un browser mobile,
indipendentemente dal sistema operativo del dispositivo utilizzato
Tra le molteplici università che dispongono di una propria applicazione
mobile, sono state selezionate quelle disponibili per Android con funzionalità di
rubrica telefonica, per la ricerca dei numeri di telefono (e non solo) di docenti e
personale universitario.
L’analisi di queste applicazioni è servita come riferimento di partenza.
Anastasia Kokonozi 566/201
Pagina 10 di 117
2.2 Applicazioni delle università estere
Sono state prese in considerazione le applicazioni delle seguenti università:
1. * University of Alabama => Nome App: Alabama
2. Auburn University => Nome App: Auburn University
3. Auburn University => Nome App: Auburn University
4. * Bucknell University => Nome App: Bucknell
5. Cardiff University => Nome App: Cardiff University
6. * Duke University => Nome App: DukeMobile
7. * Emory University => Nome App: Emory Mobile
8. * Griffith University => Nome App: Griffith
9. * University of San Diego => Nome App: MySDMobile
10. * Northewstern University => Nome App: Northwestern
11. Ohio State University => Nome App: OSU Mobile
12. * Texas A&M University => Nome App: TAMUmobile
13. University of Manitoba => Nome App: Umanitoba
14. * University of Liverpool => Nome App: UoLMobile
15. University of Virginia => Nome App: Virginia
Tra tutte queste ce ne sono alcune (quelle evidenziate dall'asterisco iniziale)
che sono molto simili per funzionalità ed interfaccia grafica, indicativamente
cambia solo il logo dell'università ed i colori. Quindi di queste, per brevità, ne sarà
illustrata solo una, quella dell'università dell'Arizona. Anche tra le rimanenti ce ne
sono alcune simili tra loro, quindi ne verranno illustrate solo alcune. Proprio da
questo si evince il fatto che le università Americane seguono un modello abbastanza
standard per quanto riguarda lo sviluppo delle loro applicazioni mobile.
Anastasia Kokonozi 566/201
Pagina 11 di 117
University of Arizona
La schermata principale presenta le icone associate alle varie funzionalità
dell'applicazione. Quella presa in esame è “Phonebook” che corrisponde alla
rubrica.
La seconda schermata, mostrata dopo aver cliccato sull'icona Phonebook della
schermata principale mostra una toolbar nella parte superiore dello schermo nella
quale è possibile inserire il nome/cognome da cercare e cercarlo cliccando
sull'apposita icona a forma di lente di ingrandimento.
Da questa schermata è possibile accedere anche ai preferiti, ovvero la lista dei
contatti segnati come tali, oppure alla cronologia della ricerca dove sono mostrate le
ultime ricerche effettuate. Il risultato della ricerca, se esiste almeno una
corrispondenza, sarà una lista di uno o più nominativi.
Anastasia Kokonozi 566/201
Pagina 12 di 117
Per accedere alle informazioni associate ad un nominativo basta cliccare sul
nominativo desiderato.
Selezionando il nominativo vengono mostrate le informazioni ad esso
associate (solo quelle disponibili, non tutti i nominativi hanno associate le stesse
informazioni). Cliccando sull'indirizzo email viene aperta l'applicazione di sistema
per la gestione della posta elettronica. Cliccando, invece, sul numero di telefono
viene mostrata la tastiera telefonica, con il numero precompilato, permettendo di
effettuare una normale telefonata.
Infine premendo il pulsante sinistro del dispositivo (tutti i dispositivi Android
ne hanno uno) vengono mostrate delle impostazioni avanzate, come l'aggiunta delle
informazioni visualizzate ad un contatto già esistente nella rubrica del telefono, la
creazione di un nuovo contatto, oppure l'aggiunta del contatto visualizzato ai
Anastasia Kokonozi 566/201
Pagina 13 di 117
preferiti (visualizzabili in seguito dalla schermata già vista in precedenza).
Cardiff University
La schermata principale presenta le icone associate alle varie funzionalità
dell'applicazione. Quella presa in esame è “Contacts” che corrisponde alla rubrica.
L'interfaccia grafica fa pensare ad un applicazione non nativa, sviluppata tramite
l'utilizzo di un qualche framework (es. PhoneGap) che permette di realizzare delle
web app utilizzando Html e Javascript. Questa deduzione parte dal fatto che le
icone e lo stile degli elementi della pagina (input, bottoni, etc.) sembra essere
proprio quello di jQuery Mobile, un framework Javascript per la realizzazione di
pagine web mobile.
La seconda schermata, mostrata dopo aver cliccato sull'icona Contacts della
Anastasia Kokonozi 566/201
Pagina 14 di 117
schermata principale mostra una pagina dove è obbligatorio inserire il cognome e,
opzionalmente, è possibile inserire il nome o parte di esso. La ricerca viene
effettuata alla pressione dell'apposito tasto “Search”.
Il risultato della ricerca, se esiste almeno una corrispondenza, sarà una lista di
uno o più nominativi. Per accedere alle informazioni associate ad un nominativo
basta cliccare sul nominativo desiderato.
Selezionando il nominativo vengono mostrate le informazioni ad esso
associate. Se al nominativo è associato un indirizzo email, viene mostrata un
pulsante al centro della pagina tramite il quale viene aperta l'applicazione di sistema
per la gestione della posta elettronica.
Se al nominativo è associato un numero di telefono, viene mostrato un
Anastasia Kokonozi 566/201
Pagina 15 di 117
pulsante al centro della pagina tramite il quale viene aperta la tastiera telefonica,
con il numero precompilato, permettendo di effettuare una normale telefonata.
University of Manitoba
Anche quest'applicazione è molto simile alle altre per grafica e funzionalità
ma, a differenza delle altre, permette di visualizzare anche una mappa con
l'ubicazione dell'ufficio del docente cercato.
Purtroppo andando a caricare la mappa viene mostrato solo un marker ma la
mappa dietro non viene caricata. Cliccando sul marker viene mostrata una foto
dell'edificio dove si trova l'ufficio selezionato.
Anastasia Kokonozi 566/201
Pagina 16 di 117
2.3 Applicazioni delle università italiane
Passando ad analizzare il panorama italiano riscontriamo la presenza di circa
una ventina di applicazioni mobile a fronte di un centinaio di università italiane
(statali, non statali e telematiche).
Tra le applicazioni provate, quelle con funzionalità di rubrica sono solo 4:
1. Università degli Studi di Bergamo => Nome App: MyUniBG
2. Università degli Studi di Napoli “Parthenope” => Nome App: Parthenope
3. Politecnico di Torino => Nome App: PoliTo
4. Università di Calabria => Nome App: UnicalFind
Università degli Studi di Bergamo
La schermata principale presenta le icone associate alle varie funzionalità
dell'applicazione. Quella presa in esame è “Persone” che corrisponde alla rubrica.
Anastasia Kokonozi 566/201
Pagina 17 di 117
La seconda schermata, mostrata dopo aver cliccato sull'icona Persone della
schermata principale, mostra un lista di nominativi ordinati alfabeticamente sul
cognome.
Nella pagina, inoltre, è presente una toolbar per la ricerca (più che una ricerca
è un filtro, in quanto la lista è inizialmente
visualizzata per intero e,
successivamente, viene filtrata mostrando solo i nominativi che corrispondono al
testo inserito). La ricerca (o filtro) è effettuata solo sul campo cognome e non sul
nome. Per accedere alle informazioni associate ad un nominativo basta cliccare sul
nominativo desiderato.
Selezionando il nominativo vengono mostrare le informazioni ad esso
associate. Oltre al nominativo vengono mostrati nella pagina 2 pulsanti per inviare
un'email al contatto o per telefonare al contatto. Questi pulsanti sono sempre
Anastasia Kokonozi 566/201
Pagina 18 di 117
visibili, anche in assenza di queste informazioni.
Università degli Studi di Napoli “Parthenope”
La schermata principale presenta le icone associate alle varie funzionalità
dell'applicazione. Quella presa in esame è “Elenco” che corrisponde alla rubrica.
La seconda schermata, mostrata dopo aver cliccato sull'icona Elenco della
schermata principale, mostra un lista di nominativi ordinati alfabeticamente sul
cognome con i dettagli disponibili (es. dipartimento, mail, numero di telefono, etc.).
Anche qui è presente un filtro per la ricerca, effettuata sia sul campo cognome che
sul campo nome.
A differenza delle altre applicazioni, non è necessario cliccare sul nominativo
per visualizzarne il dettaglio in quanto le informazioni disponibili per ogni
Anastasia Kokonozi 566/201
Pagina 19 di 117
nominativo sono già mostrate.
Cliccando invece sul nominativo viene aperta una popup con alcuni pulsanti
per inviare un'email al contatto, telefonare al contatto e chiudere la popup tornando
sulla schermata di ricerca. Su questa funzionalità è possibile che ci sia un bug in
quanto, come si evince dallo screenshot di cui sotto, la popup aperta ha come
intestazione il cognome ed il nome di una persona diversa dal contatto cercato.
Politecnico di Torino
La schermata principale presenta le icone associate alle varie funzionalità
dell'applicazione. Quella presa in esame è “Cerca” che corrisponde alla rubrica.
Anche in questo caso (vedi Cardiff University) l'interfaccia grafica fa pensare
ad un'applicazione non nativa, sviluppata tramite l'utilizzo di un qualche framework
(es. PhoneGap) grazie al quale è possibile sviluppare una web app in html e
javascript.
Anastasia Kokonozi 566/201
Pagina 20 di 117
La seconda schermata, mostrata dopo aver cliccato sull'icona Cerca della
schermata principale, mostra una pagina dove inserire il nome/cognome da cercare.
La ricerca viene effettuata alla pressione dell'apposito tasto “Cerca”.
Il risultato della ricerca, se esiste almeno una corrispondenza, sarà una lista di
uno o più nominativi. Per accedere alle informazioni associate ad un nominativo
basta cliccare sul nominativo desiderato.
Anche in questo caso, se al nominativo è associato un'indirizzo email,
cliccando su questo viene aperta l'applicazione di sistema per la gestione della posta
elettronica, mentre se al nominativo è associato un numero di telefono, cliccando su
questo viene aperta la tastiera telefonica, con il numero precompilato, permettendo
di effettuare una normale chiamata.
Anastasia Kokonozi 566/201
Pagina 21 di 117
2.4 Analisi comparativa
Le applicazioni analizzate sono, in realtà, tutte molto simili tra loro e, tra
queste, alcune utilizzano lo stesso identico schema, grafico e funzionale,
personalizzato solo nelle combinazioni di colori e loghi dell'università di
riferimento. Di seguito una tabella riassuntiva che indica le funzionalità associate ad
ogni applicazione analizzata.
Questa prima tabella prende in considerazione le seguenti funzionalità:
ricerca per nome/cognome, ricerca per dipartimento, gestione dei preferiti.
RICERCA PER
RICERCA PER
PREFERITI
NOME COGNOME DIPARTIMENTO
NOME APP
UNIVERSITA'
Alabama
University of
Alabama
SI
NO
SI
Arizona
University of
Arizona
SI
NO
SI
Auburn
University
Auburn University
SI
NO
NO
Bucknell
Bucknell
University
SI
NO
SI
Cardiff
University
Cardiff University
SI
NO
NO
DukeMobile
Duke University
SI
NO
SI
Emory Mobile
Emory University
SI
NO
SI
Griffith
Griffith University
SI
NO
SI
MySDMobile
University of San
Diego
SI
NO
SI
Northwestern
Northwestern
University
SI
NO
SI
OSU Mobile
Ohio State
University
SI
NO
NO
TAMUMobile
Texas A&M
Mobile
SI
NO
SI
Umanitoba
University of
Manitoba
SI
NO
NO
Anastasia Kokonozi 566/201
Pagina 22 di 117
UoL Mobile
University of
Liverpool
SI
NO
SI
Virginia
University of
Virginia
SI
NO
NO
MyUniBG
Università degli
studi di Bergamo
SI
NO
NO
Parthenope
Università degl
Studi di Napoli
“Parthenope”
SI
NO
NO
PoliTo
Politecnico di
Torino
SI
NO
NO
UnicalFind
Università di
Calabria
SI
SI
NO
Questa seconda tabella, invece, prende in considerazione le seguenti funzionalità:
gestione della cronologia, invio email dall'app, inoltro di una chiamata dall'app.
NOME APP
UNIVERSITA'
CRONOLOGIA
EMAIL
CHIAMATA
Alabama
University of
Alabama
SI
SI
SI
Arizona
University of
Arizona
SI
SI
SI
Auburn
University
Auburn
University
SI
SI
SI
Bucknell
Bucknell
University
SI
SI
SI
SI
SI
SI
Cardiff University Cardiff University
DukeMobile
Duke University
SI
SI
SI
Emory Mobile
Emory University
SI
SI
SI
Griffith
Griffith
University
SI
SI
SI
MySDMobile
University of San
Diego
SI
SI
SI
Northwestern
Northwestern
University
SI
SI
SI
OSU Mobile
Ohio State
University
SI
SI
SI
Anastasia Kokonozi 566/201
Pagina 23 di 117
TAMUMobile
Texas A&M
Mobile
SI
SI
SI
Umanitoba
University of
Manitoba
SI
SI
SI
UoL Mobile
University of
Liverpool
SI
SI
SI
Virginia
University of
Virginia
SI
SI
SI
MyUniBG
Università degli
studi di Bergamo
NO
SI
SI
Parthenope
Università degl
Studi di Napoli
“Parthenope”
NO
SI
SI
PoliTo
Politecnico di
Torino
NO
SI
SI
UnicalFind
Università di
Calabria
NO
SI
SI
Anastasia Kokonozi 566/201
Pagina 24 di 117
CAPITOLO III
Modello di programmazione
3.1 App native vs Web app
Google, Facebook, Amazon e Twitter hanno già rilasciato versioni delle
proprie app in HTML 5 incapsulate all’interno di applicazioni native per iOS e
Android. Un fatto che non può essere ignorato.
Che differenza c’è fra questi due generi di applicazioni per dispositivi mobili?
Le app native sono più potenti rispetto alle web app in termini di user experience e
possono fare molto perché comunicano in maniera diretta con l'hardware, ma il web
sta evolvendo molto velocemente e già rispetto all'anno scorso sono cambiate molte
cose. Fra le novità ci sono framework come PhoneGap, Titanium o jQuery Mobile
in grado di creare web app da esportare in applicazioni native.
Le app native oggi sono ancora più performanti perché non hanno la barriera
del web runtime da affrontare e possono sfruttare direttamente il processore, ma la
distanza con le web app è sempre minore. Il web runtime è un software, integrato
nei framework per lo sviluppo di web app, che permette di interagire con il sistema
operativo. Mentre un app nativa accede direttamente all'hardware del telefono, una
web app deve passare attraverso questo software per poter accedere al dispositivo.
A questo si deve aggiungere che oramai anche per creare un’app per iOS
occorre fare cinque o sei ulteriori sviluppi per adattarla ai vari iDevice. La
situazione può essere addirittura peggiore nel caso di Android perché, data la
frammentazione del sistema operativo, questo viene utilizzato su decine di diversi
dispositivi che hanno caratteristiche hardware diverse e, quindi, potrebbe essere
Anastasia Kokonozi 566/201
Pagina 25 di 117
necessario effettuare innumerevoli numerosi test e bug fixing per coprire il maggior
numero possibile di dispositivi. Mentre le app in HTML 5 si adattano senza
problemi e consentono di creare componenti personalizzati per i vari dispositivi.
Analizziamo più attentamente la differenza tra le due tipologie.
Web App:
E’ una pagina web, accessibile da qualsiasi smartphone che supporta un web
browser ed è connesso a Internet. Scritta in HTML5, JavaScript e CSS ha le sue
facce negative e positive. Può inoltre essere inserita in un contesto nativo grazie
all'uso di framework come PhoneGap.
I pro:
•
Costa poco svilupparla perchè non richiede grosse competenze tecniche. Uno
sviluppatore è in grado di realizzarla facendo attenzione a scrivere i fogli di
stile (CSS) senza dimensioni fisse (no width e height in px), quindi
utilizzando solo dimensioni in percentuali (em). Inoltre vi sono dei
framework come jQuery Mobile che semplificano di molto il lavoro,
soprattutto per quant riguarda la gestione degli eventi. Un evento è per
esempio lo scroll, il touch su un elemento o lo swipe.
•
Non richiedendo grosse competenze tecniche sia il tempo di sviluppo che di
testing è dimezzato rispetto alla creazione di una applicazione nativa.
•
Rispetto ad un’app nativa lo streaming dei contenuti multimediali è gestito
meglio rendendo il tutto molto più fluido e veloce.
•
GPS, fotocamera e audio recorder grazie ad HTML 5 sono sensori che
possono essere utilizzati senza dover per forza far uso di applicazioni native.
I contro:
•
Bisogna porre molta attenzione alla realizzazione dell'interfaccia grafica se si
vuole offrirre all'utente una user experience dello stesso livello di un app
Anastasia Kokonozi 566/201
Pagina 26 di 117
nativa.
•
L'utilizzo intensivo di JavaScript può influire sulla velocità dell'applicazione
•
Per ovviare ad alcuni problemi di velocità, accedere più facilmente ai
componenti hardware ed utilizzare alcuni componenti grafici delle app
native, la web app deve essere integrata in un framework come PhoneGap
grazie al quale viene inserita in un contesto nativo che ne permette, ad
esempio, la pubblicazione sugli stores.
Quando utilizzarla:
•
Necessità di essere compatibili con tanti dispositivi: mobile e non.
•
Divulgazione di informazioni di consumo.
•
Convertire un sito web in un sito ottimizza
App Nativa:
Le applicazioni native sono sviluppate in linguaggio macchina e devono
essere scritte e compilate appositamente per ogni tipo di sistema operativo
supportarto dal device.
Per esempio le applicazioni per iOS (iPhone/iPad/iPod) sono scritte in ObjectC, quelle per Android sono sviluppate in Java mentre quelle per Windows Mobile 7
sono sviluppate ambiente .NET.
Anche le applicazioni native hanno i loro pro e contro.
I pro:
•
Possibilità di inviare delle notifiche push geolocalizzate. Le notifiche push
sono dei messaggi che si possono inviare a tutti coloro che hanno installato la
vostra applicazione. Simili a degli SMS sono molti utili per fare marketing
sul mobile.
•
Accesso a tutti i sensori hardware installati sul dispositivo: NFC,
accellerometro, GPS, fotocamera, magnetometro, sensore di prossimità, di
Anastasia Kokonozi 566/201
Pagina 27 di 117
luminosità di posizionamento e altri.
•
GUI più reattiva perchè vengono effettuate chiamate dirette di sistema e il
codice non è interpretato come nelle web app da un browser ma è scritto
direttamente in codice macchina.
I contro:
•
Costosa: sviluppare un'applicazione nativa base, per quanto semplice possa
essere, tra sviluppo e testing richiede molto più tempo di una web app, quindi
il costo di uno sviluppo nativo in termini di tempo e costi è decisamente
superiore.
•
Le app native, essendo tali per definizione, funzionano solo per specifici
dispositivi per cui sono state scritte e compilate. Di conseguenza un’app
compilata per iPhone non funzionerà su un telefono che supporta come
sistema operativo Android e viceversa.
Quando utilizzarla?
•
Realizzazioni di giochi
•
Esigenza di accedere a particolari sensori hardware messi a disposizione dal
dispositivo e non utilizzabili via HTML 5 o tramite l'uso di framework e
relativi plugin nativi
•
3.2
In generale, di tutte le cose che non si possono fare con pagine web
Sviluppo nativo
Affrontiamo brevemente il discorso dell'implementazione nativa con Java solo
per poterne evidenziare le differenze rispetto all'approccio scelto, ovvero quello di
realizzare l'applicazione in modo non nativo.
Si afferma che il linguaggio Java per le applicazioni Android sia il Java
standard (esistono delle contestazioni a questa affermazione). Un dato di fatto: la
Anastasia Kokonozi 566/201
Pagina 28 di 117
virtual machine è diversa (Dalvik). Dal punto di vista del programmatore
l'approccio cambia: si sta programmando un terminale mobile che risponde
necessariamente ad eventi (touch schermo, azioni da tastiera). Nella tipica
applicazione Android non ci sono metodi "main": tutto viene pilotato dall'utente;
potremmo dire che l'utente stesso è il programma principale.
I concetti fondamentali a cui è legato lo sviluppo nativo per Android sono: le
Activity (attività) e l'interfaccia utente, seguiti poi da altri quali Intent e Service.
Un’Activity è un componente di un’applicazione che fornisce uno schermo
con il quale l’utente può interagire per fare qualcosa, come fare una telefonata,
scattare una foto o mandare una email. Ogni attività è fornita di uno schermo sul
quale viene disegnata l’interfaccia utente. La finestra tipicamente riempie lo
schermo, ma può essere più piccola e “galleggiare” sopra altre finestre.
Un’applicazione di solito consiste in attività multiple che sono vincolate l’una
all’altra. Tipicamente, un’attività svolge la funzione di attività principale, viene
presentata all’utente al lancio dell’applicazione per la prima volta. Ogni attività può
iniziare altre attività per svolgere diversi compiti. Ogni volta che un’attività inizia,
la precedente viene fermata, ma il sistema mantiene le attività in uno stack (il back
stack).
Quando una nuova attività inizia, viene fatto un push sul back stack e
guadagna lo schermo (anche detto focus) dell’utente. Il back stack funziona
ovviamente con il meccanismo del last in, first out. Quindi, quando l’utente ha
finito con un’attività e preme il tasto Back (presente in tutti i telefoni Android),
l’attività viene tolta dallo stack con un a pop e distrutta. L’attività immediatamente
precedente viene ripresa. Quando un’attività è fermata a favore di un’altra attività
che parte, viene notificato il cambiamento tramite i metodi di callback della vita di
un’attività.
Anastasia Kokonozi 566/201
Pagina 29 di 117
Ci sono vari metodi di callback che un attività può ricevere, dato che il
sistema può crearla, fermarla, farla ripartire, distruggerla. Ogni callback fornisce la
possibilità di svolgere specifiche azioni che sono appropriate per quel cambiamento
di stato. Per esempio quando un’attività viene fermata, dovrebbero essere rilasciati
gli oggetti che occupano più risorse, come la rete o connessioni a un database.
Quando un’attività riparte, si possono riacquistare le risorse e riprendere le azioni
che sono state interrotte. Queste transizioni di stato sono parte del ciclo di vita di
un’attività.
In un applicazione Android, l’interfaccia utente è costruita utilizzando oggetti
View e ViewGroups. Ci sono vari tipi di questi oggetti, ognuno dei quali è
discendente della classe View. Gli oggetti View sono l’unità di base dell’interfaccia
utente. La classe View serve come base per le sottoclassi che offrono oggetti come
campi testo o bottoni. La classe ViewGroup serve come base per le sottoclassi
Anastasia Kokonozi 566/201
Pagina 30 di 117
chiamate che offrono diversi tipi di stile: lineare, tabulare o relativo.
Un oggetto View è una struttura dati le cui proprietà contengono i parametri
per lo stile ed il contenuto di uno specifico rettangolo dell’area dello schermo. Un
oggetto View gestisce, relativamente al proprio rettangolo di schermo, la propria
misura, l'interazione con i tasti ed il cambio di focus. Come oggetto dell’interfaccia
utente, un oggetto View è anche un punto di interazione con l’utente ed un
ricevitore di eventi interattivi.
3.3 PhoneGap: il framework
Phonegap è un progetto Open Source della Nitobi Software, un’azienda che
crea applicazioni mobile e web applications da più di dieci anni, recentemente
acquisita da Adobe. Consiste in un insieme di librerie statiche che permettono di
sviluppare velocemente ed efficacemente applicazioni per dispositivi mobili di
diverse famiglie (piattaforme). L’idea fondamentale di questo progetto è nel cercare
di realizzare lo slogan “Write once, port everywhere”.
PhoneGap si propone di focalizzare gli sforzi degli sviluppatori
sull’applicazione piuttosto che “perdere tempo” ad adattarla ad ogni piattaforma.
Per fare ciò un’applicazione realizzata con PhoneGap richiede solo la conoscenza di
HTML, CSS e JavaScript. Il porting verso le varie piattaforme viene fatto
installando gli ambienti di sviluppo relativi e compilando la web app realizzata. I
requisiti sono quindi di installare le SDK, dove richiesto dalla piattaforma, e gli
strumenti per consentire la compilazione delle applicazioni.
PhoneGap fa da ponte tra il sistema operativo e la web application realizzata
dallo sviluppatore. Si intuisce che occorre che dalla web application esista una
modalità standard per invocare le API native in maniera indipendente dal tipo di
piattaforma sottostante. PhoneGap è infatti un framework che permette ad una web
application di invocare le API native mediante funzioni JavaScript di cui è possibile
vedere gli esempi forniti sul sito di riferimento.
Anastasia Kokonozi 566/201
Pagina 31 di 117
Il vantaggio nell’utilizzo di questo framework è che esso fornisce l’aggancio
tra la piattaforma nativa e la web application, di modo che uno sviluppatore che non
ha conoscenze specifiche sui linguaggi nativi, possa dedicarsi allo sviluppo della
web application con tecnologie standard. La caratteristica fondamentale di
PhoneGap sta nel fatto che, una volta realizzata l’applicazione per il mobile con
questo framework, l’applicazione si adatta a qualunque piattaforma supportata.
PhoneGap userà il linguaggio nativo della piattaforma per accedere alle risorse
hardware e software in modo da aggiungere le funzionalità di base al motore
JavaScript e renderle così facilmente utilizzabili dall’applicazione come fossero
tradizionali metodi di libreria. In base alla tipologia di piattaforma con la quale
dovrà interfacciarsi, l’implementazione di aggancio sarà di conseguenza sviluppata
in Objective C per iPhone, in Java per Android, e così via. Tale implementazione è
fornita dallo stesso framework.
Il risultato sarà un pacchetto composto di due elementi principali (runtime e
parti statiche) con differenti responsabilità che però cooperano tra loro per fornire
delle funzioni a valore aggiunto. Nel caso specifico, il runtime si occupa di
dialogare direttamente con il dispositivo e le parti statiche offrono l’interfaccia
verso l’utente. L’uso di JavaScript e di Ajax consente poi di dare vita alle
applicazioni che possono avere comportamenti complessi e comunicazioni verso
server remoti realizzando di fatto un’applicazione completa.
Il progetto PhoneGap è sempre in via di sviluppo. La documentazione sulle
api è aggiornata costantemente. Le funzionalità disponibili al momento sono:
•
accelerometro: utilizza il sensore di moto
•
bussola: ottiene la direzione in cui il dispositivo punta
•
camera: cattura una immagine con la fotocamera
•
contatti: lavora con il database dei contatti
•
device info: raccogli informazioni sul telefono
•
events: aggancia gli eventi nativi tramite JavaScript
Anastasia Kokonozi 566/201
Pagina 32 di 117
•
file: connetti al file system nativo tramite JavaScript
•
geolocazione: rende l’applicazione coscente della locazione
•
media: registra e ascolta file audio
•
network: controlla lo stato della rete
•
notifica: notifiche visuali, acustiche, tattili
•
storage: agganciati alle opzioni dello storage nativo del sistema
La creazione di un’applicazione richiede la sola conoscenza dei linguaggi:
HTML, CSS, JavaScript. Questi tre linguaggi contribuiscono a creare la struttura
della pagina web (HTML), di personalizzarne il suo aspetto (CSS), e di renderla
dinamica ed interattiva mediante il codice JavaScript.
3.4 Compatibilità
Le piattaforme (sistemi operativi mobile) attualmente supportati da questo
framework sono:
•
Android
•
Blackberry
•
iOS
•
Symbian
•
WebOS
•
Windows Phone
•
Windows 8
•
Bada
•
Tizen
Anastasia Kokonozi 566/201
Pagina 33 di 117
CAPITOLO IV
L'implementazione
4.1 Ambiente di sviluppo: Server
Per la preparazione dell'ambiente di sviluppo è stata analizzata l'architettura
del sistema FastGuttel e si è cercato di replicare la parte di nostro interesse. I dati di
FastGuttel sono memorizzati su un server LDAP. Quindi è stato installato e
configurato il server LDAP, è stata importata una copia dei dati utilizzati dal sistema
FastGuttel ed è stato sviluppato un WebService che si occupa di interrogare il
database ed estrarre i dati necessari al corretto funzionamento dell'applicazione.
4.1.1
Installazione e configurazione di LDAP
LDAP (Lightweight Directory Access Protocol, tradotto Protocollo d'accesso
agli annuari leggeri) è un database gerarchico (diverso, quindi, da MySql che è un
database relazionale). Viene usato principalmente per memorizzare dati relativi a
degli utenti.
LDAP presenta le informazioni sotto forma di albero, nel quale le
informazioni, dette dati (entry), sono rappresentate sotto forma di rami. Ogni entry è
costituita da un insieme di coppie chiave/valore dette attributi.
Anastasia Kokonozi 566/201
Pagina 34 di 117
Il sistema operativo del server utilizzato per l'ambiente di sviluppo è Ubuntu.
Per installare LDAP sul server, una volta effettuato l'accesso allo stesso, va digitato
il comando:
sudo apt-get install slapd
Analizziamo il comando dato:
•
sudo: viene utilizzato per eseguire un comando come amministratore. Viene
successivamente richiesta la password di root per eseguire il comando.
•
apt-get: si tratta di uno strumento a riga di comando usato per operare con
l'APT (Advanced Packaging Tool) al fine di eseguire operazioni come
l'installazione, l'aggiornamento o la rimozione di pacchetti software
•
install: opzione di apt-get che indica che vogliamo installare un nuovo
pacchetto
•
slapd: è il nome del pacchetto software da installare (OpenLDAP Server)
Al termine dell'installazione bisogna effettuare la configurazione del server LDAP
digitando questo comando:
sudo dpkg-reconfigure slapd
Viene eseguita, quindi, una procedura guidata che, tramite una serie di richieste,
Anastasia Kokonozi 566/201
Pagina 35 di 117
permette di configurare il tutto.
Analizziamo queste richieste con i relativi dati inseriti:
1. Omettere la configurazione del server OpenLDAP?
•
La risposta è, ovviamente, No
2. Nome di dominio DNS:
•
In genere si usa far corrispondere un dominio LDAP al dominio DNS
della struttura che si deve rappresentare. Quindi inseriamo: unina.it
3. Nome dell'organizzazione:
•
Il dominio viene generalmente suddivisio in Organization Unit (OU) in
base alla naturale suddivisione della realtà. Inseriamo: University
4. Password dell’amministratore:
•
La password che sarà associata all'account dell'amministratore del server
LDAP. Inseriamo: 4pprubr1c4!
5. Conferma della password:
•
Per evitare possibili errori di digitazione viene richiesto nuovamente
l'inserimento della password: 4pprubr1c4!
6. Database di backend da usare:
•
Si fa riferimento a due possibili soluzioni di Database Caching, BDB ed
HDB. Ognuna con i suoi pro e contro. Manteniamo il valore di default:
HDB
7. Eliminare il database in caso di rimozione completa di slapd?
•
Trattandosi di un'ambiente di sviluppo, in caso di problemi con il
database, sarebbe sicuramente preferibile la rimozione completa con la
disinstallazione, in modo da riavere una base dati “pulita” a seguito di
una reinstallazione. Rispondiamo: Si
8. Abilitare il protocollo LDAPv2?
•
Il protocollo corrente utilizzato per lo scambio dei dati tra il client ed il
server è LDAPv3, ma in fase di configurazione viene offerta la possibilità
Anastasia Kokonozi 566/201
Pagina 36 di 117
di abilitare il supporto anche al precedente protocollo LDAPv2. Non
avendo questa necessità, rispondiamo: No
Lo username dell'amministratore viene generato automaticamente con una
parte fissa cn=admin ed una parte variabile che dipende dal nome di dominio
dc=unina,dc=it Il risultato è: cn=admin,dc=unina,dc=it e la password ad esso
associata è quella scelta durante la configurazione.
4.1.2 Importazione dei dati su LDAP
A questo punto il server LDAP è installato e configurato, pronto per
l'inserimento dei dati. Andremo quindi a importare una copia dei dati presenti sul
database di produzione nella nostra installazione.
Il file contenente l'export dei dati è in formato LDIF (LDAP Data Interchange
Format): questo formato è usato per rappresentare i campi di LDAP in un formato
testo semplice. Per importare questo file, però, è necessario installare le LDAP
Utils. Si tratta di un pacchetto di utility composto dai seguenti componenti:
•
ldapadd: utilizzato per il caricamento di nuovi record sul database
•
ldapdelete: utilizzato per la cancellazione di record dal database
•
ldapmodify: utilizzato per modificare i record del database
•
ldapsearch: utilizzato per effettuare ricerche sul database
Installiamo, quindi, questo pacchetto con il seguente comando:
sudo apt-get install ldap-utils
Dei componenti visti, quello che c'interessa per importare i dati è ldapadd.
Procediamo all'import dei dati su LDAP utilizzando il file LDIF, con il seguente
comando:
sudo ldapadd -Wx -D “USERNAME” -f /PERCORSO-DEL-FILE/export.ldif
Anastasia Kokonozi 566/201
Pagina 37 di 117
Analizziamo il comando dato:
•
sudo: viene utilizzato per eseguire il comando come amministratore
•
ldapadd: è il tool utilizzato per aggiungere dei record al database
•
-Wx: opzione di ldapadd per l'autenticazione semplice, cioè la password non
viene passata da riga di comando, ma viene richiesta dopo l'esecuzione del
comando
•
-D “USERNAME”: opzione per specificare lo username da usare per accedere
al database, sarà successivamente richiesta la password di questo account
•
-f /PERCORSO-DEL-FILE-LDIF: opzione per specificare il percorso di un
file contenente le informazioni da aggiungere sul database
4.1.3 WebService/API
Un WebService è un componente applicativo. Possiamo definirlo come un
sistema software in grado di mettersi al servizio di un'applicazione comunicando su
di una medesima rete tramite il protocollo HTTP. Un WebService consente, quindi,
alle applicazioni che vi si collegano di usufruire delle funzioni che mette a
disposizione. Un sistema può interagire con un WebService tramite appositi
“messaggi”, trasportati tramite il protocollo HTTP e generalmente formattati
secondo lo standard XML.
L'XML (eXtensible Markup Language) è un meta linguaggio di markup, non
ha tag predefiniti e non serve per definire pagine Web né per programmare. Esso
serve esclusivamente per definire altri linguaggi. Non è altro, quindi, che un insieme
standard di regole sintattiche per modellare la struttura di documenti e dati.
Nell'ambito dei WebService, lo standard più diffuso, basato su XML (per la
modellazione della struttura dei dati da scambiare), è SOAP (Simple Object Access
Protocol).
Un WebService è in grado di offrire un'interfaccia software assieme alla
Anastasia Kokonozi 566/201
Pagina 38 di 117
descrizione delle sue caratteristiche, cioè è in grado di farci sapere che funzioni
mette a disposizione (senza bisogno di conoscerle a priori) e ci permette inoltre di
capire come vanno utilizzate. Ciò significa che con una semplice connessione al
WebService, anche senza conoscerlo, possiamo stabilire le operazioni che fornisce e
possiamo subito iniziare ad usarle perché ogni operazione ha una sua descrizione
comprendente i parametri che si aspetta di ricevere, quelli che restituirà ed il tipo di
entrambi.
JavaScript, però, non dispone delle funzioni per l'interrogazione di un
WebService. Questo non significa che JavaScript non può interrogare un
WebService, può farlo ma la request XML da spedire per una richiesta deve essere
formattata “manualmente” e non si può sfruttare quella che è una delle
caratteristiche principali di un WebService, ovvero l'autodiscover (la possibilità di
conoscere le operazioni disponibili corredate dei parametri richiesti in input e quelli
restituiti in output) proprio perché questa funzionalità non è stata implementata
nelle librerie JavaScript.
Per interagire con l'applicazione si è scelto, quindi, un approccio leggermente
diverso dettato principalmente dal fatto che l'applicazione è stata realizzata in
JavaScript, con il quale è molto più semplice lavorare con dati in formato JSON:
acronimo di JavaScript Object Notation, è una tecnologia, ma sarebbe meglio
definirlo un "formato", concepito per l'interscambio dei dati all'interno di
applicazioni di tipo client-server.
Non parleremo più, quindi, di WebService ma, per una maggior precisione,
parleremo di API (Application Programming Interface): un insieme di metodi,
ognuno caratterizzato dalla propria URL (indirizzo web), ai quali vanno passati i
parametri richiesti. Queste API sono state realizzate in PHP. Si tratta di un
linguaggio di scripting interpretato, principalmente concepito per la realizzazione di
pagine web dinamiche. Un linguaggio di scripting interpretato significa che il
codice, scritto in tale linguaggio, deve essere eseguito da un altro programma (il
programma madre o un suo modulo). A differenza dell'HTML che non è un
Anastasia Kokonozi 566/201
Pagina 39 di 117
linguaggio di programmazione, bensì un linguaggio di markup (ossia descrive le
modalità di impaginazione, formattazione e visualizzazione grafica che vengono
lette ed interpretate dal browser), il PHP non è processato dal browser ma deve
essere processato da un web server: nativamente l'ambiente “naturale” di PHP è un
server UNIX per il quale il più diffuso web server è Apache, ma ce ne sono anche
altri come Lighttpd, ad esempio; nulla vieta però di usare questo linguaggio anche
con IIS, il web server per Windows.
Il PHP permette il passaggio di parametri da una pagina ad un'altra sfruttando
tre array di variabili: $_GET, $_POST, $_SESSION. Il primo tipo di parametro
($_GET) viene passato tramite la stringa che compare come indirizzo nella relativa
barra del browser; il secondo tipo di parametro ($_POST) viene passato in
background; il terzo di parametro ($_SESSION) non solo viene passato in
background, ma resta persistente durante la sessione, quindi fino a che non viene
chiuso il browser oppure fino a quando non viene distrutta la variabile di sessione.
Nell'implementazione delle API si è scelto di accettare i parametri di input sia
in GET (principalmente per poter fare dei rapidi test direttamente da browser
cambiando facilmente i parametri, presenti sulla url chiamata) che in POST.
I metodi messi a disposizione dalle API implementate sono:
1. listaUtenti
•
Parametri d'input: nome, cognome, numero, struttura
•
Descrizione: questo metodo cerca gli utenti che corrispondono ai
parametri passati in input. Se, ad esempio, viene chiamato questo metodo
passandogli solo il parametro nome, viene restituita la lista di tutti gli
utenti che hanno quel nome. Se viene chiamato passandogli i parametri
cognome e struttura, viene restituita la lista di tutti gli utenti che hanno
quel cognome e che appartengono a quella struttura, etc. etc.
•
Output: Array(“error”, “result”)
Anastasia Kokonozi 566/201
Pagina 40 di 117
◦ error: true se si è verificato un errore, false altrimenti
◦ result: false se si è verificato un errore, altrimenti: Array(“cognome”,
“nome”, “dipartimento”, “telefono”, “email”, “uid”)
2. cercaUtente
•
Parametri d'input: uid (significa user identifier, quindi lo username)
•
Descrizione: questo metodo cerca e restituisce l'utente che corrisponde
all'uid passato in input restituendone tutti i dettagli.
•
Output: Array(“error”, “result”)
◦ error: true se si è verificato un errore, false altrimenti
◦ result: false se si è verificato un errore, altrimenti: Array(“cognome”,
“nome”, “dipartimento”, “telefono”, “email”, “uid”)
3. login
•
Parametri d'input: uid, password
•
Descrizione: questo metodo verifica la correttezza delle informazioni
passate in input. Se esiste l'uid e la password ad esso associata è corretta,
restituisce true, altrimenti restituisce false.
•
Output: Array(“error”)
◦ error: true se i dati inseriti non sono corretti, false altrimenti
4. cercaNome
•
Parametri d'input: nome
•
Descrizione: questo metodo viene utilizzato per l'autocompletamento del
campo nome. In pratica estrae tutti gli utenti che hanno un nome che
contiene la stringa passata in input. Così se scriviamo, ad esempio, gui la
ricerca restituisce tutti gli utenti il cui nome contiene la stringa gui
(Guido, ad esempio) e questi vengono utilizzati come suggerimenti per
permetterci di accedere più rapidamente all'informazione cercata.
•
Output: Array(“error”, “result”)
◦ error: true se si è verificato un errore, false altrimenti
Anastasia Kokonozi 566/201
Pagina 41 di 117
◦ result: false se si è verificato un errore, altrimenti: Array(“nome”)
5. cercaCognome
•
Parametri d'input: cognome
•
Descrizione: questo metodo viene utilizzato per l'autocompletamento del
campo cognome. Estrae, quindi, tutti gli utenti che hanno un cognome
che contiene la stringa passata in input. Così se scriviamo, ad esempio,
rus la ricerca restituisce tutti gli utenti il cui cognome contiene la stringa
rus (Russo, ad esempio) e questi vengono utilizzati come suggerimenti
per permetterci di accedere più rapidamente all'informazione cercata.
•
Output: Array(“error”, “result”)
◦ error: true se si è verificato un errore, false altrimenti
◦ result: false se si è verificato un errore, altrimenti: Array(“cognome”)
6. cercaNumero
•
Parametri d'input: numero
•
Descrizione: questo metodo viene utilizzato per l'autocompletamento del
campo numero (di telefono). In pratica estrae tutti gli utenti che hanno un
numero di telefono che contiene la stringa passata in input. Così se
scriviamo, ad esempio, 081 la ricerca restituisce tutti gli utenti il cui
numero di telefono contiene la stringa 081 e questi vengono utilizzati
come suggerimenti per permetterci di accedere più rapidamente
all'informazione cercata.
•
Output: Array(“error”, “result”)
◦ error: true se si è verificato un errore, false altrimenti
◦ result: false se si è verificato un errore, altrimenti: Array(“numero”)
7. cercaStruttura
•
Parametri d'input: struttura
•
Descrizione: questo metodo viene utilizzato per l'autocompletamento del
campo struttura. In pratica estrae tutti gli utenti associati ad una struttura
Anastasia Kokonozi 566/201
Pagina 42 di 117
il cui nome contiene la stringa passata in input. Così se scriviamo, ad
esempio, dip la ricerca restituisce tutti gli utenti associati ad una struttura
il cui nome contiene la stringa dip (Dipartimento di scienze fisiche, ad
esempio) e questi vengono utilizzati come suggerimenti per permetterci
di accedere più rapidamente all'informazione cercata.
•
Output: Array(“error”, “result”)
◦ error: true se si è verificato un errore, false altrimenti
◦ result: false se si è verificato un errore, altrimenti: Array(“struttura”)
Il funzionamento delle API può essere testato da browser passando i parametri
in GET, mentre all'interno dell'applicazione il passaggio dei parametri può essere
fatto in POST.
Per invocare un metodo va chiamata la URL delle API seguita dal nome del
metodo e, quindi, vanno passati i parametri. Un esempio generico di come deve
essere costruita la URL per un test da browser è il seguente:
http://SERVER/nomeMetodo/?parametro1=valore&parametro2=valore
Questo invece è un'esempio specifico di chiamata al metodo login:
http://SERVER/login/?uid=guidrus&password=demo
E' possibile cambiare la base dati utilizzata senza bisogno di modificare
l'applicazione. Per far questo basta utilizzare le API mantenendo la struttura ed il
formato di output.
Per modificare le API per leggere i dati da un database MySql o da un altro
WebService SOAP, ad esempio, anziché da un database LDAP bisogna sfruttare
sempre i metodi già presenti ed i parametri di input che vengono inviati
dall'applicazione.
Il codice delle API va, però, modificato come di seguito:
1. database MySql:
•
preparare la query per estrarre dal database i dati necessari, sfruttando i
parametri ricevuti in input
Anastasia Kokonozi 566/201
Pagina 43 di 117
•
effettuare la connessione al server MySql specificando i parametri per la
connessione
•
eseguire la query tramite la connessione attiva
•
ciclare i dati restituiti dalla query per costruire un'array con la struttura
prevista
•
chiudere la connessiona al database
•
restituire l'array costruito encodizzato nel formato JSON
2. WebService SOAP:
•
preparare la request per effettuare la chiamata SOAP, sfruttando i
parametri ricevuti in input
•
istanziare il SOAP Client, necessario per comunicare con il WebService
SOAP
•
chiamare il metodo necessario del WebService passando la request
costruita in precedenza
•
decodificare i dati restituiti dalla chiamata in formato XML
•
ciclare i dati decodificati per costruire un'array con la struttura prevista
•
restituire l'array costruito encodizzato nel formato JSON
4.2 Ambiente di sviluppo: Android
Android è un sistema operativo open source inizialmente sviluppato da
Android Inc. e successivamente acquistato da Google nel 2005. La piattaforma è
basata sul kernel Linux, usa il database SQLite, la libreria dedicata SGL per la
grafica bidimensionale e supporta lo standard OpenGL per la grafica
tridimensionale. Le applicazioni vengono eseguite tramite la Dalvik Virtual
Machine che è a tutti gli effetti una Java Virtual Machine adattata ai dispositivi
mobili.
Questa macchina virtuale è ottimizzata per sfruttare la poca memoria presente
Anastasia Kokonozi 566/201
Pagina 44 di 117
nei dispositivi mobili, consente inoltre di utilizzare diverse istanze della macchina
virtuale contemporaneamente e nasconde al sistema operativo sottostante la
gestione della memoria e dei thread.
Per sviluppare applicazioni Android è necessario preparare l'ambiente di
sviluppo. La preparazione di questo si concentra sull'installazione e configurazione
delle librerie di Android necessarie e sull'individuazione degli strumenti necessari
per lo sviluppo ed il testing.
4.2.1
Installazione e configurazione di Android SDK
Il primo passo per creare l'ambiente di sviluppo Android è l'installazione
dell'Android SDK. SDK è una sigla che sta per Software Development Kit, vale a
dire un kit di sviluppo di software. Attraverso questo kit di sviluppo, qualsiasi utente
potrà procurarsi il codice sorgente di ogni versione Android e modificarlo o
migliorarlo autonomamente.
Con l'SDK, scaricabile dal sito ufficiale, sarà quindi possibile disporre su pc di
un'interfaccia per lanciare applicazioni Android e modificarle. L'SDK è disponibile
per i vari sistemi operativi (Windows, Mac OS X, Linux), di seguito vediamo la
procedura per l'installazione su Linux.
Scaricare ed estrarre il pacchetto .tar.gz, relativo alla versione di Linux,
reperibile dal sito ufficiale di Android Developers:
http://developer.android.com/sdk/
Prima di iniziare a configurare SDK è necessario preparare il nostro sistema in
modo da procedere correttamente con l'installazione. Uno dei tools inclusi nell'SDK
è l'AVD Manager (Android Virtual Device Manager), un tool utilizzato per la
gestione dell'emulatore, tramite la creazione di device virtuali, dei quali è possibile
specificare le caratteristiche (versione di Android, risoluzione del device, memoria,
etc.) in fase di creazione.
Anastasia Kokonozi 566/201
Pagina 45 di 117
Per funzionare questo tool necessita che sia installato Java sul sistema, quindi
se non è installato provvediamo ad installare OpenJDK, un'implementazione di Java
che permetterà il corretto funzionamento dell'SDK, tramite il seguente comando:
sudo apt-get install openjdk-6-jre openjdk-6-jdk
Android SDK contiene, inoltre, un importante tool chiamato Android Debug
Bridge (ADB). Esso è uno strumento utilizzabile da linea di comando, utilizzato per
controllare e comunicare con dispositivi collegati con cavo USB. Una volta
installato, è possibile utilizzare ADB per copiare e trasferire file dal computer al
dispositivo mobile, installare applicazioni, lanciare comandi, visualizzare file di log
e molto altro.
Per ottenere questi strumenti è necessario eseguire Android SDK Manager.
Spostarsi quindi nella cartella ~/android-sdk-linux_x86/tools e digitare in un
terminale il seguente comando: ./android
Nella nuova finestra che comparirà, saranno disponibili le librerie per le varie
versioni di Android, dalla 1.5 all'attuale 4.2, e gli SDK Tools. Spuntare, quindi, tutti
gli elementi da installare e procedere con l'installazione cliccando su “Install
packages”.
Per un corretto funzionamento dell'SDK è necessario impostare il percorso
dove si trovano i files dell'SDK in modo che questo sia accessibile da qualsiasi
directory. Modificare con un editor di testo il file .bashrc presente nella propria
home e inserire all'inizio del file le seguenti linee di testo:
#AndroidDev PATH
export PATH=${PATH}:~/android-sdk-linux_x86/tools
export PATH=${PATH}:~/android-sdk-linux_x86/platform-tools
L'installazione dell'Android SDK è ora completata. Se si dispone di un dispositivo
con sistema operativo Android da utilizzare per lo sviluppo, basterà lanciare in un
terminale il seguente comando, per controllare se il proprio dispositivo viene
Anastasia Kokonozi 566/201
Pagina 46 di 117
riconosciuto dall'ADB:
adb devices
Comparirà in elenco il dispositivo collegato tramite cavo USB.
4.2.2
Installazione di Eclipse ed ADT Plugin
Ora che è pronto l'ambiente Android abbiamo bisogno di un'IDE (Integrated
Development Environment, in italiano Ambiente di Sviluppo Integrato). E' un
software che, in fase di programmazione, “aiuta” i programmatori nello sviluppo del
codice sorgente di un programma. Il più diffuso per lo sviluppo di Android è
Eclipse, davvero molto semplice da installare. Si tratta dell'IDE più diffuso
principalmente perchè per questo è disponibile un plugin ufficiale di Android che
permette di integrare una serie di funzionalità aggiuntive altrimenti non disponibili
su altri IDE. Per l'installazione di Eclipse basta scaricare il pacchetto .tar.gz per
Linux dal sito ufficiale http://www.eclipse.org e decomprimerlo. Una volta
decompresso verrà creata una cartella contenente un file eseguibile eclipse che,
eseguito, inizializzerà l'IDE.
ADT sta per Android Development Tools. Questo plugin è stato realizzato per
permettere agli sviluppatori di eseguire più velocemente alcune operazioni in fase di
sviluppo, quali la creazione di un nuovo progetto per Android, la creazione di
interfacce grafiche, il debug delle applicazioni sviluppate, etc.
Dopo aver installato Eclipse aprirlo e cliccare su “Help > Install new
software”. Nella finestra che compare cliccare su “Add” per aggiungere un nuovo
repository e nella finestra di dialogo che si aprirà inserire “ADT plugin” nella
casella “Name” e “https://dl-ssl.google.com/android/eclipse/” nella
casella “Location” (è l'indirizzo del repository dal quale scaricare l'ultima versione
del plugin). Cliccare OK e chiudere la finestra di dialogo.
A questo punto nella finestra “Available Software” spuntare la voce
Anastasia Kokonozi 566/201
Pagina 47 di 117
“Developer Tools” e cliccare “Next”. Poi cliccare ancora “Next” ed, infine “Finish”
(dopo aver accettato la licenza). Quando l’installazione sarà completata sarà
necessario riavviare Eclipse.
Ora bisogna dire ad Eclipse dove si trova l’Andoid SDK. Cliccare su
“Window > Preferences” e selezionare dalla colonna sinistra la voce “Android”. Nel
pannello a destra, nella voce “Location” inserire il percorso completo della cartella
nella quale abbiamo installato l’Android SDK.
4.2.3 Creazione di un nuovo progetto con PhoneGap
Per la creazione di un nuovo progetto con PhoneGap è necessario,
innanzitutto, configurare l'ambiente di sviluppo per Android. Una volta configurato
il tutto, si può procedere alla creazione del progetto con PhoneGap. A questo scopo
PhoneGap mette a disposizione delle utility a linea di comando (per Windows, Mac
OS X e Linux) grazie alle quali è possibile creare la struttura base per un nuovo
progetto, da importare successivamente su Eclipse.
Cominciamo
scaricando
l'ultima
versione
stabile
dal
sito
ufficiale
http://www.phonegap.com Decomprimendo il file scaricato abbiamo 2 directory:
•
doc: contiene tutta la documentazione per l'utilizzo del framework e delle
sue funzionalità sulle varie piattaforme supportate
•
lib: contiene le librerie per la creazione di un nuovo progetto sulle varie
piattaforme disponibili
Apriamo un terminale ed accediamo alla cartella di Android:
~/phonegap/lib/android/bin
e lanciamo il seguente comando:
./create <project_folder_path> <package_name> <project_name>
Analizziamo il comando:
•
./create: esecuzione del tool per la creazione di un nuovo progetto
Anastasia Kokonozi 566/201
Pagina 48 di 117
•
project_folder_path: è il percorso dove sarà salvato il nuovo progetto
•
package_name: è il nome del package, es: it.unina.rubrica
•
project_name: è il nome del progetto, es: Rubrica Unina
Fatto questo viene creato il nuovo progetto nel percorso specificato e non resta che
importarlo su Eclipse.
Lanciamo, quindi, Eclipse e creiamo un nuovo progetto. Tra le opzioni
proposte dal wizard per la creazione di un nuovo progetto, selezioniamo “Android
Project from Existing Code” (Progetto Android da Codice Esistente) ed indichiamo
il percorso nel quale abbiamo creato il nuovo progetto.
Nel progetto così creato ci sarà una directory assets/www nella quale è
presente una index.html, che è il file che viene caricato all'avvio dell'applicazione,
ed in questa cartella va sviluppata l'applicazione inserendo i propri files, immagini,
css, javascript, html, etc.
4.3
Struttura del progetto
La struttura del progetto è stata suddivisa in directory, per una migliore
comprensione e manutenibilità del codice:
•
config:
contiene
i
files
JavaScript
per
la
configurazione
dell'applicazione, come ad esempio i testi utilizzati, le url per le chiamate
Ajax, etc.
•
css: contiene i fogli di stile che definiscono l'impostazione grafica
dell'applicazione
•
html: contiene le pagine HTML in cui è definita la struttura del template
dell'applicazione
•
img: contiene le immagini usate nell'applicazione, quali loghi e icone
•
js: contiene tutti i files JavaScript nei quali è contenuta la logica
applicativa
Anastasia Kokonozi 566/201
Pagina 49 di 117
4.3.1 AndroidManifest
Il codice seguente, invece, fa riferimento all'AndroidManifest.xml Si tratta di
un file richiesto per qualsiasi applicazione. Si trova nella cartella principale e
descrive le variabili globali del package, le versioni minima e massima di Android
supportate, gli schermi supportati (smallScreens, normalScreens, largeScreens, etc),
i permessi richiesti per l'installazione dell'app, etc.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:windowSoftInputMode="adjustPan"
package="it.unina.rubrica" android:versionName="1.0"
android:versionCode="5">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"
/>
<application android:icon="@drawable/icon"
android:label="@string/app_name"
android:debuggable="true">
<activity android:name="mainRubrica"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:screenOrientation="nosensor"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="16"/>
</manifest>
Anastasia Kokonozi 566/201
Pagina 50 di 117
Una delle prime informazioni da indicare nel file è il package, quindi il nome
del pacchetto, associato all'app. Questo nome verrà poi utilizzato anche per la
pubblicazione su Google Play, il market di Android. E' stato utilizzato:
it.unina.rubrica Al package sono associate altre informazioni quali il numero
della versione ed un eventuale nome ad esso associato.
Vengono poi indicati gli “screens” (schermi) supportati. La configurazione
utilizzata non è per niente restrittiva, permette quindi l'installazione e l'esecuzione
dell'app su tutti i dispositivi, indipendentemente dallo schermo che hanno.
Un altro parametro molto importante è quello relativo ai permessi. Ogni volta
che si installa un'applicazione su Android, come si può notare, vengono evidenziati i
vari permessi richiesti dall'app per funzionare. Tali permessi sono relativi alla lettura
di dati del telefono come la rubrica ed i messaggi ed all'uso di alcune funzioni di
Android come la connessione internet. I permessi su Android sono del tipo prendere
o lasciare quindi, se non si è d'accordo, non rimane che rinunciare all'applicazione.
Nella maggior parte dei casi, le app chiedono le autorizzazioni per usare le
funzionalità e per leggere dati interni che, se gli fossero negati, ne
comprometterebbero il funzionamento. In altri casi, però, i permessi sono
sicuramente esagerati e può non servire, per esempio, che un gioco debba richiedere
la localizzazione oppure la connessione internet. I permessi utilizzati dall'app sono i
seguenti:
•
android.permission.INTERNET: permesso per l'accesso ad internet
•
android.permission.ACCESS_NETWORK_STATE: permesso per accedere
alle informazioni sullo stato della rete (utilizzato per verificare la
disponibilità di connessione al lancio dell'app)
Per ogni schermata dell'applicazione deve essere inserito un tag activity che
specifichi le informazioni di quella schermata, quali il nome dell'activity, i
componenti, l'orientamento, etc. Utilizzando PhoneGap, viene creata una sola
activity all'interno della quale viene eseguito il flusso di navigazione dell'app. Su
Anastasia Kokonozi 566/201
Pagina 51 di 117
questa activity è stata disattivata la rotazione del dispositivo, per forzare la visione
dell'app con l'orientamento verticale (detto portrait) per una miglior visualizzazione
delle informazioni.
Vanno poi specificate le versioni minime e massime di Android supportate
dall'app. Le versioni di Android supportate sono indicante mediante API level.
Esiste cioè un livello di API corrispondente ad ogni versione del sistema operativo.
Ad esempio la versione 2.1 (Eclair) che è la versione minima supportata
corrisponde al livello 7 delle API. Mentre l'ultima versione di Android 4.1 (Jelly
Bean) che è la versione massima supportata corrisponde al livello 16. Di seguito la
tabella che mostra l'associazione tra i livelli delle API e le versioni di Android a cui
corrisponde anche un nome:
Platform Version
API Level
VERSION_CODE
Android 4.1, 4.1.1
16
JELLY_BEAN
Android 4.0.3, 4.0.4
15
ICE_CREAM_SANDWICH_MR1
14
ICE_CREAM_SANDWICH
Android 3.2
13
HONEYCOMB_MR2
Android 3.1.x
12
HONEYCOMB_MR1
Android 3.0.x
11
HONEYCOMB
10
GINGERBREAD_MR1
9
GINGERBREAD
Android 2.2.x
8
FROYO
Android 2.1.x
7
ECLAIR_MR1
Android 2.0.1
6
ECLAIR_0_1
Android 2.0
5
ECLAIR
Android 1.6
4
DONUT
Android 4.0, 4.0.1,
4.0.2
Android 2.3.4
Android 2.3.3
Android 2.3.2
Android 2.3.1
Android 2.3
Anastasia Kokonozi 566/201
Pagina 52 di 117
Android 1.5
3
CUPCAKE
Android 1.1
2
BASE_1_1
Android 1.0
1
BASE
4.3.2 HTML5
Il panorama di Internet è cambiato molto dalla precedente versione delle
specifiche (HTML 4), avvenuta verso la fine del 1999. In quel tempo il Web era
strettamente legato al concetto di ipertesto e l’azione più comune per l’utente era la
fruizione di contenuti, tipicamente in forma testuale. La mediamente bassa velocità
di connessione e il limitato investimento sul media contribuivano ad una scarsa
presenza di applicazioni web, più care da sviluppare ed esigenti in termini di banda.
Tutto questo era ben rappresentato da un linguaggio, l'HTML, principalmente
orientato ad agevolare la stesura di semplici documenti testuali collegati fra loro.
Negli anni successivi l’interesse intorno alla rete ha subito una brusca accelerazione
e questo ha condizionato positivamente sia la diffusione che la velocità di
connessione della stessa, attirando di conseguenza maggiori investimenti e ricerca.
Al modello di fruizione dei contenuti si è aggiunta la possibilità per l’utente finale
di divenire esso stesso creatore attraverso applicazioni web sempre più elaborate ed
interessanti.
Questo nuovo livello di complessità, in termini di sviluppo, ha però dovuto
scontrarsi con un set di specifiche poco inclini ad essere utilizzate per tali fini.
Parallelamente il percorso di crescita del web ha fatto emergere alcune strutture di
contenuto ricorrenti, ben caratterizzate dal fenomeno dei blog: informazioni di
testata, menu di navigazione, elenchi di articoli, testo a piè di pagina, ed altri. La
parte dedicata al singolo articolo presenta anch’essa solitamente lo stesso set di
informazioni quali autore, data di pubblicazione, titolo e corpo del messaggio.
Anche in questo caso l’HTML4 non ha saputo fornire gli strumenti adatti a
Anastasia Kokonozi 566/201
Pagina 53 di 117
consentire una corretta gestione e classificazione del contenuto obbligando gli
sviluppatori web a ripiegare su strutture anonime, quali <div> e <p>, arricchite di
valore semantico con l’utilizzo di attributi quali class e id.
L’HTML5 nasce per risolvere questi problemi offrendo agli sviluppatori web
un linguaggio pronto ad essere plasmato secondo le più recenti necessità, sia dal
lato della strutturazione del contenuto che da quello dello sviluppo di vere e proprie
applicazioni.
A questo segue anche un rinvigorimento delle API JavaScript che vengono
estese per supportare tutte le funzionalità di cui una applicazione moderna potrebbe
aver bisogno:
•
salvare informazioni sul device dell’utente
•
accedere all’applicazione anche in assenza di una connessione Web
•
comunicare in modo bidirezionale sia con il server sia con altre applicazioni
•
eseguire operazioni in background
•
pilotare flussi multimediali (video, audio)
•
editare contenuti anche complessi, come documenti di testo
•
pilotare lo storico della navigazione
•
generare grafica 2D e 3D in tempo reale
•
accedere e manipolare informazioni generate in tempo reale dall’utente
attraverso sensori multimediali quali microfono e webcam
Tornando sull'HTML tra i cambiamenti più importanti c'è il fatto di non
utilizzare più le tabelle, impropriamente utilizzate in precedenza per creare la
struttura di una pagina, e tutti i tag relativi al concetto di frame, ritenuti pericoloso
per l'usabilità delle pagine stesse.
E non dimentichiamo che l’evoluzione dell’HTML viaggia di pari passo con
quella dei CSS e che ognuno di questi componenti è progettato nella sua versione
più recente per recare e ricevere beneficio dagli altri.
Anastasia Kokonozi 566/201
Pagina 54 di 117
4.3.3 CSS – Responsive design
I CSS (Cascading Style Sheet) comunemente detti fogli di stile, servono per
separare i contenuti dalla formattazione e permettere una programmazione più
chiara e facile da utilizzare. Con i fogli di stile possiamo definire la
rappresentazione di documenti HTML ed XHTML seguendo le regole contenute in
un insieme di direttive emanate a partire dal 1996 dal W3C (World Wide Web
Consortium).
In pratica partendo dal concetto che l’HMTL, così come la sua recente
evoluzione, l’XHTML, dovrebbe essere visto come un linguaggio strutturale, alieno
da qualunque scopo attinente la presentazione di un documento, sono stati designati
i CSS grazie ai quali è possibile separare il contenuto dalla presentazione dando al
testo della pagina l’aspetto desiderato: è possibile cambiare il colore o il font del
testo, così come anche le dimensioni, il posizionamento, i margini ed i bordi per il
testo e per tutti gli altri elementi presenti nella pagina.
Ci sono diversi standard CSS, il primo CSS 1 risale al 1996; nel 1998 è stata la
volta della seconda versione, CSS 2, che non presenta stravolgimenti, ma molte
aggiunte rispetto alla prima, e nel 2004 sono state emanate le specifiche per il CSS
2.1, la naturale evoluzione del CSS 2 ed, attualmente, lo standard più diffuso. E’ in
cantiere anche il CSS 3, di cui le specifiche non sono state ancora rilasciate, sebbene
il W3C pubblichi costantemente informazioni sulle novità in fase di sviluppo. Il
CSS 3 presenta soluzioni per la risoluzione di alcuni bug di interpretazione di
Internet Explorer ed una soluzione per realizzare i bordi arrotondati la cui
realizzazione affligge da sempre i webmaster.
Nonostante non siano state ancora rilasciate le specifiche “finali” per il CSS 3,
la maggior parte dei browser (nelle versioni più recenti) già supportano diverse
delle nuove funzionalità, come ad esempio quella per realizzare degli angoli
arrotondati: tra i vari browser quelli che attualmente offrono una buona
Anastasia Kokonozi 566/201
Pagina 55 di 117
compatibilità con questo standard sono Firefox (a partire dalla versione 3.5), Google
Chrome, Safari (a partire dalla versione 4), Internet Explorer (a partire dalla
versione 9) ed Opera (a partire dalla versione 11). Per quanto riguarda, invece, i
browser mobile supportano tutti la maggior parte delle funzionalità offerte dai
CSS3.
Per lo stile dell’interfaccia grafica dell’applicazione si è scelto di realizzare
uno stile Web 2.0. Il Web 2.0 non è propriamente uno stile di design, ma un concetto
molto più ampio che ha a che vedere, riassumendo, con l’evoluzione di internet. In
pratica le interfacce grafiche sono fortemente ispirate dal design e dall’estetica di
tutte quelle applicazione online che permettono uno spiccato livello d’interazione
sito-utente (Wikipedia, Youtube, Facebook, Myspace, Twitter, etc.).
Gli elementi grafici ed i trend più ricorrenti nello stile Web 2.0 sono:
•
Rotondità e curve morbide: lo stile Web 2.0 richiede un taglio netto con la
grafica squadrata tipica dei layout tabellari, preferendo curve morbide,
rotondità e angolature soft.
•
Colori tenui e tonalità pastello: le palette di questo stile tendono a colori
pastello, soprattutto nelle tonalità dell’azzurro e del verde. Il trend è abbinare
background soft con elementi dai colori accesi, forti e vivaci in contrasto.
•
Riflessi e ombre: i vari elementi della grafica devono possedere una certa
profondità, dimostrare di avere in qualche modo “spessore” nel layout. Per
questo si lavora molto sulle ombre, soprattutto dei pulsanti e delle modal box
(le finestre in sovrimpressione).
•
Icone: le icone, inserite nei posti giusti, calamitano l’attenzione dell’utente e
rendono i concetti universalmente chiari in modo immediato ed efficace,
favorendo la leggibilità dei contenuti testuali.
A livello di CSS seguire questo stile significa anche produrre un layout Tableless:
Tableless deriva dall’inglese e sta per “senza tabelle”, sta ad indicare il modo
corretto di creare il codice di un sito e cioè senza tabelle. O meglio, le tabelle
Anastasia Kokonozi 566/201
Pagina 56 di 117
dovrebbero essere usate solo per impaginare dati prettamente tabellari, e non per
inquadrare il layout di una pagina. La vecchia scuola di webmaster per fare un sito
con una grafica decente usava le tabelle. Se notiamo infatti, anche Photoshop o altri
programmi di grafica, per impaginare la grafica di un sito, ti consentono tuttora di
dividerla in sezioni e salvare una pagina HTML che in realtà è composta da una
tabella con le singole sezioni che compongono le celle. Il problema è relativo
all’accessibilità delle pagine per utenti disabili in quanto se impaginiamo tutto in
una tabella un utente non vedente, ad esempio, avrebbe molta difficoltà ad accedervi
in quanto le informazioni contenute in una tabella vengono lette riga per riga e se,
per farci stare la grafica, abbiamo diviso il layout in tante celle, allora il nostro
utente non vedente non potrà godersi i contenuti della nostra applicazione con un
certo ordine. Se invece dividiamo il contenuto in “box” logici (‘div’), tipo testata,
menu, pagina, etc, il lettore leggerà direttamente i contenuti con un filo logico ed
una certa sequenzialità. Potrà inoltre, tramite alcuni comandi, saltare il menu e
passare al contenuto della pagina, e tante altre cose altrimenti non fattibili con le
tabelle. Oltre a questo c’è il fatto che suddividendo in box le aree delle pagine si
riescono a gestire più cose tramite i CSS ed è possibile, modificando solo il foglio
di stile senza toccare il codice delle pagine, creare diversi layout.
Parlando di pagine web rivolte a dispositivi mobile c'è da tenere in
considerazione il “problema” della risoluzione. I dispositivi mobile, smartphone o
tablet, hanno dei display di diverse dimensioni e, di conseguenza, supportano
diverse risoluzioni. Applicando ad una pagina HTML un CSS che ne permette la
corretta visualizzazione su uno smartphone, ad esempio, con una risoluzione di
400x800 pixel, non si avrà la stessa resa con un tablet, ad esempio, con una
risoluzione di 1024x600 pixel.
Per risolvere questa problematica, bisogna utilizzare i CSS per realizzare un
template seguendo le regole del Responsive Design. La lingua inglese indica
genericamente con l’aggettivo “responsive” tutto ciò che “reagisce o risponde
rapidamente e in modo appropriato ad uno stimolo”. In italiano l'aggettivo che
Anastasia Kokonozi 566/201
Pagina 57 di 117
rende al meglio il termine inglese è “adattivo”.
Con Responsive Design indichiamo, quindi, quell’approccio per il quale la
progettazione e lo sviluppo di una pagina web dovrebbero adattarsi al
comportamento ed all’ambiente dell’utente in base a fattori come le dimensioni
dello schermo, la piattaforma e l’orientamento del dispositivo. La pratica consiste in
un mix di griglie, layout e immagini flessibili, più un uso attento delle media
queries CSS.
Già nelle prime specifiche dei CSS era previsto un meccanismo adatto a
servire fogli di stile ad hoc a seconda del dispositivo di visualizzazione. È quello
basato sull’utilizzo dell’attributo media e dei diversi tipi di media. Nei CSS3 il
meccanismo di base è stato notevolmente migliorato e reso più efficace, fornendo
agli sviluppatori uno strumento molto potente per servire stili specifici non solo in
base ai dispositivi di fruizione ma anche a diverse caratteristiche degli stessi. Si
entra così nell’epoca delle media queries.
Una media query consiste nella dichiarazione di un tipo di media e di zero o
più espressioni che verifichino le condizioni di validità o non validità delle
caratteristiche di un certo media. Vediamo alcuni esempi:
@media only screen and (min-device-width : 320px) { }
In questo modo gli stili CSS definiti vengono applicati solo a quei dispositivi che
hanno una larghezza minima (width) di 320 px.
@media only screen and (min‐device‐width : 320px) and (max‐device‐width : 480px) { }
In questo modo, invece, gli stili CSS definiti vengono applicati solo a quei
dispositivi che hanno una larghezza (width) di risoluzione, compresa tra i 320px ed i
Anastasia Kokonozi 566/201
Pagina 58 di 117
480px (in questa fascia rientrano la maggior parte degli smartphone attualmente in
circolazione).
E' importante, infine, oltre ad utilizzare le media queries, evitare di dare ai vari
elementi che compongono la pagina delle misure assolute. Ad esempio per
assegnare ad un testo la dimensione del font, bisognerebbe evitare la misura
assoluta (12px) ma utilizzare la misura in percentuale (1em) che calcola la misura
effettiva basandosi sulla dimensione effettiva della pagina.
4.3.4 JavaScript – jQuery Mobile
JavaScript è un linguaggio di scripting comunemente usato nelle applicazioni
web, con una sintassi molto vicina a quella del linguaggio Java.
Per lo sviluppo dell'applicazione è stato utilizzato un framework, jQuery
Mobile, basato sul framework JQuery. jQuery è un framework JavaScript, ovvero
una libreria di funzioni codificate in JavaScript, che si pone come obiettivo quello
di astrarre ad un livello più alto la programmazione lato client del comportamento di
ogni singola pagina. Tramite l’uso di questo framework è possibile, con poche righe
di codice, effettuare svariate operazioni come, ad esempio, ottenere le dimensioni di
un elemento oppure farlo apparire/scomparire con effetto dissolvenza. Anche la
gestione degli eventi è completamente standardizzata e gestita automaticamente
assieme alla loro propagazione. Fornisce metodi e funzioni per gestire al meglio
aspetti grafici e funzionali della pagina, manipolare il DOM (Document Object
Model), estendere il framework mediante plugin e quant’altro ancora, mantenendo
la compatibilità tra browser diversi.
Basato su jQuery ed ispirato al progetto UI, jQuery Mobile è un progetto
molto giovane, ma offre una buona stabilità ed un numero di funzionalità adeguate
per sviluppare applicazioni web mobile complete. Uno dei vantaggi dello sviluppo
web mobile è quello di poter realizzare un’unica applicazione fruibile con un largo
Anastasia Kokonozi 566/201
Pagina 59 di 117
numero di dispositivi. Pur mirando a questo scenario, gli sviluppatori di jQuery
Mobile hanno ben presente che offrire la stessa esperienza utente e le stesse
funzionalità al mondo dei dispositivi mobile è un’impresa pressoché impossibile,
principalmente per le peculiarità hardware di ogni dispositivo (dimensioni dello
schermo, potenza del processore). Proprio per questo hanno scelto un approccio nel
quale i dispositivi vengono raggruppati in gruppi con diversi livelli di supporto. In
questo modo i device più avanzati friuranno di un’esperienza ed un’interfaccia più
ricca di quelli più obsoleti, tuttavia ambedue potranno comunque fruire dei
contenuti e delle funzionalità offerte dall’applicazione. Sul sito ufficiale di jQuery
Mobile è disponibile una griglia, aggiornata all’ultima versione della libreria, nella
quale verificare il tipo di supporto offerto.
LIVELLO A – Supporto completo
• Apple iOS 3.2*-6.1 - Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 /
5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), 3GS (4.3), 4 (4.3 / 5.1), and 4S
(5.1 / 6.0), and 5 (6.0)
• Android 2.1-2.3 – Tested on the HTC Incredible (2.2), original Droid (2.2),
HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but
performance may be sluggish, tested on Google G1 (1.5)
• Android 3.2 (Honeycomb) – Tested on the Samsung Galaxy Tab 10.1 and
Motorola XOOM
• Android 4.0 (ICS) – Tested on a Galaxy Nexus. Note: transition
performance can be poor on upgraded devices
• Android 4.1 (Jelly Bean) – Tested on a Galaxy Nexus and Galaxy 7
• Windows Phone 7.5-7.8 – Tested on the HTC Surround (7.5), HTC Trophy
(7.5), LG-E900 (7.5), Nokia Lumia 800 (7.8)
• Blackberry 6-10 – Tested on the Torch 9800 (6) and Style 9670 (6),
BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
• Blackberry Playbook (1.0-2.0) – Tested on PlayBook
Anastasia Kokonozi 566/201
Pagina 60 di 117
• Palm WebOS (1.4-3.0) – Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2
(2.0), HP TouchPad(3.0)
• Firefox Mobile 18 – Tested on Android 2.3 and 4.1 devices
• Chrome for Android 18 – Tested on Android 4.0 and 4.1 devices
• Skyfire 4.1 - Tested on Android 2.3 device
• Opera Mobile 11.5-12: Tested on Android 2.3
• Meego 1.2 – Tested on Nokia 950 and N9
• Tizen (pre-release) – Tested on early hardware
• Samsung Bada 2.0 – Tested on a Samsung Wave 3, Dolphin browser
• UC Browser – Tested on Android 2.3 device
• Kindle 3, Fire, and Fire HD - Tested on the built-in WebKit browser for
each
• Nook Color 1.4.1 – Tested on original Nook Color, not Nook Tablet
• Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
• Safari Desktop 5-6 - Tested on OS X 10.8
• Firefox Desktop 10-18 – Tested on OS X 10.7 and Windows 7
• Internet Explorer 8-10 – Tested on Windows XP, Vista and 7, Windows
Surface RT
• Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
LIVELLO B – Supporto completo ad eccezione delle chiamate AJAX
• Blackberry 5.0*: Tested on the Storm 2 9550, Bold 9770
• Opera Mini 7 - Tested on iOS 6.1 and Android 4.1
• Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3),
also works on N97 (Symbian^1)
• Internet Explorer 7 – Tested on Windows XP
LIVELLO C – Supporto di base
• Internet Explorer 6 and older – Tested on Windows XP
• iOS 3.x and older – Tested on original iPhone (3.1), iPhone 3 (3.2)
Anastasia Kokonozi 566/201
Pagina 61 di 117
• Blackberry 4.x - Tested on the Curve 8330
• Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
• All older smartphone platforms and featurephones – Any device that
doesn’t support media queries will receive the basic, C grade experience
La caratteristica peculiare di jQuery Mobile è che per realizzare un’applicazione
base, basta scrivere del codice HTML5. La libreria, infatti, fa leva sulla struttura
semantica delle pagine HTML5 e sugli attributi “data-” per definire le varie parti
dell’interfaccia. Una volta caricata la pagina, jQuery Mobile utilizzerà questa
struttura per arricchirla con altri tag e agganciare gli eventi e le interazioni ai
componenti dell’applicazione.
La prima porzione di codice interessante è quella relativa al meta tag viewport,
che imposta alcune caratteristiche di default per la visualizzazione della pagina. In
questo caso la larghezza del documento deve coincidere con quella dello schermo e
lo zoom iniziale sarà uguale al 100%.
<meta name="viewport" content="width=device-width, initial-scale=1" />
In jQuery Mobile la navigazione fra le pagine viene realizzata con semplici
link, come faremmo in un tradizionale sito web:
<a href="rubrica.html" title=”rubrica”>Rubrica telefonica</a>
La differenza sostanziale sta nel fatto che il contenuto collegato verrà caricato
con una chiamata asincrona ed accodato al documento. In questo modo la
transizione fra una pagina e l’altra sarà più fluida. Quando avviene una transazione
verso una nuova pagina, effettuiamo una chiamata Ajax verso il server per
recuperare le informazioni necessarie a comporre quella pagina. Mentre viene
Anastasia Kokonozi 566/201
Pagina 62 di 117
effettuata la chiamata Ajax l'utente viene notificato con un loader che indica il
caricamento in corso. Al termine della chiamata Ajax il loader scompare lasciando il
posto alla pagina composta dai dati ottenuti dal server. Tutto questo grazie ad un
metodo messo a disposizione dal framework. Questo è il metodo da invocare prima
della chiamata Ajax per mostrare il loader:
$.mobile.showPageLoadingMsg();
e questo, invece, è il metodo che viene invocato al termine della chiamata Ajax per
nascondere il Loader:
$.mobile.hidePageLoadingMsg();
Tutti i dati, quindi, sono gestiti tramite chiamate Ajax alle API, passando ad ogni
chiamata la URL del metodo invocato ed i parametri richiesti. La risposta delle API
è in formato JSON, molto semplice da elaborare con JavaScript. Vediamo
un'esempio di chiamata Ajax:
function caricaContatto(uid) {
$.mobile.showPageLoadingMsg();
$.ajax({
type: "POST",
url: urls['cercaUtente'],
data: 'uid=' + uid,
dataType: "json",
success: function(data) {
},
error: function(richiesta, stato, errore) {
},
complete: function() {
$.mobile.hidePageLoadingMsg();
}
})
}
Questo metodo, ad esempio, viene utilizzato per cercare le informazioni di un
Anastasia Kokonozi 566/201
Pagina 63 di 117
contatto, conoscendo il suo uid (user id, username). Prima di effettuare la chiamata
Ajax viene invocato il metodo che mostra il loader (caricamento in corso).
Questi i parametri passati:
•
type: definisce il passaggio dei parametri, può essere GET oppure POST
•
url: contiene l'indirizzo del metodo delle API da invocare
•
data: contiene i parametri passati in input al metodo delle API
•
dataType: definisce il tipo di risposta che ci si aspetta, HTML o JSON
In corrispondenza degli eventi associati ad una chiamata Ajax, invece,
possiamo definire delle funzioni per effettuare delle operazioni in corrispondenza di
tali eventi, che sono:
•
success: funzione da lanciare se la richiesta ha successo. Accetta come
argomento i dati restituiti dal server
•
error: funzione lanciata in caso di errore. Accetta un riferimento alla
chiamata XMLHttpRequest, il suo stato e l'errore notificato
•
complete:
funzione
lanciata
al
completamento
della
richiesta,
indipendentemente dal suo esito
In caso di successo di una chiamata, generalmente, vengono utilizzati i dati
restituiti dal server per costruire la pagina (con le informazioni del contatto cercato,
ad esempio).
In caso di errore di una chiamata, generalmente, viene notificato l'errore
all'utente con una popup dove gli viene offerta la possibilità di riprovare a ripetere
l'operazione oppure annullarla tornando sulla pagina precedente.
Quando viene completata la richiesta, invece, indipendentemente dall'esito
della stessa viene invocato il metodo del framework che si occupa della chiusura del
loader, per far posto alla visualizzazione della pagina (in caso di successo della
Anastasia Kokonozi 566/201
Pagina 64 di 117
richiesta) oppure della popup di errore (in caso di errore nella richiesta, ad es:
problemi di connessione, oppure problemi di raggiungibilità del server, etc).
Infine, per completezza, va detto che jQuery Mobile, pur essendo un
framework JavaScript, non si occupa solo di questo, ma anche dell'HTML e dei
CSS. Dell'HTML perchè nelle pagine possiamo usare dei tag sugli elementi della
pagina che vengono “intercettati” dal framework che riesce ad associarli un
determinato significato. Vediamo qualche esempio.
Se ad un div associamo il tag data-role=“page” il framework interpreta
tutto il contenuto di quel div come una pagina dell'applicazione. Se invece
associamo il tag data-role=“header” oppure data-role=“footer” il framework
riconosce che si tratta, rispettivamente, dell'header e del footer della pagina e li
posiziona automaticamente nella parte alta (l'header) e nella parte bassa (il footer)
della pagina.
Per quanto riguarda, invece, i CSS jQuery Mobile offre dei CSS con una
struttura responsive. Questo significa che tutti gli elementi di una pagina, come ad
esempio gli input, le select o gli altri elementi di un form, vengono automaticamente
stilizzati dal framework con le opportune dimensioni in base alla risoluzione
supportata dal dispositivo utilizzato.
In questo modo, assieme con le media queries, riusciamo ad ottenere un
template completamente responsive, in grado di adattarsi da solo alle dimensioni del
dispositivo di visualizzazione.
4.3.5 JavaScript – PhoneGap
Come abbiamo visto PhoneGap oltre a fungere da “contenitore” convertendo
la web app in HTML + JavaScript in codice nativo, mette anche a disposizione delle
API JavaScript grazie alle quali è possibile accedere alle funzionalità native del
telefono, come l'accesso alla fotocamera, al GPS, alla rubrica, etc.
Anastasia Kokonozi 566/201
Pagina 65 di 117
Per lo sviluppo di quest'applicazione non è stata necessaria una particolare
interazione con le funzionalità native del telefono.
Nello specifico ne sono state usate soltanto alcune, tra quelle disponibili:
•
verifica della connessione
•
creazione di alert con l'interfaccia nativa
•
accesso al localStorage
•
gestione del pulsante per tornare indietro
All'avvio dell'applicazione, durante il caricamento della prima pagina, come prima
cosa viene verificata la connessione. Per fare questo controllo basta controllare il
valore di questa variabile:
navigator.connection.type
che può assumere i seguenti valori:
•
WiFi: se il dispositivo è connesso alla rete tramite la rete Wireless
•
2G/3G: se il dispositivo è connesso alla rete tramite la rete mobile della sim
inserita nel dispositivo
•
null: se il dispositivo non è connesso alla rete
Dal momento che l'applicazione per funzionare interroga un server dal quale
recupera i dati, in assenza di connessione di rete, viene mostrato un alert che invita
l'utente a riprovare o ad uscire dall'applicazione.
Per la creazione di alert con l'interfaccia nativa, invece, è stato utilizzato il
metodo Notification. Un'alert con l'interfaccia nativa è un alert che presenta un
titolo, un testo ed uno o più pulsanti con l'interfaccia grafica nativa di Androd.
Anastasia Kokonozi 566/201
Pagina 66 di 117
Questa è la sintassi del metodo utilizzato:
navigator.notification.alert(message, callback, title, buttonName)
e questi i parametri richiesti:
•
message: il messaggio da mostrare nell'alert
•
callback: la funzione che viene chiamata alla pressione del pulsante
•
title: titolo della finestra di alert
•
buttonName: etichetta del pulsante mostrato nell'alert
Il localStorage è una delle novità introdotte dall'HTML5 e si tratta di una
versione avanzata dei cookies. Si tratta, quindi, di una sorta di cache nella quale
possiamo memorizzare delle informazioni che restano permanenti anche dopo la
chiusura del browser. Dal momento che nel nostro caso la pagina HTML viene
caricata all'interno di un'applicazione e non di un browser, per accedere alle
informazioni del localStorage bisogna utilizzare i metodi messi a disposizione dalle
API di PhoneGap per questo scopo, che sono:
•
getItem(key): ritorna l'oggetto identificato tramite la sua chiave
•
setItem(key,
value): salva il dato passato associandolo alla chiave
passata
•
removeItem(key): rimuove l'oggetto identificato tramite la sua chiave
•
clear: cancella tutti i dati memorizzati nel localStorage
Queste funzionalità sono state utilizzate nell'applicazione per memorizzare i dati
della cronologia e dei preferiti. In questo modo queste informazioni restano
disponibili anche dopo la chiusura ed il riavvio dell'applicazione.
Anastasia Kokonozi 566/201
Pagina 67 di 117
Vediamone un esempio di utilizzo:
var storage = window.localStorage;
// memorizziamo lo user id del docente
storage.setItem(“cronologia”, “guidrus”);
// recuperiamo gli utenti presenti nella cronologia
var utenti = storage.getItem(“cronologia”);
// svuotiamo la cronologia
storage.removeItem(“cronologia”);
Ovviamente per inserire nella cronologia più contatti, va memorizzato un'array con
gli user id di tutti i contatti che deve essere di volta in volta aggiornato.
Infine è stato impostato un listener che resta in ascolto attendendo la
pressione del pulsante per tornare indietro. Dal momento che in tutte le pagine
dell'applicazioni sono state inserite nell'header le icone per tornare alla pagina
precedente, si è scelto di disattivare questo pulsante per la navigazione all'interno
dell'applicazione. Se, invece, si è sulla pagina principale, la pressione del tasto fa
mostrare un alert in cui viene chiesto all'utente se vuole veramente chiudere
l'applicazione e, alla pressione del tasto Ok, viene chiusa l'applicazione.
document.addEventListener("backbutton", manageBackButton);
“backbutton” è l'evento inoltrato dal framework alla pressione del tasto, mentre
“manageBackButton” è la funzione che controlla su quale pagina siamo e se siamo
su una pagina diversa dalla principale, non fa nulla.
Anastasia Kokonozi 566/201
Pagina 68 di 117
CAPITOLO V
La sperimentazione
Vediamo ora il funzionamento dell'app realizzata. Lanciando l'app ci si trova
nella schermata principale dalla quale è possibile:
1. Effettuare la ricerca di un contatto
2. Effettuare la login al sistema
Premendo sul pulsante “Rubrica telefonica” accediamo alla funzionalità di
ricerca di un contatto. La ricerca può essere effettuata inserendo uno o più parametri
Anastasia Kokonozi 566/201
Pagina 69 di 117
come la struttura, il cognome, il nome ed il numero. Per ogni campo è presente la
funzione di autocompletamento che, a partire dalla scrittura del terzo carattere,
suggerisce dei possibili valori contenti la stringa cercata. Selezioniamo i parametri
su cui effettuare la ricerca e premiamo il pulsante “Cerca”.
Mentre viene effettuata la chiamata Ajax al server per il recupero dei dati,
viene mostrata una schermata che indica il “caricamento in corso”. Questa
schermata si chiude alla ricezione dei dati per mostrare la lista dei contatti trovati. In
caso di problemi di connessione di rete viene mostrato un alert all'utente offrendo la
possibilità di riprovare l'operazione oppure annullarla tornando alla pagina
precedente.
Nella lista mostrata, contente i dati dei contatti che corrispondono al criterio di
ricerca inserito, sono disponibili le principali informazioni di ogni contatto, quali il
Anastasia Kokonozi 566/201
Pagina 70 di 117
nominativo, l'indirizzo email, la struttura di afferenza ed il numero di telefono.
Premendo sul nome di un contatto viene, invece, caricata la pagina di dettaglio del
contatto.
Anastasia Kokonozi 566/201
Pagina 71 di 117
Dalla pagina di dettaglio del contatto è possibile effettuare alcune operazioni.
Premendo il pulsante “Invia Email” verrà automaticamente lanciata l'app di sistema
per l'invio delle mail. La nuova email creata avrà come destinatario l'indirizzo email
del contatto visualizzato. Premendo, invece, sul pulsante “Chiama il Contatto” viene
mostrata in sovrimpressione una finestra dalla quale è possibile scegliere se
chiamare il contatto utilizzando la “normale” linea telefonica (in questo caso viene
lanciata l'app di sistema per la composizione delle chiamate, con il campo del
numero di telefono precompilato) oppure se effettuare la chiamata utilizzando il
servizio di Skype (in questo caso viene lanciata l'app di Skype e, dopo un
messaggio di conferma, viene inoltrata la telefonata). E' possibile aggiungere il
contatto ai preferiti premendo il pulsante “Aggiungi ai preferiti”. Infine premendo il
pulsante “Visualizza Mappa” viene mostrata una nuova schermata con la mappa
centrata sull'indirizzo associato al contatto.
Anastasia Kokonozi 566/201
Pagina 72 di 117
Se il contatto visualizzato è presente nei preferiti, dal dettaglio del contatto è
possibile rimuovere il singolo preferito premendo il pulsante “Rimuovi dai
Preferiti”.
La pagina dei preferiti, accessibile tramite il pulsante “Preferiti” nel footer
della pagina, mostra la lista dei contatti aggiunti ai preferiti. Per ogni contatto è
sempre possibile accedere al dettaglio, come se fosse stato ricercato. E' possibile
inoltre cancellare tutti i preferiti premendo l'icona in alto a destra con il simbolo del
cestino. La cancellazione effettiva di tutti i preferiti è preceduta da un alert in cui
viene chiesta conferma all'utente sull'operazione da eseguire.
C'è, infine, la pagina della cronologia molto simile per veste grafica e
funzionalità a quella dei preferiti, si differenzia da questa solo per la modalità di
inserimento dei contatti. Un contatto, infatti, viene aggiunto nella cronologia nel
Anastasia Kokonozi 566/201
Pagina 73 di 117
momento stesso in cui viene visualizzato il suo dettaglio.
Oltre alla funzionalità di ricerca di un contatto è disponibile anche la “login”.
Si tratta per ora solo di una maschera che verifica la correttezza dei dati inseriti per
permettere l'accesso ad un'area riservata. L'implementazione dell'area riservata fa
parte dei possibili sviluppi futuri.
In prospettiva di un'eventuale futuro porting su altre piattaforme, sono stati
inseriti in tutte le pagine delle icone nell'header che permettono di tornare nel menù
principale ed alla pagina principale. Ciò è stato fatto tenendo in considerazione il
fatto che non tutti i dispositivi (ad esempio quelli con sistema operativo iOS) hanno
disposizione il tasto per tornare indietro (back button). Per incoraggiare l'utilizzo di
tale sistema di navigazione, il tasto back button (anche se disponibile su Android) è
stato disabilitato per tutte le pagine diverse dal menù principale.
Anastasia Kokonozi 566/201
Pagina 74 di 117
Premendo questo tasto, infatti, dal menù principale viene offerta all'utente la
possibilità di uscire dell'app, terminandola e liberando la memoria (possibilità
offerta dal sistema operativo Android, ma non disponibile su tutti i sistemi operativi
mobile).
Anastasia Kokonozi 566/201
Pagina 75 di 117
Conclusioni
Concludendo, i requisiti funzionali richiesti per lo sviluppo dell'applicativo
sono stati completamente soddisfatti.
L'approccio scelto non è stato quello standard dello sviluppo nativo con Java,
ma c'è stato un approccio nuovo che permetterà di proseguire questo lavoro sotto
diversi aspetti. Il lavoro svolto può, innanzitutto, essere portato su altre piattaforme
preoccupandosi quasi esclusivamente dell'installazione e configurazione dei vari
ambienti di sviluppo. Inoltre potrebbe diventare un tassello di un puzzle più ampio.
Ovvero la rubrica telefonica potrebbe essere considerata come una delle
funzionalità da inserire in un'eventuale applicazione ufficiale dell'Università degli
Studi di Napoli Federico II.
Con la struttura delle API creata sarà possibile modificare la base dati
utilizzata, passando a quella di produzione (che è in fase di realizzazione e dovrebbe
trattarsi di un WebService SOAP) senza bisogno di modificare l'applicazione.
Sarebbe interessante, infine, valutare la reale possibilità/utilità di servizi
evoluti da inserire nella rubrica, quali le chiamate tramite un sistema voip, la chat o
altro.
In definitiva ritengo che PhoneGap sia un ottimo framework per lo sviluppo di
applicazioni mobile multipiattaforma perché, oltre a garantire la creazione di
applicazioni native, è un prodotto in rapida evoluzione ed un ottimo supporto online
per i programmatori. Tutto ciò lascia intendere un incessante investimento
lavorativo rivolto a questo prodotto che, in questo modo, risulta qualitativamente
valido.
Anastasia Kokonozi 566/201
Pagina 76 di 117
APPENDICE
A. Installazione dell'applicazione
Dal momento che l'applicazione non è stata rilasciata ufficialmente su Google
Play, il market di Android, va seguita una determinata procedura per l'installazione
dell'applicazione su smartphone o tablet.
Come prima cosa bisogna andare nelle impostazioni del dispositivo e, sotto il
menù “Applicazioni” spuntare la voce “Sorgenti sconosciute”. Quest'impostazione
Anastasia Kokonozi 566/201
Pagina 77 di 117
consente l'installazione di applicazione non ufficiali, quindi non pubblicate sul
Market di Android. Per motivi di sicurezza normalmente è disattivata.
Dopo bisogna aprire il browser del telefono e puntare la URL dalla quale
scaricare l'applicazione:
http://SERVER/rubrica.apk
In questo modo l'applicazione viene scaricata sul dispositivo. Basta, quindi, aprire il
gestore di file di sistema, entrare nella directory dov'è stata scaricata l'applicazione
(download in questo caso) e cliccare sul nome del file.
Partirà l'installazione dell'applicazione, al termine della quale sarà possibile lanciare
l'applicazione dal menù delle applicazioni alla voce Rubrica Unina.
L'applicazione è disponibile per le versioni di Android a partire dalla 2.1
Anastasia Kokonozi 566/201
Pagina 78 di 117
B. Porting dell'applicazione
Per portare l'applicazione sulle altre piattaforme, tutto ciò che serve è
l'installazione/configurazione dell'ambiente di sviluppo della piattaforma scelta.
Per tutte le piattaforme è disponibile, come per Android, uno script per la
creazione di un nuovo progetto (sempre sia per Windows, che per Mac OS X, che
per Linux). In base alla piattaforma scelta sarà di seguito riportato l'ambiente di
sviluppo necessario:
•
Bada: Bada SDK, IDE Eclipse, Eclipse Plugin
•
BlackBerry: BlackBerry Java SDK, IDE Eclipse, Eclipse Plugin
•
iOS: iOS SDK, IDE Xcode, su sistema operativo Mac OS X
•
Windows Phone: Windows Phone SDK, IDE Visual Studio Express, su
sistema operativo Windows
Sui siti dei rispettivi produttori sono riportate tutte le istruzioni per l'installazione e
configurazione dell'SDK e dell'IDE. Una volta configurato l'ambiente di sviluppo si
può usare lo script per la creazione di un nuovo progetto, esattamente come fatto per
la versione Android. Al termine va lanciato l'IDE di riferimento e creato un nuovo
progetto partendo dalla directory creata dallo script.
A questo punto basta sostituire la cartella assets/www con quella dell'applicazione
e testarne il corretto funzionamento. In base alla piattaforma su cui si sta
sviluppando, le API di PhoneGap possono avere delle lievi differenze, come
ampiamente documentato sul sito di PhoneGap, e quindi bisognerà effettuare dei
test ed eventualmente apportare alcune modifiche per ripristinare il corretto
funzionamento dell'applicazione.
Inoltre il sito di PhoneGap offre un ulteriore strumento per la compilazione,
denominato PhoneGap Build. Si tratta di un prodotto a pagamento che, tramite
un'interfaccia web, permette di caricare l'applicazione realizzata con PhoneGap per
una piattaforma e provvede alla conversione del codice per tutte le altre piattaforme
Anastasia Kokonozi 566/201
Pagina 79 di 117
senza bisogno, così, di installare e configurare vari ambienti di sviluppo.
Anastasia Kokonozi 566/201
Pagina 80 di 117
C. Testare l'applicazione con l'emulatore
L’Android SDK include un emulatore di un dispositivo mobile, un dispositivo
mobile virtuale che viene eseguito sulla propria macchina. L’emulatore consente di
sviluppare e testare applicazioni Android senza l’utilizzo di un dispositivo fisico.
L’emulatore di Android simula tutte le funzioni hardware e software di un
dispositivo mobile tipico, con la differenza che non può effettuare chiamate
telefoniche reali. Esso fornisce una serie di pulsanti di navigazione e di controllo,
che si possono “premere” con il mouse o la tastiera per generare eventi per le
applicazioni. Esso prevede, inoltre, uno schermo in cui vengono visualizzate le
applicazioni Android attive.
Per testare le applicazioni più facilmente, l’emulatore utilizza configurazioni
Anastasia Kokonozi 566/201
Pagina 81 di 117
Android Virtual Device (AVD). Un Android Virtual Device (AVD) è una
configurazione per un emulatore che permette di plasmare un vero e proprio
dispositivo attraverso la definizione di opzioni hardware e software per essere
emulate dall’emulatore Android. Un AVD è composto da:
•
un profilo hardware: definisce le caratteristiche hardware del dispositivo
virtuale. Ad esempio, è possibile definire la quantità di memoria che ha, se il
dispositivo ha una fotocamera, se utilizza una tastiera fisica QWERTY o un
pad alfanumerico, etc. etc.
•
una mappatura di un’immagine del sistema: è possibile definire quale
versione della piattaforma Android verrà eseguita sul dispositivo virtuale. È
possibile scegliere una versione della piattaforma standard di Android o
l’immagine del sistema fornita con un add-on dell’SDK
•
altre opzioni: è possibile specificare la skin (aspetto grafico) dell’emulatore
che si desidera utilizzare con l’AVD, consentendo di controllare le
dimensioni dello schermo, l’aspetto, e così via. È inoltre possibile specificare
la scheda SD emulata da utilizzare con l’AVD
•
un’area di memorizzazione ad hoc sulla macchina di sviluppo: i dati utenti
del dispositivo (applicazioni installate, impostazioni, e così via) e la scheda
SD emulata vengono memorizzate in questa area
È possibile creare tanti AVD quanti se ne ha bisogno, in base ai tipi di
dispositivi che si desidera plasmare. Per testare a fondo un’applicazione, occorre
creare un AVD per ogni configurazione del dispositivo (ad esempio, differenti
dimensioni dello schermo e diverse versioni della piattaforma) con la quale
l’applicazione è compatibile, e testare l’applicazione su ciascuno di essi.
Il modo più semplice per creare un AVD è quello di utilizzare l’interfaccia grafica
del AVD Manager. È possibile avviare questo strumento sia da Eclipse cliccando su
Window > AVD Manager, sia dalla riga di comando richiamando il tool android
con l’opzione avd. In alternativa è possibile creare un AVD dalla riga di comando
Anastasia Kokonozi 566/201
Pagina 82 di 117
attraverso l’uso del tool android.
Una volta che un’applicazione è in esecuzione sull’emulatore, è possibile
utilizzare i servizi della piattaforma Android per richiamare altre applicazioni,
accedere alla rete, riprodurre file audio e video, archiviare e recuperare dati,
mandare notifiche all’utente, ed eseguire il rendering delle transizioni grafiche e dei
temi. L’emulatore include anche una varietà di funzionalità di debug, come una
console da cui è possibile registrare l’output del kernel, simulare gli interrupt di
un’applicazione (come la ricezione di SMS o di telefonate), e simulare gli effetti di
latenza e caduta di segnale sulla rete dati.
Le immagini del sistema Android disponibili tramite l’Android SDK Manager
contengono il codice per il kernel Linux di Android, le librerie native, la Dalvik
VM, e i vari pacchetti Android (come il framework di Android e le applicazioni
preinstallate). L’emulatore fornisce la traduzione binaria dinamica del codice
macchina del dispositivo al sistema operativo e all’architettura del processore della
propria macchina. L’emulatore di Android supporta molte caratteristiche hardware
che possono essere presenti sui dispositivi mobili, tra cui:
•
unità di gestione della memoria (MMU)
•
display LCD
•
una o più tastiere (una tastiera Qwerty e i pulsanti del telefono associati)
•
un chip audio con funzioni di ingresso e di uscita
•
un modem GSM, tra cui una scheda SIM simulata
•
partizioni di memoria flash (emulate attraverso i file di immagine del
disco sulla propria macchina)
•
una fotocamera, utilizzando una webcam collegata alla propria macchina
•
sensori come l’accelerometro, utilizzando i dati da un dispositivo Android
collegato tramite USB
Anastasia Kokonozi 566/201
Pagina 83 di 117
La seguente tabella elenca le opzioni hardware che si possono impostare al
momento della creazione di un nuovo AVD e che vengono memorizzate nel file di
configurazione dell’AVD (il file config.ini nella directory locale dell’AVD).
Caratteristica
Descrizione
Device ram size
La quantità di RAM fisica sul
dispositivo, in megabyte. Il hw.ramSize
valore di default è “96”.
Touch-screen support
Se c’è un touch screen nel
dispositivo. Il valore di default hw.touchScreen
è “yes”.
Trackball support
Se c’è un trackball nel
dispositivo. Il valore di default hw.trackBall
è “yes”.
Keyboard support
Se il dispositivo ha una tastiera
QWERTY. Il valore di default è hw.keyboard
“yes”.
DPad support
Se il dispositivo ha pulsanti
DPad. Il valore di default è hw.dPad
“yes”.
GSM modem support
Se c’è un modem GSM nel
dispositivo. Il valore di default hw.gsmModem
è “yes”.
Camera support
Se il dispositivo ha una
fotocamera. Il valore di default hw.camera
è “yes”.
Maximum horizontal
camera pixels
Il valore di default è “640”.
hw.camera.maxHorizon
tal-Pixels
Il valore di default è “480”.
hw.camera.maxVertical
Pixels
Maximum vertical
camera pixels
Anastasia Kokonozi 566/201
Proprietà
Pagina 84 di 117
GPS support
Se c’è GPS nel dispositivo. Il
hw.gps
valore di default è “yes”.
Se il dispositivo può registrare
Audio recording support audio. Il valore di default è hw.audioInput
“yes”.
Se il dispositivo può riprodurre
Audio playback support audio. Il valore di default è hw.audioOutput
“yes”.
Battery support
Se il dispositivo può essere
eseguito su una batteria. Il hw.battery
valore di default è “yes”.
Accelerometer
Se c’è un accelerometro nel
dispositivo. Il valore di default hw.accelerometer
è “yes”.
SD Card support
Se il dispositivo supporta
l’inserimento/rimozione
di
hw.sdCard
schede SD virtuali.
Il valore di default è “yes”.
Se si usa una partizione cache
Cache partition support sul dispositivo. Il valore di disk.cachePartition
default è “yes”.
Cache partition size
Il valore di default è “66MB”.
disk.cachePartition.size
Imposta la densità utilizzata
Abstracted LCD density dallo schermo dell’AVD. Il hw.lcd.density
valore di default è “160”.
Sia quando si avvia l’emulatore, che in fase di esecuzione, è possibile
utilizzare una varietà di comandi e opzioni per controllare il suo comportamento.
Queste opzioni possono essere specificate solo dalla riga di comando attraverso
l’uso del comando emulator. Ecco la sintassi del comando:
Anastasia Kokonozi 566/201
Pagina 85 di 117
emulator -avd <avd_name> [-<option> [<value>]] [-<qemu args>]
La seguente tabella elenca tutti i comandi emulator e spiega il loro significato e
utilizzo.
Categoria
Comando
-avd <avd_name> o
AVD
@<avd_name>
Descrizione
Obbligatorio. Specifica l’AVD da
caricare
per
questa
istanza
dell’emulatore. È necessario creare una
configurazione AVD prima di lanciare
l’emulatore.
-cache <filepath>
Utilizza <filepath> come immagine
della partizione di cache di lavoro. Un
percorso assoluto o relativo alla
directory di lavoro corrente. Se non è
specificato nessun file di cache, il
comportamento
predefinito
dell’emulatore è quello di utilizzare un
file temporaneo.
-data <filepath>
Utilizza <filepath> come immagine del
disco dei dati utente di lavoro.
Opzionalmente, è possibile specificare
un percorso relativo alla directory di
lavoro corrente. Se -data non viene
utilizzato, l’emulatore cerca un file
chiamato userdata-qemu.img nella zona
di memoria dell’AVD utilizzato.
Disk Image
Quando si azzera l’immagine dei dati
utente (attraverso -wipe-data), copia il
contenuto di questo file nella nuova
immagine del disco dei dati utente. Di
-initdata <filepath>
default,
l’emulatore
copia
<system>/userdata.img. Opzionalmente,
è possibile specificare un percorso
relativo alla directory di lavoro corrente.
-wipe-data
Anastasia Kokonozi 566/201
Ripristina l’immagine del disco corrente
Pagina 86 di 117
dei dati utenti (cioè il file specificato da
-datadir e -data, o il file di default).
L’emulatore cancella tutti i dati dal file
immagine dei dati utente, quindi copia il
contenuto del file del dato -inidata nel
file dell’immagine prima dei iniziare.
-nocache
Avvia l’emulatore senza una partizione
di cache.
-ramdisk <filepath>
Utilizza <filepath> come immagine
della ramdisk. Il valore di default è
<system>/ramdisk.img. Opzionalmente,
è possibile specificare un percorso
relativo alla directory di lavoro corrente.
-sdcard <filepath>
Utilizza <filepath> come immagine
della scheda SD. Il valore di default è
<system>/sdcard.img. Opzionalmente, è
possibile specificare un percorso relativo
alla directory di lavoro corrente.
-verbose
Abilita
un
output
dettagliato.
Equivalente a -debug-init. È possibile
definire le opzioni di output predefinite,
utilizzate dalle istanze dell’emulatore,
nella variabile di ambiente Android
ANDROID_VERBOSE. Per fare ciò, si
definiscono le opzioni che si voglio-no
utilizzare in un elenco separato da
virgole, specificando solo la radice di
ogni opzione: -debug-<tags>. Ecco un
esempio che mostra ANDROID_
VERBOSE definita con le opzioni
-debug-init
e
-debug-modem:
ANDROID_VERBOSE=init,modem
Debug
-debug <tags>
Anastasia Kokonozi 566/201
Abilita/disabilita i messaggi di debug
per il tag di debug specificato. <tags> è
un
elenco
separato
da
spazi/virgole/colonne di nomi di
componenti di debug.
Pagina 87 di 117
Media
-debug-<tag>
Abilita/disabilita i messaggi di debug
per il tag di debug specificato.
-debug-no-<tag>
Disattiva i messaggi di debug per il tag
di debug specificato.
-logcat <logtags>
Abilita l’output di logcat con i tag dati.
Se la variabile di ambiente ANDROID_
LOG_TAGS è definita e non vuota, il
suo valore sarà utilizzato per abilitare
l’output di logcat per impostazione di
default.
-shell
Crea una console shell di root sul
terminale corrente. È possibile utilizzare
anche se il demone adb nel sistema
emulato è rotto. Premendo CTRL+C
dalla shell, viene fermato l’emulatore
invece che la shell.
-show-kernel <name>
Visualizza i messaggi del kernel.
-trace <name>
Abilita il profiling del codice (premere
F9 per iniziare), scritto in un file
specificato.
-audio <backend>
Utilizza il backend audio specificato.
-audio-in <backend>
Utilizza
il
specificato.
-audio-out <backend>
Utilizza il
specificato.
-noaudio
Disabilita il supporto audio nell’istanza
dell’emulatore corrente.
-radio <device>
Reindirizza l’interfaccia radio modem a
un dispositivo host.
-useaudio
Abilita il supporto audio nell’istanza
dell’emulatore corrente. Abilitato per
Anastasia Kokonozi 566/201
backend
backend
audio-input
audio-output
Pagina 88 di 117
default.
Network
Utilizza i server DNS specificati. Il
valore di <servers> deve essere un
-dns-server <servers> elenco separato da virgole di un
massimo di 4 nomi di server DNS o
indirizzi IP.
Effettua tutte le connessioni TCP
attraverso un proxy HTTP/HTTPS
specifico. Il valore di <proxy> può
essere
uno
dei
seguenti:
http://<server>:<port>
-http-proxy <proxy>
http://<username>:<password>@<serve
r>:<port>
Il prefisso http:// può essere omesso. Se
il comando -http-proxy <proxy> non
viene fornito, l’emulatore cerca la
variabile di ambiente http_proxy e
automaticamente utilizza qualsiasi
valore corrispondente al formato
<proxy> descritto in precedenza.
-netdelay <delay>
Imposta l’emulazione della latenza di
rete a <delay>. Il valore di default è
none.
-netspeed <speed>
Imposta l’emulazione della velocità di
rete a <speed>. Il valore di default è full.
-netfast
Scorcaitoia per
-netspeed full -netdelay none
-port <port>
Anastasia Kokonozi 566/201
Imposta il numero di porta della console
per questa istanza dell’emulatore a
<port>. Il numero di porta della console
deve essere un numero intero pari tra
5554 e 5584, inclusi. <port>+1 deve
essere libero e sarà riservato ad ADB.
Pagina 89 di 117
-report-console
<socket>
Sistema
-cpu-delay <delay>
Riporta la porta della console assegnata
per questa istanza dell’emulatore ad una
terza parte remota prima di avviare
l’emulazione.
Rallenta la velocità della CPU emulata
di <delay>. I valori supportati per
<delay> sono numeri interi tra 0 e 1000.
Reindirizza
dispositivo.
-gps <device>
il
GPS
NMEA
al
Utilizzare questo commando per
emulare un GPS compatibile con NMEA
collegato ad un dispositivo esterno o a
un socket. Il formato di <device> deve
essere una specificazione QEMU del
dispositivo seriale.
Passa argomenti al software emulatore
qemu.
-qemu
-qemu -enable-kvm
Quando si utilizza questa opzione,
assicurarsi che sia l’ultima opzione
specificata, dal momento che tutte le
opzioni successive sono interpretate
come opzioni specifiche qemu.
Abilita l’accelerazione KVM della
macchina
virtuale
dell’emulatore.
Questa opzione è efficace solo quando il
sistema è impostato per utilizzare
l’accelerazione KVM della macchina
virtuale. È possibile specificare una
dimensione della memoria (-m <size>)
per la macchina virtuale, che deve
corrispondere alla dimensione della
memoria dell’emulatore:
-qemu -m 512 -enable-kvm
-qemu -m 1024 -enable-kvm
-qemu -h
Anastasia Kokonozi 566/201
Visualizza l’help di qemu.
Pagina 90 di 117
-nojni
Disabilita i controlli JNI nella Dalvik
runtime.
Attiva l’accelerazione
l’emulatore.
-gpu on
-radio <device>
grafica
per
Questa opzione è disponibile solo per gli
emulatori che utilizzano un’immagine di
sistema con API Level 15, revision 3 e
superiori.
Reindirizza la modalità radio al
dispositivo specificato. Il format di
<device> deve essere una specificazione
QEMU del dispositivo seriale.
Imposta il fuso orario per il dispositivo
emulato a <timezone>, invece che al
fuso orario dell’host. <timezone> deve
essere specificato nel formato zoneinfo.
-timezone <timezone>
Per esempio:
“America/Los_Angeles”
“Europe/Paris”
-version
Visualizza il numero
dell’emulatore.
-dpi-device <dpi>
Ridimensiona
la
risoluzione
dell’emulatore in modo che corrisponda
alle dimensioni dello schermo di un
dispositivo fisico. Il valore di default è
165.
UI
-no-boot-anim
Anastasia Kokonozi 566/201
di
versione
Disabilita l’animazione di boot durante
l’avvio dell’emulatore. Disabilitare
l’animazione di boot può velocizzare il
tempo di avvio per l’emulatore.
Pagina 91 di 117
-no-window
Disabilita la visualizzazione
finestra grafica dell’emulatore.
-scale <scale>
Ridimensiona la finestra dell’emulatore.
<scale> è un numero tra 0.1 e 3 che
rappresenta il fattore di scala desiderato.
È inoltre possibile specificare la scala
come un valore DPI se si aggiunge il
suffisso “dpi” al valore della scala. Un
valore “auto” dice all’emulatore di
selezionare la migliore dimensione della
finestra.
-raw-keys
Disabilita la tastiera Unicode reversemapping.
-noskin
Non viene utilizzata
dell’emulatore.
-keyset <file>
Utilizza il file keyset specificato invece
di quello predefinito. Il file keyset
definisce l’elenco delle combinazioni di
tasti tra l’emulatore e la tastiera
dell’host.
-onion <image>
Utilizza l’immagine overlay sullo
schermo. Nessun supporto per JPEG.
Solo PNG è supportato.
-onion-alpha
<percent>
Specifica il valore della translucenza
della skin (in percentuale). Il valore di
default è 50.
-onion-rotation
<position>
-skin <skinID>
-skindir <dir>
Anastasia Kokonozi 566/201
alcuna
della
skin
Specifica la rotazione della skin.
<position> deve essere uno dei valori 0,
1, 2, 3.
Queste opzioni dell’emulatore sono
deprecate. Utilizzare gli AVD per
impostare le opzioni della skin, piuttosto
che
utilizzare
questa
opzione
dell’emulatore. L’utilizzo di questa
Pagina 92 di 117
opzione può provocare inaspettati e in
alcuni casi fuorvianti risultati, poiché la
densità con cui si rende la skin può non
essere definita. Gli AVD consentono di
associare ogni skin con una densità
predefinita e non tener conto di quella
predefinita se necessario.
Help
-help
Stampa un elenco di tutte le opzioni
dell’emulatore.
-help-all
Stampa l’help per tutte le opzioni di
avvio.
-help-<option>
Stampa l’help per una specifica opzione
di avvio.
-help-debug-tags
Stampa un elenco di tutti i tag per
-debug <tags>.
-help-disk-images
Stampa l’help per l’utilizzo delle
immagini del disco dell’emulatore.
-help-environment
Stampa l’help per le variabili di
ambiente dell’emulatore.
-help-keys
Stampa la mappatura corrente delle tasti.
-help-keyset-file
Stampa l’help per definire un file di
mappa-tura delle chiavi personalizzato.
-help-virtual-device
Stampa l’help per l’utilizzo dell’Android
Virtual Device.
Anastasia Kokonozi 566/201
Pagina 93 di 117
D. Pubblicazione dell'applicazione
Quando lo sviluppo ed il testing dell'applicazione è completato, possiamo
pubblicarla su Google Play Store. E' il nuovo store digitale per dispositivi Android
che ha sostituito l’Android Market (su cui erano disponibili solo applicazioni e non
aveva un'interfaccia web). Da esso è possibile scaricare ed acquistare non solo
applicazioni ma anche giochi, libri, film e musica da usare su smartphone e tablet
equipaggiati con il sistema operativo Android.
Usare Google Play Store è facile e gratuito, basta avere un account Google ed
effettuare l’accesso con quest’ultimo. L’accesso può essere effettuato da qualsiasi
dispositivo: non solo telefonini e tablet ma anche PC (in questo caso, gli oggetti
scaricati vengono inviati al dispositivo di destinazione non appena questo viene
connesso ad Internet).
Per procedere alla pubblicazione possiamo seguire la guida che Google ci
mette a disposizione. Di cosa abbiamo bisogno?
•
L'applicazione salvata in un file con estensione .apk di dimensione massima
50 MB
•
Essere registrati a Google
•
Un paio di screenshots (almeno)
•
Icona applicazione ad alta risoluzione
Il file apk è un file che contiene tutti i dati dell'applicazione. Senza saperlo, per
provare la nostra applicazione, abbiamo sempre inviato al dispositivo (fisico o
virtuale) un file apk generato automaticamente che, però, non è firmato digitalmente
(o meglio è firmato con chiave di debug). Google Play Store non accetterà mai un
file apk senza firma digitale, quindi vediamo come crearlo firmato. Con Eclipse
generare il file apk firmato è semplice: cliccare con il tasto destro del mouse
Anastasia Kokonozi 566/201
Pagina 94 di 117
sull'applicazione e selezionare “Export”. Nella prossima schermata controllare che
nel campo Project ci sia proprio l'applicazione che vogliamo esportare e proseguire.
A questo punto deve essere creato un portachiavi dove salvare tutte le firme
digitali (chiavi). Mettere la spunta su Create new keystore, scegliere un percorso a
piacere nel campo Location, una password di almeno 6 caratteri (inserendola in
entrambi i campi) e cliccare su Next. Compilare, infine, i campi della firma digitale
inserendo un alias, una password, la validità della chiave (minimo 25 anni), nome e
cognome. Finita questa fase, scegliere il percorso dove vogliamo che il file apk
venga generato e cliccare su Finish.
Anastasia Kokonozi 566/201
Pagina 95 di 117
Il file generato è già in grado di essere installato su qualsiasi dispositivo anche
senza essere inviato su Google Play Store. Volendo inviarlo la procedura da seguire
è necessario, innanzitutto, acquistare la licenza per sviluppatori Android (il costo
attuale è di 25$ una tantum).
Nel momento in cui viene effettuato il caricamento dell'applicazione tramite
l'account sviluppatore registrato, è necessario specificare una serie di impostazioni:
•
verificare che il funzionamento dell'applicazione rispetti le linee guida di
Google
•
verificare che l'applicazione non superi la dimensione massima consentita
(50MB)
•
definire la distribuzione (paese, versioni di android supportate, risoluzioni
supportate, etc)
•
definire la tipologia di applicazione, gratuita o a pagamento, e nel caso
venga pubblicata a pagamento impostare il prezzo di vendita
•
caricare il materiale promozionale (descrizione, screenshots, video, etc)
A questo punto è possibile inviare l'applicazione allo Store. Prima di essere
pubblicata, però, sarà soggetta alla revisione da parte del team di Google, che
verificherà che siano stati rispettati tutti i presupposti e prerequisiti.
Anastasia Kokonozi 566/201
Pagina 96 di 117
E. Codice dell'applicazione
index.html (pagina iniziale)
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Rubrica</title>
<!-- INCLUSIONE DEI CSS -->
<link rel="stylesheet" href="../css/framework/jquery.mobile.css" type="text/css"
media="screen" />
<link rel="stylesheet" href="../css/app/style.css" type="text/css" media="screen" />
<!-- INCLUSIONE DELLE LIBRERIE JAVASCRIPT -->
<script type="text/javascript" charset="utf-8"
src="../js/framework/cordova.js"></script>
<script type="text/javascript" charset="utf-8"
src="../js/framework/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8"
src="../js/framework/jquery.mobile.min.js"></script>
<!-- INCLUSIONE DEGLI SCRIPT -->
<script type="text/javascript" charset="utf-8" src="../js/app/library.js"></script>
<script type="text/javascript" charset="utf-8" src="../js/app/main.js"></script>
<script type="text/javascript" charset="utf-8" src="../js/app/login.js"></script>
<script type="text/javascript" charset="utf-8" src="../js/app/rubrica.js"></script>
<script type="text/javascript" charset="utf-8"
src="../js/app/searchResult.js"></script>
<script type="text/javascript" charset="utf-8" src="../js/app/contatto.js"></script>
<script type="text/javascript" charset="utf-8"
src="../js/app/preferiti.js"></script>
<script type="text/javascript" charset="utf-8"
src="../js/app/cronologia.js"></script>
<script type="text/javascript" charset="utf-8" src="../js/app/mappa.js"></script>
<script type="text/javascript" charset="utf-8" src="../js/app/chiamata.js"></script>
<!-- INCLUSIONE DELLE LIBRERIE DI GOOGLE MAPS -->
<script type="text/javascript" charset="utf-8"
src="http://maps.google.com/maps/api/js?sensor=true"></script>
<!-- INCLUSIONE DEI FILES DI CONFIGURAZIONE -->
<script type="text/javascript" charset="utf-8" src="../config/common.js"></script>
<script type="text/javascript" charset="utf-8" src="../config/urls.js"></script>
<script type="text/javascript" charset="utf-8" src="../config/text.js"></script>
<!-- ATTENDERE IL CARICAMENTO DI PHONEGAP -->
<script type="text/javascript">
document.addEventListener("deviceready", onDeviceReady, false);
</script>
</head>
<body>
<div data-role="page" id="main" data-dom-cache="true">
<div data-role="header" data-position="fixed" data-theme="b"
id="headerMain">
<div><h1>Rubrica Unina</h1></div>
</div>
<div data-role="content" id="contentMain">
<div id="searchButtonsMain">
<a href="#" onclick="showSpinner(); refreshToPage('rubrica');"
data-role="button" data-theme="b" data-icon="search" data-iconpos="right">Rubrica
telefonica</a>
<a href="#" onclick="showSpinner(); refreshToPage('login');"
data-role="button" data-theme="b" data-icon="gear" data-iconpos="right">Login</a>
</div>
Anastasia Kokonozi 566/201
Pagina 97 di 117
<div id="loghiMain">
<div id="logoCsiMain">
<img src="../img/logo_csi.gif" />
</div>
<div id="logoUninaMain">
<img src="../img/logo_unina.gif" />
</div>
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b"
id="footerMain"></div>
</div>
</body>
</html>
main.js (javascript associato alla pagina principale)
function onDeviceReady() {
log("FUNCTION: onDeviceReady()");
init();
}
function init() {
log("FUNCTION: init()");
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
connectionType = checkConnection();
if (connectionType == null || connectionType == "none") {
log(error["noConnection"]);
notify(error["noConnection"], "Attenzione!", "Riprova", "init", "Esci",
"closeApp");
} else {
log("Connection Type: " + connectionType);
document.addEventListener("backbutton", manageBackButton, false);
var initialScreenSize = window.innerHeight;
window.addEventListener("resize", function() {
if(window.innerHeight < initialScreenSize){
$("[data-role=footer]").hide();
} else {
$("[data-role=footer]").show();
}
});
}
}
rubrica.html (pagina della ricerca)
<div data-role="page" id="rubrica">
<div data-role="header" data-position="fixed" data-theme="b" id="headerRubrica">
<div id="headerLeftRubrica">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
</div>
Anastasia Kokonozi 566/201
Pagina 98 di 117
<div data-role="content" id="contentRubrica">
<div data-role="fieldcontain">
Struttura:
<p><ul id="struttura" data-role="listview" data-inset="true" datafilter="true" data-filter-placeholder=" " data-filter-theme="d"></ul></p>
<input id="struttura-value" type="hidden" value="" />
Cognome:
<p><ul id="cognome" data-role="listview" data-inset="true" datafilter="true" data-filter-placeholder=" " data-filter-theme="d"></ul></p>
<input id="cognome-value" type="hidden" value="" />
Nome:
<p><ul id="nome" data-role="listview" data-inset="true" data-filter="true"
data-filter-placeholder=" " data-filter-theme="d"></ul></p>
<input id="nome-value" type="hidden" value="" />
Numero:
<p><ul id="numero" data-role="listview" data-inset="true" data-filter="true"
data-filter-placeholder=" " data-filter-theme="d"></ul></p>
<input id="numero-value" type="hidden" value="" />
</div>
<div id="searchButtonsRubrica">
<a href="#" data-role="button" data-theme="b" data-icon="search"
data-inline="true" data-iconpos="right" id="cercaContatto">Cerca</a>
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b" id="footerRubrica">
<div data-role="navbar">
<ul>
<li><div><a href="#" class="ui-btn-active ui-statepersist">Cerca</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('preferiti');">Preferiti</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('cronologia');">Cronologia</a></div></li>
</ul>
</div>
</div>
</div>
rubrica.js (javascript associato alla pagina della ricerca)
var
var
var
var
strutturaToSearch = "";
cognomeToSearch = "";
nomeToSearch = "";
numeroToSearch = "";
$(document).delegate("#rubrica", "pagecreate", function() {
searchResultToLoad = true;
$("#struttura").on("listviewbeforefilter", function (e,data) {
autocomplete('struttura', data, urls['cercaStruttura'], '1');
});
$("#cognome").on("listviewbeforefilter", function (e,data) {
autocomplete('cognome', data, urls['cercaCognome'], '2');
});
$("#nome").on("listviewbeforefilter", function (e,data) {
autocomplete('nome', data, urls['cercaNome'], '3');
});
$("#numero").on("listviewbeforefilter", function (e,data) {
autocomplete('numero', data, urls['cercaNumero'], '4');
});
$("#cercaContatto").on("click", function (e,data) {
checkInputs();
if (($("#struttura-value").val() == "") && ($("#cognome-value").val() == "")
&& ($("#nome-value").val() == "") && ($("#numero-value").val() == "")) {
Anastasia Kokonozi 566/201
Pagina 99 di 117
notify(error["campiVuoti"], "Attenzione!", "Ok", "doNothing");
} else {
strutturaToSearch = $("#struttura-value").val();
cognomeToSearch = $("#cognome-value").val();
nomeToSearch = $("#nome-value").val();
numeroToSearch = $("#numero-value").val();
refreshToPage('searchResult');
}
});
});
function checkInputs() {
$('input[data-type="search"]').each(function (i) {
if ((i+1) == 1) {
var val = $("#struttura-value").val();
if (val == "") {
$("#struttura-value").val($(this).val());
}
} else if ((i+1) == 2) {
var val = $("#cognome-value").val();
if (val == "") {
$("#cognome-value").val($(this).val());
}
} else if ((i+1) == 3) {
var val = $("#nome-value").val();
if (val == "") {
$("#nome-value").val($(this).val());
}
} else if ((i+1) == 4) {
var val = $("#numero-value").val();
if (val == "") {
$("#numero-value").val($(this).val());
}
}
});
}
function setChoice(fieldName,data,searchId) {
$('#' + fieldName).html("");
$('#' + fieldName).listview("refresh");
$('#' + fieldName).trigger("updatelayout");
$('#' + fieldName + '-value').val(data);
$('input[data-type="search"]').each(function (i) {
if (i == (searchId - 1)) {
$(this).val(data);
}
});
}
function autocomplete(fieldName,data,url,searchId) {
log("autocomplete('" + fieldName + "', '" + data + "', '" + url + "', '" + searchId
+ "')");
var $ul = $('#' + fieldName),
$input = $(data.input),
value = $input.val(),
html = "";
$ul.html("");
if (value && value.length > 2) {
showSpinner();
$.ajax({
url: url + value,
dataType: "json",
async: true,
timeout: 15000,
success: function(data) {
if (data.result) {
$.each(data.result, function (i,val) {
html += "<li class=\"liContatto\" datafieldname=\"" + fieldName + "\" data-searchid=\"" + searchId + "\">" + val + "</li>";
});
$ul.html(html);
Anastasia Kokonozi 566/201
Pagina 100 di 117
$ul.listview("refresh");
$ul.trigger("updatelayout");
$(".liContatto").on("click", function (e,data) {
setChoice($(this).data("fieldname"), $
(this).html(), $(this).data("searchid"));
});
}
hideSpinner();
},
error: function() {
hideSpinner();
}
});
}
}
searchResult.html (pagina contenente i risultati della ricerca)
<div data-role="page" id="searchResult" data-dom-cache="true">
<div data-role="header" data-position="fixed" data-theme="b"
id="headerSearchResult">
<div id="headerLeftSearchResult">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
<div id="headerRightSearchResult">
<a href="#" onclick="refreshToPage('rubrica');"><img
src="../img/icons/backward.png" /></a>
</div>
</div>
<div data-role="content" id="contentSearchResult">
<ul data-role="listview" id="contentSearchResultUL"></ul>
<input type="hidden" id="uidRubrica" value="" />
<input type="hidden" id="nominativoRubrica" value="" />
<input type="hidden" id="strutturaRubrica" value="" />
<input type="hidden" id="emailRubrica" value="" />
<input type="hidden" id="telefonoRubrica" value="" />
<div id="noSearchResult" align="center">
Siamo spiacenti, la tua ricerca non ha prodotto risultati.
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b"
id="footerSearchResult">
<div data-role="navbar">
<ul>
<li><div><a href="#"
onclick="refreshToPage('rubrica');">Cerca</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('preferiti');">Preferiti</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('cronologia');">Cronologia</a></div></li>
</ul>
</div>
</div>
</div>
Anastasia Kokonozi 566/201
Pagina 101 di 117
searchResult.js
(javascript associato alla pagina contenente i risultati della ricerca)
$(document).delegate("#searchResult", "pageshow", function(e,data) {
if (searchResultToLoad) {
caricaContatti(strutturaToSearch,cognomeToSearch,nomeToSearch,numeroToSearch);
searchResultToLoad = false;
}
});
function caricaContatti(struttura,cognome,nome,numero) {
log("caricaContatti('" + struttura + "', '" + cognome + "', '" + nome + "', '" +
numero + "')");
showLoader();
var params = "";
var i = 0;
$.each( { struttura: struttura, cognome: cognome, nome: nome, numero: numero },
function(key, val) {
if (val) {
i++;
if (i > 1) {
params = params + "&" + key + "=" + val;
} else {
params = params + key + "=" + val;
}
}
});
$.ajax({
type: "GET",
url: urls['listaUtenti'],
data: params,
dataType: "json",
async: true,
success: function(data) {
if (data.error) {
loadNoSearchResultBox();
hideLoader();
} else {
if ($("#contentSearchResultUL").html() != "") {
$("#contentSearchResultUL").html("");
}
$.each(data.result, function(i, val) {
html = '<li class="contacts" data-uid="' + val.uid +
'" data-nominativo="' + val.cognome + ' ' + val.nome + '" data-struttura="' +
val.dipartimento + '" data-email="' + val.email + '" data-telefono="' + val.telefono +
'"><a href="#" onclick="refreshToPage(\'contatto\');"><h3>' + val.cognome + ' ' + val.nome
+ '</h3><p>' + val.dipartimento + '<br/>EMAIL: ' + val.email + '<br/>TELEFONO: ' +
val.telefono + '</p></a></li>';
$("#contentSearchResultUL").append(html);
});
$("#contentSearchResultUL").listview("refresh");
$("#contentSearchResultUL").trigger("updatelayout");
$("#searchResult").page({ domCache: true });
$(".contacts").click(function(e) {
$("#uidRubrica").val($(this).attr("data-uid"));
$("#nominativoRubrica").val($(this).attr("datanominativo"));
$("#strutturaRubrica").val($(this).attr("datastruttura"));
$("#emailRubrica").val($(this).attr("data-email"));
$("#telefonoRubrica").val($(this).attr("data-telefono"));
});
hideLoader();
}
Anastasia Kokonozi 566/201
Pagina 102 di 117
},
error: function() {
hideLoader();
notify(error["network"], "Attenzione!", "Riprova",
"ricaricaContatti", "Annulla", "backFromSearchResult");
}
});
}
function ricaricaContatti() {
log("FUNCTION: ricaricaContatti()");
caricaContatti(strutturaToSearch,cognomeToSearch,nomeToSearch,numeroToSearch);
}
function backFromSearchResult() {
refreshToPage('rubrica');
}
function loadNoSearchResultBox() {
$('#contentSearchResultUL').remove();
$('#uidRubrica').remove();
$('#nominativoRubrica').remove();
$('#strutturaRubrica').remove();
$('#emailRubrica').remove();
$("#telefonoRubrica").remove();
$('#noSearchResult').show();
}
contatto.html (pagina con i dettagli del contatto selezionato)
<div data-role="page" id="contatto">
<div data-role="header" data-position="fixed" data-theme="b" id="headerContatto">
<div id="headerLeftContatto">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
<div id="headerRightContatto">
<a href="#" onclick="backFromContatto()"><img
src="../img/icons/backward.png" /></a>
</div>
</div>
<div data-role="content" id="contentContatto" style="display:none">
<div id="contentContattoNominativo"></div>
<div id="contentContattoStruttura"></div>
<div id="contentContattoEmail"></div>
<div id="contentContattoTelefono"></div>
<div align="center">
<div id="searchButtonsContatto" data-role="controlgroup">
<a href="#" data-role="button" data-theme="b"
id="inviaEmail"><div id="inviaEmailIcon"> </div>Invia Email</a>
<a href="#" onclick="slideToPage('chiamata');" datarel="dialog" data-transition="none" data-role="button" data-theme="b"
id="chiamaContatto"><div id="chiamaContattoIcon"> </div>Chiama il Contatto</a>
<div id="buttonPreferito"></div>
<a href="#" onclick="slideToPage('mappa');" datarole="button" data-theme="b" id="vediMappa"><div id="vediMappaIcon"> </div>Visualizza
Mappa</a>
</div>
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b" id="footerContatto">
<div data-role="navbar">
<ul>
<li><div><a href="#"
Anastasia Kokonozi 566/201
Pagina 103 di 117
onclick="refreshToPage('rubrica');">Cerca</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('preferiti');">Preferiti</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('cronologia');">Cronologia</a></div></li>
</ul>
</div>
</div>
</div>
contatto.js
(javascript associato alla pagina con i dettagli del contatto selezionato)
var
var
var
var
var
var
var
previousPage;
ultimoContatto = "";
uid = "";
nominativo = "";
struttura = "";
email = "";
telefono = "";
var dialogNominativo = "";
var dialogNumero = "";
$(document).delegate("#contatto", "pagebeforeshow", function(e,data) {
if ((data.prevPage.attr("id") != "mappa") && (data.prevPage.attr("id") !=
"chiamata")) {
previousPage = data.prevPage.attr("id");
}
if (data.prevPage.attr("id") == "searchResult") {
uid = $("#uidRubrica",data.prevPage).val();
nominativo = $("#nominativoRubrica",data.prevPage).val();
struttura = $("#strutturaRubrica",data.prevPage).val();
email = $("#emailRubrica",data.prevPage).val();
telefono = $("#telefonoRubrica",data.prevPage).val();
aggiungiCronologia(uid, nominativo, struttura, email, telefono);
} else if (data.prevPage.attr("id") == "preferiti") {
uid = $("#uidPreferiti",data.prevPage).val();
nominativo = $("#nominativoPreferiti",data.prevPage).val();
struttura = $("#strutturaPreferiti",data.prevPage).val();
email = $("#emailPreferiti",data.prevPage).val();
telefono = $("#telefonoPreferiti",data.prevPage).val();
aggiungiCronologia(uid, nominativo, struttura, email, telefono);
} else if (data.prevPage.attr("id") == "cronologia") {
uid = $("#uidCronologia",data.prevPage).val();
nominativo = $("#nominativoCronologia",data.prevPage).val();
struttura = $("#strutturaCronologia",data.prevPage).val();
email = $("#emailCronologia",data.prevPage).val();
telefono = $("#telefonoCronologia",data.prevPage).val();
} else {
uid = ultimoContatto;
}
});
$(document).delegate("#contatto", "pageshow", function(e,data) {
ultimoContatto = uid;
caricaContatto(uid);
});
function backFromContatto() {
log("FUNCTION: backFromContatto()");
if (previousPage == "preferiti") {
refreshToPage("preferiti");
} else if (previousPage == "cronologia") {
Anastasia Kokonozi 566/201
Pagina 104 di 117
refreshToPage("cronologia");
} else {
slideToPage("searchResult");
}
}
function caricaContatto(uid) {
log("FUNCTION: caricaContatto(" + uid + ")");
showLoader();
$.ajax({
type: "GET",
url: urls['cercaUtente'],
data: 'uid=' + uid,
dataType: "json",
async: true,
success: function(data) {
if (data.error) {
hideLoader();
} else {
dialogNominativo = data.result.cognome + " " +
data.result.nome;
dialogNumero = data.result.telefono;
$('#contentContattoNominativo').html(data.result.cognome + " "
+ data.result.nome);
$('#contentContattoStruttura').html("<b>Struttura: </b>" +
data.result.dipartimento);
$('#contentContattoEmail').html("<b>Email: </b>" +
data.result.email);
$('#contentContattoTelefono').html("<b>Telefono: </b>" +
data.result.telefono);
$('#inviaEmail').attr("href", "mailto:" + data.result.email);
if (searchPreferito(data.result.uid)) {
$("#buttonPreferito").html('<a href="#" data-uid="' +
data.result.uid + '" data-nominativo="' + data.result.cognome + ' ' + data.result.nome + '"
data-struttura="' + data.result.dipartimento + '" data-email="' + data.result.email + '"
data-telefono="' + data.result.telefono + '" data-role="button" data-theme="b"
id="rimuoviPreferito"><div id="rimuoviPreferitoIcon"> </div>Rimuovi dai
Preferiti</a>');
$("#rimuoviPreferito").click(function() {
rimuoviPreferito($(this).attr("data-uid"), $
(this).attr("data-nominativo"), $(this).attr("data-struttura"), $(this).attr("data-email").
$(this).attr("data-telefono"));
});
} else {
$('#buttonPreferito').html('<a href="#" data-uid="' +
data.result.uid + '" data-nominativo="' + data.result.cognome + ' ' + data.result.nome + '"
data-struttura="' + data.result.dipartimento + '" data-email="' + data.result.email + '"
data-telefono="' + data.result.telefono + '" data-role="button" data-theme="b"
id="aggiungiPreferito"><div id="aggiungiPreferitoIcon"> </div>Aggiungi ai
Preferiti</a>');
$("#aggiungiPreferito").click(function() {
aggiungiPreferito($(this).attr("data-uid"), $
(this).attr("data-nominativo"), $(this).attr("data-struttura"), $(this).attr("data-email"),
$(this).attr("data-telefono"));
});
}
$('#contentContatto').trigger("create");
$('#contentContatto').show();
hideLoader();
}
},
error: function() {
hideLoader();
notify(error["network"], "Attenzione!", "Riprova",
"ricaricaContatto", "Annulla", "backFromContatto");
}
})
}
Anastasia Kokonozi 566/201
Pagina 105 di 117
function ricaricaContatto() {
log("FUNCTION: ricaricaContatto()");
caricaContatto(uid);
}
function searchPreferito(uid) {
log("FUNCTION: searchPreferito(" + uid + ")");
var found = false;
var retrievedObject = window.localStorage.getItem("preferitiRubrica");
if (retrievedObject) {
var preferiti = JSON.parse(retrievedObject);
$.each(preferiti, function(key, val) {
if (val.uid == uid) {
found = true;
}
});
return found;
} else {
return found;
}
}
function searchCronologia(uid) {
log("FUNCTION: searchCronologia(" + uid + ")");
var found = false;
var retrievedObject = window.localStorage.getItem("cronologiaRubrica");
if (retrievedObject) {
var preferiti = JSON.parse(retrievedObject);
$.each(preferiti, function(key, val) {
if (val.uid == uid) {
found = true;
}
});
return found;
} else {
return found;
}
}
function aggiungiPreferito(uid, nominativo, struttura, email, telefono) {
log("FUNCTION: aggiungiPreferito('" + uid + "', '" + nominativo + "', '" + struttura
+ "', '" + email + "', '" + telefono + "')");
var contatto = {uid: uid, nominativo: nominativo, struttura: struttura, email:
email, telefono: telefono};
var retrievedObject = window.localStorage.getItem("preferitiRubrica");
if (retrievedObject) {
var preferiti = JSON.parse(retrievedObject);
var count = preferiti.length;
preferiti[count] = contatto;
} else {
var preferiti = new Array();
preferiti[0] = contatto;
}
window.localStorage.setItem("preferitiRubrica", JSON.stringify(preferiti));
notify(text["preferitoAggiunto"], label["preferitoAggiunto"], "Ok", "doNothing");
$("#buttonPreferito").html('<a href="#" data-uid="' + uid + '" data-nominativo="' +
nominativo + '" data-struttura="' + struttura + '" data-email="' + email + '" datatelefono="' + telefono + '" data-role="button" data-theme="b" id="rimuoviPreferito"><div
id="rimuoviPreferitoIcon"> </div>Rimuovi dai Preferiti</a>');
$("#rimuoviPreferito").click(function() {
rimuoviPreferito($(this).attr("data-uid"), $(this).attr("data-nominativo"),
$(this).attr("data-struttura"), $(this).attr("data-email"), $(this).attr("data-telefono"));
Anastasia Kokonozi 566/201
Pagina 106 di 117
});
$('#contentContatto').trigger("create");
}
function rimuoviPreferito(uid, nominativo, struttura, email, telefono) {
log("FUNCTION: rimuoviPreferito('" + uid + "', '" + nominativo + "', '" + struttura
+ "', '" + email + "', '" + telefono + "')");
var retrievedObject = window.localStorage.getItem("preferitiRubrica");
var preferiti = JSON.parse(retrievedObject);
var tmpPreferiti = new Array();
var count = 0;
$.each(preferiti, function(key, val) {
if (val.uid != uid) {
tmpPreferiti[count] = val;
count = count + 1;
}
});
window.localStorage.removeItem("preferitiRubrica");
window.localStorage.setItem("preferitiRubrica", JSON.stringify(tmpPreferiti));
notify(text["preferitoRimosso"], label["preferitoRimosso"], "Ok", "doNothing");
$('#buttonPreferito').html('<a href="#" data-uid="' + uid + '" data-nominativo="' +
nominativo + '" data-struttura="' + struttura + '" data-email="' + email + '" datatelefono="' + telefono + '" data-role="button" data-theme="b" id="aggiungiPreferito"><div
id="aggiungiPreferitoIcon"> </div>Aggiungi ai Preferiti</a>');
$("#aggiungiPreferito").click(function() {
aggiungiPreferito($(this).attr("data-uid"), $(this).attr("data-nominativo"),
$(this).attr("data-struttura"), $(this).attr("data-email"), $(this).attr("data-telefono"));
});
$('#contentContatto').trigger("create");
}
function aggiungiCronologia(uid, nominativo, struttura, email, telefono) {
log("FUNCTION: aggiungiCronologia('" + uid + "', '" + nominativo + "', '" +
struttura + "', '" + email + "', '" + telefono + "')");
if (searchCronologia(uid)) {
return;
}
var contatto = {uid: uid, nominativo: nominativo, struttura: struttura, email:
email, telefono: telefono};
var retrievedObject = window.localStorage.getItem("cronologiaRubrica");
if (retrievedObject) {
var cronologia = JSON.parse(retrievedObject);
var count = cronologia.length;
if (count < 20) {
cronologia[count] = contatto;
} else {
var tmpCronologia = new Array();
for (var i=0; i < 20; i++) {
if (i<19) {
tmpCronologia[i] = cronologia[i+1];
} else {
tmpCronologia[i] = contatto;
}
}
cronologia = tmpCronologia;
}
} else {
var cronologia = new Array();
cronologia[0] = contatto;
}
window.localStorage.setItem("cronologiaRubrica", JSON.stringify(cronologia));
}
Anastasia Kokonozi 566/201
Pagina 107 di 117
chiamata.html (pagina contente la maschera per effettuare una chiamata)
<div data-role="dialog" data-close-btn="none" id="chiamata">
<div data-role="header" data-theme="b">
<h1> </h1>
</div>
<div data-role="content" id="contentChiamata">
<p><div id="contentChiamataNominativo" align="center"></div></p>
<p><div id="contentChiamataNumero" align="center"></div></p>
<p> </p>
<a href="#" id="chiamataTelefono" data-role="button" datatheme="b">Chiama</a>
<a href="#" id="chiamataSkype" data-role="button" data-theme="b">Chiama con
Skype</a>
<p> </p>
<a href="#" onclick='$("#chiamata").dialog("close");' data-role="button"
data-theme="c">Chiudi</a>
</div>
</div>
chiamata.js
(javascript associato alla pagina per effettuare una chiamata)
$(document).delegate("#chiamata", "pagebeforeshow", function(e,data) {
$("#contentChiamataNominativo").html("<h2>" + dialogNominativo + "</h2>");
$("#contentChiamataNumero").html("<h3>" + dialogNumero + "</h3>");
$("#chiamataTelefono").attr("href", "tel:+39" + dialogNumero);
$("#chiamataSkype").attr("href", "skype:+39" + dialogNumero + "?call");
});
mappa.html (pagina contente la mappa associata al contatto)
<div data-role="page" id="mappa">
<div data-role="header" data-position="fixed" data-theme="b" id="headerMappa">
<div id="headerLeftMappa">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
<div id="headerRightMappa">
<a href="#" onclick="refreshToPage('contatto')"><img
src="../img/icons/backward.png" /></a>
</div>
</div>
<div data-role="content" id="contentMappa" style="padding: 0 !important">
<div id="map_canvas"></div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b" id="footerMappa">
<div data-role="navbar">
<ul>
<li><div><a href="#"
onclick="refreshToPage('rubrica');">Cerca</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('preferiti');">Preferiti</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('cronologia');">Cronologia</a></div></li>
</ul>
Anastasia Kokonozi 566/201
Pagina 108 di 117
</div>
</div>
</div>
mappa.js (javascript associato alla pagina contente la mappa del contatto)
$(document).delegate("#mappa", "pageshow", function(e,data) {
showLoader();
caricaMappa();
});
function caricaMappa() {
var myLatlng = new google.maps.LatLng(40.83965,14.18851);
var myOptions = {
zoom: 14,
mapTypeControl: false,
streetViewControl: false,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.SMALL
},
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
aggiungiMarker(40.83965,14.18851,'<strong>Polo delle Scienze e
Tecnologie<br/>Scienze MM.FF.NN.');
google.maps.event.addListenerOnce(map, 'idle', function(){
hideLoader();
});
}
function aggiungiMarker(parallelo, meridiano, html) {
var mPos=new google.maps.LatLng(parallelo, meridiano);
var marker = new google.maps.Marker({map: map, position: mPos});
var infowindow = new google.maps.InfoWindow();
infowindow.setContent(html);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
}
cronologia.html (pagina contente la cronologia di ricerca)
<div data-role="page" id="cronologia">
<div data-role="header" data-position="fixed" data-theme="b" id="headerCronologia">
<div id="headerLeftCronologia">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
<div id="headerRightCronologia">
<a href="#" onclick="svuotaCronologia();"><img
src="../img/icons/cestino.png" /></a>
</div>
</div>
Anastasia Kokonozi 566/201
Pagina 109 di 117
<div data-role="content" id="contentCronologia">
<ul data-role="listview" id="contentCronologiaUL"></ul>
<input type="hidden" id="uidCronologia" value="" />
<input type="hidden" id="nominativoCronologia" value="" />
<input type="hidden" id="nominativoCronologia" value="" />
<input type="hidden" id="emailCronologia" value="" />
<div id="noCronologia" align="center">
Non hai ancora cercato nessun contatto
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b" id="footerCronologia">
<div data-role="navbar">
<ul>
<li><div><a href="#"
onclick="refreshToPage('rubrica');">Cerca</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('preferiti');">Preferiti</a></div></li>
<li><div><a href="#" class="ui-btn-active ui-statepersist">Cronologia</a></div></li>
</ul>
</div>
</div>
</div>
cronologia.js (javascript associato alla pagina contente la cronologia di ricerca)
$(document).delegate("#cronologia", "pagebeforeshow", function(e,data) {
var cronologia = getCronologia();
if (cronologia != false) {
caricaCronologia(cronologia);
} else {
$('#contentCronologiaUL').remove();
$('#uidCronologia').remove();
$('#noCronologia').show();
}
});
function getCronologia() {
if (window.localStorage.getItem("cronologiaRubrica")) {
return JSON.parse(window.localStorage.getItem("cronologiaRubrica"));
} else {
return false;
}
}
jQuery.fn.reverse = [].reverse;
function caricaCronologia(cronologia) {
var html = "";
var count = cronologia.length - 1;
cronologia = cronologia.reverse();
$.each(cronologia, function(key, val) {
html = html + '<li class="contacts" data-uid="' + val.uid + '" datanominativo="' + val.nominativo + '" data-struttura="' + val.struttura + '" data-email="' +
val.email + '" data-telefono="' + val.telefono + '"><a href="#"
onclick="refreshToPage(\'contatto\');"><h3>' + val.nominativo + '</h3><p>' + val.struttura
+ '<br/>EMAIL: ' + val.email + '<br/>TELEFONO: ' + val.telefono + '</p></a></li>';
if (key == count) {
$("#contentCronologiaUL").html(html);
$("#contentCronologiaUL").listview("refresh");
$("#contentCronologiaUL").trigger("updatelayout");
}
$(".contacts").click(function(e) {
$("#uidCronologia").val($(this).attr("data-uid"));
$("#nominativoCronologia").val($(this).attr("data-nominativo"));
Anastasia Kokonozi 566/201
Pagina 110 di 117
$("#strutturaCronologia").val($(this).attr("data-struttura"));
$("#emailCronologia").val($(this).attr("data-email"));
$("#telefonoCronologia").val($(this).attr("data-telefono"));
});
});
}
function svuotaCronologia() {
if (window.localStorage.getItem("cronologiaRubrica")) {
notify(text["svuotaCronologia"], label["attenzione"], "Ok",
"clearCronologia", "Annulla", "doNothing");
}
}
function clearCronologia() {
window.localStorage.removeItem("cronologiaRubrica");
$('#contentCronologiaUL').remove();
$('#uidCronologia').remove();
$('#nominativoCronologia').remove();
$('#strutturaCronologia').remove();
$('#emailCronologia').remove();
$("#telefonoCronologia").remove();
$('#noCronologia').show();
}
preferiti.html (pagina contente la lista dei preferiti)
<div data-role="page" id="preferiti">
<div data-role="header" data-position="fixed" data-theme="b" id="headerPreferiti">
<div id="headerLeftPreferiti">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
<div id="headerRightPreferiti">
<a href="#" onclick="svuotaPreferiti();"><img
src="../img/icons/cestino.png" /></a>
</div>
</div>
<div data-role="content" id="contentPreferiti">
<ul data-role="listview" id="contentPreferitiUL"></ul>
<input type="hidden" id="uidPreferiti" value="" />
<input type="hidden" id="nominativoPreferiti" value="" />
<input type="hidden" id="strutturaPreferiti" value="" />
<input type="hidden" id="emailPreferiti" value="" />
<div id="noPreferiti" align="center">
Non hai ancora aggiunto nessun contatto ai preferiti
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b" id="footerPreferiti">
<div data-role="navbar">
<ul>
<li><div><a href="#"
onclick="refreshToPage('rubrica');">Cerca</a></div></li>
<li><div><a href="#" class="ui-btn-active ui-statepersist">Preferiti</a></div></li>
<li><div><a href="#"
onclick="refreshToPage('cronologia');">Cronologia</a></div></li>
</ul>
</div>
</div>
</div>
Anastasia Kokonozi 566/201
Pagina 111 di 117
preferiti.js (javascript associato alla pagina contente la lista dei preferiti)
$(document).delegate("#preferiti", "pagebeforeshow", function(e,data) {
var preferiti = getPreferiti();
if (preferiti != false) {
caricaPreferiti(preferiti);
} else {
$('#contentPreferitiUL').remove();
$('#uidPreferiti').remove();
$('#noPreferiti').show();
}
});
function getPreferiti() {
if (window.localStorage.getItem("preferitiRubrica")) {
return JSON.parse(window.localStorage.getItem("preferitiRubrica"));
} else {
return false;
}
}
function caricaPreferiti(preferiti) {
var html = "";
var count = preferiti.length - 1;
$.each(preferiti, function(key, val) {
html = html + '<li class="contacts" data-uid="' + val.uid + '" datanominativo="' + val.nominativo + '" data-struttura="' + val.struttura + '" data-email="' +
val.email + '" data-telefono="' + val.telefono + '"><a href="#"
onclick="refreshToPage(\'contatto\');"><h3>' + val.nominativo + '</h3><p>' + val.struttura
+ '<br/>EMAIL: ' + val.email + '<br/>TELEFONO: '+ val.telefono + '</p></a></li>';
if (key == count) {
$("#contentPreferitiUL").html(html);
$("#contentPreferitiUL").listview("refresh");
$("#contentPreferitiUL").trigger("updatelayout");
}
$(".contacts").click(function(e) {
$("#uidPreferiti").val($(this).attr("data-uid"));
$("#nominativoPreferiti").val($(this).attr("data-nominativo"));
$("#strutturaPreferiti").val($(this).attr("data-struttura"));
$("#emailPreferiti").val($(this).attr("data-email"));
$("#telefonoPreferiti").val($(this).attr("data-telefono"));
});
});
}
function svuotaPreferiti() {
if (window.localStorage.getItem("preferitiRubrica")) {
notify(text["svuotaPreferiti"], label["attenzione"], "Ok", "clearPreferiti",
"Annulla", "doNothing");
}
}
function clearPreferiti() {
window.localStorage.removeItem("preferitiRubrica");
$('#contentPreferitiUL').remove();
$('#uidPreferiti').remove();
$('#nominativoPreferiti').remove();
$('#strutturaPreferiti').remove();
$('#emailPreferiti').remove();
$("#telefonoPreferiti").remove();
$('#noPreferiti').show();
}
Anastasia Kokonozi 566/201
Pagina 112 di 117
login.html (pagina contente la maschera per la login)
<div data-role="page" id="login">
<div data-role="header" data-position="fixed" data-theme="b" id="headerLogin">
<div id="headerLeftLogin">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
</div>
<div data-role="content" id="contentLogin">
<div data-role="fieldcontain">
<p>
<div id="usernameLabel">Username:</div>
<input type="text" name="usernameLogin" id="usernameLogin"
value="" />
</p>
<p>
<div id="passwordLabel">Password:</div>
<input type="password" name="passwordLogin"
id="passwordLogin" value="" />
</p>
</div>
<div id="buttonsLogin">
<a href="#" data-role="button" data-theme="b" data-icon="gear" datainline="true" data-iconpos="right" id="submitLogin">Login</a>
</div>
<div id="loghiLogin">
<div id="logoCsiLogin">
<img src="../img/logo_csi.gif" />
</div>
<div id="logoUninaLogin">
<img src="../img/logo_unina.gif" />
</div>
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b" id="footerLogin"></div>
</div>
login.js (javascript associato alla pagina contente la maschera per la login)
$(document).delegate("#login", "pagebeforeshow", function(e,data) {
$("#submitLogin").click(function(e) {
checkLogin();
});
});
function checkLogin() {
log("FUNCTION: checkLogin()");
showLoader();
$.ajax({
type: "GET",
url: urls['login'],
data: 'uid=' + $('#usernameLogin').val() + '&password=' + $
('#passwordLogin').val(),
dataType: "json",
success: function(data) {
hideLoader();
if (data.error) {
Anastasia Kokonozi 566/201
Pagina 113 di 117
notify(error["datiErrati"], "Attenzione!", "Ok", "doNothing");
} else {
slideToPage("areaPrivata");
}
},
error: function() {
hideLoader();
notify(error["network"], "Attenzione!", "Riprova", "checkLogin",
"Annulla", "doNothing");
}
});
}
areaPrivata.html (pagina riservata all'area privata, non implementata)
<div data-role="page" id="areaPrivata" data-dom-cache="true">
<div data-role="header" data-position="fixed" data-theme="b" id="headerAreaPrivata">
<div id="headerLeftAreaPrivata">
<a href="#" onclick="slideToPage('index');"><img
src="../img/icons/home.png" /></a>
</div>
<div><h1>Rubrica Unina</h1></div>
</div>
<div data-role="content" id="contentAreaPrivata" align="center">
<div id="contentAreaPrivataInner">
Area privata
<img src="../img/areaPrivata.png"/>
</div>
</div>
<div data-role="footer" data-position="fixed" data-theme="b"
id="footerAreaPrivata"></div>
</div>
library.js
(insieme di funzioni comuni, utilizzate in diversi punti dell'applicazione)
function checkConnection() {
log("FUNCTION: checkConnection()");
return navigator.connection.type;
}
function manageBackButton() {
log("FUNCTION: manageBackButton()");
if ($.mobile.activePage.attr('id') == "main") {
notify(text['exit'], 'Attenzione!', 'Ok', 'closeApp', 'Annulla',
'doNothing');
}
}
function slideToPage(page) {
log("FUNCTION: slideToPage('" + page + "')");
if (!loading) {
$.mobile.changePage(page + ".html", {showLoadMsg: false, transition:
"none"});
}
}
function refreshToPage(page) {
log("FUNCTION: refreshToPage('" + page + "')");
Anastasia Kokonozi 566/201
Pagina 114 di 117
if (!loading) {
$.mobile.changePage(page + ".html", {reloadPage: true, transition: "none"});
}
}
function showSpinner() {
log("FUNCTION: showSpinner()");
$.mobile.showPageLoadingMsg();
}
function hideSpinner() {
log("FUNCTION: hideSpinner()");
$.mobile.hidePageLoadingMsg();
}
function showLoader() {
log("FUNCTION: showLoader()");
loading = true;
$.mobile.showPageLoadingMsg("a", "Caricamento in corso ...", false);
}
function hideLoader() {
log("FUNCTION: hideLoader()");
$.mobile.hidePageLoadingMsg();
loading = false;
}
function doNothing() {
log("FUNCTION: doNothing()");
}
function closeApp() {
log("FUNCTION: closeApp()");
navigator.app.exitApp();
}
function notify(msg, label, button1, method1, button2, method2) {
log("FUNCTION: notify(" + msg + ", " + label + ", " + button1 + ", " + method1 + ",
" + button2 + ", " + method2 + ")");
if (msg == null || msg == undefined) {
msg = "Siamo spiacenti si è verificato un errore!";
}
if (button2 != null) {
if (method2 == null) {
method2 = "doNothing";
}
buttons = button1 + "," + button2;
navigator.notification.confirm(
msg,
function(buttonIndex) {
if (buttonIndex == 1) {
notifyCallback(method1);
} else {
notifyCallback(method2);
}
},
label,
buttons
);
} else {
navigator.notification.confirm(
msg,
function() {
notifyCallback(method1);
},
label,
button1
);
}
}
Anastasia Kokonozi 566/201
Pagina 115 di 117
function notifyCallback(method) {
eval(method)();
}
function log(msg) {
if (development) {
console.log(msg);
}
}
Anastasia Kokonozi 566/201
Pagina 116 di 117
Bibliografia
•
Android, Portale Android per gli sviluppatori
◦ http://developer.android.com/index.html
•
Android, Guida allo sviluppo
◦ http://developer.android.com/guide/index.html
•
Android, Pubblicazione su Google Play
◦ http://developer.android.com/guide/publishing/publishing.html
•
Forum HTML.IT, guide e forum di supporto per sviluppatori
◦ http://www.html.it
•
JQuery, JQuery Mobile
◦ http://www.jquerymobile.com/
•
PhoneGap
◦ http://www.phonegap.com
•
PhoneGap, gruppo di supporto per gli sviluppatori
◦ https://groups.google.com/forum/?fromgroups#!forum/phonegap
•
Autori Vari, Wikipedia
◦ http://www.wikipedia.it
•
Autori Vari, StackOverflow
◦ http://www.stackoverflow.com
Anastasia Kokonozi 566/201
Pagina 117 di 117