UNIVERSITÀ DEGLI STUDI DEL SANNIO

UNIVERSITÀ DEGLI STUDI DEL SANNIO
FACOLTÀ DI INGEGNERIA
CORSO DI LAUREA IN INGEGNERIA INFORMATICA
TESI DI LAUREA
IN
TECNOLOGIE DI PRODUZIONE DEL SOFTWARE
STUDIO DI UN FRAMEWORK
APPLICATIVO MULTIPIATTAFORMA
PER AMBIENTI MOBILE
RELATORE:
Prof. Luigi Troiano
CANDIDATO:
Umberto Russo
Matr. 195/001063
CORRELATORE:
Dott. Maria Carmela Vitelli
ANNO ACCADEMICO 2012/2013
A i miei genitori...
Sommario
Indice delle Figure .................................................................... 6
Indice delle Tabelle .................................................................. 7
CAPITOLO 1
INTRODUZIONE ....................................................................... 8
1.1 Organizzazione del lavoro ................................................ 10
CAPITOLO 2
LE APPLICAZIONI IN AMBITO MOBILE ................................... 12
2.1 Panoramica sui sistemi operativi mobile........................... 12
2.2 Sviluppo di un'app in ambienti nativi ............................... 16
2.3 Ambienti: Android, iOS e Windows Phone ........................ 18
2.4 Realizzazione di un'app attraverso un framework
multipiattaforma ................................................................. 27
CAPITOLO 3
PHONEGAP ............................................................................ 29
3.1 Scegliere un buon framework .......................................... 29
3.2 Caretteristiche di PhoneGap ............................................ 32
3.3 Architettura di PhoneGap e il suo modello di
programmazione .................................................................. 37
3.4 Linguaggi di programmazione utilizzati e la loro relazione
con PhoneGap ..................................................................... 42
3.5 jQuery Mobile: un framework nel framework .................... 50
4
CAPITOLO 4
PORTING DI UN'APPLICAZIONE ............................................. 57
4.1 Interfaccia grafica e navigazione tra le pagine ................... 58
4.2 Persistenza dei dati ......................................................... 67
4.3 Accesso alle API native con PhoneGap.............................. 70
4.4 Interazione con un web server ......................................... 85
CAPITOLO 5
CONCLUSIONI E SVILUPPI FUTURI ....................................... 93
Appendice ............................................................................... 97
BIBLIOGRAFIA ....................................................................... 108
5
Indice delle Figure
Figura 1: Build Emulation Flow Android ............................. 20
Figura 2: Layers of iOS ....................................................... 22
Figura 3: Condivisione API Window 8 e Windows Phone 8 .. 24
Figura 4: Architettura Windows Phone 8 ............................ 26
Figura 5: Unificazione delle piattaforme Windows 8 ............ 26
Figura 6: PhoneGap Build Diagram .................................... 36
Figura 7: Architettura PhoneGap ........................................ 39
6
Indice delle Tabelle
Tabella 1: Funzioni supportate da PhoneGap per i diversi OS
Mobile parte 1 ..................................................................... 34
Tabella 2: Funzioni supportate da PhoneGap per i diversi OS
Mobile parte 2 ..................................................................... 34
Tabella 3: Tabella delle affinità Sqlite3 ................................ 55
7
CAPITOLO 1
INTRODUZIONE
Sono passati solo pochi anni dall'introduzione sul mercato di dispositivi
mobili quali smartphone e tablet, ed è incredibile come questi hanno
rivoluzionato il modo di vivere delle persone, oggi è quasi indispensabile
potersi connettere ad internet tramite il proprio smartphone per poter
usufruire della miriade di servizi atti a fornire un insieme sempre più
organizzato di informazioni. Parallelamente allo sviluppo hardware, come
sempre accade, il mondo del software ha dovuto reinventarsi per
approcciare ad un mercato in crescita esponenziale, giganti dell' IT come
Google e Apple hanno rivoluzionato il concetto di "cellulare" a tal punto da
da domandarsi quale potrà mai essere lo step successivo.
Attualmente esistono milioni di applicazioni mobile, la maggior parte per
ambienti Android e iOS, ma si contano almeno una decina di sistemi
operativi mobile con caratteristiche diverse. Questo si traduce, per lo
sviluppo di applicazioni, nell'utilizzo di innumerevoli strumenti di sviluppo
diversi fra loro e un dispendio notevole di risorse atti a garantire il
funzionamento delle medesima applicazione sulla maggior parte di questi
sistemi operativi.
8
Esistono però delle alternative: infatti, tramite l'utilizzo di opportuni
framework applicativi si può risparmiare tempo, risorse e garantire la
compatibilità dell'applicazione su diversi sistemi mobile.
Lo scopo della seguente tesi è quello di valutare le attuali tecniche di
sviluppo di applicativi mobile e confrontarle con l'uso alternativo di
framework cross-platform, per comprendere se allo stato attuale è possibile
realizzare applicazioni di qualità con un approccio multipiattaforma in
grado di competere con lo sviluppo in ambienti nativi.
Il vantaggio principale che spinge alla realizzazione di framework per
ambienti mobile è certamente l'approccio cross-platform, il quale garantisce
un notevole risparmio di risorse sia nella fase di progettazione che di
sviluppo. Questo tipo di approccio è stato già brillantemente adoperato in
passato, per esempio dalla Sun Microsystem, la quale ha prodotto il
linguaggio di programmazione orientato agli oggetti Java, attualmente uno
dei più utilizzati al mondo .
9
1.1 Organizzazione del lavoro
Il presente lavoro propone lo studio e lo sviluppo di un applicativo
multipiattaforma mobile, mediante il porting di un' applicazione già
esistente in ambiente Android.
Utilizzando il framework PhoneGap sarà possibile evidenziare le tecniche
necessarie per il conseguimento dello scopo e valutare le eventuali
alternative.
Nel Capitolo 2 viene proposta una panoramica sull'ambiente mobile,
vengono presi in considerazione gli attuali sistemi operativi più importanti
e ne vengono delineate le differenze in termini di progettazione e sviluppo
di software. Vengono presentati, inoltre, gli aspetti peculiari dello sviluppo
in ambienti nativi e attraverso i diversi framework multipiattaforma oggi
disponibili.
Nel Capitolo 3 verrà presentato PhoneGap un framework cross-platform
mobile realizzato dalla software house statunitense Adobe System, che
consente di sviluppare delle applicazioni native attraverso l'utilizzo di
tecnologie web quali HTML5 , CSS3 e JavaScript.
10
Nel Capitolo 4 viene concretizzata l'attività di analisi con la descrizione
del lavoro svolto per realizzare il porting di un applicativo già esistente,
progettato per l'ambiente Android, attraverso l'uso di PhoneGap.
Infine nel Capitolo 5 confrontando l'applicazione nativa con quella ottenuta
attraverso il porting, sarà possibile comprendere i diversi comportamenti
dovuti a modelli di programmazione differenti. Evidenziando, per
concludere, vantaggi e svantaggi offerti dall'utilizzo di un framework
multipiattaforma rispetto alle tradizionali tecniche si sviluppo in ambienti
mobile.
11
CAPITOLO 2
LE APPLICAZIONI IN AMBITO MOBILE
Un'applicazione per dispositivi mobili si differenzia da quelle tradizionali
sia per il supporto con cui viene usata sia per la concezione che racchiude
in sé.
Generalmente questo tipo di applicazioni vengono definite anche "App",
poiché rispetto ad un'applicazione classica risultano più semplici e leggere
ed hanno il compito di ampliare le capacità native del dispositivo su cui
vengono installate. Negli ultimi anni però il mondo delle app è diventato
sempre più complesso e la semplicità che caratterizzava le applicazioni
mobile sta lasciando il posto a software più articolati, complice anche la
repentina evoluzione hardware dei dispositivi quali smartphone e tablet.
2.1 Panoramica sui sistemi operativi mobile
Un sistema operativo mobile, detto anche "mobile OS", controlla un
dispositivo mobile con lo stesso principio con cui i sistemi operativi
desktop controllano un PC o un Laptop.
12
La maggior parte delle problematiche affrontate da un sistema operativo
mobile sono le stesse della controparte desktop: ossia la gestione della
memoria RAM, l'utilizzo della CPU da parte dei processi attivi, la gestione
di un file system ecc. In più, hanno il difficile compito di gestire fattori non
presenti in ambienti desktop, come ad esempio: la gestione limitata delle
risorse, l'assenza di alimentazione esterna, differenti tecnologie per
l'accesso ad internet (WiFi, GPRS, HSDPA), nuovi metodi di immissione
testuale ecc.
Inoltre non bisogna dimenticare che uno smartphone è principalmente un
telefono, un mezzo di comunicazione e quindi un OS mobile deve poter
gestire anche questa fondamentale funzionalità.
Una delle prime aziende informatiche a lavorare su sistemi operativi
mobile più evoluti è stata la Microsoft Corporation, la quale nel 2005 lancia
Windows Mobile 5. Successivamente nel 2007 Apple rivoluziona il mondo
degli smartphone proponendo il suo sistema operativo mobile iOS (anche
se inizialmente era chiamato iPhone OS), mentre l'anno successivo nel
2008 Google lancia la prima versione di Android.
Di seguito una lista dei principali sistemi operativi mobile, che attualmente
sono presenti sul mercato ed equipaggiano smartphone ed alcuni tablet.
13
iOS: sviluppato da Apple a partire dal 2007, caratterizzato da un kernel1
ibrido XNU basato su kernel Mach e FreeBSD, il modello del sorgente è
proprietario anche se il nucleo Darwin è open source, è disponibile un SDK
per lo sviluppo di app attraverso Xcode, attualmente è uno dei principali
OS mobile.
Android: sviluppato da Google a partire dal 2008 caratterizzato da un
kernel linux monolitico, il modello del sorgente è completamente open
source infatti è possibile trovare diverse varianti del sistema operativo
sviluppate da appassionati, è disponibile un SDK per lo sviluppo di app
attraverso Eclipse che comunque non rappresenta l'unico metodo per
sviluppare in ambiente Android. Insieme ad iOS attualmente è uno dei
principali OS mobile.
Windows Phone: sviluppato da Microsoft Corporation a partire dal 2010
caratterizzato da un kernel Windows NT / Windows CE, il modello del
sorgente è completamente proprietario, è disponibile un SDK per lo
sviluppo di app attraverso Microsoft Visual Studio 2010 Express, anche se
non è diffuso come Android e iOS rappresenta comunque un sistema
operativo mobile presente in un ampia fetta di mercato.
1
Il kernel costituisce il nucleo di un sistema operativo, fornisce ai processi in esecuzione un accesso
sicuro e controllato all'hardware.
14
BlackBerry: sviluppato da Research In Motion a partire dal 2002
caratterizzato da un kernel sviluppato in C++ con la presenza di un livello
di astrazione che permette l'utilizzo di librerie scritte in java, il modello del
sorgente è completamente proprietario ed è disponibile un SDK nativo per
lo sviluppo di app in C/C++, anche se è possibile utilizzare altre tipi di
linguaggi di programmazione.
Open WebOS: sviluppato da Palm dal 2009 e successivamente acquistato
da Hewlett-Packard, è caratterizzato da un kernel Linux monolitico, il
modello del sorgente è proprietario con alcune parti open source, è
disponibile un SDK per lo sviluppo di app attraverso vari linguaggi di
programmazione tra cui C/C++.
Symbian OS: sviluppato da Symbian Foundation a partire dal 2001,
caratterizzato da un kernel del tipo Microkernel , ha un modello di sorgente
libero, fino ad oggi ha equipaggiato quasi esclusivamente dispositivi nokia
ed ormai il suo stato di sviluppo è concluso, è disponibile un SDK per lo
sviluppo di app in un dialetto del C++ chiamato Symbian C++.
Bada: sviluppato da Samsung dal 2010, caratterizzato da un kernel ibrido
RTOS / Free BSD Kernel / Linux kernel, ha un modello di sorgente misto
alcune parti sono open source, altre proprietarie o libere, è disponibile un
15
SDK per lo sviluppo di app in C++ mediante l'ambiente di sviluppo
Eclipse.
Nei prossimi paragrafi e capitoli per lo scopo che si prefigge il presente
lavoro di tesi, verranno presi in considerazione i sistemi operativi più
diffusi nell'attuale mercato mobile ossia Android [1], iOS [2] e Windows
Phone [3].
2.2 Sviluppo di un'app in ambienti nativi
Sviluppare un applicativo mobile in ambienti nativi vuol dire utilizzare una
serie di strumenti messi a disposizione dell'azienda produttrice del sistema
operativo, tra cui l'importantissimo SDK 2 e la documentazione ad esso
associata.
Non tutti gli SDK sono uguali in termini di componenti, i quali formano
l'ambiente di sviluppo. Infatti gli strumenti solitamente messi a
disposizione per gli sviluppatori sono: un compilatore, che dà la possibilità
di tradurre il codice sorgente in un eseguibile, una serie di librerie standard
dotate di interfacce pubbliche, tecnicamente definite API
3
e la
2
Software Development Kit, insieme di tools messi a disposizione dal produttore di un sistema operativo
per realizzare un software in un determinato ambiente.
3
Acronimo di Application Programming Interface, insieme di procedure disponibili al programmatore
raggruppate a formare un insieme di strumenti specifici per eseguire un determinato compito.
16
documentazione sulle licenze da utilizzare per distribuire programmi creati
con l'SDK.
Questi componenti di base possono essere estesi con strumenti di vario tipo
come: compilatori per diversi linguaggi di programmazione, IDE 4 molto
avanzati e simulatori che permettono di simulare i dispositivi mobili.
Molti SDK sono disponibili gratuitamente mentre altri vengono distribuiti
attraverso l'uso di licenze commerciali, questo panorama così ampio
permette di comprendere come la giusta scelta di sviluppo in ambienti
specifici sia di peculiare importanza, poiché l'utilizzo di più kit di sviluppo
richiede un cospicuo utilizzo di risorse.
A complicare maggiormente lo sviluppo in ambienti nativi è l'utilizzo dei
più disparati linguaggi di programmazione; si passa dai più diffusi C/C++ a
dialetti degli stessi, da linguaggi orientati al web come JavaScript a
tecnologie più datate come J2ME.
Nel caso di studio riguardante questo lavoro gli ambienti di sviluppo
analizzati riguardano i sistemi operativi Android, iOS e Windows Phone, di
cui segue una trattazione.
4
Integrated Development Environment, ambiente di sviluppo integrato che aiuta i programmatori nello
sviluppo del codice sorgente di un programma.
17
2.3 Ambienti: Android, iOS e Windows Phone
Android
Le applicazioni in ambiente Android sono sviluppate all'interno di un
framework5, ossia una struttura dati specifica. Solitamente viene utilizzato
come ambiente di sviluppo integrato Eclipse, il quale attraverso l'uso di
plug-in può estendere le sue funzionalità e integrare completamente tutte le
caratteristiche del SDK Android.
Le applicazioni Android sono caratterizzate da una certa dualità: da un lato,
si trovano le parti dinamiche (sviluppate in un dialetto del linguaggio Java)
che costituiscono l'applicazione mobile, come la gestione degli eventi.
Dall'altro si trovano le parti statiche, ad esempio alcuni elementi delle
interfacce, queste vengono scritte in XML6. Questa suddivisione tra parti
dinamiche e statiche rappresenta in realtà un'astrazione, utile comunque per
comprendere il modello di programmazione generale su cui si basa lo
sviluppo per il sistema operativo Android. In effetti le applicazioni
realizzate per questo SO vengono interpretate dalla Dalvik Virtual Machine
in modo molto simile a ciò che avviene in ambienti Java con la Java Virtual
Machine.
5
Un framework è una struttura logica di supporto su cui un software può essere progettato è realizzato.
eXtensible Markup Language, linguaggio di markup basato su un meccanismo sintattico che consente di
definire e controllare il significato degli elementi contenuti in un documento o in un testo.
6
18
Quando si compila un sorgente scritto in dialetto Java per Android il
compilatore produce un codice che potremmo definire "intermedio"
chiamato Bytecode; quest'ultimo viene interpretato dalla Dalvik Virtual
Machine e solo a questo punto si ha la reale esecuzione dell'applicazione.
Questo approccio, ovviamente ripreso da ciò che avviene già in ambienti
Java, è molto interessante poiché permette di eseguire un'applicazione su
ogni dispositivo Android anche con architetture hardware diverse. Per ogni
dispositivo esiste una versione specifica della Dalvik Virtual Machine in
grado di interpretare nel medesimo modo la stessa applicazione, che
ovviamente viene scritta e compilata in bytecode solo una volta.
In questo modo la filosofia "write once run everywhere" coniata dalla Sun
Microsystem viene, in modo più limitato, adottata anche dall'ambiente
Android estendendo la portabilità del codice su architetture hardware
diverse fra loro. Come risultato di questa idea, molti costruttori hanno
deciso di adottare come sistema operativo mobile Android, potendo cosi
fornire ai propri utenti un ambiente condiviso da moltissimi altri utenti.
Un altro elemento che compone un'applicazione Android è il file
"Manifest.xml", un documento scritto in XML che descrive l'applicazione
al dispositivo prescelto definendo i contenuti e il comportamento
dell'applicazione stessa. All'interno di questo file sono elencate le Activity
e i Service con i permessi che l'applicazione necessita per funzionare
correttamente. Infine uno strumento di fondamentale importanza completa
19
il kit di sviluppo Android: l'emulatore. Esso permette di emulare diversi
dispositivi e versioni di Android dando così la possibilità allo sviluppatore
di eseguire accurate sessioni di debug.
Figura 1: Build Emulation Flow Android
iOS
Il sistema operativo iOS di Apple usa una variante del kernel "XNU
Kernel" utilizzato nell' OS per ambienti desktop "Mac OS X", ed è per
questo motivo che il pacchetto SDK messo a disposizione dalla Apple per
lo sviluppo di applicazioni mobile è molto simile, in termini di risorse
disponibili, alla controparte desktop. L'IDE utilizzato in questo tipo di
ambiente è Xcode, va però specificato che il pacchetto SDK Apple per lo
20
sviluppo di software è compatibile solo ed esclusivamente con ambienti
desktop Apple. Questo di per sè rappresenta già una limitazione in quanto
si rende necessario l'acquisto di una macchina desktop Apple, inoltre la
licenza di iOS non ne permette l'installazione su hardware di terze parti.
Tornando alla descrizione del pacchetto SDK esso comprende:
 Cocoa Touch: un framework per la creazione di interfacce grafiche
utilizzabile per i dispositivi iPhone, iPad e iPod.
 Media: un set di strumenti dedicati alla creazione di contenuti
multimediali come audio e grafica, in particolare sono presenti
librerie come OpenAL e OpenGL ES.
 Core Services: per la gestione di funzionalità più specifiche come la
geolocalizzazione (Core Location), i servizi di rete, la gestione dei
Threads, ecc.
 Core OS: per la gestione di funzionalità caratteristiche del Sistema
Operativo come TCP/IP, Sockets, Power Management, File System,
ecc.
Queste componenti vengono viste come un insieme di livelli attraverso i
quali
iOS implementa le proprie funzionalità, il livello più basso è
rappresentato dal Core OS mentre il livello più alto è il Cocoa Touch.
21
Figura 2: Layers of iOS
Oltre alla Xcode toolchain appena presentata, il pacchetto SDK contiene un
efficiente simulatore di iPhone utilizzato per testare le app prima
dell'effettivo deploy su un reale dispositivo.
Il linguaggio di programmazione necessario per realizzare applicazioni in
ambiente iOS è l'Objective-C , che è un linguaggio orientato agli oggetti e
di fatto rappresenta un'estensione del linguaggio C. Essendo un'estensione,
l'Objective-C, mantiene una compatibilità totale con i costrutti utilizzati nel
linguaggio C.
Anche le applicazioni iOS, come quelle Android, vengono sviluppate
mediante l'utilizzo di un framework tramite il quale è possibile accedere
alle interfacce di sistema. In questo caso il framework è visto come una
22
directory che contiene una serie di librerie dinamiche condivise e risorse a
supporto di tali librerie.
Il compilatore utilizzato per lo sviluppo di app in ambiente iOS si chiama
Apple LLVM Compiler. Quest'ultimo a differenza di Android, dove il
codice prodotto dal compilatore viene successivamente interpretato dalla
DVM, compila il codice Objective-C producendo direttamente un
programma eseguibile. Bisogna precisare infine che il pacchetto SDK di
iOS contiene un simulatore di iPhone, che nonostante sia molto
performante in termini di velocità, non simula tutte le caratteristiche di un
dispositivo reale: per esempio la memoria disponibile sull'emulatore non è
limitata come quella presente su di un dispositivo reale.
Windows Phone
Windows Phone 8 è l'ultima versione del sistema operativo Microsoft
destinato agli smartphone. Questo, rilasciato alla fine del 2012, rappresenta
un ulteriore passo avanti nei progetti di Microsoft stessa.
Bisogna infatti pensare che Microsoft produce anche il famoso sistema
operativo desktop Windows 8 e commercialmente sta tentando di unificare
(dal punto di vista utente) le diverse versioni dei suoi sistemi operativi.
Il pacchetto SDK per lo sviluppo di applicazioni mobile contiene:
23
 Microsoft Visual Studio Express 2012 for Windows Phone: un
IDE molto avanzato per le fasi di progettazione e sviluppo.
 Windows Phone Emulator: un emulatore di dispositivi
Windows Phone versione 8 e 7.
 Microsoft Expression Blend for Windows Phone: un tool di
design per la realizzazione di interfacce grafiche .
 XNA Game Studio: uno strumento basato sul framework
gratuito XNA per lo sviluppo di videogiochi su più piattaforme
come: PC, Xbox 360 e ovviamente Windows Phone.
Windows Phone 8 è basato sul kernel Windows NT lo stesso utilizzato
appunto in Windows 8, questa sorta di unificazione permette lo sviluppo di
applicazioni sia mobile che desktop attraverso l'uso dei linguaggi C++ e
C#.
Figura 3: Condivisione API Windows 8 e Windows Phone 8
24
Le applicazioni Windows Phone 8 condividono alcuni aspetti con il sistema
operativo versione desktop, alcune API e driver models sono condivisi
semplificando la fase di sviluppo se si intende operare negli ambienti
desktop e mobile contemporaneamente.
L'utilizzo del nuovo Kernel NT ridefinisce i diversi livelli dell'architettura
che rispetto alla versione precedente, Windows Phone 7, puntano sempre
di più a costruire una sorta di unificazione nello sviluppo di applicativi
desktop e mobile.
25
Figura 4: Architettura Windows Phone 8
Figura 5: Unificazione delle piattaforme Windows 8
26
2.4
Realizzazione di un'app attraverso un framework
multipiattaforma
Sviluppare un'applicazione mediante un framework cross-platform implica
un approccio differente rispetto alle tecniche tradizionali. La progettazione
dell'applicazione deve tener conto delle diverse caratteristiche dei sistemi
operativi e dell'hardware dei dispositivi. Infatti nel caso di sviluppo in
ambienti nativi, si tende a progettare il software considerando le
funzionalità messe a disposizione da un singola piattaforma. Con
l'approccio cross-platform è necessario valutare insieme le caratteristiche
delle diverse piattaforme su cui verrà rilasciato il software. Se vengono
sfruttate le funzionalità comuni tra più sistemi operativi sarà possibile
mantenere un unica linea di sviluppo. Ad esempio se consideriamo i
dispositivi Android e iOS si può facilmente notare che sulla prima
piattaforma citata i dispositivi dispongono di diversi pulsanti soft touch
(menu, back button, search, ecc. ) mentre nella seconda piattaforma questi
pulsanti sono assenti. Pertanto con un approccio cross-platform, il cui
obiettivo è il deployment 7 sui sistemi sopra citati, non è consigliabile
utilizzare nell'applicazione il pulsante soft touch menu (relativo alla
piattaforma Android), poiché non esiste una funzione equivalente in iOS.
7
Il deployment è una fase del ciclo di vita del software che conclude lo sviluppo e da inizio alla
manutenzione.
27
Questo comporterebbe la nascita di due linee di sviluppo parallele, andando
contro l'idea che sta alla base dell'approccio multipiattaforma.
Un altro aspetto da affrontare riguarda la scelta del framework crossplatform, di cui oggi ne esistono almeno una ventina che si differenziano
per svariati aspetti. Un'attenta trattazione delle caratteristiche necessarie per
un buon framework verrà affrontata nel prossimo capitolo. Di seguito un
elenco dei framework più conosciuti:
 PhoneGap
 Appspresso
 AppFurnace
 Application Craft
 NS Basic/App Studio
 WorkLight
 QuickConnectFamily
 Rhodes
28
CAPITOLO 3
PHONEGAP
PhoneGap è un Framework cross-platform mobile prodotto inizialmente da
Nitobi e successivamente acquistato da Adobe System. Esso consente di
sviluppare delle applicazioni per dispositivi mobili attraverso l'uso delle
tecnologie orientate al web come: HTML5, CSS3 e JavaScript; al posto di
linguaggi specifici per ogni device come l'Objective-C. Il risultato che si
ottiene è un'applicazione ibrida, poiché il rendering del layout avviene
attraverso l'utilizzo delle WebView presenti in modo nativo all'interno delle
User Interface dei diversi Sistemi Operativi Mobile. Le caratteristiche
ibride riguardano anche il lato back-end
8
dell'applicazione; poiché
quest'ultima non è soltanto una web app, essa ha accesso alle API native
del dispositivo. Questa caratteristica non è presente nelle applicazioni
esclusivamente web based.
3.1 Scegliere un buon framework
La scelta di un buon framework multipiattaforma per lo sviluppo di
applicazioni mobile è di fondamentale importanza. Nelle fasi che
8
Il back-end rappresenta la parte software che elabora i dati generati dal front-end, che a sua volta è la
parte software che gestisce l'interazione con l'utente.
29
caratterizzano la realizzazione di un software, in generale analisi,
progettazione, implementazione e collaudo, risulta conveniente utilizzare
strumenti che agevolano le varie fasi.
Tutto questo si traduce in un notevole risparmio di risorse e tempo, inoltre
un framework di qualità si riconosce anche dalla notorietà della software
house che lo produce. Nel caso di PhoneGap parliamo di Adobe System,
un'azienda presente sul mercato da diversi anni è che ha sempre realizzato
prodotti di successo.
Bisogna poi ricordare che un framework multipiattaforma permette
l'accesso alle API native dell'ambiente mobile specifico, e non tutti i
framework esistenti supportano tutte le funzionalità messe a disposizione
delle diverse API.
Un'altra caratteristica da notare riguarda le tempistiche di rilascio delle
nuove versioni di un determinato framework. Rilasci relativamente
frequenti danno l'opportunità di comprendere che il framework in questione
è seguito ed utilizzato da molti e per tanto raggiunge fasi di sviluppo
avanzate che permettono l'implementazione di funzionalità sempre più
complete.
La possibilità di espandere le caratteristiche di un framework è un altro
punto a favore, poiché i progetti software più importanti sono sempre
accompagnati da folte community di appassionati. Queste ultime
30
sviluppano plug-in di terze parti e creano un'ampia documentazione a
corredo di tali estensioni.
Infine bisogna sempre pensare quale sarà l'obiettivo da raggiungere con lo
sviluppo di un'applicazione mobile. Esistono progetti open source e
commerciali che richiedono attenzioni differenti per la successiva fase di
distribuzione. Per quanto riguarda i progetti commerciali, il cui obiettivo è
la monetizzazione, l'uso di licenze adatte allo scopo è fondamentale.
Se non si desidera investire in strumenti per lo sviluppo che adottano a loro
volta licenze commerciali, è necessario far riferimento a strumenti
comunque professionali che si basano su licenze di tipo: MIT, open source,
ecc.
La scelta dell'utilizzo di PhoneGap, per il porting di un'applicazione già
esistente in ambiente Android , è stata dettata da tutte le caratteristiche
sopra elencate, il confronto del framework PhoneGap con altri concorrenti
ha portato alla scelta di quest'ultimo in quanto ben rispondeva alle necessità
relative al lavoro di porting9.
9
processo di trasposizione di un componente software, volto a consentirne l'uso in un ambiente di
esecuzione diverso da quello originale.
31
3.2 Caratteristiche di PhoneGap
Il core delle applicazioni PhoneGap utilizza HTML5 e CSS3 per il
rendering dell'interfaccia grafica, mentre JavaScript viene utilizzato per
implementare la logica dell'applicazione e contemporaneamente per
accedere alle funzionalità native messe a disposizione dalle API.
HTML5 ha la possibilità, grazie alle sue nuove caratteristiche, di accedere
alle funzionalità native del dispositivo, anche se questo approccio non è
raccomandabile poiché esso non è ancora uno standard perfettamente
definito.
Molti dispositivi mobile più datati supportano solo poche caratteristiche del
linguaggio di markup HTML5, il World Wide Web Consortium [4] ha
annunciato che la prima versione dello standard è prevista per la fine del
2014.
Per incorporare l'applicazione realizzata mediante tecnologie web
all'interno di una WebView e accedere alle API native, PhoneGap fa
ampiamente uso di Foreign Function Iterface. Ossia un meccanismo
attraverso il quale un programma scritto in un determinato linguaggio, può
chiamare routines o far uso di servizi scritti in un altro linguaggio di
programmazione. PhoneGap utilizza una libreria JavaScript comune a tutti
Figura 5: Flow Diagram dell’architettura
32
gli ambienti mobile, la quale è collegata attraverso le FFI, ai servizi messi a
disposizione delle librerie scritte in linguaggio nativo per ogni piattaforma
mobile. In questo modo il codice scritto mediante PhoneGap rimane lo
stesso per ogni sistema operativo mobile. Infine per ottenere il codice
eseguibile è necessario nei diversi ambienti di sviluppo collegare
esclusivamente le librerie native ed eseguire il build 10 dell'applicazione.
Questo approccio però, rende le prestazioni dell'applicazione meno
performanti rispetto ad un'applicazione sviluppata in ambiente nativo. In
realtà quest'ultimo punto è una caratteristica di tutti i framework mobile
multipiattaforma, un comportamento tra l'altro prevedibile se si pensa che
l'applicazione per poter essere eseguita, deve necessariamente passare per
una serie di wrapper. I sistemi operativi supportati da PhoneGap sono:
Android, Windows Phone, iOS, Bada, Blackberry, webOS e Symbian.
Di seguito alcune tabelle comparative che specificano le funzionalità native
supportate da PhoneGap per i diversi sistemi operativi Mobile.
10
Il termine software build sta ad indicare il processo di conversione del codice sorgente in un
programma eseguibile.
33
Tabella 1: Funzioni supportate da Phonegap per i diversi OS Mobile parte 1
Tabella 2: Funzioni supportate da Phonegap per i diversi OS Mobile parte 2
34
PhoneGap dispone di una community molto attiva, infatti è possibile
trovare una serie di plug-in di terze parti sviluppati per migliorare o
estendere le funzionalità originali previste dal framework. Ciò che
realmente manca in PhoneGap è un tool che permette di gestire la
dinamicità dell'interfaccia grafica e gli effetti di transizione caratteristici
delle applicazioni native per ambienti mobile. Questa lacuna viene
brillantemente riempita grazie all'utilizzo di JavaScript con il quale è
possibile realizzare qualunque effetto grafico, anche se ciò aumenta i tempi
di sviluppo e rende il codice molto più complesso. D'altronde la natura
stessa di JavaScript permette l'utilizzo di innumerevoli framework e librerie
che semplificano lo sviluppo delle interfacce grafiche.
Non a caso uno dei framework JavaScript più utilizzati per lo sviluppo di
applicazioni PhoneGap è jQuery Mobile [5], il quale implementa una serie
di funzionalità che migliorano l'user experience come: componenti di
interfaccia grafica, dialog box, messaggi di servizio, elementi dei form, ecc.
Di seguito un diagramma molto esplicativo che mostra in che modo
vengono estese le funzionalità di PhoneGap con l'uso di plug-in e librerie
JavaScript.
35
Figura 6: Phonegap buil diagram
Nel dettaglio: viene utilizzato un IDE, ad esempio NetBeans o Eclipse, per
la scrittura del codice HTML5, CSS3 e JavaScript. Mediante quest'ultimo è
possibile utilizzare librerie esterne o framework JavaScript come jQuery
Mobile migliorando cosi l'user experience. Successivamente nella fase di
Building si possono aggiungere Plug-in sviluppati per PhoneGap in modo
da estendere le funzionalità previste originariamente, ottenendo infine in
base all'ambiente in cui viene fatto il deploy un'applicazione pronta per
essere eseguita.
36
3.3 Architettura di PhoneGap e il suo modello di
programmazione
L'architettura di PhoneGap è divisa in quattro livelli software differenti
denominati: livello del sistema operativo, livello nativo di PhoneGap,
livello JavaScript di PhoneGap e livello applicativo.
Il livello del sistema operativo rappresenta quello più basso del framework
PhoneGap, cioè la parte che più si avvicina alla struttura del sistema
operativo su cui viene eseguita l'applicazione. Quando si sviluppa
un'applicazione nativa, attraverso gli strumenti messi a disposizione del
produttore del sistema operativo (SDK), si accede direttamente a questo
livello, sfruttando cosi le API native previste dall'ambiente.
Il livello nativo di Phonegap, chiamato anche "PhoneGap bridge layer",
permette al browser, in particolare alle WebView, di accedere alle
funzionalità native del dispositivo. Gli sviluppatori di PhoneGap con
questo livello hanno creato una prima parte del "ponte" che lega il codice
JavaScript con il codice nativo di ogni differente ambiente. Inoltre il
"PhoneGap bridge layer" contiene un'altra componente software chiamata
"webkit view" che permette di eseguire le applicazioni create dagli
sviluppatori.
Il livello JavaScript di PhoneGap rappresenta la seconda parte del "ponte"
creato nel "PhoneGap bridge layer", esso contiene infatti la seconda parte
del codice che permette di legare gli script JavaScript con l'ambiente nativo
37
del dispositivo. Questo livello contiene anche le API definite dal
framework PhoneGap, che fungono da wrapper per accedere attraverso i
livelli più bassi alle reali API di ogni piattaforma mobile. Questa parte
dell'architettura può essere considerata il "cuore" di PhoneGap poiché
contiene le interfacce di accesso alle funzionalità native del sistema
operativo, permettendo così di accedere attraverso opportuni script a
funzionalità come: geolocalizzazione , storage, filesystem, accelerometro,
ecc.
Per evitare frequenti casi di overhead, la chiamata alle API di PhoneGap a
funzioni implementate nativamente nelle WebView viene reindirizzata
attraverso questo livello alle API native, a cui è possibile accedere
mediante i livelli sottostanti.
Infine il livello applicativo rappresenta lo strato più elevato e astratto di
PhoneGap, esso contiene l'applicazione realizzata dallo sviluppatore in
HTML, CSS e JavaScript.
Gli unici strati dell'architettura di PhoneGap accessibili allo sviluppatore
sono il livello applicativo e l'interfaccia del livello JavaScript. Tutti gli altri
livelli non sono visibili ad un programmatore PhoneGap e questo
rappresenta
una
conseguenza
dell'applicazione
del
principio
di
incapsulamento. Pertanto una parte di un'applicazione può nascondere
informazioni incapsulandole in un costrutto dotato di interfaccia,
permettendo l'information hiding. L'incapsulamento riduce il costo da
pagare per correggere gli errori in fase di sviluppo di un'app. Questo
38
risultato viene ottenuto strutturando l'intero progetto, ed i moduli che lo
compongono, in modo che un'errata decisione presa nell'implementazione
di un singolo modulo non si ripercuota sull'intero progetto, e possa essere
corretta modificando soltanto quel modulo.
Figura 7: Architettura PhoneGap
39
Nell'architettura iniziale di PhoneGap i livelli Javascript e nativo erano
uniti in un unico strato e successivamente con l'introduzione dei plug-in è
stato necessario separare tali livelli. Essi sono stati riprogettati e resi
componenti separati anche nella funzionalità di accesso alle API native.
La possibilità di includere plug-in di terze parti espande le potenzialità di
PhoneGap e l'uso di tali plug-in è reso flessibile grazie alla possibilità di
poterli collegare sia al livello nativo che JavaScript. Ciò è necessario in
quanto i plug-in consistono sempre di una parte nativa che esegue il codice
e di una parte JavaScript che fornisce le interfacce (tra l'applicazione e il
codice nativo che viene eseguito).
I plug-in, quindi, non sono cross-platform e le due parti di cui sono
composti devono essere sviluppate per ogni piattaforma mobile.
Il modello di programmazione su cui si basa PhoneGap prevede l'utilizzo
delle tecniche adoperate nelle web application e in particolare si divide
nella progettazione di due componenti principali: l'interfaccia grafica e la
logica dell'applicazione.
L'interfaccia grafica viene implementata mediante i linguaggi HTML e
CSS, nello stesso modo con cui viene realizzata una web application. Ci
sono però alcuni accorgimenti che devono essere adottati per non incorrere
in problemi legati al rendering dell'interfaccia. I dispositivi mobili oltre ad
essere caratterizzati da un'ampia gamma di risoluzioni video, possono
essere utilizzati anche in modalità landscape e portrait, questo implica
40
l'utilizzo di tecniche specifiche per la realizzazione di mobile web app
come le media queries.
La logica dell'applicazione viene implementata mediante JavaScript con il
quale si ha pieno accesso alla capacità computazionale del dispositivo.
Inoltre grazie all'architettura di PhoneGap è possibile accedere agli oggetti
messi a disposizione dalle API, con i quali si possono manipolare alcune
funzionalità hardware del sistema su cui viene eseguita l'applicazione. La
logica JavaScript, come accade per le web application, segue il
meccanismo della cattura degli eventi. Il modello di programmazione
prevede la gestione degli eventi mediante i tradizionali event handler
JavaScript e attraverso gli eventi PhoneGap. Con gli event handler messi a
disposizione da JavaScript si possono catturare tutti gli eventi che accadono
nel Document Object Model. Gli eventi PhoneGap, invece, permettono di
differenziare
un'applicazione
web
da
un'applicazione
mobile
multipiattaforma, poiché in questo caso sarà possibile catturare eventi
strettamente legati al dispositivo come: la variazione della posizione
geografica (geolocalizzazione), il movimento spaziale (accelerometro),ecc.
La fase successiva alla cattura di un evento prevede l'esecuzione di una
determinata porzione di codice (funzione, procedura,ecc.) che gestisce la
risposta a tale evento.
41
3.4 Linguaggi di programmazione utilizzati e la loro relazione
con PhoneGap
Come previsto da PhoneGap, i linguaggi utilizzati per creare applicazioni
mobile sono presi in "prestito" dall'ambiente web e sostanzialmente
vengono utilizzati HTML5, CSS3 e JavaScript.
HTML5
Il linguaggio HTML (Hyper Text Markup Language) è un linguaggio di
markup ossia un'insieme di regole che descrivono i meccanismi di
rappresentazione di un ipertesto nel World Wide Web, utilizzando
convenzioni standardizzate.
Benché HTML5 [6] sia ancora un linguaggio di markup, in realtà nella sua
ultima versione si è evoluto a tal punto da integrare funzionalità molto
avanzate come ad esempio: la geolocalizzazione, la persistenza dei dati nel
browser attraverso le Web Storage, il controllo dei contenuti multimediali,
ecc. Questa sua evoluzione lo ha reso uno strumento molto potente, infatti
viene utilizzato anche in altri ambiti che non riguardano strettamente le
applicazioni web. Il ruolo di HTML5 nella realizzazione di un'applicazione
PhoneGap è di definire sia la struttura dell'interfaccia grafica che le varie
viste di cui è composta l'applicazione stessa.
42
E' possibile utilizzare diversi approcci per strutturare un'applicazione
mediante HTML5, se non si desidera utilizzare framework JavaScript è
possibile strutturarla in più file HTML e richiamarli in seguito ad un'azione
specifica. Nel caso in cui si sceglie di utilizzare un framework JavaScript o
comunque una libreria esterna per migliorare l'user experience, è necessario
attenersi al modello di programmazione previsto. Nel caso di jQuery
Mobile si utilizza un solo file HTML diviso in una struttura particolare che
prevede l'uso di specifici attributi all'interno dei tag, con cui delineare gli
elementi di una particolare vista.
Di seguito un esempio di struttura a pagine in un singolo file HTML5, da
notare l'uso di attributi come data-role="page" che definiscono la singola
vista e i restanti attributi header, content e footer che a loro volta
definiscono le tre componenti che costituiscono una vista.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile1.3.1.min.js"></script>
</head>
<body>
<div data-role="page" id="pagina_1">
<div data-role="header">
<h1>Page Title</h1>
</div><!-- /header -->
43
<div data-role="content">
<p>Page content.</p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div><!-- /fine pagina 1 -->
<div data-role="page" id="pagina_2">
<div data-role="header">
<h1>Page Title</h1>
</div><!-- /header -->
<div data-role="content">
<p>Page content.</p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div><!-- /fine pagina 2 -->
</body>
</html>
Mediante questo approccio è possibile gestire in modo chiaro le diverse
viste che compongono l'applicazione e si possono facilmente aggiungere,
qualora ve ne fosse la necessità , ulteriori viste.
CSS3
Il CSS (Cascading Style Sheets) è un linguaggio usato per definire la
formattazione di documenti HTML, XHTML o XML. Le regole per
comporre il CSS sono contenute in un insieme di direttive emanate a partire
dal 1996 dal World Wide Web Consortium. Questo linguaggio è stato
ultimamente aggiornato alla terza versione e come nel caso di HTML5,
44
sono state introdotte molte novità. Le specifiche CSS3 [7] non sono state
ancora pubblicate, questo significa che nella fase di sviluppo di
un'applicazione, che prevede l'uso dei fogli di stile, bisogna fare attenzione
al tipo di browser engine che verrà utilizzato. Infatti, in base a quest'ultimo
si rende necessario adottare un insieme di determinate direttive che
risultano compatibili.
Per lo sviluppo di un'app PhoneGap i CSS vengono utilizzati insieme all'
HTML5, grazie ad essi è possibile definire l'intero stile dell'interfaccia
grafica in modo molto simile a quanto avviene per le web application.
L'inserimento di codice CSS, può essere fatto in tre modi differenti ma
nella maggior parte dei casi avviene includendo, tra i tag <head> del
codice HTML, un collegamento ad un foglio di stile esterno. Utilizzare
questo approccio è molto interessante, poiché è possibile con la sola
sostituzione del foglio di stile cambiare totalmente l'intera interfaccia. Un
vantaggio non da poco che può garantire un risparmio di risorse nel caso di
restyling dell'applicazione.
Di seguito un esempio di inclusione di un file CSS all'interno di una pagina
HTML:
45
<html>
<head>
<title>Esempio</title>
<link rel="stylesheet" type="text/css" href="foglio_di_stile.css"/>
</head>
<body>
</body></html>
Un esempio generico della struttura di un CSS:
selettore1 {
proprietà1 : valore1;
proprietà2 : valore2, valore3;
}
selettore2 {
proprietà1 : valore1;
proprietà2 : valore2, valore3;
proprietà3 : valore3, valore4;
}
selettore3 {
proprietà1 : valore1;
proprietà2 : valore2, valore3;
}
Come si può notare le proprietà CSS vengono applicate alla struttura
HTML mediante l'uso di opportuni selettori, i quali si dividono
fondamentalmente in tre tipi: le classi, gli identificatori e i tag.
46
Un esempio specifico potrebbe essere quello di assegnare un colore di
sfondo all'intera interfaccia, una font valida per tutte le viste e definire una
larghezza ed altezza specifici per una classe di liste.
//in questo caso il selettore è un tag
body {
background-color : #ffffff;
font-family : tahoma;
}
//qui invece il selettore è una classe
.liste_tipo_1{
height: 200px;
width: 300px;
}
JavaScript
JavaScript [8] è un linguaggio di scripting orientato agli oggetti
comunemente utilizzato nella creazione di siti web, è stato standardizzato a
partire dal 1997 e l'ultima versione risale al 2011. Va precisato che tra Java
e JavaScript non intercorre nessuna relazione benché i nomi dei due
linguaggi siano simili. JavaScript è un linguaggio interpretato dal browser
engine, la sua sintassi è relativamente simile a quella del Java ed è
debolmente tipizzato.
47
Le interfacce che consentono a JavaScript di rapportarsi con un browser
sono chiamate DOM11. Molti siti web utilizzano la tecnologia JavaScript
lato client per creare potenti applicazioni web dinamiche.
Un uso principale del JavaScript in ambito web è la scrittura di funzioni
integrate nelle pagine HTML che interagiscono con il DOM del browser,
per compiere determinate azioni non possibili con il solo HTML. Questo
tipo di linguaggio risulta molto diffuso poiché non viene utilizzato solo ed
esclusivamente in ambito web.
Nel caso del suo utilizzo con PhoneGap, JavaScript ha il compito di gestire
la logica dell'applicazione e allo stesso tempo di interagire con le API
native dell'ambiente attraverso PhoneGap. Questo importante compito può
essere affrontato utilizzando librerie di supporto esterne o addirittura interi
framework JavaScript, in modo da migliorare l'user experience del
programma senza necessariamente aumentarne la complessità.
Per integrare uno script JavaScript all'interno del codice HTML si utilizza
uno speciale tag <script>, all'interno del quale è possibile collegare uno
script esterno oppure scrivere direttamente al suo interno il codice
JavaScript. Nella maggior parte dei casi per mantenere separati i
componenti di un'applicazione PhoneGap si sceglie di collegare script
esterni, di seguito un esempio di un collegamento :
11
Document Object Model, è una forma di rappresentazione dei documenti strutturati come modello
orientato agli oggetti. Il DOM è uno standard ufficiale del W3C.
48
<html>
<head>
<script type="text/javascript" src="codice_javascript_esterno.js"></script>
</head>
<body>
</body>
</html>
Infine un esempio di codice JavaScript: una funzione che recupera una
stringa inserita dall'utente all'interno di un form, la quale viene
successivamente stampata in una dialog box.
<script type="text/javascript">
function getText(){
var text = document.getElementById('textbox_id').value;
return text;
}
alert(getText());
</script>
Questa operazione non poteva essere eseguita mediante l'uso del solo
HTML.
Nel caso dell'applicazione realizzata per il presente lavoro di tesi, è stato
scelto jQuery mobile come framework JavaScript.
49
3.5 jQuery Mobile: un framework nel framework
jQuery Mobile è un web framework ottimizzato per i dispositivi touch, è
sviluppato dalla jQuery foundation e viene distribuito con licenza MIT.
Questo framework JavaScript è molto diffuso grazie alla sua compatibilità
con la maggior parte degli smartphone e tablet esistenti sul mercato, inoltre
si integra perfettamente con diversi mobile app framework come
PhoneGap. Ci sono diversi motivi per cui si sceglie di utilizzare una libreria
JavaScript o un framework per lo sviluppo di un'applicazione mobile
multipiattaforma, sicuramente le motivazioni più rilevanti riguardano il
risparmio di tempo e risorse per migliorare l'user experience. La possibilità
di disporre, in un'unica risorsa software, di strumenti testati su varie
piattaforme e con un buon indice di degrado aumenta la produttività e non
espone a problemi (brillantemente risolti dal framework). Il connubio di
PhoneGap con jQuery Mobile è perfetto: da un lato abbiamo un mobile
app framework che ci permette di accedere alle API native del dispositivo,
dall'altro un mobile web framework che ci permette di strutturare la UI e di
catturare gli eventi legati al touchscreen (es. Custom Gesture). Nel
paragrafo 3.4 è stata presentata la struttura di una pagina HTML che sfrutta
jQuery Mobile. Da come si può notare l'intero file HTML viene utilizzato
per creare delle pagine che rappresentano le viste dell'applicazione mobile.
50
Ogni vista è ulteriormente suddivisa in tre sezioni: header, content e footer;
queste sezioni rappresentano rispettivamente: la parte alta della pagina, il
contenuto centrale e il piè pagina. Per indicare al framework jQuery Mobile
i ruoli delle varie sezioni, la loro posizione, gli effetti di transizione e il
tema grafico ad essi associato vengono utilizzati degli speciali attributi:
 data-role: specifica il ruolo di un elemento (header, content, footer,
ecc).
 data-position: specifica se l'elemento deve essere fixed, in tal caso
l'header o il footer saranno fissi durante lo scorrimento della pagina.
 data-transition: specifica l'effetto di transizione quando si passa in
una nuova pagina.
 data-theme: specifica il tema css associato ad un determinato
elemento.
Un'altra caratteristica, che rende questo framework molto flessibile,
riguarda lo sviluppo di temi css personalizzati. Attraverso il jQuery Mobile
Theme Roller, un'applicazione che permette di sviluppare diversi temi, è
possibile modificare gli stili css associati all'interfaccia grafica e poter
visualizzare dal vivo le modifiche apportate.
jQuery Mobile utilizza un sistema di supporto di degrado a 3 livelli,
permettendo così di rendere accessibile il contenuto di una pagina anche
51
con browser engine ormai datati. I tre livelli si dividono in: A-grade, Bgrade e C-grade; nel livello A viene garantita la miglior user experience
con effetti di transizione Ajax-based, nel livello B non è prevista l' Ajax
navigation e nel livello C sono disabilitate la maggior parte delle features
mantenendo un'interfaccia funzionale alla navigazione di base.
La sintassi utilizzata da questo framework è molto semplice per chi ha
esperienza con il web framework jQuery, la versione web desktop di
jQuery Mobile. Essa si basa sulla selezione di elementi del DOM e sulla
loro manipolazione attraverso la chiamata di uno o più metodi.
La logica che permette di eseguire determinate azioni nel contesto
dell'applicazione si basa sulla cattura di determinati eventi, i quali
avvengono durante l'utilizzo dell'applicazione; esistono diversi event
handler che permettono di catturare un determinato comportamento
dell'utente. In particolare per la versione mobile di jQuery vi sono degli
eventi associati al touchscreen del dispositivo, di seguito un esempio degli
eventi più utilizzati per realizzare un'applicazione mobile.
//viene lanciato la prima volta che viene caricata una vista
$('#page_1').live('pageinit',function(e){
});
//viene lanciato ogni volta che viene caricata una vista
$('#page_1').live('pageshow',function(e){
});
52
//viene lanciato ogni volta che viene eseguito uno swipe verso sinistra
$('#div_1').on('swipeleft',function(e){
});
//viene lanciato ogni volta che viene premuto a lungo un elemento
$('#div_2').on('taphold',function(e){
});
//viene lanciato ogni volta che incomincia lo scrolling di una vista
$('#div_3').on('taphold',function(e){
});
//viene lanciato ogni volta che viene premuto il pulsante con id "btn_1"
$('#btn_1').on('tap',function(e){
});
Quando un evento viene intercettato solitamente viene eseguita
un'operazione di risposta all'evento stesso. Ad esempio: la pressione
prolungata di un elemento del DOM può corrispondere alla comparsa di un
menu, che permette all'utente di accedere ad una serie di opzioni. Per
inserire o manipolare elementi del DOM si usa una particolare sintassi di
jQuery che permette di selezionare le diverse componenti di una pagina
HTML.
La selezione di un determinato elemento del DOM può essere
un'operazione anche molto complessa e per questo motivo jQuery mette a
disposizione un set di strumenti per il matching degli elementi che
compongono il DOM.
53
Di seguito un esempio di alcuni selettori usati in jQuery:
//Non fa riferimento a classi o id, seleziona direttamente i tag HTML, in questo
//caso tutti i div della pagina.
$('div')
//Seleziona un elemento il cui id è "container"
$('#container')
//Seleziona una classe di elementi il cui attributo class è "lista"
$('.lista')
//Seleziona tutti i paragrafi che nel DOM sono figli di elementi con classe
//"testo"
$('.testo p')
//Seleziona il campo input del form con id "form_1", che ha come attributo name
//"provincia"
$('#form_1 input[name=provincia]')
//Seleziona l'ultima riga di ogni tabella presente nel DOM
$('tr:last')
//Seleziona le righe pari di ogni tabella presente nel DOM
$('tr:odd')
Esistono moltissime combinazioni di selezione grazie alle quali è possibile
accedere a tutti gli oggetti del DOM, questo meccanismo permette di
gestire l'interfaccia di un'applicazione mobile manipolando correttamente
gli elementi.
Dopo la selezione di un elemento della pagina HTML si procede alla sua
manipolazione e, anche questa operazione è affidata a jQuery o
eventualmente a JavaScript puro. La libreria jQuery mette a disposizione,
attraverso le sue API, una serie di metodi che permettono di operare su tutti
54
gli elementi selezionati attraverso un selettore. E' possibile cambiare le
proprietà css, creare un'animazione complessa, nascondere o visualizzare
elementi, ecc.
Di seguito un esempio di manipolazione degli stessi elementi selezionati
nella pagina precedente:
//Fa scomparire tutti i div del DOM con un effetto di dissolvenza
$('div').fadeOut();
// Colora di bianco lo sfondo dell'elemento con id "container" e
//aggiunge un bordo sinistro di 5px in stile solid di colore nero.
$('#container').css({backgroundColor: '#fff', borderLeft: '5px solid #000'});
//Nasconde tutti gli elementi con classe "lista".
$('.lista').hide();
//Sostituisce il testo di tutti i paragrafi, che nel DOM sono figli di elementi
//con classe "testo", con la frase "Testo di prova".
$('.testo p').text('Testo di prova');
//Recupera il valore del campo input del form con id "form_1", che ha come
attributo name "provincia"
$('#form_1 input[name=provincia]').val();
//Aggiunge un bordo inferiore di 1px nero con stile solido, all'ultima riga di
//ogni tabella presente nella pagina.
$('tr:last').css({border-bottom: '1px solid black'});
//Aggiunge uno sfondo grigio alle righe pari di ogni tabella presente nella
//pagina.
$('tr:odd').css({backgroundColor: '#ccc'});
Si può quindi affermare, in sintesi, che il modello di programmazione
adottato, per creare un'applicazione attraverso il framework jQuery Mobile,
segue le operazioni di: cattura di eventi legati all'interfaccia, selezione degli
55
elementi del DOM, manipolazione degli stessi in risposta all'evento
catturato.
Infine viene presentata una porzione di codice in cui viene applicato il
modello di programmazione appena descritto, unendo gli esempi sopra
citati:
//evento che intercetta il caricamento della pagina con id "page_1"
$('#page_1').live('pageshow',function(e){
//Aggiunge uno sfondo grigio alle righe pari di ogni tabella presente
//nella pagina.
$('tr:odd').css({backgroundColor: '#ccc'});
//viene lanciato ogni volta che viene premuto il pulsante con id "btn_1"
$('#btn_1').on('tap',function(e){
//Nasconde tutti gli elementi con classe "lista".
$('.lista').hide();
});
});
In pratica, al caricamento della pagina con id="page_1" lo sfondo delle
righe pari di tutte le tabelle presenti nella pagina diventa grigio e premendo
il tasto con id="btn_1" si nascondono tutti gli elementi con la classe
"lista_1".
56
CAPITOLO 4
PORTING DI UN'APPLICAZIONE
In questo capitolo viene analizzato nel dettaglio il lavoro svolto per rendere
un'applicazione
Android
multipiattaforma
attraverso
il
framework
PhoneGap [9]. L'applicazione prevede l'utilizzo delle funzionalità native
del dispositivo mobile come: la connessione ad internet, l'accesso alla
memoria di massa, la consultazione della rubrica contatti, la gestione delle
telefonate, invio SMS, ecc.
L'applicazione, inoltre, è di tipo gestionale e fornisce una serie di
informazioni organizzate prevalentemente in liste e tabelle. In più è
presente un'agenda collegata ad un calendario per la gestione degli eventi,
una lista contatti derivante dalla rubrica del dispositivo e una serie di form
per l'immissione di dati.
Le fasi che hanno caratterizzato il porting sono:
 Studio preliminare delle funzionalità dell'applicazione per ambiente
Android.
 Scelta degli strumenti per replicare l'interfaccia grafica e gli effetti ad
essa legati.
 Scelta delle tecniche per replicare le funzionalità dell'app originale in
un ambiente multipiattaforma.
57
4.1 Interfaccia grafica e navigazione tra le pagine
La prima parte del porting è stata focalizzata sulla progettazione
dell'interfaccia grafica e sul meccanismo di navigazione tra le pagine che
compongono l'applicazione. Le scelte grafiche e tecniche effettuate hanno
seguito in primis la necessità di replicare il più fedelmente possibile
l'interfaccia dell'applicazione originale. Successivamente sono state
valutate le modifiche necessarie per rendere utilizzabile l'applicazione su
più sistemi operativi. Quest'ultimo punto è fondamentale, poiché bisogna
tenere conto della diversa user experience legata alle varie piattaforme e
riprogettare l'applicazione in modo da adattarsi senza stravolgere, allo
stesso tempo, l'interfaccia originale. Il componente d'interfaccia più
complesso da realizzare è stato il menu globale dell'applicazione, un menu
di servizio che permette la navigazione tra le diverse viste che compongono
l'app. Nella versione originale per Android tale menu veniva richiamato
con la pressione del pulsante soft touch "menu", questo comportamento
non è replicabile in altri ambienti come ad esempio iOS. E' stato, dunque,
necessario implementare secondo una diversa modalità la presenza di
questo menu, in particolare utilizzando jQuery Mobile e l'evento "live
click".
L'intera interfaccia grafica è stata realizzata secondo il modello di
programmazione del framework jQuery Mobile: la pagina HTML utilizzata
per definire l'interfaccia è stata suddivisa in più viste, ognuna contiene i
58
diversi componenti che si differenziano in base alla funzione della vista
stessa. Il meccanismo di navigazione prevede una pagina principale, la
vista indice, che contiene i collegamenti alle pagine secondarie ognuna
relativa ad una funzionalità o servizio specifico dell'applicazione. In ogni
pagina l'utente può accedere al menu globale per cambiare contesto e
passare ad una vista qualsiasi, oltre che poter accedere alla vista settings
(dedicata alle impostazioni generali dell'app).
Un'altro aspetto che ha caratterizzato la fase di porting dell'interfaccia
riguarda gli effetti di transizione legati alla navigazione tra le viste.
PhoneGap non supporta effetti di transizione nativamente, mentre
l'applicazione Android originale prevedeva alcuni effetti di sliding e
fading12, i quali sono stati implementati nella versione multipiattaforma con
jQuery Mobile.
Per la realizzazione dell'interfaccia relativa alla vista "calendario" è stato
utilizzato un plug-in jQuery il cui nome è "fullcalendar", che permette di
ottenere un calendario dinamico con cui è stata realizzata anche la funzione
di agenda eventi.
12
Letteralmente scorrimento e dissolvenza, indicano gli effetti di transizione che è possibile notare su
molte applicazioni mobile con un'interfaccia utente più accattivante.
59
Di seguito una parte della struttura HTML utilizzata per definire la vista
indice e agenda:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="css/jquery.mobile-1.3.0.min.css"/>
<link rel="stylesheet" href="css/index.css"/>
<script src="js/jquery-1.8.2.min.js"></script>
<script src="js/jquery.mobile-1.3.0.min.js"></script>
<script type="text/javascript" src="cordova-2.5.0.js"></script>
<script src="js/index.js" type="text/javascript"></script>
<script type='text/javascript' src='js/fullcalendar.js'></script>
<link rel='stylesheet' type='text/css' href='js/fullcalendar.css' />
<link rel="stylesheet" type="text/css" href="js/jqm-datebox.css" />
<script type="text/javascript" src="js/jqm-datebox.core.js"></script>
<script type="text/javascript" src="js/jqm-datebox.mode.flipbox.js"></script>
<!-- PLUGIN PHONEGAP-->
<script type='text/javascript' src='js/SmsComposer.js'></script>
<script type='text/javascript' src='js/EmailComposer.js'></script>
</head>
<body>
<!-- inizio index -->
<div data-role="page" id="index_page" >
<div id="flag_orange"><img src="img/tag_orange.png"/></div>
<div id="wrapper">
<div id="logo"><img src="img/logo.png"/></div>
<table id="icon_index">
<tr>
<td><a href="#profilo_page" data-transition="slide"><img
src="img/profilo_n.png"/><br/> Profilo</a></td>
<td><a href="#agenda_page" data-transition="slide" ><img
src="img/agenda_n.png"/><br/> Agenda</a></td>
<td><a href="#contatti_page_tutti" datatransition="slide"><img src="img/contatti_n.png"/><br/> Contatti</a></td>
</tr>
60
<tr>
<td><a href="#regali_page" data-transition="slide"><img
src="img/regali_n.png"/><br/> Regali</a></td>
<td><a href="#invitati_page" data-transition="slide"><img
src="img/invitati_n.png"/><br/> Invitati</a></td>
<td><a href="#budget_page" data-transition="slide"><img
src="img/budget_n.png"/><br/> Budget</a></td>
</tr>
</table>
<!-- messaggio di errore o successo sincronizzazione client/server-->
<div id="sync_msg">
<p></p>
</div>
</div>
</div>
<!-- fine index -->
<!-- inizio agenda -->
<div id="agenda_page" data-role="page">
<div data-role="panel" class="mypanel" data-display="overlay" dataposition="left">
<img src="img/logo.png" class="global_menu_logo"/>
<ul data-role="listview" data-inset="true">
<li><a href="#index_page" data-transition="flip"><img
src="img/home_n.png" class="ui-li-icon ui-corner-none">Home</a></li>
<li><a href="#profilo_page" data-transition="flip"><img
src="img/profilo_n.png" class="ui-li-icon">Profilo</a></li>
<li><a href="#agenda_page" data-transition="flip"><img
src="img/agenda_n.png" class="ui-li-icon">Agenda</a></li>
<li><a href="#contatti_page_tutti" datatransition="flip"><img src="img/contatti_n.png" class="ui-liicon">Contatti</a></li>
<li><a href="#settings_page" data-transition="flip"><img
src="img/settings_n.png" class="ui-li-icon">Settings</a></li>
<li><a href="#regali_page" data-transition="flip"><img
src="img/regali_n.png" class="ui-li-icon">Regali</a></li>
<li><a href="#invitati_page" data-transition="flip"><img
src="img/invitati_n.png" class="ui-li-icon">Invitati</a></li>
<li><a href="#budget_page" data-transition="flip"><img
src="img/budget_n.png" class="ui-li-icon ui-corner-none">Budget</a></li>
</ul>
</div>
<div class="section_title">
<div class="yellow_cube"></div>
<div class="orange_cube"></div>
<div class="green_cube"></div>
<a>Agenda</a>
61
</div>
<div class="content_1">
<a class="agenda_title2">Agenda</a>
<br/>
<a class="agenda_subtitle">Tutte le date</a>
<div class="lateral_button" id="agenda_calendario_button"><a
style="color: #ffffff; text-decoration: none;" href="#calendario_page" datatransition="slide" class="button_link">Calendario</a></div>
<br/><br/>
<div class="lateral_button" id="agenda_diario_button"><a
style="color: #ffffff; text-decoration: none;" href="#diario_page" datatransition="slide" class="button_link">Diario</a></div>
</div>
<div id="agenda_list">
</div>
<div class="content_3">
<p style="clear: both;" class="paragraph plus_sign"><img
src="img/agenda_tag_n.png" width="15"> <a style="color: #000000; text-decoration:
none;" href="#aggiungi_in_calendario_page"> Aggiungi</a></p>
</div>
</div>
<!-- fine agenda -->
</body>
</html>
Nel codice si possono notare le due viste index e agenda realizzate
mediante il modello di programmazione di jQuery Mobile. Le viste sono
racchiuse tra div con attributo data-role="page".
Inoltre nella pagina agenda, evidenziato in verde, si può notare la struttura
del menu globale caratterizzato dall'attributo data-role="panel".
62
Segue il codice jQuery per le viste index e agenda, strutturato secondo il
meccanismo di cattura degli eventi:
$('#index_page').live('pageinit',function(e){
$('#index_page').live('click',function(e){
$('#sync_msg p').html('');
});
//script per cambiare il colore dell'icona nella pagina principale all'evento
touch
$('#icon_index a[href="#profilo_page"]').hover(
function () {
$(this).children("img").attr("src", "img/profilo_p.png");
},
function () {
$(this).children("img").attr("src", "img/profilo_n.png");
}
);
$('#icon_index a[href="#agenda_page"]').hover(
function () {
$(this).children("img").attr("src", "img/agenda_p.png");
},
function () {
$(this).children("img").attr("src", "img/agenda_n.png");
}
);
$('#icon_index a[href="#contatti_page_tutti"]').hover(
function () {
$(this).children("img").attr("src", "img/contatti_p.png");
},
function () {
$(this).children("img").attr("src", "img/contatti_n.png");
}
);
$('#icon_index a[href="#regali_page"]').hover(
function () {
$(this).children("img").attr("src", "img/regali_p.png");
},
function () {
$(this).children("img").attr("src", "img/regali_n.png");
}
);
});
63
$('#agenda_page').live('pageshow',function(e){
$("#menu_label").live('click',function() {
$( "#agenda_page .mypanel" ).panel( "open" );
});
//apro la connessione con il db
var db = window.openDatabase("Database", "1.0", "db", 200000);
//query che recupera gli eventi in agenda
db.transaction(function(tx){
tx.executeSql("SELECT * FROM AgendaItemJDO GROUP BY dataInizio ORDER
BY dataInizio ASC", [], initAgendaList);
});
//aggiorna l'agenda
function initAgendaList(tx, results) {
$('#agenda_list').html('');
var len = results.rows.length;
if(len == 0){
$('#agenda_list').append('<div class="paragraph agenda_row">Non ci
sono appuntamenti o scadenze in agenda.</div>');
}
var anno = "";
var anno_precedente = "";
var mesi = new
Array("Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic");
for (var i=0; i<len; i++){
//appendo tutti gli elementi della lista in sequenza nel div
contatti_tutti_list
var date = new Date(results.rows.item(i).dataInizio);
anno = date.getFullYear();
if(anno != anno_precedente){
$('#agenda_list').append('<div class="agenda_year">'+ anno
+'</div>');
}
anno_precedente = anno;
$('#agenda_list').append('<div data_ev="'+
results.rows.item(i).dataInizio +'" class="paragraph agenda_row">'+
'<div class="flag_agenda">'+ date.getDate() +' '+
mesi[date.getMonth()] + '</div>'+
'<div id="'+ results.rows.item(i).dataInizio +'"
class="eventi_giorno">'+
'</div>'+
'</div>');
}
$('.agenda_row:last').css('border-bottom', 'solid 1px #999');
64
}
//query che recupera gli eventi in agenda
db.transaction(function(tx){
tx.executeSql("SELECT * FROM AgendaItemJDO ORDER BY dataInizio ASC",
[], initAgendaRowList);
});
//aggiorna l'agenda
function initAgendaRowList(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
$('#'+results.rows.item(i).dataInizio).append('<div>'+
results.rows.item(i).note +'</div>');
}
}
});
A pagina 64 si può notare l'evento "pageshow" che cattura il caricamento
della vista agenda. Inoltre è presente anche l'event handler "live click" che
intercetta l'evento touch relativo alla comparsa del menu globale.
65
La struttura HTML è collegata con delle regole CSS per definire lo stile di
ogni singola vista, in particolare sono stati definiti alcuni parametri CSS
globali per un uso tipicamente mobile, di seguito una porzione di codice
CSS3:
body {
-webkit-touch-callout: none;
-webkit-text-size-adjust: none;
-webkit-user-select: none;
height:100%;
margin:0px;
padding:0px;
width:100%;
background: -moz-linear-gradient(100% 100% 180deg, #f8f8f8, #cccccc);
background: -webkit-gradient(linear, right top, right bottom, from(#f8f8f8),
to(#cccccc));
background-repeat: no-repeat;
background-attachment: fixed;
}
input, textarea { -webkit-user-select: text; }
I primi parametri relativi al tag body vengono utilizzati per prevenire la
copia di eventuali immagini in seguito ad un evento touch prolungato e il
resizing text to fit, funzione che adatta il testo alle dimensioni della
schermata. Bisogna infatti sottolineare che il rendering del layout avviene
in un'istanza del browser ma bisogna dare l'illusione all'utente di utilizzare
un'app nativa disabilitando parte delle feature che caratterizzano i browser
mobile.
66
4.2 Persistenza dei dati
Per garantire che i dati immessi attraverso l'uso dell'applicazione PhoneGap
siano disponibili anche quando l'applicazione viene terminata è stato
necessario utilizzare un meccanismo di persistenza dei dati. La scelta è
ricaduta su Sqlite3 [10], un database management system SQL, utilizzato
ampiamente in dispositivi come: telefoni cellulari, PDA, set-top boxes, ecc.
Sqlite è una libreria scritta in linguaggio C che implementa un DBMS SQL
di tipo ACID, il suo utilizzo è regolato da una licenza libera e permette di
creare una base di dati incorporata in un unico file.
Sqlite3 è compatibile con la maggior parte dei sistemi operativi mobile e
risulta uno strumento perfettamente adatto per fornire la persistenza dei dati
in un'applicazione mobile, inoltre essendo un DBMS SQL permette
appunto l'utilizzo delle Structured Query Language (un linguaggio standard
per manipolare i database).
A differenza di altri database, Sqlite3 non è un processo standalone
utilizzabile di per sè (come ad esempio MySql), ma può essere incorporato
all'interno di un altro programma.
Le caratteristiche più importanti di Sqlite3, per cui è stato scelto come
strumento per garantire la persistenza dei dati, sono:
 la compattezza della libreria (solo 500KB per l'intera libreria)
 la velocità di esecuzione delle query
67
 supporta buona parte dello standard SQL92
 ha transizioni atomiche, consistenti, isolate e durabili (ACID), anche
in caso di crash di sistema
 un database consiste di un unico file, il cui formato interno è
indipendente dalla piattaforma
La struttura del database, a supporto dell'applicazione, è organizzata in più
tabelle le quali vengono referenziate tra di loro mediante il meccanismo
delle chiavi primarie e delle chiavi esterne.
In totale sono state utilizzate 10 tabelle per la gestione dei dati, la struttura
del database viene creata nell'istante in cui l'applicazione viene avviata per
la prima volta, di seguito un esempio di query utilizzata per la creazione del
database:
//Query in SQL per la creazione di una tabella nell'istante del primo avvio
//dell'applicazione
CREATE TABLE IF NOT EXISTS UserJDO
(id INTEGER PRIMARY KEY, name VARCHAR(255), email VARCHAR(255), emailLowerCase
VARCHAR(255), password VARCHAR(255), age VARCHAR(255), birthDate DATE, phone
VARCHAR(255), city VARCHAR(255), sex VARCHAR(255), activated BOOLEAN, disabled
BOOLEAN, promoter VARCHAR(255))
Come si può notare viene utilizzato lo statement sql "CREATE TABLE IF
NOT EXIST" il quale garantisce la creazione della tabella solo se essa non è
stata già creata precedentemente. In questa fase vengono definiti anche i
datatype associati alle colonne della tabella. In Sqlite3 i datatype non sono
definiti in modo statico e fortemente tipizzato come avviene in altri
68
database, ma viene utilizzato un approccio dinamico in modo che il
datatype di un valore, sia associato con il valore stesso e non con il suo
container. I datatype definiti in Sqlite3 sono quindi in numero minore
rispetto ad altri database. Per garantire la completa compatibilità con il
linguaggio SQL è possibile utilizzare i più comuni datatype presenti nelle
implementazioni SQL tradizionali. Sqlite provvederà attraverso una tabella
di affinità ad eseguire l'operazione di casting per rendere i dati coerenti con
l'implementazione di Sqlite3.
Di seguito la tabella di affinità usata da Sqlite3:
Tabella 3: Tabella delle affinità Sqlite3
69
Nella query precedente è possibile notare come la colonna "id" sia stata
definita "INTEGER PRIMARY KEY" ossia una colonna con datatype intero
e caratteristica di chiave primaria auto incrementante.
Le restanti query per la creazione del database hanno tutte la medesima
struttura ovviamente con colonne differenti, scelte in base alla funzione a
cui la tabella è destinata.
Per poter accedere al database ed eseguire una query è necessario utilizzare
PhoneGap e la sua capacità di sfruttare le API native del dispositivo.
Un'accurata trattazione di questa metodologia è illustrata nel paragrafo
seguente.
4.3 Accesso alle API native con PhoneGap
PhoneGap permette l'accesso alle API native del dispositivo mobile, il
modo in cui è possibile eseguire questa operazione è stato trattato nel
paragrafo 3.2 (Caratteristiche di PhoneGap). Si ricorda che per alcuni
sistemi operativi mobile non è possibile utilizzare tutte le funzionalità del
dispositivo ma per gli OS Mobile per cui è previsto il porting (iOS,
Windows Phone 8 e Android) non ci sono particolari limitazioni.
70
Di seguito vengono illustrate alcune funzionalità supportate da PhoneGap e
quindi prese in considerazione le parti relative alle API utilizzate per il
porting dell'applicazione.
Storage
Per poter accedere alla memoria di massa del dispositivo bisogna
richiamare delle particolari funzioni che fanno riferimento alla libreria
JavaScript di PhoneGap. Questa parte delle API è stata utilizzata per
eseguire le query necessarie al corretto funzionamento dell'applicazione e
per poter accedere in scrittura alla memoria. Di seguito un esempio del
codice JavaScript necessario per la creazione della struttura del database,
ed un esempio di codice HTML che richiama la libreria PhoneGap per
l'accesso alle API native.
<!-- Codice HTML -->
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- Foglio di stile di jQuery Mobile -->
<link rel="stylesheet" href="css/jquery.mobile-1.3.0.min.css"/>
<!-- Foglio di stile dell' interfaccia grafica -->
<link rel="stylesheet" href="css/index.css"/>
<!-- inclusione del framework jQuery Mobile -->
<script src="js/jquery-1.8.2.min.js"></script>
<script src="js/jquery.mobile-1.3.0.min.js"></script>
71
<!-- libreria Phonegap per l'accesso alle API native -->
<script type="text/javascript" src="cordova-2.5.0.js"></script>
<!-- codice javascript contenente la logica dell'applicazione -->
<script src="js/index.js" type="text/javascript"></script>
</head>
<body>
<!-- struttura della pagina html -->
</body>
</html>
//codice Javascript
//Event listner associato all'evento "deviceready" di Phonegap
document.addEventListener("deviceready", onDeviceReady, false);
//funzione che viene richiamata al presentarsi dell'evento "deviceready"
function onDeviceReady() {
var db = window.openDatabase("Database", "1.0", "db", 200000);
db.transaction(function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS UserJDO (id INTEGER, name
VARCHAR(255), email VARCHAR(255), emailLowerCase VARCHAR(255), password
VARCHAR(255), age VARCHAR(255), birthDate DATE, phone VARCHAR(255), city
VARCHAR(255), sex VARCHAR(255), activated BOOLEAN, disabled BOOLEAN, promoter
VARCHAR(255))');
});
}
Il
codice
HTML
nell'esempio
mostra
come
vengono
integrate
nell'applicazione le diverse librerie JavaScript (jQuery Mobile e
PhoneGap), i fogli di stile e la logica dell'applicazione. Il secondo esempio
72
mostra una parte della logica dell'applicazione ed in particolare la creazione
del database. Si può notare come viene aggiunto un evento PhoneGap,
detto anche "PhoneGap lifecycle events", ossia "deviceready" e come
questo venga catturato quando il dispositivo avvia l'applicazione in quanto
la libreria PhoneGap viene caricata completamente. Al verificarsi di queste
condizioni viene richiamata la funzione "onDeviceReady" nella quale viene
stabilita la connessione al database e successivamente, mediante le funzioni
"db.transaction" e "tx.executeSql", viene eseguita la query. In questo caso
la query crea una tabella e non ritorna nessun risultato da gestire come nel
caso di una select.
Le funzione "tx.executeSql" può essere utilizzata per eseguire tutte le
query, essa prevede (quando necessario) l'utilizzo di due funzioni di
callback. La prima viene lanciata dopo l'esecuzione della query, quando
quest'ultima ha successo e contiene nel caso di una select il result set.
Mentre la seconda funzione viene lanciata nel caso di errore nell'esecuzione
della query e viene usata per gestire l'eventuale eccezione.
Di seguito un esempio di codice con lo statement SQL Select:
var db = window.openDatabase("Database", "1.0", "db", 200000);
db.transaction(init_page);
function init_page(tx) {
tx.executeSql('SELECT * FROM Lista', [], initList, errorCB);
}
function initList(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
73
$('#list_1').append('<div db_id="'+ results.rows.item(i).id +'"
class="box_list">'+
'<div class="box_list_top">'+ results.rows.item(i).name
+'</div></div>');
}
}
function errorCB(err){ alert("Error processing SQL " + err.code); }
Come si può notare dopo la connessione con il database viene eseguita una
query di selezione, se non si presentano errori viene eseguita la funzione
"initList" che ha il compito di popolare una lista scorrendo le righe
attraverso il result set corrispondente al risultato della query. Nel caso
venga sollevata un'eccezione questa viene gestita mediante la funzione
"errorCB". Anche le query che prevedono l'uso degli statement "insert",
"update" o "delete" vengono eseguite mediante la chiamata a funzione
"tx.executeSql".
Le API che garantiscono l'accesso alla memoria del dispositivo sono basate
sulle specifiche del W3C Web SQL Database e W3C Web Storage.
Connection
L'oggetto "connection" previsto dalle API di PhoneGap, viene utilizzato
per reperire informazioni riguardo le connessioni del dispositivo a reti WiFi o cellulari. La possibilità di conoscere lo stato di connessione alla rete
74
internet di un dispositivo è di fondamentale importanza nel caso ci sia la
necessità di utilizzare servizi web associati ad un'applicazione.
Nel caso dell'applicazione sviluppata, essa integra un servizio di
sincronizzazione con un web server e l'utilizzo di una serie di servizi web
come la verifica delle credenziali utente, per cui si rende necessaria la
manipolazione dell'oggetto "connection". In particolare tale oggetto viene
utilizzato per conoscere se il dispositivo è connesso ad una rete e di che
rete si tratti. In base alla verifica di tale informazione si può procedere alla
sincronizzazione o all'utilizzo di altri servizi web.
Di seguito una porzione di codice che utilizza l'oggetto "connection":
function checkConnection() {
var networkState = navigator.connection.type;
//impostare lo states a 0 per le connessioni non ammesse
//esempio: se voglio aggiornare il dispositivo solo con connessione wifi
e 3g impostare ad 1 WIFI e CELL_3G
var states = {};
states[Connection.UNKNOWN] = 1;
states[Connection.ETHERNET] = 1;
states[Connection.WIFI]
= 1;
states[Connection.CELL_2G] = 1;
states[Connection.CELL_3G] = 1;
states[Connection.CELL_4G] = 1;
states[Connection.CELL]
= 1;
states[Connection.NONE]
= 0;
return states[networkState];
}
if(checkConnection() == 1){
alert('Connessione valida');
}else{
alert('Connessione non valida');
}
75
La funzione "checkConnection" viene utilizzata per verificare il tipo di
connessione usata dal dispositivo e in particolare è stata progettata per
ritornare il valore "0" oppure "1". In pratica è necessario associare all'array
"states", che riporta i diversi tipi di connessioni possibili, i valori "0" per le
connessioni che non si desidera utilizzare e "1" per le connessioni valide.
Successivamente quando viene richiamata la funzione essa ritornerà due
valori possibili. Mediante tali valori sarà possibile decidere se eseguire una
determinata operazione che coinvolge la connessione del dispositivo o
meno. Nell'esempio si può notare un costrutto "if-else" che esegue un check
sulla connessione e stampa a video il suo stato. Il codice completo per la
gestione della sincronizzazione e del controllo credenziali utente verrà
mostrato nei paragrafi successivi.
Contacts
L'oggetto "contacts" permette di accedere alle informazioni presenti nella
rubrica del dispositivo. Questa funzionalità è stata implementata
nell'applicazione per poter recuperare alcune informazioni dei contatti
presenti in rubrica. Tali informazioni vengono successivamente manipolate
e salvate nel database in modo da creare delle liste contatti alternative con
la possibilità di dividere i contatti in gruppi o selezionare dei preferiti.
Inoltre l'applicazione permette l'inserimento, mediante una vista con un
76
form specifico, di ulteriori contatti non presenti nella rubrica del
dispositivo.
Questa parte dell'applicazione prevede l'utilizzo di 5 viste separate con i
seguenti compiti:
 Mostrare tutti i contatti presenti nel database (importati dalla rubrica
o inseriti manualmente).
 Mostrare i contatti divisi in gruppi con la possibilità di selezionare
solo uno specifico gruppo (Amici, Parenti,Colleghi, ecc.).
 Mostrare solo i contatti classificati come "Preferiti".
 Fornire un Form per l'inserimento manuale dei contatti o in
alternativa importarli mediante l'oggetto "contacts".
Per importare i contatti è stata creata un'ulteriore vista che permette di
visualizzarli in modo ordinato ed eventualmente filtrarli mediante un
campo di ricerca dinamico.
Di seguito il codice utilizzato per creare la lista dei contatti presenti nel
dispositivo e per realizzare la vista che permette di selezionare il contatto
da importare:
//carico l'elenco dei contatti presenti nella rubrica
var options = new ContactFindOptions();
options.filter="";
options.multiple=true;
77
//seleziono i campi che desidero recuperare dalla rubrica
filter = ["displayName","phoneNumbers","emails","urls","addresses"];
navigator.contacts.find(filter, onSuccess, onError, options);
function onSuccess(contacts) {
for (var i=0; i<contacts.length; i++) {
var phone = '';
var name = '';
var alt_phone = '';
var email = '';
var web = '';
var address = '';
if (contacts[i].phoneNumbers != null && contacts[i].phoneNumbers !=
'undefined'
&& contacts[i].displayName != null && contacts[i].displayName !=
'undefined') {
phone = contacts[i].phoneNumbers[0].value;
if(contacts[i].phoneNumbers[1] != null && contacts[i].phoneNumbers[1]
!= 'undefined'){
alt_phone = contacts[i].phoneNumbers[1].value;
}
if(contacts[i].emails){
email = contacts[i].emails[0].value;
}
if(contacts[i].urls){
web = contacts[i].urls[0].value;
}
if(contacts[i].addresses){
address = contacts[i].addresses[0].formatted;
}
name = contacts[i].displayName;
$('#import_contact_list').append('<li><a name="'+ name +'" phone="'+
phone +'" alt_phone="'+ alt_phone +'" email="'+ email +'" web="'+ web +'"
address="'+ address +'">'+
'<h2>'+ name +'</h2>'+
'<p>'+ phone +'</p>'+
'<p>'+ alt_phone +'</p>'+
'<p>'+ email +'</p></a>'+
'</li>');
}
}
$("#import_contact_list").listview("refresh");
}
78
//funzione chimata nel caso di errori
function onError(contactError) {
alert('onError!');
}
Come si può notare l'oggetto "contacts" prevede una funzione filtro che
viene utilizzata per selezionare solo gli attributi dei contatti che si desidera
recuperare. Nel caso specifico: il nome e cognome del contatto, i numeri di
telefono, le email, i siti web e gli indirizzi stradali. Viene così prodotta una
lista di contatti la cui lunghezza coincide con il numero di quelli presenti in
rubrica e a questo punto è possibile, mediante un ciclo "for", scorrere tale
lista e recuperare le informazioni di ogni contatto. Queste informazioni
vengo infine utilizzate per creare una lista completa di tutti i contatti i quali
risultano singolarmente selezionabili per essere importati nell'applicazione.
Device
Attraverso questo oggetto è possibile accedere alle informazioni software e
hardware riguardanti il dispositivo su cui è in esecuzione l'applicazione.
Queste informazioni vengono utilizzate per filtrare particolari porzioni di
codice, come ad esempio funzioni che fanno riferimento a plug-in di terze
parti, che potrebbero funzionare solo su alcune piattaforme mobile. In
effetti
benché
l'applicazione
realizzata
tramite
PhoneGap
sia
multipiattaforma, per implementare particolari funzionalità a volte è
79
necessario sfruttare plug-in di terze parti che spesso non vengono sviluppati
per tutte le piattaforme mobile. Nel caso dell'applicazione di cui è stato
effettuato il porting, è necessario accedere alla funzioni di chiamata, invio
SMS ed E-mail. Queste funzioni non sono previste nativamente da
PhoneGap per cui sono state aggiunte mediante plug-in; il problema
sollevato da questa soluzione però riguarda alcune linee di codice che non
risultano identiche nella piattaforma Android e iOS. Per garantire quindi
un'unica linea di sviluppo del codice sorgente è stata adottata una tecnica
che prevede il riconoscimento della piattaforma su cui viene eseguita
l'applicazione e la selezione del codice corretto per l'esecuzione di
determinate funzionalità.
Di seguito un esempio di utilizzo dell'oggetto "device":
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var element = document.getElementById('deviceProperties');
element.innerHTML = 'Device Name: '
+ device.model
+ '<br />' +
'Device Cordova: ' + device.cordova + '<br />' +
'Device Platform: ' + device.platform + '<br />' +
'Device UUID: '
+ device.uuid
+ '<br />' +
'Device Version: ' + device.version + '<br />';
}
80
Le proprietà dell'oggetto "device" sono le seguenti:
 model: ritorna il nome del dispositivo
 cordova: ritorna la versione di cordova utilizzata (l'engine di
PhoneGap)
 platform: ritorna il nome del sistema operativo in uso.
 uuid: ritorna un identificativo del dispositivo.
 version: ritorna la versione del sistema operativo.
Utilizzando la proprietà "platform" insieme a "version" è possibile
individuare con precisione il sistema operativo su cui è in esecuzione
l'applicazione e quindi scegliere il codice opportuno da eseguire per
accedere ad una determinata funzionalità.
Events
Gli eventi gestiti da PhoneGap sono una parte molto importante delle API.
Grazie ai "cordova lifecycle events" è possibile individuare e catturare
alcuni eventi che si possono presentare durante l'utilizzo dell'applicazione,
eventi che il framework jQuery Mobile non può gestire. Nella prima parte
di questo paragrafo è stato descritto l'evento "deviceready" per mostrare un
esempio di codice che utilizzava tale evento. In realtà "deviceready" è
essenziale per ogni applicazione PhoneGap poiché segnala quando le API
di PhoneGap sono correttamente caricate. Questo significa che tutte le
81
chiamate alle API PhoneGap possono avvenire solo dopo che l'evento
"deviceready" sia stato catturato. Di seguito una lista con una breve
descrizione degli eventi gestiti da PhoneGap:
 deviceready: l'evento che segnala il caricamento completo delle API
PhoneGap.
 pause: evento che segnala quando l'applicazione viene messa in
background dal sistema operativo.
 resume: segnala quando l'applicazione ritorna alla sua normale
esecuzione uscendo dallo stato di background.
 online: segnala la connessione del dispositivo alla rete internet.
 offline: segnala la disconnessione del dispositivo dalla rete internet.
 backbutton: segnala la pressione del pulsante back (Disponibile solo
su hardware che prevede la presenza di tale componente).
 batterycritical: segnala che la batteria del dispositivo è quasi
scarica.
 batterylow: segnala che la carica della batteria e minima.
 batterystatus: segnala quando cambia lo stato della batteria di
un'unita (1%), oppure quando viene collegata o scollegata dal
caricabatterie.
 menubutton: segnala la pressione del pulsante menu (Disponibile
solo su hardware che prevede la presenza di tale componente).
82
 searchbutton: segnala la pressione del pulsante menu (Disponibile
solo su Android).
 startcallbutton: segnala la pressione del pulsante avvio chiamata
(disponibile solo su blackberry).
 endcallbutton: segnala la pressione del pulsante fine chiamata
(disponibile solo su blackberry).
 volumedownbutton: segnala la pressione del pulsante per ridurre il
volume.
 volumeupbutton: segnala la pressione del pulsante per aumentare il
volume.
Segue un esempio di codice utilizzato per lo sviluppo dell'applicazione
multipiattaforma:
//event listner per intercettare il corretto caricamento delle API
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
//event
listner
per
intercettare
l'evento
//background
document.addEventListener("pause", onPause, false);
che
pone
l'app
in
//event listner per intercettare l'evento di connessione ad internet
document.addEventListener("online", onOnline, false);
}
function onPause(){
syncData();
}
83
function onOnline(){
syncData();
}
Dal codice di esempio si nota che solo l'evento "ondeviceready" viene
aggiunto all'inizio del codice, mentre gli altri eventi vengono aggiunti nella
funzione "onDeviceReady" che viene lanciata dopo il completo
caricamento delle API PhoneGap. Questo approccio viene utilizzato con
tutti gli altri eventi per evitare che le chiamate alla API non vengano
eseguite. Nell'applicazione, in particolare, i due eventi "pause" e "online"
vengono utilizzati per chiamare la funzione di sincronizzazione con il web
server, che verrà mostrata nel paragrafo successivo.
84
4.4 Interazione con un web server
L'applicazione
originale
Android
prevede
la
funzionalità
di
sincronizzazione con un web server basato sulla piattaforma Google App
Engine. Per questo motivo anche l'applicazione realizzata per il porting
multipiattaforma integra la stessa funzionalità; le tecnologie che
permettono lo scambio di dati nell'architettura server/client implementata
sono AJAX [11] e JSON [12].
AJAX
AJAX è una tecnica di sviluppo software per la realizzazione di
applicazioni web interattive (Rich Internet Application). Lo sviluppo di
applicazioni con AJAX si basa su uno scambio di dati in background fra
web browser e server, che consente l'aggiornamento dinamico di una
pagina web senza esplicito ricaricamento da parte dell'utente. AJAX è
asincrono nel senso che i dati extra sono richiesti al server e caricati in
background senza interferire con il comportamento della pagina esistente.
Normalmente le funzioni richiamate sono scritte con linguaggio JavaScript
e nel caso dell'applicazione in esame è stato utilizzato jQuery. AJAX è una
tecnica multipiattaforma utilizzabile cioè su molti sistemi operativi,
architetture informatiche e browser web. In realtà AJAX non è una
tecnologia individuale, piuttosto è un gruppo di tecnologie usate insieme.
85
Questa tecnica utilizza una combinazione di: HTML e CSS per il markup e
lo
stile,
JavaScript
per
la
manipolazione
del
DOM,
l'oggetto
XMLHttpRequest per l'interscambio asincrono dei dati. Inoltre utilizza un
protocollo di scambio dati come JSON.
Di seguito un esempio di chiamata AJAX tramite jQuery:
$.ajax({
type: "GET",
url: "http://www.sito.com/servlet.jsf",
dataType: "html",
data: "username=" + username + "&password=" + password,
success: function(response) {
alert(response);
},
error: function(jqXHR, textStatus, errorThrown) {
alert("error: "+jqXHR.responseText);
alert("error: "+textStatus);
alert("error: "+errorThrown);
}
});
}
La chiamata AJAX effettuata tramite jQuery prevede l'utilizzo di una serie
di parametri, i più importanti sono
 type: definisce il metodo di invio dei parametri al server (POST e
GET).
 url: definisce l'URL del server a cui inviare i dati, solitamente una
pagina di servizio che manipola i dati inviati dal client.
 dataType: il formato dei dati inviati al server.
 data: un array di dati che vengono inviati al server nella forma
chiave/valore.
86
Le funzioni "success" e "error" gestiscono rispettivamente l'esito dell'invio
dei dati al server e gli eventuali errori ed eccezioni sollevate. La funzione
"success" prevede l'utilizzo di un parametro che contiene la risposta del
server alla chiamata, mentre la funzione "error" implementa tre parametri
per la gestione degli errori.
JSON
JSON è l'acronimo di JavaScript Object Notation, un formato adatto per lo
scambio dei dati in applicazioni client/server. Viene usato in AJAX come
alternativa a XML/XSLT. La semplicità di JSON ne ha decretato una
rapida diffusione specialmente nella programmazione AJAX, il suo uso è
particolarmente semplice infatti in JavaScript l'interprete è in grado di
eseguirne il parsing tramite una semplice chiamata a funzione. I tipi di dato
supportati da JSON sono:
 booleani
 interi, reali e virgola mobile.
 stringhe
 array e array associativi
 null
87
Di seguito un esempio di dati organizzati in una struttura JSON:
var dati = {
"type": "menu",
"value": "File",
"items": [
{"value": "New", "action": "CreateNewDoc"},
{"value": "Open", "action": "OpenDoc"},
{"value": "Close", "action": "CloseDoc"}
]
}
Infine
alcune
porzioni
di
codice
utilizzate
nell'applicazione
multipiattaforma.
Verifica delle credenziali:
function checkCredentialSettings(){
//checkConnection verifica la presenza di connessione ad internet
if(checkConnection() == 1){
//messaggio di avviso per l'utente
$('#info_message').html('Verifica delle credenziali...');
//recupero delle credenziali di accesso dal form
var username = $('#settings_form input[name=nome_utente]').val();
var password = $('#settings_form input[name=password_utente]').val();
//verifica l'esistenza dell'account sul server
$.ajax({
type: "GET",
url: urlServerCheckCredential,
dataType: "html",
data: "username=" + username + "&password=" + password,
success: function(response) {
var ser_resp = response.split('<body>');
var check = ser_resp[1].replace('</body>','').replace(/^\s\s*/,
'').replace(/\s\s*$/, '');
if(check == 'OK'){
$( "#info_message" ).html('Credenziali corrette !');
}else{
88
$( "#info_message" ).html('Credenziali errate');
}
},
error: function(jqXHR, textStatus, errorThrown) {
$( "#info_message" ).html('Errore di connessione
con
il
server.');
}
});
}else{
$( "#info_message" ).html('Connessione assente.');
}
}
Sincronizzazione del dispositivo con il web server:
var html = '';
$.ajax({
type: "GET",
url: urlServerSync,
dataType: "html",
data: "username=" + username + "&password=" + password + "&change=" + lastChange,
success: function(response) {
//recupero il messaggio html come oggetto jquery
html = jQuery(response);
//eseguo il parsing html per recuperare ack e data, nel caso di data
eseguo un replace del carattere '+' con uno spazio
var ack = $.trim($(html).filter('ack').text());
var data = $.trim($(html).filter('data').text().replace(/\+/g, '%20'));
//decodifico i dati nel formato utf-8
data = decodeURIComponent(data);
//se ack è server devo aggiornare lo smartphone (client)
if(ack == 'server'){
//eseguo il parsing dei dati JSON
var parse_json = $.parseJSON(data);
//apro la connessione con il db
var db = window.openDatabase("Database","1.0","123nozze", 200000);
89
db.transaction(function(tx){
tx.executeSql('DELETE FROM UserJDO');
tx.executeSql('INSERT INTO UserJDO
(name, birthDate, email, city, sex) VALUES
("'+parse_json.wedding.bride.name+'","'+parse_json.wedding.bride.birthda
te+'","' + parse_json.wedding.bride.email + '", "'+ parse_json.wedding.bride.city
+'", "female")');
}
//se il server mi invia il json dell'agenda procedo all'aggiornamento
if(parse_json.hasOwnProperty('agenda')){
tx.executeSql('DELETE FROM AgendaItemJDO');
$.each(parse_json.agenda, function(i,item){
//aggiorno l'agenda
var data_agenda = parse_json.agenda[i].dataInizio;
//prendo solo la data eliminando l'ora
data_agenda = data_agenda.substr(0,10);
tx.executeSql('INSERT INTO AgendaItemJDO
(dataInizio,note) VALUES
("'+ data_agenda +'","'+ parse_json.agenda[i].notes +'")');
});
}
});
}
//se ack è client devo aggiornare il web server (server)
if(ack == 'client'){
var data_json = '';
//creo il json dal db
var db = window.openDatabase("Database", "1.0", "123nozze", 200000);
db.transaction(function(tx){
tx.executeSql('SELECT * FROM DbModifyJDO', [], jsonDati);
tx.executeSql('SELECT * FROM UserJDO WHERE sex="male"', [], jsonUser);
});
function jsonDati(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
data_json=data_json+'{"date":"'+results.rows.item(i).date +'",';
}
}
function jsonUser(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
90
data_json = data_json + '"user":{'+
'"id":1,'+
'"name":"'+results.rows.item(i).name+'",'+
'"email":"'+results.rows.item(i).email+'",'+
'"age":0,'+
'"sex":"MALE",'+
'"birthdate":"'+results.rows.item(i).birthDate+'",'+
'"activated":true,'+
'"disabled":"false",'+
'"city":"'+results.rows.item(i).city+'"'+
'},';
}
}
//chiudo l'array JSON
data_json = data_json + '}';
$.ajax({
type: "POST",
url: urlUpdateServerSync,
headers: {"Accept":"*/*","username": username, "data": data_json},
dataType: "html",
data: "username=" + username + "&data=" + data_json,
success: function(response) {
response = $.trim(response);
if(response == 'update_ok'){
$.mobile.changePage("#index_page");
$( "#sync_msg p" ).html('Sincronizzazione completata !');
}else{
$.mobile.changePage("#index_page");
$( "#sync_msg p" ).html('Errore di sincronizzazione.');
}
},
error: function(jqXHR, textStatus, errorThrown) {
$.mobile.changePage("#index_page");
$( "#sync_msg p" ).html('Errore: impossibile aggiornare
il server.');
}
});
}
});
Per la sincronizzazione con il web server sono state utilizzate più chiamate
AJAX per via del protocollo di comunicazione già presente nel lato server.
La prima parte dello script prevede una chiamata AJAX iniziale inviando al
server le credenziali di accesso e la data di ultima modifica dei dati sul
91
dispositivo mobile. Il server risponde con due informazioni racchiuse nei
tag "ack" e "data". Valutando il primo tag è possibile capire in che
direzione deve avvenire l'aggiornamento, mentre il secondo tag contiene i
dati nel caso di aggiornamento del dispositivo mobile.
Nel caso di aggiornamento del dispositivo vengono recuperati i dati in
formato JSON inviati dal server e aggiornato il database, mentre nel caso
opposto viene creato un pacchetto dati JSON e inviato tramite AJAX al
server per la sincronizzazione.
92
CAPITOLO 5
CONCLUSIONI E SVILUPPI FUTURI
Per verificare gli obiettivi raggiunti da questa tesi sono stati confrontati i
due metodi attualmente disponibili per lo sviluppo di applicazioni mobile.
Ed è stata così valutata la qualità delle applicazioni multipiattaforma
realizzate mediante un framework, rispetto alle applicazioni sviluppate in
ambienti nativi. La valutazione di queste tecniche è stata dettata da diversi
fattori chiave: in particolare disponendo dell'applicazione originale scritta
per il sistema operativo Android è stato possibile confrontare l'applicazione
multipiattaforma nel medesimo ambiente. Ovviamente le stesse valutazioni
sono state effettuate per altri ambienti come iOS e Windows Phone 8, però
in questi casi, non disponendo dell'applicazione scritta in questi ambienti è
stata analizzata la versione multipiattaforma secondo alcuni criteri come: le
prestazioni generali, il corretto rendering del layout, l'interazione con le
API native, ecc.
Queste valutazioni hanno dato la possibilità di comprendere i principali
vantaggi
e
i
conseguenti
svantaggi
dell'utilizzo
di
framework
multipiattaforma come alternativa allo sviluppo di applicazioni in ambienti
nativi. Tra i vantaggi che caratterizzano un framework multipiattaforma
sicuramente bisogna considerare la grande possibilità di adottare la
93
filosofia "write once run everywhere", ossia scrivere una sola volta il
codice per poterlo eseguire su più architetture differenti. Questa
caratteristica sicuramente è il motivo principale per cui nasce la necessità di
adottare un framework multipiattaforma. Oggi esistono molti ambienti
diversi tra loro e poter sviluppare (anche solo per i dispositivi più diffusi)
un applicativo richiede risorse non indifferenti, le quali vengono
risparmiate con l'utilizzo di un buon framework. Grazie a questo approccio
si ha la possibilità di seguire una sola linea di sviluppo, facilitando il
processo di versioning e manutenzione del codice, che in alternativa
dovrebbe essere differente per ogni sistema operativo mobile. Inoltre viene
utilizzato un set limitato di linguaggi e tecnologie, nel caso di PhoneGap
HTML5, CSS3 e JavaScript, per realizzare l'applicazione. Si può quindi
affermare che mediante l'utilizzo di un framework multipiattaforma per
ambienti mobile si riducono notevolmente i tempi di sviluppo e le risorse
impiegate nel progetto. Ovviamente a queste favorevoli considerazioni
seguono anche alcuni svantaggi che devono essere necessariamente
considerati prima dell'adozione di un framework multipiattaforma. In
primis, i framework ora disponibili potrebbero non supportare lo sviluppo
per alcuni sistemi operativi. Questo rappresenta un problema relativo,
poiché data la presenza di svariati OS Mobile si tende a realizzare
applicazioni per i dispositivi più diffusi evitando sistemi poco conosciuti.
Nel caso di PhoneGap, comunque, il problema non sussiste del tutto,
94
poiché i sistemi operativi supportati sono i più diffusi, comprendendo
anche Symbian OS il cui sviluppo è ormai concluso. Un problema più
rilevante riguarda le prestazioni dell'applicazione in termini di velocità di
esecuzione. In effetti le prestazioni di un'applicazione multipiattaforma
rispetto ad una scritta in ambiente nativo sono inferiori. Il motivo di tale
decadimento prestazionale è comunque da ricercare nel modo in cui
operano i diversi framework e in particolare PhoneGap. Ricorrere a FFI,
wrapper pattern e ovviamente alle WebView non aumenta le prestazioni
ma al contrario introduce un discreto overhead. Ciò non significa che
l'applicazione sia estremamente lenta e inutilizzabile, anzi confrontando
l'app nativa Android con la versione multipiattaforma si nota leggermente
la perdita di reattività e tutto ciò rimane comunque accettabile. Bisogna
ricordare che un'applicazione multipiattaforma per sua stessa natura non
può essere completamente paragonata ad una nativa, però con l'utilizzo di
alcuni accorgimenti si può realizzare un'app di ottima qualità garantendo
una user experience comparabile alle applicazioni native. Inoltre in un
ambiente multipiattaforma in cui l'applicazione viene eseguita grazie alle
WebView, le prestazioni della stessa app potrebbero essere differenti sui
diversi sistemi operativi mobile. Questo dipende dalle prestazioni dei
browser engine (es. Webkit, Trident, ecc.) utilizzati nei browser dei diversi
OS Mobile. Infine utilizzare un approccio multipiattaforma vuol dire
rendere il software totalmente dipendente dal framework, che potrebbe non
95
implementare alcune funzionalità previste invece dall'ambiente nativo.
Valutando tutti gli aspetti sopra elencati si può giungere ad una conclusione
oggettiva: l'utilizzo di un framework multipiattaforma non rappresenta
un'alternativa allo sviluppo in ambienti nativi, ma un metodo differente che
può affiancare le tradizionali tecniche di sviluppo. E' necessario valutare
in fase di progettazione gli obiettivi di un'applicazione e vedere se si presta
ad essere realizzata mediante un framework multipiattaforma o in ambienti
nativi. Un'applicazione che ha necessità di sfruttare la maggior parte delle
API native, che non richiede il rilascio su più OS Mobile e che necessità di
elevate prestazioni computazionali è sicuramente candidata ad essere
sviluppata in ambiente nativo. Al contrario, un'applicazione che richiede un
breve periodo di sviluppo, che deve essere rilasciata per più sistemi
operativi e non necessità di elevate prestazioni computazionali, è perfetta
per essere realizzata mediante un framework multipiattaforma. In ogni
modo PhoneGap, come altri framework, è una risorsa recente nell'ambito
delle applicazioni mobile. Ed avendo riscosso molto successo negli ultimi
anni, c'è motivo di credere che con le future release gli svantaggi che ora
limitano l'utilizzo completo delle risorse del dispositivo saranno via via
sempre minori.
Come spesso accade nel mondo dell'IT nulla è facilmente prevedibile e un
domani sviluppare applicazioni mobile multipiattaforma potrebbe divenire
un nuovo standard !
96
Appendice
Viene riportato parte del codice sviluppato per la realizzazione del porting:
1) Funzioni di servizio utilizzate più volte nella logica dell'applicazione:
//gestione primo avvio dell'applicazione
function firstStart(){
$.mobile.changePage( "#first_log", { role: "dialog" } );
$( "#first_log" ).dialog({ closeBtn: "none" });
$('#new_user').live('click',function(e){
$.mobile.changePage("#registrazione_page");
});
$('#login_user').live('click',function(e){
$.mobile.changePage("#settings_page");
});
}
//aggiornamento data di ultima modifica del database
function lastChangeUpdate(){
//formatto la data corrente nel formato YYYY-MM-DD HH:MM:SS
var lastChange = new Date();
97
lastChange=lastChange.getUTCFullYear()+"+AddZero(lastChange.getUTCMonth()+1)+"-"+AddZero(lastChange.getUTCDate())+"
"+AddZero(lastChange.getUTCHours())+":"+AddZero(lastChange.getUTCMinutes())+":"
+AddZero(lastChange.getUTCSeconds());
var db = window.openDatabase("Database", "1.0", "db", 200000);
db.transaction(function(tx) {
tx.executeSql('UPDATE DbModifyJDO SET date="'+ lastChange +'"');
});
}
//Gestione delle connessioni del dispositivo
function checkConnection() {
var networkState = navigator.connection.type;
//impostare lo states a 0 per le connessioni non ammesse
//esempio: se voglio aggiornare il dispositivo solo con connessione wifi e 3g
impostare ad 1 WIFI e CELL_3G
var states = {};
states[Connection.UNKNOWN] = 1;
states[Connection.ETHERNET] = 1;
states[Connection.WIFI]
= 1;
98
states[Connection.CELL_2G] = 1;
states[Connection.CELL_3G] = 1;
states[Connection.CELL_4G] = 1;
states[Connection.CELL]
states[Connection.NONE]
= 1;
= 0;
return states[networkState];
}
//Verifica delle credenziali utente
function checkCredentialSettings(){
if(checkConnection() == 1){
$('#info_message').html('Verifica delle credenziali...');
var username = $('#settings_form input[name=nome_utente]').val();
var password = $('#settings_form input[name=password_utente]').val();
//verifica l'esistenza dell'account sul server
$.ajax({
type: "GET",
url: urlServerCheckCredential,
dataType: "html",
data: "username=" + username + "&password=" + password,
success: function(response) {
99
var ser_resp = response.split('<body>');
var
check
=
ser_resp[1].replace('</body>','').replace(/^\s\s*/,
'').replace(/\s\s*$/, '');
if(check == 'OK'){
$( "#info_message" ).html('Credenziali corrette !');
}else{
$( "#info_message" ).html('Credenziali errate');
}
},
error: function(jqXHR, textStatus, errorThrown) {
$( "#info_message" ).html('Errore di connessione con il server.');
}
});
}else{
$( "#info_message" ).html('Connessione assente.');
}
}
//La seguente funzione viene eseguita quando l'app viene messa in background
function onPause() {
var db = window.openDatabase("Database", "1.0", "db", 200000);
db.transaction(function(tx){
100
tx.executeSql('SELECT * FROM DbModifyJDO', [], selectSync);
});
function selectSync(tx, results) {
var len = results.rows.length;
var sync = 0;
for (var i=0; i<len; i++){
sync = results.rows.item(i).sync;
}
if(sync == 1){
syncData();
}
}
}
101
2) Script per la gestione del calendario dinamico:
//Calendario dinamico con funzione di agenda
$('#calendario_page').live('pageshow',function(e){
$("#calendario_page").swiperight(function() {
$( "#calendario_page .mypanel" ).panel( "open" );
});
$('#calendar').fullCalendar('destroy');
$('#calendar').fullCalendar({
editable: true,
viewDisplay: function(view) {
var date = $("#calendar").fullCalendar('getDate');
var month_int = $.fullCalendar.formatDate(date, "MMMM");
$('#agenda_month').html(month_int);
var year_int = date.getFullYear();
$('#agenda_year').html(year_int);
//apro la connessione con il db
var db = window.openDatabase("Database", "1.0", "db", 200000);
//query che recupera tutti gli eventi in agenda
db.transaction(function(tx){
102
tx.executeSql("SELECT * FROM AgendaItemJDO GROUP BY dataInizio", [],
initCalendary);
});
function initCalendary(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
var data_evento = results.rows.item(i).dataInizio;
var myEvent = {
title:"",
allDay: true,
start: data_evento,
end: data_evento,
color: "#f05923",
backgroundColor: "#f05923"
};
$('#calendar').fullCalendar( 'renderEvent', myEvent );
}
$('.diario_row:last').css('border-bottom', 'solid 1px #999');
103
}
},
buttonText: {
today: 'Oggi',
day: 'Giorno',
week:'Settimana',
month:'Mese'
},
dayClick: function(date, allDay, jsEvent, view) {
var selectedDate = $.fullCalendar.formatDate( date, "yyyy-MM-dd");
$('#current_date').val(selectedDate);
$.mobile.changePage("#diario_page");
}
});
});
104
3)
Codice per la gestione di un singolo contatto della rubrica con
possibilità di telefonata, invio SMS ed e-mail:
$('#contatti_scheda_page').live('pageshow',function(e){
$("#contatti_scheda_page").swiperight(function() {
$( "#contatti_scheda_page .mypanel" ).panel( "open" );
});
var iddb_mod = $('#scheda_contatto_form input[name=id_contatto]').val();
//apro la connessione con il db
var db = window.openDatabase("Database", "1.0", "db", 200000);
db.transaction(function(tx){
tx.executeSql('SELECT * FROM ContattoRubricaJDO WHERE id='+ iddb_mod +'', [],
function(tx, results){
//setto i campi della pagina scheda contatto con le informazioni recuperate dal db
if(results.rows.item(0).preferiti == 1){
$('#preferito_scheda').attr('src','img/star_on.png');
}else{
$('#preferito_scheda').attr('src','img/star_off.png');
}
$('#preferito_scheda').attr('alt',iddb_mod);
105
$('#scheda_contatto_form
input[name=nome_scheda]').val(results.rows.item(0).nome);
var el = $('#scheda_contatto_form select[name=categoria_cont_scheda]');
el.val(results.rows.item(0).categoria).attr('selected',
true).siblings('option').removeAttr('selected');
el.selectmenu("refresh", true);
$('#scheda_contatto_form
input[name=tel1_scheda]').val(results.rows.item(0).telefono1);
$('#scheda_contatto_form
input[name=tel2_scheda]').val(results.rows.item(0).telefono2);
$('#scheda_contatto_form
input[name=email_cont_scheda]').val(results.rows.item(0).email);
$('#scheda_contatto_form
input[name=sito_web_scheda]').val(results.rows.item(0).sitoWeb);
$('#scheda_contatto_form
textarea[name=indirizzo_cont_scheda]').val(results.rows.item(0).indirizzo);
$('#scheda_contatto_form
textarea[name=note_cont_scheda]').val(results.rows.item(0).note);
$('#tel_contact a').attr('href','tel:' + results.rows.item(0).telefono1);
$('#sms_contact').live('click',function(e){
106
window.plugins.smsComposer.showSmsComposer("",[results.rows.item(0).telefono1])
;
});
$('#email_contact').live('click',function(e){
window.plugins.emailComposer.showEmailComposer("","",[results.rows.item(0).email
], [], [], true); //, []
});
});
});
});
107
BIBLIOGRAFIA
108
109
Ringraziamenti:
Come ogni tesi che si rispetti dedico quest'ultima parte al ringraziamento
delle persone che mi hanno sostenuto e accompagnato in questo percorso
fatto di gioia, sudore e passione. Ringrazio quindi:
Il Relatore di questa tesi: Prof. Luigi Troiano,
oltre ad essere un ottimo professore, negli ultimi mesi mi ha dimostrato di
essere anche una persona molto umana e disponibile.
Il Correlatore di questa tesi: Dott. Maria Carmela Vitelli,
che mi ha (in)seguito durante il tirocinio con tanta pazienza e
comprensione, grazie Maria Carmela !
I ragazzi di Intelligentia srl,
in particolare Davide De Pasquale per il supporto tecnico nei momenti di
difficoltà.
I miei genitori,
che mi hanno sempre sostenuto durante il mio lungo percorso e che hanno
sempre avuto fiducia in me.
I miei compagni di studio,
Claudio Fioretti, Antonio Ascione, Fabio Fusco, Antonio Di Meola,
Francesco Alfieri e in particolare Silvio Napoletano con cui ho condiviso
gli ultimi momenti prima del traguardo.
110
Gli amici di sempre,
Vincenzo Russo e Marco Frangiosa che mi hanno accompagnato in tutto il
mio percorso sapendomi distrarre quando la pressione era diventata
troppo alta.
Stefano Mastrocinque con cui ho condiviso momenti di studio e amicizia, in
quel di Lentace, indimenticabile !
Valeria De Rosa,
Per la sua costante e fondamentale presenza nel mio percorso di laurea,
nella stesura di questa tesi e ovviamente nella vita...
Grazie per avermi supportato e, soprattutto, sopportato !
111