Progettazione e Realizzazione di una Applicazione Android per l

UNIVERSITÀ DEGLI STUDI DI PARMA
DIPARTIMENTO DI MATEMATICA E
INFORMATICA
Corso di Laurea in Informatica
Tesi di Laurea
Progettazione e Realizzazione
di una Applicazione Android
per l’Accesso a Learning
Management System
Relatore:
Prof. Federico Bergenti
Candidato:
Bartolomeo Lombardi
Anno Accademico 2014/2015
Ai miei genitori, Vito e Teresa.
Alle mie sorelle, Mariagrazia e Giusy.
Indice
1 Learning Management System
1.1 Introduzione . . . . . . . . . . . . . .
1.2 CampusNet . . . . . . . . . . . . . .
1.2.1 Introduzione . . . . . . . . . .
1.2.2 Sezioni di CampusNet . . . .
1.2.3 Caratteristiche . . . . . . . .
1.2.4 Autenticazione . . . . . . . .
1.3 EasyCourse . . . . . . . . . . . . . .
1.3.1 Introduzione . . . . . . . . . .
1.3.2 Motivi dell’utilizzo . . . . . .
1.3.3 Vantaggi . . . . . . . . . . . .
1.3.4 Integrazione . . . . . . . . . .
1.4 ESSE3 . . . . . . . . . . . . . . . . .
1.4.1 Introduzione . . . . . . . . . .
1.4.2 Scopo dell’utilizzo . . . . . . .
1.4.3 Integrazione con altri sistemi .
1.4.4 Vantaggi . . . . . . . . . . . .
1.4.5 Usabilità . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
6
6
6
8
9
10
10
10
11
13
14
14
14
16
17
17
2 Fonti Dati Utilizzate
2.1 Pagine di CampusNet . . . . . .
2.1.1 Avvisi e news . . . . . .
2.1.2 Docenti . . . . . . . . .
2.1.3 Corsi . . . . . . . . . . .
2.2 Pagine di ESSE3 . . . . . . . .
2.2.1 Bacheca Appelli d’esame
2.2.2 Carriera universitaria . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
18
18
18
21
23
25
25
28
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Implementazione e Funzionamento
30
3.1 Strumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . 30
3.1.1 Android SDK . . . . . . . . . . . . . . . . . . . . . . . 30
2
3.2
3.3
3.1.2 Android Studio . . . . . . . . .
Libreria Jsoup . . . . . . . . . . . . . .
3.2.1 Introduzione . . . . . . . . . . .
3.2.2 Caricare documenti . . . . . . .
3.2.3 Estrazione e manipolazione dati
Architettura dell’applicazione . . . . .
3.3.1 View . . . . . . . . . . . . . . .
3.3.2 Model . . . . . . . . . . . . . .
3.3.3 Controller . . . . . . . . . . . .
Riferimenti bibliografici
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
33
33
33
35
41
42
54
66
70
3
Sommario
L’obiettivo di questa tesi è di indagare la possibilità di realizzare un’applicazione Android in grado di accedere ad alcune informazioni contenute in alcuni LMS, attualmente il corso di informatica fa riferimento a tre piattaforme
LMS.
Quindi lo scopo principale è stato quello di studiare la struttura di ogni
singola piattaforma e di implementare componenti in grado di ricavare informazioni da esse e gestirle nel miglior modo possibile. Le informazioni che
si è scelto di rendere accessibili attraverso l’applicazione sono: avvisi, news,
docenti, corsi, appelli e la propria carriera universitaria.
Il lavoro di tesi è organizzato nel modo seguente: Il capitolo 1 introduce
brevemente la nozione di Learning Management System e descrive più in
dettaglio le piattaforme utilizzate dal corso di informatica. Il capitolo 2
descrive le pagine HTML che sono state utilizzate per acquisire informazioni
riguardo le varie piattaforme. Il capitolo 3 descrive tutti i processi di sviluppo
di ogni singola sezione dell’applicazione partendo dagli strumenti e le librerie
utilizzate. Infine vi è spazio alle conclusioni e sviluppi futuri.
4
Capitolo 1
Learning Management System
1.1
Introduzione
Con il termine Learning Management System LMS si identifica una piattaforma applicativa in grado di erogare informazioni e servizi, tipicamente usata
per l’amministrazione di corsi di formazione e corsi di laurea.
LMS presidia la distribuzione dei corsi on-line, l’iscrizione degli studenti, il
tracciamento delle attività on-line. La maggior parte degli LMS sono strutturati in maniera tale da facilitarne, dovunque e in qualunque momento,
l’accesso e la gestione dei contenuti, la maggior parte di questi sistemi tengono conto dello studente principiante, facilitandone l’auto-iscrizione e l’accesso
ai corsi. Il motivo principale dell’uso è la capacità di erogare strumenti quali
creazione, gestione, memorizzazione dei contenuti didattici, composizione e
modularizzazione delle unità didattiche fondamentali, tracciamento e memorizzazione delle interazioni degli studenti. L’Università di Parma attualmente
adopera tali sistemi per offrire dati relativi ai corsi di laurea.
Il corso di studio di Informatica attualmente adopera tre LMS, ovvero
CampusNet http://informatica.unipr.it/cgi-bin/campusnet/home.pl
per informazioni relative al corso di studio, EasyCourse http://easycourse.
unipr.it/Orario/CdS_in_Matematica_e_Informatica/2014-2015/index.
html per gli orari delle lezioni e Esse3 https://unipr.esse3.cineca.it/
Home.do per la gestione amministrativa e carriera universitaria.
5
1.2 CampusNet
1.2
CampusNet
1.2.1
Introduzione
Learning Management System
CampusNet è una piattaforma informatica che consente di gestire in modo
facile ed intuitivo tutti i servizi Web relativi ad uno o più percorsi formativi
universitari. CampusNet mette a disposizione di studenti e docenti un ambiente Web altamente integrato al fine di facilitare e promuovere uno scambio
diretto di informazioni.
Attraverso CampusNet i docenti possono inserire tutte le informazioni
relative ai propri corsi di insegnamento, inserire materiale didattico, gestire
l’orario delle lezioni, pubblicare le date degli appelli, inserire i risultati degli
esami, prenotare un’aula, mettere avvisi nella homepage, proporre argomenti
di tesi, inviare email a gruppi di studenti, mantenere un proprio registro delle
attività.
Invece gli studenti, possono consultare le informazioni relative ai corsi,
scaricare il materiale didattico, iscriversi online agli appelli, inserire annunci
in bacheca, consultare l’agenda del docente, iscriversi ad attività proposte
dal docente, ricevere per email informazioni riguardanti corsi, appelli ed altre
attività.
1.2.2
Sezioni di CampusNet
Si possono notare le varie sezioni del sito dal menu principale, in figura 1.1,
che sono appunto i moduli base che mette a disposizione la piattaforma,
ovvero:
• Home viene descritto il corso di laurea e eventuali avvisi e news relativi
ad uno specifico corso o docente.
• Docenti contiene tutte le informazioni relative ai docenti: nome, indirizzo, contatti, ruolo, orario di ricevimento studenti e interessi. Ogni
docente può modificare le proprie informazioni in qualsiasi momento.
• Corsi gestisce i dati relativi ai corsi di insegnamento: nome del corso,
tipologia, crediti, obiettivi formativi, programma, testi consigliati. É
mantenuto dai singoli docenti che possono modificare solo i dati relativi
ai propri corsi.
• Orario Lezioni organizza l’orario delle lezioni dell’intero corso provvedendo alla prenotazione delle aule e fornisce strumenti per evitare
sovrapposizioni di orario o di aula. Gli orari possono essere inseriti dai
singoli docenti, dall’amministratore o dalla segreteria didattica.
6
1.2 CampusNet
Learning Management System
• Aule raccoglie le informazioni relative alle aule quali nome, capienza,
strumenti disponibili e responsabile. Un sistema di mappe interattive
che utilizza la Google Maps API https://developers.google.com/
maps/ permette una facile localizzazione dell’aula. A seconda delle
esigenze le strutture didattiche possono o meno essere inserite nel calendario delle prenotazioni. Oltre alle singole informazioni è possibile
effettuare prenotazioni degli spazi didattici, con possibilità di prenotazione per uno o più giorni, controllando automaticamente la disponibilità. Un sistema di ricerca permette di trovare un aula disponibile in
modo semplice e veloce.
• Appelli gestisce le date degli appelli, prenota l’aula e consente agli studenti di iscriversi online. Gli appelli possono essere inseriti dai docenti o
dalla segreteria didattica. Il docente può inserire i risultati degli esami
che verranno mostrati solo allo studente iscritto. Il docente può inviare
email al gruppo di studenti iscritti ad un determinato appello. Un sistema automatico invia un promemoria al docente alcuni giorni prima
dell’appello. Appelli imminenti vengono automaticamente visualizzati
nella homepage.
• Iscrizioni Esami consente agli studenti di iscriversi agli appelli d’esame. Studenti iscritti agli appelli possono ricevere comunicazioni email
da parte del docente e consultare il risultato del loro esame.
Figura 1.1: Homepage di CampusNet
7
1.2 CampusNet
1.2.3
Learning Management System
Caratteristiche
La caratteristica principale di CampusNet è senza dubbio l’estrema versatilità
del software all’adeguarsi alle innumerevoli situazioni presenti nel panorama
della didattica universitaria. Lo testimonia il fatto che CampusNet è in
grado di gestire percorsi formativi di facoltà letterarie, mediche e scientifiche
e soddisfare le esigenze di diversi atenei.
Le principali caratteristiche sono:
• Pagine Web create in modo dinamico a partire da informazioni inserite
direttamente dai docenti e dagli studenti.
• Informazioni non ridondanti, tutti i database sono interconnessi tra
loro in modo da permettere lo scambio di informazioni e facilitare
l’aggiornamento dei contenuti.
• Grafica omogenea e facilmente personalizzabile senza intervenire sul
codice.
• Amministrazione tramite Web browser.
• L’amministratore di un’istanza ha la possibilità di cambiare aspetto e
contenuti di tutte le pagine del sito da lui gestito.
• Pagine conformi ai requisiti della legge sull’accessibilità, inoltre è previsto un foglio di stile adatto per la navigazione da parte di persone
ipovedenti.
• Protezione dei dati, infatti tutte le informazioni sono modificabili dall’utente che le ha inserite o dall’amministratore dell’istanza.
• Tutti i contenuti possono essere facilmente esportati in formati tabulari,
CSV, XML, JSON.
• Tutte le form di inserimento dati si basano su uno schema comune al
fine di facilitare l’utilizzo da parte di docenti e studenti.
• Utilizzo della Google maps API per la creazione di mappe interattive
utili per localizzare strutture, aule, laboratori.
• I siti di CampusNet prevedono l’uso di AJAX per creare pagine con
contenuti ottenuti in modo asincrono mediante XMLHttpRequest.
8
1.2 CampusNet
1.2.4
Learning Management System
Autenticazione
Per accedere a risorse private come materiale didattico o iscrizione agli esami,
CampusNet prevede un’autenticazione; esistono quattro tipologie di utenti
che possono accedere:
• Guest
• Studenti
• Docenti
• Ammministratore
L’autenticazione degli studenti e dei docenti avviene o mediante server remoto LDAP o accesso federato CAS, quindi le credenziali sono le stesse per
l’accesso alla Web mail.
La piattaforma consiste di trenta database relazionali gestiti dal kernel
WODA (Web-Oriented-Database) attraverso dei file di definizione scritti in
Perl. L’architettura di CampusNet garantisce un’elevata velocità di esecuzione e questo rende facilmente la navigabilità con qualsiasi tipo di connessione.
La grafica risulta accessibile con qualsiasi tipo di browser. La struttura modulare del software permette una facile integrazione di CampusNet con altri
servizi Web.
CampusNet facilita notevolmente anche il lavoro del Webmaster mettendo
a disposizione una serie di strumenti avanzati per l’amministrazione del sito,
la creazione di pagine Web e la gestione dei contenuti. Tutte le operazioni di
amministrazione vengono interamente svolte attraverso Web browser.
9
1.3 EasyCourse
1.3
EasyCourse
1.3.1
Introduzione
Learning Management System
La seconda piattaforma utilizzata è EasyCourse http://easycourse.unipr.
it/Orario/CdS_in_Matematica_e_Informatica/2014-2015/index.html,
un sistema informatico per la gestione e la ottimizzazione degli orari delle
lezioni. EasyCourse è capace di contemperare gli interessi di studenti e docenti, restituendo un orario delle lezioni ottimizzato in funzione degli spazi
disponibili e dei vincoli inseriti dall’amministratore.
1.3.2
Motivi dell’utilizzo
La scelta è ricaduta su EasyCourse in quanto la compilazione manuale degli
orari produceva i seguenti problemi:
• Procedimento di pianificazione degli orari delle lezioni lungo e macchinoso;
• Assenza di un procedimento automatico di controllo;
• Recupero difficoltoso delle richieste dei docenti;
• Incastro laborioso delle lezioni dello studente;
• Aule sovraffollate;
• Errore umano.
Dopo aver inserito tutti i vincoli e gli orari delle lezioni, l’algoritmo considera tutti i dati e rispetto alle disponibilità delle aule restituisce il calendario
delle lezioni per ogni giorno della settimana. In figura 1.2 viene mostrata la
pagina principale della piattaforma.
10
1.3 EasyCourse
Learning Management System
Figura 1.2: Homepage di EasyCourse
1.3.3
Vantaggi
Il vantaggio principale della piattaforma è la possibilità di raccogliere dati in
modo automatica, ovvero tutti i docenti accedono al proprio profilo online
ed esprimono le loro disponibilità temporali.
I docenti possono esprimere preferenze del tipo:
• Fascia oraria;
• Giorni allocabili;
• Giorni di impossibilità;
• Giorni di sgradevolezza;
• Aule desiderate;
• Aule indifferenti;
• Aule non conforme;
• Aule sgradite.
11
1.3 EasyCourse
Learning Management System
Il docente fuori sede potrà scegliere di fare lezione giorni consecutivi e la
fascia oraria di inizio per il primo giorno e la fascia oraria di fine per l’ultimo
giorno. Successivamente è compito dell’amministratore scegliere se accettare
o modificare le preferenze desiderate dai docenti.
Il secondo vantaggio di EasyCourse è rappresentato dal fatto che in fase
di calcolo il software è in grado di prendere in considerazione regole inserite
dall’amministratore, ciascuna regola ha un peso, infatti l’algoritmo lavora su
un’insieme di regole ponderandole in funzione del suddetto peso. Ogni regola può essere impostata come vincolo, ossia irrinunciabile nell’elaborazione
dell’orario, oppure come obiettivo al quale può essere attribuito un livello di
importanza da 0 a 100. Una regola o un vincolo che riguardano le aule, i
docenti, gli insegnamenti e le esigenze degli studenti vengono quindi prese
in carico dall’algoritmo di ottimizzazione elaborandole ed ottenendo come
risultato l’orario delle lezioni.
Il terzo vantaggio di EasyCourse è poter revisionare manualmente l’orario
in modo semplice attraverso pratiche funzioni di gestione e controlli automatici. Il livello di revisione degli orari prevede diverse funzionalità, per esempio
è possibile visualizzare i conflitti per insegnamento di sovrapposizione, oppure le indisponibilità temporale dei docenti.
L’ultimo vantaggio importante della piattaforma è dato dalla possibilità di
pubblicare l’orario sul Web in modo automatico, in modo tale da renderlo
accessibile agli studenti e ai docenti, figura 1.3. Gli orari sono visualizzabili e organizzati per categoria: specifici docenti, aule e percorso di studio.
Cliccando su ogni cella è possibile visualizzare le informazioni del corso, per
esempio: insegnamento, crediti, nome del docente, sede e capienza dell’aula.
Mentre cliccando sul nome del docente è possibile visualizzare tutti i corsi
da egli sostenuti.
12
1.3 EasyCourse
Learning Management System
Figura 1.3: Tabella orario lezione
1.3.4
Integrazione
EasyCourse è completamente integrabile con sistemi informatici per la gestione dell’offerta didattica, come ESSE3 e SIADI http://www.cineca.it/it;
è possibile accedere a tale piattaforma con le credenziali di Ateneo, poiché
può comunicare con: LDAP, CAS, SHIBBOLETH; inoltre può gestire la prenotazione delle aule direttamente con: MRBS o EasyRoom. Una funzione
utile per gli studenti è Umemo, ovvero la possibilità di ricevere notifiche delle
lezioni tramite SMS.
13
1.4 ESSE3
1.4
1.4.1
Learning Management System
ESSE3
Introduzione
ESSE3 https://unipr.esse3.cineca.it/Home.do è il sistema informatico
di gestione della Didattica che offre a studenti e docenti un’area riservata
dove gestire le proprie iscrizioni agli esami, la pubblicazione degli appelli,
la gestione dei voti, il pagamento delle tasse, la partecipazione ad iniziative
organizzate dall’Ateneo, ecc. ESSE3 è un gestionale studenti per le segreterie
universitarie (servizi e segreteria studenti) nato per la gestione della riforma
universitaria italiana (D.M. 509) e per l’attuazione del Bologna Process in
Italia. Permette di gestire la carriera dello studente e l’organizzazione dell’Ateneo con un unico sistema informativo, una base dati coerente e accessi
Web per tutti gli utenti della didattica.
1.4.2
Scopo dell’utilizzo
Lo scopo principale è quello di fornire allo stesso tempo sia le funzionalità
rivolte all’amministrazione universitaria (segreteria studenti) per gestire tutto il percorso di attraversamento dello studente, sia i servizi Web a valore
aggiunto rivolti al singolo studente. ESSE3 è quindi al tempo stesso in tutte
le università che lo adottano il principale sistema di backoffice centrale ad
uso non solo delle segreterie studenti ma anche degli uffici che si occupano di
altri processi amministrativi legati alla gestione (presidenze, nuclei di valutazione, uffici tirocini e stage, uffici Erasmus, ecc..) e ma anche il sito Web di
riferimento dei servizi studente in università spesso integrato con altri servizi
del portale universitario o legati all’e-learning.
Le funzioni principali di ESSE3 sono suddivise in diverse aree:
• Area didattica:
– Gestione dell’offerta didattica per il controllo carriere;
– Gestione della carriera dello studente;
– Esami di profitto e certificazione titolo;
– Area Amministrativa;
– Gestione ammissioni;
– Gestione studente in ingresso e in uscita.
• Area tasse:
– Gestione tasse per studente;
14
1.4 ESSE3
Learning Management System
– Configurazione e operazioni massive;
– Gestione diritto allo studio;
– Chiusure contabili per la ragioneria.
• Area Post-Lauream:
– Gestione Esame di Stato;
– Gestione Scuole di Specializzazione;
– Gestione Dottorati di Ricerca;
– Gestione stage e tirocini professionalizzanti.
Oltre a queste funzioni applicative il sistema fornisce alcuni servizi comuni,
relativi a:
• Amministrazione del sistema;
• Funzioni di servizio;
• Statistiche e Reportistica generale.
É possibile notare in figura 1.4 le varie sezioni appena menzionate.
Figura 1.4: Homepage di ESSE3
15
1.4 ESSE3
1.4.3
Learning Management System
Integrazione con altri sistemi
La Programmazione Didattica trasmette a ESSE3 oltre all’assetto globale
dell’offerta formativa anche lo scadenzario del calendario accademico e la
pianificazione degli appelli d’esame. L’attivazione del modulo Community
consente, tramite un apposito gateway di comunicazione, l’integrazione con
il mondo delle piattaforme e-learning, facilitando enormemente la gestione
dell’iscrizione e dell’accesso ai corsi a distanza. Attraverso University Planner, arricchisce i propri servizi Web dei dati relativi agli orari delle lezioni e
della possibilità di consultare la disponibilità delle risorse.
L’integrazione di questo Modulo con U-GOV Risorse Umane garantisce
l’allineamento della anagrafica dei docenti, con il dettaglio dei dati necessario.
Fondamentale risulta anche l’integrazione con U-GOV Contabilità, legata a
tutta l’area finanziaria e di gestione delle tasse. Per quanto riguarda i moduli
di U-GOV Pianificazione e Controllo, sono già disponibili report standard di
analisi sui flussi degli studenti e di monitoraggio delle performance degli stessi
(esami di profitto, laurea, crediti acquisiti, etc).
ESSE3 consente ovviamente integrazioni con altri sistemi esterni quali:
• Sistemi MiUR: per tutti gli adempimenti necessari (Es: rilevazioni
statistiche, Anagrafe Nazionale Studenti).
• Banche ed enti tesorieri: il sistema gestisce il flusso finanziario dei dati
relativi ai pagamenti con banche o enti convenzionati con l’Università,
compresa la modalità di pagamento on line.
• Enti Regionali per il diritto allo studio: gestisce il flusso di dati delgi
studenti in uscita e in ingresso per determinare il criterio di assegnazione delle borse di studio.
• Banche dati studenti laureati: Consorzio Almalurea e Vulcano.
• Gestionali studenti CINECA di altre università: per quanto riguarda
la gestione dei trasferimenti esiste un protocollo di scambio fra dati
che facilità l’acquisizione/esportazione dei dati degli studenti trasferiti
fra un Ateneo e l’altro; per la verifica di autocertificazioni presentate
dagli studenti presso pubbliche amministrazioni è attivabile l’adesione
a E3Network.
• Sistemi per la gestione della mobilità internazionale: Move-on, Move-on
net (prodotti del partner Unisolution).
16
1.4 ESSE3
1.4.4
Learning Management System
Vantaggi
ESSE3 dispone di un’area Web sia per l’accesso pubblico che per l’interazione diretta da parte di studente e docente, i principali attori della didattica,
ma anche aziende e pubbliche amministrazioni. L’architettura permette una
portabilità multi-piattaforma dell’interfaccia, consentendo anche l’uso di postazioni remote (totem) e device portatili. Il servizio si configura come un
vero e proprio portale della didattica che si compone di un’area pubblica,
sulla quale ogni utente può liberamente consultare informazioni relative all’offerta didattica dell’Ateneo, ai test di ingresso di ammissione, agli appelli
e alle sessioni di laurea.
Dall’area pubblica ogni utente può effettuare una registrazione al portale,
che dal punto di vista del sistema, significa prendere in carico una nuova persona nella fase di prescrizione-orientamento all’Ateneo. Dall’area registrato,
il futuro studente può iscriversi ad un test di ammissione o immatricolarsi,
iniziando l’iter della carriera come studente effettivo.
Una volta immatricolato, dall’area riservata studente, si può accedere alle
funzionalità caratteristiche della gestione ordinaria del proprio iter universitario, sia dal punto di vista amministrativo che dal punto di vista didattico
(pagamento tasse, iscrizione, piano di studi, prenotazione esami, ecc..). Parallelamente anche il docente o in generale chi ha una parte nella gestione
della didattica ha un accesso privilegiato alla gestione della propria attività.
Esiste dunque un’area docente, riservata ai docenti titolari e/o ai loro collaboratori, da dove compilare il syllabus, il registro delle proprie attività, e
verbalizzare gli esami - anche con firma digitale.
1.4.5
Usabilità
Il modulo offre un’interfaccia client per le funzionalità di back-office (rivolta
essenzialmente al personale amministrativo interno) e un interfaccia Web
per gli attori principali della didattica (studenti e docenti). Entrambe sono
ampiamente customizzabili secondo le esigenze organizzative dell’Ateneo e
progettate secondo i criteri documentati di usabilità e accessibilità.
Le funzionalità gestionali di back office si avvalgono anche di strumenti
per l’organizzazione del lavoro (task manager), per rendere più immediato
l’utilizzo del software e ottimizzare la distribuzione del carico. Automatismi
configurabili consentono anche la generazione automatica di alcuni task, sulla
base del workflow impostato nel sistema.
17
Capitolo 2
Fonti Dati Utilizzate
In questo capitolo verranno descritte le pagine HTML che sono state utilizzate per acquisire informazioni riguardo le varie piattaforme. Le informazioni
sono poi state usate per l’implementazione di alcune sezioni dell’applicazione,
che verranno descritte poi nel capitolo seguente.
2.1
2.1.1
Pagine di CampusNet
Avvisi e news
Nella homepage di CampusNet è possibile notare una tabella contenente gli
avvisi importanti del corso di laurea, come: comunicazioni relative al corso,
esiti degli esami o modifiche relative agli orari di lezione. Ogni avviso è
identificato dal titolo e dal docente che lo ha creato e cliccando su questo si
viene reindirizzati alla pagina contenente la descrizione completa dell’avviso
con ulteriori precisazioni.
Figura 2.1: Elenco degli avvisi in CampusNet
18
2.1 Pagine di CampusNet
Fonti Dati Utilizzate
La figura 2.1 riporta un esempio di avvisi probabili della homepage di
CampusNet. Volendo ottenere informazioni in modo dinamico, si è scelto di
ricavare tali dati attraverso la lettura della pagina sorgente HTML, inoltre
tale tecnica è stata utilizzata per tutte le pagine delle piattaforme, descritte
in questo capitolo.
Prendendo il primo avviso come riferimento, possiamo notare l’HTML, generato dalla piattaforma.
<DIV C L A S S = H O M E - A V V I S I _ D C >
<TABLE C L A S S = A V V I S I - F O R M A T - 3 BORDER=0 CELLSPACING=2
CELLPADDING=2 WIDTH= " 100 " >
<TH C L A S S = A V V I S I - F O R M A T - 3 ALIGN=LEFT COLSPAN=2 >
<B > Avvisi </B > </TH >
<TD C L A S S = A V V I S I - F O R M A T - 3 >
<TR >
<A HREF= " http: // i n f o r m a t i c a . u n i p r . i t / cgi-bin /
campusnet / avvisi.pl / Show ?
_ i d = 9 a 9 a ; s o r t = U 1 ; s e a r c h = %7 btipologia %7 d %20%21%7
e %20 m %2 fprimopiano %2 fi %20 and %20%7 bdata %7 d %20 ge
%20%272015%2 f05 %2 f21 %27; hits=3 " >
Recupero lezioni di Intelligenza Artificiale
</A >
<B R > Dott. Federico Bergenti </TD > </TR >
...
</TABLE >
</DIV >
19
2.1 Pagine di CampusNet
Fonti Dati Utilizzate
Le informazioni relative agli avvisi e alle news, sono racchiuse in una sezione della pagina web, separate dal resto delle aree della pagina, pertanto
è risultato molto semplice focalizzarsi su questa porzione di codice in quanto caratterizzata dai tag <DIV> . . . </DIV>. Lo scopo dei DIV è quello
di fungere da semplici contenitori il cui aspetto, dimensione, posizione e
funzione sono definiti, dal designer della pagina web. Gli avvisi vengono
strutturati all’interno di una tabella, infatti ogni avviso/news è racchiuso dal
tag <TR>. . . </TR> il quale identifica ogni singola riga della tabella. Nel
<DIV> in questione è assegnato un attributo classe, questo ha permesso di
accedere alle informazioni della sezione. Il metodo usato per l’estrapolazione
dei dati verrà descritto nel capitolo seguente. Le informazioni raccolte per
identificare ogni singolo avviso/news sono:
• Titolo: posto sempre nel tag <A>. . . </A> infatti nell’avviso in questione possiamo rilevare il titolo dalla seguente riga: <A Recupero
lezioni di Intelligenza Artificiale</A>;
• Link: posto sempre come attributo HREF del tag <A HREF=link>;
• Autore: posto tra il tag <BR> e </TD>.
20
2.1 Pagine di CampusNet
2.1.2
Fonti Dati Utilizzate
Docenti
Nella sezione docenti della piattaforma è possibile ottenere la lista di tutti
i docenti che fanno parte del corso di laurea di informatica. Cliccando su
ognuno di essi è possibile avere ulteriori precisazioni come: nome, indirizzo, contatti, ruolo, orario di ricevimento studenti e interessi. La figura 2.2
ripropone la pagina in descrizione.
Figura 2.2: Elenco dei docenti
21
2.1 Pagine di CampusNet
Fonti Dati Utilizzate
Analizzando il sorgente della pagina in figura 2.2, è possibile notare che
la lista dei docenti è strutturata in una tabella, ogni riga a sua volta è
caratterizzata da: un’immagine, il nome completo del docente e la mail.
<DIV ID= " searchFromTo " C L AS S = SE A R CH - F R OM T O > <H3 > Da 1 a 17
di 17 < / H3 > </DIV >
<TABLE C L A S S = D O C E N T I - F O R M A T - D E F A U L T BORDER=0
CELLSPACING=2 CELLPADDING=2 WIDHT= " 100 " >
...
<TR >
<TD >
<A HREF= " / cgi-bin / campusnet / docenti.pl / Show ?
_id=bergenti;sort=DEFAULT;search=;hits=17 "
style= " color: #000000; t e x t - d e c o r a t i o n : n o n e ; " >
<B > Bergenti Dott. Federico </B >
</A >
</TD >
</TR >
...
</TABLE >
</DIV >
Questa porzione di codice mostra una singola riga della tabella, notiamo appunto che il tutto è contenuto in un <DIV>, dove all’interno viene stanziata
la tabella contenente tutti i docenti del corso di laurea. La tabella ha come
attributo CLASS=DOCENTI-FORMAT-DEFAULT, questo ha permesso al
parse di focalizzarsi solamente sulle informazioni contenute tra i tag <TABLE> . . . </TABLE>.
I dati utili per identificare ogni singolo docente sono:
• Nome: posto sempre nel tag <B>. . . </B>;
• Link: posto sempre come attributo HREF del tag <A HREF=link>.
22
2.1 Pagine di CampusNet
2.1.3
Fonti Dati Utilizzate
Corsi
Nella sezione corsi di CampusNet vengono gestiti tutti i dati relativi ai corsi
di insegnamento disponibili per il corso di laurea di informatica. Per ogni
insegnamento è possibile visualizzare: nome, tipologia, crediti, obiettivi formativi, programma, testi consigliati, ecc. La figura 2.3 riporta i primi tre
corsi disponibili.
Figura 2.3: Elenco di alcuni corsi di CampusNet
Analizzando il sorgente della pagina in figura 2.3, è possibile notare che
la lista dei corsi è strutturata in una tabella, ogni riga a sua volta è caratterizzata da un’ulteriore tabella che specifica il singolo corso e contiene:
un’immagine, il nome completo del corso, anno accademico, classe del corso
di studi e docente.
<DIV ID= " searchFromTo " C L AS S = SE A R CH - F R OM T O > <H3 > Da 1 a 26
di 26 < / H3 > </DIV >
<TABLE C L A S S = C O R S I - F O R M A T - D E F A U L T BORDER=0
CELLSPACING=0 CELLPADDING=1 width= " 100% " >
<TR > <TD C L A S S = C O R S I - F O R M A T - D E F A U L T WIDTH= " 99% "
VALIGN=TOP >
<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=1 width= "
100% " >
<TR > <TD C L A S S = C O R S I - F O R M A T - D E F A U L T >
<A HREF= " / cgi-bin / campusnet / corsi.pl / Show ?
_ i d = e a d 6 ; s o r t = D E F A U L T ; s e a r c h = %20%7 baa %7 d %20%3 d
%3 d %20%222014%2 d2015 %22%20; hits=26 " >
<B > Algebra e Geometria </B > </A > </TD > </TR >
<TR > <TD C L A S S = C O R S I - F O R M A T - D E F A U L T > Anno accademico:
2014/2015 </TD > </TR >
<TR > <TD C L A S S = C O R S I - F O R M A T - D E F A U L T > Corso di studi
in: L31 Informatica </TD > </TR >
23
2.1 Pagine di CampusNet
Fonti Dati Utilizzate
<TR > <TD C L A S S = C O R S I - F O R M A T - D E F A U L T > Docente:
<A HREF= " / cgi-bin / campusnet / docenti.pl / Show ?
_id=alessandrini " onmouseover= " ShowContactInfo
( ’ alessandrini ’) " onmouseout= " UnTip () " > Prof.
Lucia Alessandrini </A >
</TABLE >
...
</TABLE >
</DIV >
Anche in questo caso i dati sono ben strutturati secondo una tabella principale contenente tante sotto tabelle quante il numero di corsi disponibili sulla
pagina. Nell’esempio in questione possiamo notare la tabella principale avente come attributo CLASS=CORSI-FORMAT-DEFAULT e una sotto tabella
composta da quattro righe, formate da:
• Nome del corso: contenuto nella prima riga posto tra i tag <B>
. . . </B>;
• Anno accademico: seconda riga, quindi tra i tag <TR> . . . </TR>
che identificano la creazione di una nuova riga;
• Corso di appartenenza: anch’esso posto tra i tag <TR> . . . </TR>
come terza riga;
• Docente: come ultima riga della tabella posto tra i tag <A> . . . </A>.
Quindi presi in sequenza queste informazioni, poiché fisse per ogni singolo
corso, si è riusciti a creare un oggetto con appunto quattro attributi per
contenere i singoli dati per ogni corso.
24
2.2 Pagine di ESSE3
2.2
2.2.1
Fonti Dati Utilizzate
Pagine di ESSE3
Bacheca Appelli d’esame
La bacheca appelli d’esame su ESSE3 consente di accedere in sola consultazione alle informazioni sugli appelli d’esame disponibili per tutte i corsi
di studio dell’Università di Parma, infatti prima di avviare la ricerca è indispensabile impostare il dipartimento e il corso di studio di appartenenza.
La figura 2.4 mostra alcuni degli appelli del dipartimento di matematica e
informatica per il corso di studio di informatica.
Figura 2.4: Elenco di alcuni appelli di ESSE3
Le informazioni risultanti dalla ricerca sono:
• Nome appello;
• Periodo iscrizioni;
• Data e ora della prova;
• Tipo appello che può essere scritto o orale;
• Tipo prova poiché una prova può essere finale o parziale;
• Docenti che fanno parte della commissione;
• Numero iscritti all’appello.
Esaminando il sorgente della pagina Web in figura 2.4 possiamo notare la
struttura scelta dalla piattaforma per organizzare i tali dati.
25
2.2 Pagine di ESSE3
Fonti Dati Utilizzate
<TD ID= " " WIDTH= " " VALIGN= " TOP " COLSPAN= " " STYLE= " "
ROWSPAN= " " CLASS= " DETAIL_TABLE " >
[06149] INTELLIGENZA ARTIFICIALE </TD >
<TD ID= " " WIDTH= " " VALIGN= " TOP " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
02/06/2015 - 14/06/2015 </TD >
<TD ID= " " WIDTH= " " VALIGN= " TOP " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
<A CLASS= " DETAIL_TABLE " TITLE= " " HREF= "
DETTAGLIOTURNOOFFERTA.DO ">
17/06/2015 - 09:00 </A > </TD >
<TD ID= " " WIDTH= " " VALIGN= " TOP " COLSPAN= " " STYLE= " "
ROWSPAN= " " CLASS= " DETAIL_TABLE " >
SCRITTO </TD >
<TD ID= " " WIDTH= " " VALIGN= " " COLSPAN= " " STYLE= " "
ROWSPAN= " " CLASS= " DETAIL_TABLE " >
PROVA FINALE </TD >
<TD ID= " " WIDTH= " " VALIGN= " " COLSPAN= " " STYLE= " "
ROWSPAN= " " CLASS= " DETAIL_TABLE " >
<TABLE BORDER= " 0 " CELLSPACING= " 0 " CELLPADDING= " 0 " >
<TR CLASS= " DETAIL_TABLE " >
<TD VALIGN= " TOP " >
BERGENTI FEDERICO </TD >
</TR >
<TR CLASS= " DETAIL_TABLE " >
<TD VALIGN= " TOP " >
DAL PALU ’ ALESSANDRO </TD >
</TR >
</TABLE >
</TD >
<TD ID= " " WIDTH= " " VALIGN= " TOP " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
0 </TD >
</TR >
Si può notare dal frammento di codice la diversità della composizione scelta da ESSE3 rispetto le altre piattaforme, per esempio CampusNet mette
a disposizione la singola struttura che per la maggior parte delle volte è
una tabella contenuta in un <DIV> separatore, con un singolo attributo
CLASS per identificare un gruppo particolare di elementi. Mentre ESSE3
26
2.2 Pagine di ESSE3
Fonti Dati Utilizzate
contiene tutti gli appelli disponibili in una singola tabella dove per ogni riga
vengono incolonnate le informazioni precedentemente descritte riguardante
il singolo appello. Infatti possiamo notare i dati importanti posti tra i tag
<TD> . . . </TD> tutti avente un attributo CLASS=DETAIL_TABLE per
specificare il gruppo e le proprietà che gli elementi devono avere. Grazie all’attributo CLASS siamo riusciti ad ottenere l’insieme delle informazioni per
ogni singola riga che identifica il singolo appello, prendendo come esempio la
parte di codice descritta precedentemente, le informazioni chiave sono:
• Nome appello posto come prima colonna quindi tra i tag <TD>
. . . </TD>;
• Periodo iscrizione posto in seconda colonna tra i tag <TD> . . . </TD>;
• Data e ora posto come terza colonna tra i tag <A> . . . </A>;
• Tipo appello posto come quarta colonna tra i tag <TD> . . . </TD>;
• Tipo prova posto come quinta colonna tra i tag <TD> . . . </TD>;
• Docenti posto nella sotto tabella tra i tag <TD>. . . </TD>;
• Numero iscritti posto come ultima colonna tra i tag <TD> . . . </TD>
della tabella principale.
Presi questi dati in sequenza si è riusciti a costruire un oggetto appello per
poterlo utilizzare poi nell’applicazione in modo da costruire lo stesso elenco
degli appelli.
27
2.2 Pagine di ESSE3
2.2.2
Fonti Dati Utilizzate
Carriera universitaria
Tramite la piattaforma ESSE3 è possibile visualizzare la propria carriera
universitaria, l’elenco completo degli esami sostenuti che sono stati registrati
in segreteria, con il voto, la data e i CFU acquisiti, ma questo solo dopo
aver fatto l’accesso utilizzando le proprie credenziali di ateneo. La figura 2.5
mostra alcuni dei miei esami sostenuti.
Figura 2.5: Elenco di alcuni esami di ESSE3
Esaminando la figura, si può notare che la lista degli esami sostenuti è
costituita da una tabella, dove a ogni riga corrisponde un singolo esame ed
è caratterizzata da:
• Anno di corso;
• Codice e nome dell’insegnamento;
• Peso in CFU;
• Stato dell’esame (frequentato o sostenuto);
• Anno di frequenza;
• Voto e data di verbalizzazione.
La parte di codice che verrà riportata identifica la riga dell’esame di analisi
matematica, questo per poter studiare la struttura scelta dalla piattaforma
per la esposizione dei dati. Come si può notare segue le stesse line guida della
pagina bacheca degli appelli d’esame descritta nella sezione 2.2.1 di questo
capitolo. Infatti la disposizione è identica, una singola tabella contenente la
lista degli esami sostenuti, in ogni riga viene descritto un singolo esame con
le caratteristiche appena descritte.
28
2.2 Pagine di ESSE3
Fonti Dati Utilizzate
<TR >
<TD ID= " " WIDTH= " " VALIGN= " CENTER " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
1 </TD >
<TD ID= " " WIDTH= " " VALIGN= " CENTER " COLSPAN= " " STYLE= "
BORDER-RIGHT: 0 PX NONE TRASPARENT; " ROWSPAN= " "
CLASS= " D ET A I L_ T A BL E _ MI D D LE " >
<A HREF= " AUTH / STUDENTE / LIBRETTO / L I B R ET T O AD S C EL T A .D O ?
ADSCE_ID=7160219 & AMP;LREG_ID= " >
00013 - ANALISI MATEMATICA </A > </TD >
<TD ID= " " WIDTH= " " VALIGN= " CENTER " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
9 </TD >
<TD ID= " " WIDTH= " " VALIGN= " CENTER " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
2011/2012 </TD >
<TD ID= " " WIDTH= " " VALIGN= " CENTER " COLSPAN= " " STYLE= "
T EXT -A LI GN :C EN TE R; " ROWSPAN= " " CLASS= " DETAIL_TABLE
">
28& NBSP;- & NBSP;23 /07/2013 </TD >
</TR >
Il codice riportato mostra il contenuto della riga che identifica l’esame
di analisi matematica all’interno della tabella, infatti possiamo notare le caratteristiche poste tra i tag <TD> . . . </TD>. Seguendo il codice in modo
sequenziale troviamo: l’anno del corso, nome dell’insegnamento, CFU dell’esame, l’anno di frequenza e il voto e la data di verbalizzazione. Avendo questa
struttura fissa è risultato molto semplice estrapolare e salvare queste informazioni dalla pagina per poi poterle utilizzare nell’applicazione sviluppata
descritta nel capitolo seguente.
29
Capitolo 3
Implementazione e
Funzionamento
In questo capitolo verranno descritti tutti i processi per lo sviluppo di ogni
singola sezione dell’applicazione partendo dagli strumenti e le librerie utilizzate.
3.1
Strumenti utilizzati
Prima di entrare nei dettagli implementativi è bene mostrare i componenti
necessari per lo sviluppo dell’applicazione.
3.1.1
Android SDK
Android SDK (Software Development Kit) è un pacchetto di sviluppo per
applicazioni che contiene un set completo di API (Application Programming
Interface), librerie e strumenti di sviluppo utili a compilare, testare e debuggare applicazioni per Android. I linguaggi di programmazione alla base della
maggior parte delle applicazioni studiate per Android sono Java e C/C++.
Con l’SDK, scaricabile dal sito ufficiale https://developer.android.com/
sdk/index.html, sarà quindi possibile disporre sul proprio PC di un’interfaccia in grado di lanciare e modificare le applicazioni Android. É anche possibile ottenere i driver necessari per interfacciare il nostro dispositivo al pc,
per poter compilare ed eseguire l’applicazione direttamente sullo smartphone
senza dover usare l’emulatore dell’SDK.
30
3.1 Strumenti utilizzati
3.1.2
Implementazione e Funzionamento
Android Studio
Android Studio è l’ambiente di sviluppo integrato ufficiale firmato Google,
basato su IntelliJ IDEA https://www.jetbrains.com/idea/, per sviluppare su piattaforma Android, liberamente disponibile per Windows, Mac OS
X e Linux, sotto licenza Apache 2.0 al sito https://developer.android.
com/sdk/index.html. Un editor intelligente capace di offrire: completamento avanzato del codice, refactoring, e analisi; grazie a queste caratteristiche
rendono lo sviluppatore più produttivo e veloce nel completamento dell’applicazione. La figura 3.1 mostra la schermata di progettazione di Android
Studio.
Figura 3.1: Schermata di sviluppo di Android Studio
Una delle caratteristiche principali è la possibilità di avviare nuovi progetti utilizzando template messi a disposizione da Android Studio. Inoltre
è possibile configurarlo con GitHub https://github.com/ in modo da importare codice dal canale di Google oppure esportare e rendere pubblico il
proprio progetto. Con Android Studio risulta molto semplice sviluppare applicazioni multi-schermo (smartphone Android, tablet, Android Wear, TV
Android, Android Auto e Google Glass) poiché è integrato un modulo capace di facilitare la gestione delle risorse e delle risoluzioni come si può notare
dalla figura 3.2. Infatti ad ogni esecuzione/debug dell’applicazione è possibile
scegliere il profilo del dispositivo Android da emulare tra quelli più comuni.
31
3.1 Strumenti utilizzati
Implementazione e Funzionamento
Figura 3.2: Multi-schermo Android Studio
Uno dei punti di forza di Android Studio è la possibilità di creare APK
multipli dell’applicazione con caratteristiche magari differenti specificate nel
file build.gradle del progetto. Entrando nel dettaglio Gradle è un software per l’automazione dello sviluppo fondato sulle idee di Apache Ant
e Apache Maven, che introduce un Domain-Specific Language (DSL) basato su Groovy, al posto della più tradizionale modalità XML usata per
dichiarare la configurazione del progetto. Gradle https://gradle.org/
getting-started-android/ è stato progettato per sviluppi multi-progetto
che possono crescere fino a divenire abbastanza grandi e supporta sviluppi
incrementali determinando in modo intelligente quali parti del build tree sono
aggiornate (up-to-date), in modo che tutti i processi che dipendono solo da
quelle parti non avranno bisogno di essere ri-eseguiti; così facendo, il software
riduce significativamente il tempo di costruzione del progetto, in quanto, durante il nuovo tentativo di costruzione, verranno eseguite solo le attività il
cui codice è effettivamente stato alterato a partire dall’ultima costruzione
completata. Gradle supporta anche la costruzione del progetto per processi
concorrenti, il che consente di svolgere alcuni compiti durante la costruzione
(ad esempio, i test automatizzati attraverso gli unit test), eseguiti in parallelo
su più core della medesima CPU, su più CPU o su più computer.
32
3.2 Libreria Jsoup
3.2
3.2.1
Implementazione e Funzionamento
Libreria Jsoup
Introduzione
Jsoup http://jsoup.org/ è una potente libreria Java di parsing HTML/XML le cui API consentono di estrarre dati e manipolare in maniera
estremamente semplice documenti sfruttando le potenzialità di DOM, CSS
e metodi di accesso simili a quelli offerti da JQuery. Jsoup è un progetto
open source sviluppato da Jonathan Hedley e distribuito sotto liberale licenza MIT.
La libreria attualmente è in grado di fornire tali servizi:
• Caricare pagine HTML da un URL, un file o una stringa;
• Trovare ed estrarre i dati utilizzando un attraversamento DOM o dei
selettori CSS;
• Manipolare elementi HTML come attributi e testo;
• Ricevere l’output con una struttura ben ordinata;
• Organizzare i dati in una white-list sicura, per prevenire attacchi XSS.
Jsoup è stato progettato per analizzare tutte le varianti di HTML presenti
nella rete, poiché l’analizzatore crea per ogni pagina un albero di analisi
sensibile.
3.2.2
Caricare documenti
Jsoup come già menzionato permette di effettuare facilmente il parsing di
una pagina HTML fornita come stringa, da file o direttamente come URL.
In Jsoup un documento XML è rappresentato dalla classe Document, i nodi
del documento da istanze della classe Node e i tag da istanze della classe
Element.
Volendo effettuare il parsing a partire da una stringa, si utilizza il seguente
metodo statico:
String html = "<html><head><title>First parse</title></head>"
+ "<body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html, "http://example.com/");
33
3.2 Libreria Jsoup
Implementazione e Funzionamento
Il metodo parse(String html, String baseUri) crea un nuovo Document con
il codice HTML di ingresso. L’argomento baseUri viene utilizzato per risolvere URL relativi in URL assoluti, e deve essere impostato con l’URL
in cui il documento è stato prelevato. É possibile utilizzare il metodo di
base parse(String html) quando si conosce il codice HTML. Una volta che
si è ottenuto un Document, è possibile estrarre i dati utilizzando i metodi
appropriati della classe Document e delle sue super classi Element e Node.
Se invece si desidera ottenere il documento HTML direttamente dall’URL
si utilizza il metodo connect della classe Jsoup:
Document doc = Jsoup.connect("http://example.com/").get();
Il metodo connect(String url) crea una nuova connessione e get() recupera e
analizza la pagina HTML. Se dovesse verificarsi un errore durante il recupero,
viene lanciata un’eccezione della classe IOException, il quale può essere gestita. L’interfaccia di collegamento è stata progettata per poter concatenare
e costruire specifiche richieste, come ad esempio:
Documento doc = Jsoup.connect ("http://example.com")
.data ("query", "Java")
.userAgent ("Mozilla")
.cookie ("auth", "token")
.timeout (3000)
.post ();
Per lo sviluppo dell’applicazione è stato utilizzato principalmente questo metodo poiché per la piattaforma ESSE3 le richieste erano di tipo POST, a
differenza delle richieste GET di CampusNet.
L’ultimo modo possibile per ottenere il documento è la lettura del codice
HTML contenuto in un file attraverso il metodo statico della classe Jsoup:
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
Il metodo parse(file in, String charsetName, String baseUri) carica e analizza
un file contenente codice HTML. Se si verifica un errore durante il caricamento del file, esso genera un IOException, che si dovrebbe gestire in modo
appropriato.
34
3.2 Libreria Jsoup
3.2.3
Implementazione e Funzionamento
Estrazione e manipolazione dati
Prima di procedere a spiegare i metodi della classe Document è opportuno
ripetere alcuni concetti fondamentali. L’oggetto Document contiene tutti gli
elementi della pagina Web, disposti in un albero mantenendone la struttura
gerarchica originaria. Il contenuto delle pagine Web consiste in un documento
HTML contenente una struttura ad albero annidato di elementi, definiti da
marcatori detti tag, un esempio di struttura HTML è rappresentata in figura
3.3.
Figura 3.3: Esempio di struttura documento HTML
Il documento HTML contiene un tag di apertura, uno o più attributi di
tale elemento con i rispettivi valori (che possono definirne colore, stile, posizione, etc), il contenuto informativo (che può essere una stringa di testo o
una struttura di altri elementi) e infine un tag di chiusura. Un documento
comincia con la definizione del tipo di pagina, la quale segnala al browser le
specifiche HTML utilizzate, che permettono l’identificazione delle regole di
interpretazione per visualizzare correttamente la pagina. Segue poi la struttura degli elementi che compongono la pagina, compresa tra i tag <HTML>
. . . </HTML>, suddivisa in due sezioni principali:
• Header è l’intestazione contenente alcune informazioni di controllo
solitamente non visualizzabili.
• Body è il corpo del documento che contiene la parte informativa, cioè
la vera e propria pagina che sarà visualizzata dal browser.
35
3.2 Libreria Jsoup
Implementazione e Funzionamento
Una volta caricato il Document è possibile stanziare l’oggetto di tipo Element,
il fulcro centrale della libreria, poiché grazie ad esso è possibile rappresentare
un elemento (tag) ben specifico della pagina HTML con relativa sottostruttura. Quindi a partire da esso è possibile estrarre dati ed attraversare il grafo
dei nodi. Document è sottoclasse di Element con alcuni metodi specifici per
la radice di una pagina HTML, tra cui un metodo per ottenere il titolo e due
metodi per ottenere l’Element di header o del body della pagina. Ricordando
che un Document altro non è che l’Element radice di tutto l’albero.
Il codice che viene riportato utilizza il metodo di attraversamento DOM:
File input = new File ("/tmp/input.html");
Document doc = Jsoup.parse (input,"UTF-8","http://example.com/");
Element content = doc.getElementById("content");
Elements links = content.getElementsByTag("a");
for( Element link : links ){
String linkHref = link.attr("href");
String linkText = link.text();
}
Il tipo Elements fornisce un range di metodi tipo DOM per cercare elementi
e estrae e manipola i loro dati. I metodi get sono contestuali, chiamati su un
nodo genitore Document cerca gli elementi corrispondenti in quel documento;
mentre chiamate su un nodo figlio cerca gli elementi a partire da quel nodo.
In questo modo è possibile cercare i dati che si vogliono utilizzare, vediamo
ora i metodi applicabili su un oggetto Element per cercare i dati:
• getElementById(String id) individua l’elemento con l’id indicato.
L’id è un semplice attributo che deve però assumere per ogni elemento
un valore univoco in tutto il documento HTML.
• getElementsByTag(String tag) restituisce gli elementi di un certo
tipo, ovvero quelli con il tag di apertura coincidente a quello da noi
passato nella stringa tag.
• getElementsByClass(String className) restituisce gli elementi
con l’attributo class che assume il valore specificato.
• getElementsByAttribute(String key) restituisce gli elementi che
contengono un attributo così denominato. Esistono inoltre metodi associati che permettono di trovare elementi con attributi che iniziano,
36
3.2 Libreria Jsoup
Implementazione e Funzionamento
terminano o contengono la stringa desiderata; similmente esistono metodi che permettono di individuare elementi con attributi che assumono
un valore desiderato (o soddisfano una certa espressione).
I metodi forniti dalla libreria per attraversare la struttura, sono:
• siblingElements() restituisce tutti i nodi dell’elemento allo stesso
livello dell’albero;
• firstElementSibling() restituisce il primo figlio del nodo;
• lastElementSibling() restituisce l’ultimo figlio del nodo;
• nextElementSibling() restituisce il prossimo figlio;
• previousElementSibling() restituisce il figlio precedente;
• parent() restituisce il nodo genitore;
• parents() restituisce il nodo genitore e tutti gli ascendenti fino alla
radice del documento compresi;
• children() restituisce tutti i nodi figli;
• child(int index) restituisce il nodo figlio con l’indice indicato dal
parametro index.
Un metodo alternativo più potente per trovare elementi consiste nell’uso
dei selettori. I selettori permettono di selezionare e manipolare gli elementi
HTML. Gli elementi possono essere identificati attraverso l’id, la classe, gli
attributi, i valori degli attributi e altro ancora. In Jsoup la sintassi dei
selettori è quella utilizzata da CSS e jQuery. La porzione di codice propone
la ricerca con i selettori:
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
Elements links = doc.select("a[href]");
Element masthead = doc.select("div.masthead").first();
Elements resultLinks = doc.select("h3.r > a");
I selettori possono essere chiamati su oggetti di tipo: Document, Element
o Elements. Pertanto sono contestuali, quindi è possibile filtrare scegliendo
un elemento specifico oppure una catena di selettori; la selezione restituisce
37
3.2 Libreria Jsoup
Implementazione e Funzionamento
un elenco contenuto nell’oggetto chiamante Elements, il quale fornisce una
serie di metodi per estrarre e manipolare i risultati.
I selettori principali sono:
• tagname trova gli elementi per tag;
• #id trova gli elementi per id;
• .class trova gli elementi per classe;
• [attr] elementi con nome dell’attributo coincidente;
• [∧ attr] elementi con nome dell’attributo con tale prefisso;
• [attr=value] elementi con attributo che assume il valore dato;
• [attr∧ = value], [attr$ = value], [attr*= value] elementi con valore
dell’attributo che inizia per, finisce o contiene la stringa data;
I selettori possono essere combinati tra di loro, ad esempio:
• el# id elementi con ID, esempio div# logo;
• el.class elementi con classe class, esempio div.masthead;
• el[attr] elementi con attributo attr, esempio a[href];
• ancestor child trova gli elementi child discendenti dall’elemento ancestor;
• parent > child elementi child con genitore diretto parent;
• siblingA + siblingB trova gli elementi siblingB con fratello immediatamente precedente siblingA;
• siblingA ∼ siblingX cerca gli elementi siblingX precedente a siblingA,
esempio h1 ∼ p;
• el, el, el gruppo multiplo di selettori, cerca un unico elemento equivalente con i risultati di tutti i selettori, esempio div.logo.
Tutti i selettori possono essere combinati tra loro, da qui la loro potenza rispetto ai singoli metodi visti precedentemente, vediamo ora alcuni esempi su
codice HTML posto nel capitolo precedente. Per ottenere gli avvisi dalla pagina http://informatica.unipr.it/cgi-bin/campusnet/avvisi.pl, si è
usato la combinazione di più selettori, ovvero: td.AVVISI-FORMAT-3 a
38
3.2 Libreria Jsoup
Implementazione e Funzionamento
poiché le informazioni che si vogliono ottenere sono poste tra i tag <A>
. . . </A> nelle colonne della tabella (<TD> . . . </TD>) di classe=.AVVISIFORMAT-3.
Esistono infine alcuni pseudo selettori che permettono di trovare elementi
che contengono o non contengono elementi che soddisfano un certo selettore,
o che corrispondono ad una espressione regolare:
• :lt(n) cerca gli elementi figli il cui indice è inferiore rispetto a n (cioè
la sua posizione nell’albero DOM rispetto al suo genitore);
• :gt(n) cerca gli elementi figli il cui indice è maggiore rispetto a n;
• :eq(n) cerca gli elementi figli il cui indice è uguale a n;
• :has(seletor) cerca gli elementi che contengono elementi corrispondenti del selettore, esempio div:has(p);
• :not(selector) cerca gli elementi che non coincidono con il selettore;
• :contains(text) cerca gli elementi che contengono il testo dato;
• :containsOwn(text) cerca gli elementi che contengono direttamente
il testo dato;
• :matches(regex) cerca gli elementi il cui testo corrisponde all’espressione regolare specificata;
• :matchesOwn(regex) cerca gli elementi il cui testo proprio corrisponde all’espressione regolare specificata.
I selettori si applicano utilizzando il metodo select(String cssQuery) della
classe Element. Il metodo, come tutti gli altri metodi visti inizialmente,
restituisce la lista di elementi come un oggetto di tipo Elements, implementazione dell’interfaccia List di Java. Per estrarre dati da un oggetto Element
si utilizzano i seguenti metodi principali:
• text() restituisce il testo puro contenuto tra tag di apertura e tag di
chiusura;
• attr(String name) restituisce il valore dell’attributo name;
• html() restituisce il codice HTML racchiuso tra tag di apertura e
chiusura;
• outerHtml() restituisce il codice HTML esterno di definizione dell’elemento;
39
3.2 Libreria Jsoup
Implementazione e Funzionamento
Esistono infine metodi che consentono di aggiungere, modificare ed eliminare
attributi dell’elemento e metodi che permettono di modificare l’albero stesso,
aggiungere o rimuovendo elementi secondo la parentela desiderata. Questo
consente, se desiderato, di usare Jsoup per modificare o persino creare da
zero un documento HTML in modo procedurale con una chiara gerarchia.
É possibile testare direttamente la libreria, semplicemente collegandosi al
sito http://try.jsoup.org/ e incollare il codice HTML della pagina che si
vuole effettuare il parse, oppure inserendo il link, a questo punto si possono
applicare le diverse combinazioni di più selettori per ottenere le informazioni
ricercate.
40
3.3 Architettura dell’applicazione
3.3
Implementazione e Funzionamento
Architettura dell’applicazione
Come già accennato, l’obiettivo è stato quello di progettare e realizzare un
Applicazione per gli studenti del corso di Informatica capace di offrire informazioni importanti in tempo reale: avvisi, news, docenti, corsi, appelli e la
propria carriera. Prima di passare alla parte implementativa sarebbe meglio
chiarire l’architettura che si è scelto di utilizzare per poter realizzare tale
progetto.
Il pattern architetturale usato è il Model-View-Controller (MVC) uno dei
più diffusi nella programmazione object oriented e nello sviluppo di interfacce
grafiche in quanto rappresenta uno dei concetti fondamentali della programmazione ad oggetti e permette di strutturare l’applicazione in maniera molto
efficiente. Aumenta la coesione del nostro sistema software, in quanto ogni
singolo oggetto può ricoprire solo uno dei seguenti ruoli: modello, vista o controllore. Infatti ogni classe del progetto viene mirata a compiti ben specifici,
inoltre questi ruoli rappresentano una sorta di classificazione dell’oggetto che
stiamo utilizzando che risultano dunque essere elementi logicamente separati
ai quali però è consentita, ovviamente, una stretta comunicazione. Il grafico
in figura 3.4 illustra lo schema del design pattern utilizzato.
Figura 3.4: Schema design pattern MVC
Il pattern non solo stabilisce che ruolo deve avere un determinato oggetto
all’interno dell’applicazione, ma anche il modo in cui gli oggetti comunicano
tra di loro. Analizzando la struttura in figura 3.4 andiamo ad approfondire
i tipi di oggetti che il pattern definisce:
• Model: contiene i dati specifici dell’applicazione e si occupa di definire
tutte le varie procedure che effettuano la manipolazione dei dati stessi,
in lettura e scrittura. Il modello non può avere connessione diretta con
un oggetto di tipo view, in quanto ha il compito di gestire i dati che
non devono essere legati ad un particolare tipo di visualizzazione.
41
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
• View: il ruolo della vista è quello di presentare all’utente i dati contenuti all’interno di un modello. Concettualmente il modello è un oggetto
non concreto, mentre la vista è un oggetto concreto e con il quale l’utente può interagire. La vista è dunque una realizzazione di un oggetto
non concreto e mette a disposizione un’interfaccia per la modifica dei
dati contenuti nel modello. L’oggetto di tipo vista non deve avere un
riferimento esplicito ad un oggetto di tipo modello e quindi a questo
punto viene usato l’oggetto controllore.
• Controller: svolge la funzione di intermediario tra oggetti di tipo vista
ed oggetti di tipo modello. Un singolo controllore può avere un numero
di relazioni arbitrarie tra oggetti di tipo modello e vista, che possono
essere relazioni uno ad uno o molti a molti. Il controllore si occupa di
inizializzare la vista con i dati contenenti nel modello e informare alla
vista le modifiche dei dati subite dall’utente.
3.3.1
View
L’interfaccia utente è stata progettata seguendo un semplice layout che rende intuitivo l’utilizzo, il menu principale
permette la navigazione all’interno dell’applicazione. Utilizzando il GridLayout
come impaginazione della vista, è stato
possibile disporre bottoni e i relativi testi
al centro della pagina, in una griglia formata da quattro righe e tre colonne. In
figura 3.5 viene mostrata l’activity principale che si accede all’apertura dell’applicazione; composta da una griglia di sei
bottoni allineati, uno per ogni funzionalità implementata, che sono: news, avvisi, docenti, corsi, appelli e carriera. L’utente toccando l’icona relativa alla sezione nella quale desidera accedere, entrerà in una vista secondaria contenente le
informazioni desiderate.
Figura 3.5: Schermata principale
42
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
L’implementazione del layout di questa activity è avvenuta tramite codice
XML, specificando gli attributi per ottenere tale struttura.
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageButton
android:id="@+id/btnNews"
android:layout_column="0"
android:layout_row="0"
android:background="@drawable/news"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_column="0"
android:layout_row="1"
android:text="News"
android:textAlignment="center"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:textStyle="bold" />
...
</GridLayout>
Dalla porzione di codice appena mostrata si può osservare la struttura e la
disposizione di ogni oggetto nel punto della griglia, ovvero grazie agli attributi android:layout_column e android:layout_row si specifica la posizione
in cui si vuole mettere l’oggetto, possiamo notare che il bottone btnNews è
nella posizione layout_column=0 layout_row=0 ovvero la prima cella della
tabella, mentre il testo News è posizionato in layout_column=0 layout_row=1. Possiamo immaginare quindi la disposizione dei restanti componenti
seguendo tale struttura.
Per gestire le azioni che l’utente può svolgere dalla schermata è stata
scritta la classe HomeActivity la quale estende la classe Activity, per ogni
bottone viene descritta la procedura che l’applicazione deve svolgere. La porzione di codice mostra l’implementazione e le funzioni chiamate per realizzare
il bottone News.
43
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
public class HomeActivity extends Activity {
private ImageButton btnNews;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homepage);
btnNews = (ImageButton) findViewById(R.id.btnNews);
....
btnNews.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i;
i = new Intent(getApplicationContext(),
FragmentManagerActivity.class);
i.putExtra("fragment", 0);
startActivity(i);
}
});
Il metodo setContentView(R.layout.activity_homepage), non è altro un riferimento alla risorsa che si vuole prelevare, ossia il layout che si è descritto
precedentemente. Una volta caricata la risorsa è stato possibile stanziare
l’oggetto btnNews di tipo ImageButton e inizializzarlo con il metodo findViewById(R.id.btnNews) il quale cerca l’elemento all’interno del layout con
attributo id specificato tra parentesi. Volendo gestire il click sul bottone,
si è usato il metodo OnClickListener() e si è ridefinito l’istanza del metodo
OnClick(). In questo metodo è stato inserito il codice relativo al comportamento voluto quando il listener cattura l’evento a cui è associato. Data la
presenza di due activity all’interno dell’applicazione è stato necessario fornire una funzionalità di navigazione tra di esse e per fare questo si è fatto
uso degli Intent. Viene dichiarato un oggetto esplicito di tipo Intent e viene
istanziato fornendo come parametri il contesto dell’activity e l’activity versa
la quale è rivolto l’intent. Inoltre viene spedito un messaggio generalmente
chiamato Extras e può essere di varie tipologie, sia appartenenti a classi più
comuni che ad altre purché serializzabili. Il metodo i.putExtra(fragment, 0)
manda l’extra etichettato con una chiave fragment e il valore 0 che verrà poi
44
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
gestito nell’activity secondaria. Infine il metodo startActivity(i) dimostra
l’azione che si vuole attivare con questo Intent. Verrà spiegato in seguito
il motivo del messaggio che si è voluto mandare verso l’activity secondaria
FragmentManagerActivity.
News/Avvisi
Toccando l’icona relativi agli avvisi,
viene aperta una seconda activity istanziando un fragment contenente una lista
ordinata degli avvisi di CampusNet, caratterizzati da un titolo in grassetto di
colore blu e dall’autore presentato in corsivo di colore grigio, come noto in figura 3.6. Si è scelto di utilizzare i fragment per poter creare una sola activity
secondaria che svolge il ruolo di contenitore, ecco il motivo dell’invio del messaggio extra contenente la chiave fragment e
un valore intero, mediante il quale viene
istanziato il fragment con indice uguale
al valore ricevuto. Identica è la scelta
utilizzata per mostrare le news. Il componente di Android utilizzato per creare
la lista è ListView, un gruppo che mostra un elenco di elementi scorrevoli. Le
voci di elenco vengono inserite automaticamente utilizzando un adattatore che
Figura 3.6: Schermata avvisi
inietta i contenuti da una fonte, nel nostro caso dal database e converte ogni voce in una vista che verrà poi inserita
nella lista. Il layout per rappresentare la ListView è dato dal seguente codice
XML:
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listaAvvisi"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:footerDividersEnabled="true" />
45
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
I dati da mostrare e il layout di una singola cella vengono definiti da un
ListAdapter, infatti una ListView ha sempre associato un ListAdapter; è
una interfaccia Java implementata a secondo del contesto, nel nostro caso si
è scelta la classe ArrayAdapter poichè gestisce una lista di oggetti di tipo
Avviso. I valori sono stati inseriti con il metodo setText() nelle TextView
definite all’interno del layout layout_row_avvisi. Possiamo immaginare la
struttura del layout contenente due TextView, una per il titolo e l’altra per
l’autore dell’avviso. La porzione di codice implementa l’adattatore, il quale
nel metodo getView gestisce la lista di avvisi e la rende adattabile a una
qualsiasi ListView. Per ogni oggetto avviso vengono chiamati i metodi getTitolo() e getData(), poiché sono le informazioni che si vogliono visualizzare
all’interno della lista.
public class ArrayAdapterAvvisi extends ArrayAdapter<Avviso> {
private final Context context;
private final Avviso[] values;
public ArrayAdapterAvvisi(Context context, Avviso[] values) {
super(context, R.layout.layout_row_avvisi, values);
this.context = context;
this.values = values;
}
@Override
public View getView(int position, View convertView, ViewGroup
parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.layout_row_avvisi,
parent, false);
TextView titolo = (TextView)
rowView.findViewById(R.id.titolo);
TextView data = (TextView) rowView.findViewById(R.id.data);
titolo.setText(values[position].getTitolo());
data.setText(values[position].getData());
return rowView;
}
}
46
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Una volta creato l’adattatore basta semplicemente creare e poi istanziare
ArrayAdapterAvvisi(getActivity(), arrayAvvisi) passandogli come parametro
l’activity e l’array di oggetti da visualizzare nella lista. Possiamo notare dal
frammento di codice che una volta presi gli avvisi dalla base di dati vengono
poi inseriti all’interno di un array di tipo avvisi e adattati alla lista. Se il
database non contiene avvisi verrà mostrato un testo all’interno della schermata che indica la non presenza di avvisi. É stato utilizzato tale metodo per
la visualizzazione delle altre sezioni disponibili nell’applicazione, effettuando
opportune modifiche.
public class AvvisiFragment extends Fragment {
private ListView listView;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
...
databaseManager = new DatabaseManager(getActivity());
databaseManager.open();
avvisi = databaseManager.fetchAllAvvisi();
databaseManager.close();
if(avvisi.size() > 0) {
Avviso[] arrayAvvisi = new Avviso[avvisi.size()];
int i = 0;
for (Avviso a : avvisi) {
arrayAvvisi[i] = a;
i++;
}
ArrayAdapterAvvisi adapter = new
ArrayAdapterAvvisi(getActivity(), arrayAvvisi);
listView.setAdapter(adapter);
}else {
textAssenza.setText("Non ci sono avvisi.");
}
...
}
47
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Docenti
Toccando l’icona relativi ai docenti,
viene aperta la seconda activity istanziando un fragment contenente una lista
ordinata dei docenti presenti sulla piattaforma CampusNet, come noto in figura
3.7. La tecnica è praticamente la stessa usata per tutte le schermate avente
al loro interno una lista; le voci di elenco
vengono inserite automaticamente utilizzando in questo caso un adattatore predefinito layout.simple_list_item_1, che
inietta i contenuti da una fonte, nel nostro caso dal database e converte ogni
voce in una vista che verrà poi inserita
nella lista. In questo caso l’informazione visualizzata per ogni riga è il nome
completo del docente. Volendo ottenere
maggiori dettagli, per esempio: indirizzo, contatto, ruolo, orario di ricevimento
studenti e interessi, basterà cliccare sulla riga del docente di interesse. Il codice
Figura 3.7: Schermata docenti
propone la richiesta al database per ottenere l’elenco dei docenti e l’inserimento all’interno di un array di stringhe
per adattarli alla lista.
databaseManager.open();
docenti = databaseManager.fetchAllDocenti();
databaseManager.close();
String[] nome = new String[docenti.size()];
int i = 0;
for(Docente a: docenti){
nome[i] = a.getNome();
i++;
}
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(rootView.getContext(),
android.R.layout.simple_list_item_1 ,nome);
listaDocenti.setAdapter(adapter);
48
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Corsi
Toccando l’icona relativi ai corsi, viene aperta la seconda activity istanziando
un fragment contenente una lista ordinata dei corsi presenti sulla piattaforma
CampusNet, come è possibile notare in
figura 3.8. La struttura della lista è praticamente identica a quella degli avvisi.
Poiché le informazioni da visualizzare per
ogni riga sono due: il nome del corso e il
docente che lo tiene. Infatti l’adattatore
utilizzato in questo caso è simile a quello
precedentemente proposto; deve gestire
anche in questo caso due TextView, una
per il nome del corso e l’altra per il docente, infatti le informazioni visualizzate
per ogni riga sono due come si può notare
dalla figura 3.8. Volendo ottenere maggiori dettagli come: tipologia del corso,
crediti, obiettivi formativi, programma o
testi consigliati basterà cliccare sulla riga
del corso di interesse. Il codice ripropoFigura 3.8: Schermata corsi
ne la richiesta al database per ottenere
l’elenco dei corsi e l’inserimento all’interno di un array di tipo Corsi per
adattarli alla lista.
databaseManager = new DatabaseManager(getActivity());
databaseManager.open();
corsi = databaseManager.fetchAllCorsi();
databaseManager.close();
Corso[] arrayCorso = new Corso[corsi.size()];
int i = 0;
for(Corso a: corsi){
arrayCorso[i] = a;
i++;
}
ArrayAdapterCorsi adapter = new ArrayAdapterCorsi(getActivity(),
arrayCorso);
listCorsi.setAdapter(adapter);
49
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Appelli
Figura 3.9: Schermata appelli
Toccando l’icona relativi agli appelli, viene aperta la seconda activity istanziando un fragment contenente uno spinner e una lista inizialmente vuota. Lo
spinner fornisce un modo rapido per selezionare un valore da un elenco. Nello
stato di default, viene mostrato seleziona
il corso di laurea. Toccando su di esso si
visualizza un menu a discesa con tutti gli
altri corsi di studio disponibili: [1101] informatica, [3027] informatica, [0314] informatica, [0275] matematica e informatica. L’utente può selezionare il proprio
corso di studio e visualizzare dinamicamente gli appelli disponibili ordinati in
base alla data. Le informazioni che vengono visualizzate per ogni riga sono: il
corso (colore blu), il periodo di iscrizione
(colore grigio) e la data dell’appello (colore rosso). Il layout di tale schermata è
stato strutturato attraverso tale porzione di codice XML.
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/spinnerCorsi"
android:layout_gravity="center_horizontal"
android:clickable="true"
android:entries="@array/corso_di_studio"/>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listAppelli"
android:layout_gravity="center_horizontal" />
z
50
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Le informazioni sono state prese dalla piattaforma ESSE3 all’url https:
//unipr.esse3.cineca.it/ListaAppelliOfferta.do con richieste di tipo
POST, restringendo il campo di ricerca solo per i corsi di studio di informatica. In questo caso i dati non risiedono nella base di dati poiché sono in
continuo aggiornamento. Quindi la scelta è stata di far gestire al controllore
i vari scaricamenti delle informazioni ogni volta che si effettua la scelta del
corso di studio. L’adattatore in questo caso gestisce l’oggetto di tipo Appello con il layout di riga stabilito, infatti viene creato un oggetto di tipo
View e instanziato con il layout layout_row_appelli. Dalla porzione codice
è possibile osservare quanto detto.
private final Context context;
private final Appello[] values;
public ArrayAdapterAppelli(Context context, Appello[] values) {
super(context, R.layout.layout_row_appelli, values);
this.context = context;
this.values = values;
}
@Override
public View getView(int position, View convertView, ViewGroup
parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.layout_row_appelli,
parent, false);
TextView titolo = (TextView) rowView.findViewById(R.id.titolo);
TextView periodo = (TextView) rowView.findViewById(R.id.periodo);
TextView data = (TextView) rowView.findViewById(R.id.dataEora);
titolo.setText(values[position].getTitolo());
periodo.setText(values[position].getPeriodoIscrizione());
data.setText(values[position].getDataOraEsame());
return rowView;
}
51
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Carriera
Toccando l’ultima icona relativa alla carriera, viene aperta la seconda activity istanziando un fragment contenente
un WebViewClient e una ListView inizialmente non visibile data la presenza
della WebView. Una WebView è un tipo di View che permette di visualizzare pagine Web. La sua utilità principale
è quella di permettere di integrare con
una Web application o più in generale
un sito Web nella propria applicazione.
Il motore del WebView risiede nella libreria WebKit già inclusa all’interno di
Android per questo possiamo parlare di
questo componente come di un browser
vero e proprio in grado di eseguire Javascript e mostrare layout nella maniera
più completa possibile. La figura 3.10
mostra il primo accesso a questa sezione,
viene visualizzata la pagina di autenticazione poiché i dati che si vogliono recuFigura 3.10: Schermata login
perare sono accessibili solo dopo essersi
autenticati alla piattaforma ESSE3. Per ottenere questo risultato si è creato
un layout come il seguente.
<WebView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/webView"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:layout_alignParentStart="true"
android:layout_below="@+id/space" />
52
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Una volta che l’utente ha immesso la
propria mail e password dell’ateneo, la
WebViewClient viene resa invisibile e si
visualizza la lista degli esami verbalizzati con il rispettivo voto e la media ponderata dei voti nella barra delle azioni,
come in figura 3.11. Anche in questo caso i dati vengono presi direttamente dalla piattaforma ESSE3. Per poter ricavare l’HTML di tale pagina si è fatto uso
di una strategia che tante applicazioni al
giorno d’oggi adottano, ovvero una volta istanziato l’oggetto di tipo WebView
viene fatto Overraide del metodo onPageFinished() ciò vuol dire riuscire a gestire il fine del caricamento di ogni pagina
Web. Infatti nella porzioni di codice si
può notare lo statement if con la clausola url.equals() la quale una volta finita di
caricare la pagina del libretto universitario su ESSE3 la WebView viene settata
Figura 3.11: Schermata carriera
in modalità invisibile. La strategia utilizzata per poter ottenere i dati verrà poi descritta in maniera più accurata
nella prossima sezione di questo capitolo.
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
if(url.equals("https://unipr.esse3.cineca.it/auth/"
+"studente/Libretto/LibrettoHome.do")){
view.setVisibility(View.GONE);
...
53
3.3 Architettura dell’applicazione
3.3.2
Implementazione e Funzionamento
Model
Database
I dati vengono organizzati in una base dati, questa scelta è stata pensata per
poter permettere agli utenti di accedere alle informazioni anche in assenza di
segnale internet (3G) ovvero la cosiddetta modalità offline.
SQLite è un leggerissimo database engine transazionale che occupa poco spazio in memoria e sul disco (da circa 4KiB a circa 350KiB, a seconda
del target della piattaforma), pertanto è la tecnologia perfetta per creare e
gestire database in un ambiente come quello degli applicativi mobile, dove le risorse sono molto limitate e dunque è molto importante ottimizzarne
l’utilizzo. A differenza della maggior parte degli altri database SQL, SQLite non ha un processo server separato ma legge e scrive direttamente su
file ordinari sul disco: possiede praticamente tutti gli strumenti principali che caratterizzato i più importanti database SQL (tabelle, viste, indici,
trigger) ed il codice è distribuito gratuitamente sia per scopi commerciali
che privati. SQLite è più diffuso di quanto ci si aspetterebbe, infatti viene
utilizzato in moltissimi applicativi e device che utilizziamo quotidianamente, come: iPhone, Mozilla Firefox, negli smartphone Symbian, in Skype,
in diversi applicativi PHP o Adobe AIR, e in molti altri progetti. Un database SQLite è, nella pratica, un file: possiamo spostarlo, copiarlo in un
altro sistema (ad esempio dallo smartphone al nostro pc) e continuerà a
funzionare tutto regolarmente. Android fa uso di SQLite, considerato appunto il motore di database più diffuso al mondo. Rispetta tutti i requisiti
di efficienza e disponibilità di cui si è detto. Si tratta, in realtà, di una
libreria software che permette di gestire in un unico file un database relazionale. Oltretutto è un progetto in continua espansione che mette a disposizione molti aspetti dei moderni DBMS: View, Trigger, transazioni, indici
oltre al comunissimo e comodissimo interfacciamento con linguaggio SQL.
Android memorizza i file seguendo uno schema preciso; il file SQLite del database dell’applicazione viene memorizzato in una directory il cui percorso
è: /data/data/it.unipr.informatica.bartolomeo.appcampusnet/databases dove it.unipr.informatica.bartolomeo.appcampusnet è il nome del package dell’applicativo. Per accedere al file del database dalla nostra app abbiamo
ovviamente a disposizione gli statements SQL. Grazie alle classi che vedremo
e che permettono di implementare helper e adapter. Il database implementato per questa applicazione è molto semplice e intuitivo poiché tutte le tabelle
contenute nella struttura sono indipendenti, ciò vuol dire non avere relazioni
logiche tra le entità. I dati che si sono scelti di tenere in modalità offline
sono: le news, gli avvisi, i docenti e i corsi. Infatti il codice propone l’im-
54
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
plementazione della classe helper che permette di creare il database con le
rispettive tabelle.
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "database.db";
private static final String DATABASE_CREATE_AVVISI =
"CREATE TABLE AVVISI(" +
"TITOLO TEXT PRIMARY KEY," +
"LINK TEXT NOT NULL," +
"DATA TEXT NOT NULL)";
private static final String DATABASE_CREATE_NEWS =
"CREATE TABLE NEWS(" +
"TITOLO TEXT PRIMARY KEY," +
"LINK TEXT NOT NULL," +
"DATA TEXT NOT NULL)";
private static final String DATABASE_CREATE_DOCENTI =
"CREATE TABLE DOCENTI(" +
"NOME TEXT PRIMARY KEY," +
"LINK TEXT NOT NULL)";
private static final String DATABASE_CREATE_CORSI =
"CREATE TABLE CORSI(" +
"NOME TEXT PRIMARY KEY," +
"LINK TEXT NOT NULL," +
"DOCENTE TEXT NOT NULL)";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE_AVVISI);
database.execSQL(DATABASE_CREATE_NEWS);
database.execSQL(DATABASE_CREATE_DOCENTI);
database.execSQL(DATABASE_CREATE_CORSI);
}
}
55
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Dal codice proposto è possibile notare l’override del metodo onCreate, questo
viene invocato nel momento in cui non si trova nello spazio dell’applicazione
un database con nome indicato nel costruttore. Il metodo verrà invocato
una sola volta, ovvero quando il database non esiste ancora. Il parametro
passato in input è un riferimento all’oggetto che astrae il database. La classe
SQLiteDatabase è importantissima in quanto per suo tramite invieremo i
comandi di gestione dei dati. Il metodo onCreate contiene la query SQL che
serve a creare il contenuto del database.
Una volta creato il database si è scelto di affidare la gestione del database alla classe che prende il nome di DatabaseManager, l’obiettivo di tale
classe è avere metodi che eseguono query SQL sulla base di dati per estrarre
e manipolare dati da questa. La classe DatabaseManager fornisce per l’appunto l’interfaccia diretta per manipolare il database. Un Manager è, nella
pratica, un livello di astrazione: fornisce tutta una serie di metodi che, una
volta testati opportunamente, permettono la creazione, la cancellazione, la
modifica o la manipolazione di record nel database.
Inizialmente vengono definite alcune proprietà e alcune costanti che verranno utilizzate massicciamente all’interno della classe: la prima costante
definisce il nome della tabella mentre le altre definiscono il nome di ogni
colonna della stessa. Da questo momento in poi per l’implementazione del
manager verranno utilizzate queste costanti nelle query SQL, in modo da
poterne modificare il nome in caso di necessità senza dover riscrivere tutte
le query. Il codice riportato mostra soltanto i metodi implementati per la
tabella avvisi poiché sono logicamente equivalenti alle altre.
public class DatabaseManager {
private static final String DATABASE_TABLE_AVVISI = "AVVISI";
...
public static final String KEY_TITOLO = "TITOLO";
public static final String KEY_LINK = "LINK";
public static final String KEY_DATA = "DATA";
...
public DatabaseManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
return this;
}
public void close() {
dbHelper.close();
}
56
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
private ContentValues createContentValues(String titolo, String
link, String data) {
ContentValues values = new ContentValues();
values.put( KEY_TITOLO, titolo );
values.put( KEY_LINK, link );
values.put( KEY_DATA, data);
return values;
}
public long createAvviso(String titolo, String link, String data){
ContentValues initialValues =
createContentValues(titolo,link,data);
return database.insertOrThrow(DATABASE_TABLE_AVVISI, null,
initialValues);
}
public int deleteAvvisi() {
return database.delete(DATABASE_TABLE_AVVISI, null, null);
}
public List<Avviso> fetchAllAvvisi() {
Cursor cursor;
List<Avviso> avvisoList = new LinkedList<Avviso>();
cursor = database.query(DATABASE_TABLE_AVVISI,
new String[] {KEY_TITOLO, KEY_LINK, KEY_DATA},
null, null, null, null, null);
while(cursor.moveToNext()){
String titolo = cursor.getString(cursor
.getColumnIndex(DatabaseManager.KEY_TITOLO));
String link = cursor.getString(cursor
.getColumnIndex(DatabaseManager.KEY_LINK));
String data = cursor.getString(cursor
.getColumnIndex(DatabaseManager.KEY_DATA));
avvisoList.add(new Avviso(titolo, link, data));
}
cursor.close();
return avvisoList;
}
I metodi open() e close(), sono metodi che verranno usati ogni volta che si
dovrà comunicare con il database: sarà intatti sufficiente chiamare questi
57
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
metodi per poter lavorare con il database. All’interno viene stanziato un oggetto di tipo DatabaseHelper che, come abbiamo visto, fornisce l’interfaccia
di creazione/aggiornamento/gestione del database. Dopodiché viene invocato il metodo getWritetableDatabase() definito in SQLiteOpenHelper, il quale
restituisce un oggetto database in modalità lettura/scrittura attivo fino a
quando non viene richiamato il metodo close(). La prima volta che viene
chiamato getWritableDatabase() il database viene aperto e vengono automaticamente richiamato il metodo onCreate() e se necessario anche il metodo
onOpen(). Il metodo close() invece non fa altro che richiamare il metodo
close() della classe SQLiteOpenHelper, il quale chiude ogni oggetto database
aperto.
Un metodo molto importante è quello che implementa l’operazione di
creazione di un nuovo avviso. createAvviso() richiede 3 parametri in ingresso: titolo, link e data, i parametri utili per identificare un nuovo avviso. Dopo
aver richiamato createContentValues(), il metodo utilizza l’istanza SQLiteDatabse database correttamente impostata nel metodo open() per richiamare
la funzione insertOrThrow(): questa permette di inserire un record nel database e prende come parametri in input il nome della tabella in cui inserire
la riga in questo caso DATABASE_TABLE_AVVISI, un valore che indica
come comportarsi nel caso in cui i valori iniziali siano vuoti ed infine i valori
da inserire. Il secondo parametro stabilisce il comportamento della insert
nel caso in cui initialValues sia vuoto: se non impostato a null, il parametro
indica in quali colonne vogliamo che sia inserito un null lì dove initialValues
è vuoto.
Il metodo deleteAvvisi() è molto più semplice ed intuitivo, poiché va a
cancellare l’intera tabella contenente gli avvisi. É stato utile in quanto ad
ogni avvio dell’applicazione viene richiamato tale metodo per semplificare la
sincronizzazione, ovvero cancellare e aggiornare con i nuovi avvisi disponibili
su CampusNet.
L’ultimo metodo è fetchAllAvvisi() ovvero è un metodo che permette di
recuperare tutti gli avvisi presenti nel nostro database. Si utilizza un istanza della classe SQLiteDatabase per richiamare la funzione specifica messa
a disposizione dalla piattaforma Android, in questo caso a noi interessa la
funzione query(). Questa funzione, in base ai parametri passati, genera le
query necessarie per interrogare il database e recuperare i dati che ci interessano. La funzione query() restituisce un oggetto di tipo Cursor: questo
oggetto fornisce l’accesso in modalità di lettura-scrittura al result set restituito dalla query. Il metodo moveToNext() utilizzato nella clausola del while,
muove il cursore alla riga successiva, dalla quale possiamo ricavare il valore
che ci interessa attraverso il metodo getColumnIndex(), che restituisce l’indice della colonna richiesta, e il metodo getString(), che invece ritorna come
58
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
stringa il valore della colonna richiesta. Ad ogni ciclo quindi vengono presi
gli avvisi dalla base di dati e vengono aggiunti alla lista avvisoList di tipo List<Avviso>, infatti all’interno dell’applicativo le informazioni vengono
condivise da tali liste una per ogni tipo di oggetto: News, Avviso, Docenti e
Corsi. Alla fine dell’estrazione delle informazioni viene chiuso il cursore con
il metodo close(), che rilascia tutte le risorse invalidandolo completamente.
Modello dei dati
La manipolazione dei dati è avvenuta grazie alla presenza di classi modello,
la base della programmazione orientata agli oggetti. Il modello comprende
attributi e metodi che verranno condivisi da tutti gli oggetti creati a partire
dalla classe. Un oggetto infatti è l’istanza di una classe. Una classe è identificabile come un tipo di dato astratto che può rappresentare l’astrazione di
un concetto. Fondamentalmente, vengono definiti al proprio interno lo stato,
i cui dati sono memorizzati nelle cosiddette variabili membro o attributi, e il
comportamento dell’entità di cui è rappresentazione, descritto da blocchi di
codice riutilizzabili chiamati metodi.
Quando il parser ricava le informazioni dalla rete deve istanziare dei nuovi
oggetti di tipo: news/avviso, docenti, corsi, appello e esame. Queste classi
contengono degli attributi, ovvero le proprietà che ogni oggetto deve avere.
Ad esempio nel caso degli avvisi, come abbiamo appena visto, nel database
vengono salvate tre informazioni per ogni entità: il titolo, il link e la data
di emissione. Quindi ogni avviso predispone di attributi, infatti è stata costruita una classe avente delle proprietà che il singolo oggetto avviso deve
contenere. Si sono implementate cinque classi diverse una per ogni sezione
dell’applicativo, poiché le informazioni da ricavare sono totalmente differenti
tra di loro, a parte per le news che hanno la stessa forma degli avvisi.
La classe Avviso/News:
private String titolo;
private String link;
private String data;
La classe Docente:
private String nome;
private String link;
59
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
La classe Corso:
private String nome;
private String link;
private String docente;
La classe Appello contiene tali attributi:
private
private
private
private
private
private
private
String
String
String
String
String
String
String
titolo;
periodoIscrizione;
dataOraEsame;
tipo;
tipoProva;
docente;
numIscritti;
La classe Esame per la manipolazione dei dati della sezione carriera ha
queste proprietà:
private
private
private
private
private
private
String
String
String
String
String
String
annoCorso;
nome;
crediti;
aaFreq;
voto;
data;
Tutte le classi appena descritte contengono i metodi getter e setter per ogni
attributo, generalmente le classi definiscono metodi getter che forniscono
accesso in lettura e metodi setter che forniscono accesso in scrittura a una
data proprietà.
Il discorso può sembrare assurdo ma un oggetto non è altro che un elemento dotato di attributi e metodi o in parole povere di variabili e funzioni, la
cosa importante da dire è che tali attributi sono nascosti, o meglio incapsulati
nei metodi, in modo tale da nascondere agli utenti le proprie caratteristiche
le quali sono accessibili solo mediante le funzioni. Un metodo getter non
accetta parametri e restituisce sempre un valore, mentre un metodo setter
accetta sempre un parametro e non restituisce mai valori.
60
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Parse pagine CampusNet
Per ricavare le informazioni dalle varie piattaforme si è fatto uso della libreria Jsoup, descritta precedentemente. Verranno mostrare le varie classi
che permettono di effettuare il parse delle pagine Web, mostrando le varie
configurazioni di selettori CSS. Per implementare ed eseguire il parse si è
fatto uso della classe AsyncTask. La classe AsyncTask di Android consente
di effettuare delle elaborazioni in background e quindi gestire i risultati dal
tread principale. Solitamente viene utilizzata per eseguire operazioni di breve
durata. Ogni elaborazione asincrona si compone di circa 4 passi che Android
esegue consecutivamente e sono onPreExecute, doInBackground, onProgressUpdate and onPostExecute. Infatti le operazioni vengono svolte nel metodo
doInBackground ovvero le azioni che il task deve svolgere in background.
public class ParseAvvisiNews extends
AsyncTask<String,Void,List<Avviso>>{
private List<Avviso> avvisi;
@Override
protected List<Avviso> doInBackground(String... strings) {
avvisi = new LinkedList<>();
try {
Document doc = Jsoup.connect(strings[0]).get();
Elements topicList = doc.select(strings[1]);
Avviso avviso;
ParseData p = new ParseData();
for(Element topic : topicList){
String titolo = topic.text();
String link = topic.attr("href");
String data = p.doInBackground(link).toString();
avviso = new Avviso(titolo, link, data);
avvisi.add(avviso);
}
} catch (Throwable t) {
t.printStackTrace();
}
return avvisi;
}
}
61
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
La porzione di codice proposta implementa la classe per effettuare il parse
degli avvisi/news, passando come parametri l’url e il selettore. Il metodo
connect(String url) crea una nuova connessione e get() recupera e analizza la
pagina HTML. Una volta che si è ottenuto il Document, è possibile estrarre i
dati utilizzando i metodi appropriati della classe Document e delle sue super
classi Element e Node. A questo punto è possibile stanziare l’oggetto di tipo
Element, il fulcro centrale della libreria, poiché grazie ad esso è possibile rappresentare un elemento (tag) ben specifico della pagina HTML con relativa
sottostruttura. Quindi a partire da esso è possibile estrarre dati ed attraversare il grafo dei nodi. Infatti scorrendo la lista topicList per ogni Element si
catturano i dati: titolo, link e data. Il tutto viene poi impacchettato in un
oggetto di tipo Avviso e si aggiunge alla lista di avvisi.
All’apertura dell’applicativo viene invocata una funzione che popola il
database, infatti viene istanziato un oggetto di tipo ParseAvvisiNews e viene invocato il metodo che effettua appunto il parse della pagina http://
informatica.unipr.it/cgi-bin/campusnet/home.pl.
try {
avvisi = parseAvvisiNews.execute(new String[]{
"http://informatica.unipr.it/cgi-bin/campusnet/avvisi.pl",
"td.AVVISI-FORMAT-3 a"}).get();
news = parseURLnews.execute(new String[]{
"http://informatica.unipr.it/cgi-bin/campusnet/avvisi.pl",
"td.AVVISI-FORMAT-4 a"}).get();
}catch (Exception e) {
...
}
if(!avvisi.isEmpty()) {
databaseManager.deleteAvvisi();
for (Avviso avviso : avvisi) {
String titolo = avviso.getTitolo();
String link = avviso.getLink();
String data = avviso.getData();
databaseManager.createAvviso(titolo, link, data);
}
}
62
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Per ottenere gli avvisi dalla pagina di CampusNet, si è usato la combinazione di più selettori, come è possibile notare dalla porzione di codice, ovvero: td.AVVISI-FORMAT-3 a poiché le informazioni che si vogliono ottenere sono poste tra i tag <A> . . . </A> nelle colonne della tabella (<TD>
. . . </TD>) di classe=.AVVISI-FORMAT-3.
Parse pagine ESSE3
Le classi che effettuano parsing delle pagine contenente informazioni sui docenti e i corsi sono logicamente equivalenti poiché sono pagine della stessa
piattaforma CampusNet, mentre è doveroso descrivere la tecnica utilizzata
per ricavare i dati dal Learning Management System ESSE3, strutturata in
maniera diversa rispetto questa. La piattaforma ESSE3 comunica mediante
richieste POST, la libreria Jsoup permette questo metodo di connessione,
infatti possiamo notare dalla porzione di codice che viene invocato un metodo durante l’inizializzazione della connect passando come parametro una
costante Connection.Method.POST.
@Override
protected List<Appello> doInBackground(String... strings) {
private List<Appello> appelloList;
appelloList = new LinkedList<>();
try {
Connection.Response res = Jsoup.connect(strings[0])
.data("TIPO_FORM","1","fac_id","10024",
"cds_id",strings[1],"ad_id","",
"docente_id","","data","",
"btnSubmit","Avvia+Ricerca")
.method(Connection.Method.POST)
.execute();
Document doc = res.parse();
Elements topicList = doc.select(strings[2]);
Appello appello = new Appello();
for(Element topic : topicList) {
...
appelloList.add(appello);
appello = new Appello();
}
}
return appelloList;
}
63
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Con il metodo data() è possibile aggiungere parametri di richiesta di dati, tali
parametri vengono inviati nel corpo della richiesta. Questo poiché alla pagina
https://unipr.esse3.cineca.it/ListaAppelliOfferta.do prima di avviare la ricerca degli appelli, è doveroso impostare il dipartimento e il corso
di studio; grazie al metodo data() è possibile inviare tali parametri utili alla
ricerca che identificano gli appelli del corso di informatica.
La tecnica che si è scelta di usare per ricavare il sorgente HTML per la
sezione della carriera è molto interessante, in quanto dopo svariati tentativi
di approccio con il protocollo che gestisce la parte di login CAS non è risultato semplice. Non è stato possibile creare una connessione neanche con Jsoup,
in quanto la libreria non supporta tale protocollo usato dall’università di Parma. Questo perché la piattaforma ESSE3 usa un servizio per l’autenticazione
Single Sign-On (SSO) di una comunità Web, in questo caso l’università di
Parma. I componenti sono: il CAS server, che gestisce l’identità della comunità (Identity Provider) e i Service Providers, che forniscono le applicazioni
che richiedono accesso autenticato. Utilizza un proprio protocollo basato su
HTTP e sulla redirezione dell’url.
Figura 3.12: Autenticazione CAS
Quindi per ovviare questo problema di scambi e redirezione dei pacchetti,
l’idea è stata quella di effettuare il login attraverso una WebView, cosicché
la gestione dei pacchetti è lasciata direttamente al componente. Una volta
64
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
effettuato il login, viene nascosta la WebView e viene chiamata una funzione JavaScript per la cattura e l’esportazione su file del sorgente HTML
della pagina contenente la tabella dei voti, https://unipr.esse3.cineca.
it/auth/studente/Libretto/LibrettoHome.do. Questo metodo è risultato più veloce ed efficiente per accedere al sorgente HTML. Viene mostrato
la porzione di codice che identifica, una volta resa la WebView invisibile, la
chiamata showHTML mediante interfaccia JavaScript.
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
if(url.equals("https://unipr.esse3.cineca.it/auth/"
+"studente/Libretto/LibrettoHome.do")){
view.setVisibility(View.GONE);
view.loadUrl("javascript:window.HtmlViewer.showHTML"+
"(’<html>’
+document.getElementsByTagName(’html’)[0].innerHTML
+’</html>’);");
...
}
}
}
La classe con il metodo showHTML è definita come @JavascriptInterface, ovvero una procedura JavaScript, infatti viene invocata nella query javascript:window.HtmlViewer.showHTML, l’output della funzione restituisce
una stringa contenente l’HTML completo della pagina.
class MyJavaScriptInterface {
private Context ctx;
MyJavaScriptInterface(Context ctx) {
this.ctx = rootView.getContext();
}
@JavascriptInterface
public void showHTML(String html) {
write(html);
}
...
}
65
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
Una volta ottenuto l’HTML viene passato alla funzione write() che presa
una stringa, crea un file di contenuto html nella memoria del dispositivo.
Dopodiché viene fatto partire il parse caricando tale file contente l’HTML.
La porzione di codice mostra il caricamento del file è l’istanza dell’albero
Elements con il selettore .detail_table td.
File input = new File("/storage/emulated/0/html.txt");
Document doc = null;
try {
doc = Jsoup.parse(input, "UTF-8", "");
} catch (IOException e) {
e.printStackTrace();
}
Elements topicList = doc.select(".detail_table td");
A questo punto è bastato scorrere la lista di Element e settare le proprietà
per ogni oggetto esame creato, ovvero: anno di corso, codice e nome dell’insegnamento, CFU, stato dell’esame, anno di frequenza, voto e data di
verbalizzazione. Nella lista si è scelto di far visualizzare solamente il nome e
il voto come noto in figura 3.11, le informazioni più importanti che uno studente vorrebbe visualizzare. Inoltre prendendo tutti i voti e i rispettivi cfu si è
calcolato il voto base di laure, visualizzabile nella ActionBar dell’applicativo.
3.3.3
Controller
Il Controller, come descritto in precedenza è tutto quello che riguarda la
logica che avviene dopo l’interazione con l’utente e va a modificare lo stato
del model e delle view. Nell’applicativo esiste solo una classe che fa parte delle categoria controllore, con il ruolo di notificare la presenza di nuovi
avvisi sulla piattaforma CampusNet. Per poter implementare dei task che
lavorano a lunga durata o addirittura indeterminata, si è fatto uso di un
componente Android, i Service. Esistono diversi tipi di Service, ma per la
tipologia di lavoro che deve svolgere all’interno dell’applicativo, si sono usati
i service Started. La loro particolarità è di essere eseguiti in background
indefinitamente anche se la componente che li ha avviati viene terminata.
Generalmente non offrono interazione con il chiamante e proseguono finché
non vengono interrotti. Inoltre i Service Started sono da prediligere per operazioni con una loro finalità indipendente dallo stato delle altre applicazioni,
infatti si occuperà di scaricare gli avvisi dalla pagina Web e confrontarli con
66
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
quelli contenuti nella base dati, notificherà con un pop-up l’avviso che non è
presente nel database. Il servizio viene avviato alla prima esecuzione dell’applicazione in background. La porzione di codice mostra l’implementazione
della procedura appena descritta.
private void startService() {
timer.scheduleAtFixedRate(new mainTask(), 60000*15, 60000*15);
}
private class mainTask extends TimerTask {
public void run() {
boolean nuovo;
parseAvvisiNews = new ParseAvvisiNews();
try{
avvisiOnline = parseAvvisiNews.execute(new String[]{
"http://informatica.unipr.it/cgi-bin/"
+ "campusnet/avvisi.pl",
"td.AVVISI-FORMAT-3 a"}).get();
if(!avvisiOnline.isEmpty()) {
for(Avviso avviso : avvisiOnline) {
nuovo = true;
for (Avviso avviso1 : avvisiLocali) {
if (avviso.getTitolo().equals(avviso1.getTitolo())) {
nuovo = false;
}
}
if(nuovo){
showNotification();
}
}
}
}catch (Exception e) {
...
}
}
}
Come è possibile notare dal codice si è fatto uso della classe TimerTask,
tramite questa è possibile schedulare un’azione, infatti la sincronizzazione di
67
3.3 Architettura dell’applicazione
Implementazione e Funzionamento
nuovi avvisi e il controllo viene avviata ogni quindici minuti attraverso il metodo scheduleAtFixedRate(). Quando viene invocato il metodo startService(),
non viene controllata subito la presenza di nuovi avvisi ma lo scheduler partirà dopo quindici minuti al primo avvio e continuerà a controllare ogni quarto
d’ora finché non verrà terminato il servizio. Gli avvisi vengono confrontati dal titolo infatti notiamo la clausola del costrutto if mediante il metodo
equals() fra due stringhe: if(avviso.getTitolo().equals(avviso1.getTitolo())),
se il risultato della valutazione è falso viene impostata una variabile booleana per poter entrare in un secondo costrutto if dove verrà invocata la
funzione showNotification() che creerà il pop-up visualizzabile sul display
dello smartphone.
68
Conclusioni
Come conclusioni di questa tesi è possibile affermare di aver raggiunto gli
obiettivi proposti, ovvero la possibilità di realizzare un’applicazione Android
in grado di accedere ad alcune informazioni contenute in LMS. Dopo aver
studiato la struttura di ogni singola piattaforma, si sono implementati componenti ad hoc in grado di ricavare informazioni dalle piattaforme scelte e
gestirle nel miglior modo possibile. Le sezioni che si sono sviluppate e rese
accessibili dall’applicativo sono: avvisi, news, docenti, corsi, appelli e la propria carriera universitaria. Le fonti di dati sono state acquisite dall’unione
dei due LMS che il corso di informatica fa riferimento: CampusNet e ESSE3.
Gli sviluppi futuri possibili su questa tesi sono:
• Possibilità di condividere le informazioni visibili dall’applicativo su
Google+ o Facebook;
• Possibilità di iscriversi ad un appello d’esame attraverso l’applicativo;
• Funzionalità per cui una volta avvenuta l’iscrizione ad un appello d’esame, viene sincronizzato sul calendario Google e il giorno precedente
avvisa con una notifica pop-up;
• Cercare di integrare perfettamente l’applicazione con le funzionalità di
ESSE3, usando il protocollo di autenticazione CAS;
• Sviluppare un eventuale porting per iOS.
69
Bibliografia
[1] Learning Management System
http://it.wikipedia.org/wiki/Learning_Management_System
[2] CampusNet
Caratteristiche, Tecnologia, Documentazione, Moduli
http://www.campusnet.it/index.html
[3] EasyStaff - Optimization Solvers - Gruppo ZUCCHETTI S.p.A.
EasyCourse, Guida
http://www.easystaff.it/it/content/easycourse
[4] ESSE3 by KION a CINECA Company
Documentazione, Servizi di segreteria, FAQ
http://www.kion.it/it/soluzioni/esse3-servizi-segreteria-studenti
[5] Google - Android Studio
Project and File Structure, Android Build System, Debug and Performance
https://developer.android.com/sdk/index.html
[6] Jonathan Hedley
Java HTML Parser, API Reference, Cookbook
http://jsoup.org
[7] Matteo Petrioli
Paradigma di programmazione MVC
http://www.html.it/pag/32833/paradigma-di-programmazione-mvc/
[8] Marco Lecce
Database e SQLite in Android
http://www.html.it/articoli/la-gestione-dei-database-in-android-2/
70
Ringraziamenti
Arrivato a questo punto molto importante della mia carriera sento il desidero
di ringraziare tutti coloro che mi hanno aiutato e sostenuto durante questo
percorso.
Un primo ringraziamento va ai miei genitori per avermi concesso l’opportunità di rimanere a Parma e continuare a studiare in questa città magnifica
anche dopo il loro trasferimento.
Inoltre, ringrazio sentitamente il Prof. Federico Bergenti, sempre disponibile
a dirimere i miei dubbi durante tutto il periodo di stesura di questo lavoro.
Grazie a Gianluca Lutero per i numerosi consigli di carattere informatico
durante il periodo di ricerca.
Grazie a Filippo Soncini per aver contribuito con le sue doti grafiche disegnando le icone e progettando il Design dell’applicazione.
Ho desiderio di ringraziare con affetto anche tutti i miei compagni di corso
e in generale tutti gli amici conosciuti durante questo periodo per avermi
permesso di condividere un’esperienza indimenticabile.
71