Tesi di Laurea GECO MOBILE Una realizzazione J2ME per la
Transcript
Tesi di Laurea GECO MOBILE Una realizzazione J2ME per la
Università degli studi di Salerno Facoltà di Scienze Matematiche Fisiche e Naturali Corso di Laurea in Informatica Tesi di Laurea GECO MOBILE Una realizzazione J2ME per la georeferenziazione di utenti all’interno di una mobile community Relatori: Dott.ssa Monica Sebillo Dott. Michele Di Capua Candidato: Guardi Giovanni 056/100656 Anno accademico 2006 / 2007 1 Ringraziamenti I miei più sentiti ringraziamenti alle persone che hanno reso possibile la realizzazione di questa tesi, la prof. Monica Sebillo e il dott. Michele Di Capua, per l’ampia disponibilità e continua assistenza concessa. Ringraziamenti, inoltre, al dott. De Chiara e a tutto lo staff di U-S che mi hanno sostenuto soprattutto nei momenti di maggiore bisogno. Un affettuoso ringraziamento ai miei Genitori che mi hanno dato la possibilità di studiare sostenendomi in tutte le mie scelte. A loro dedico con gioia il raggiungimento di questo importante traguardo. A Tutti Voi Grazie. 2 Prefazione Il progetto GECO MOBILE, illustrato in questa tesi, nasce dalla volontà di realizzare una infrastruttura software in grado di erogare servizi ad utenti di una mobile community1. Data la natura opensource2 del progetto, la prima necessità è stata quella di verificare l’esistenza di librerie o servizi, con tale licensa [1], per l’erogazione di mappe. Sono state comunque analizzate anche le soluzioni commerciali disponibili di vari produttori come TomTom, Nokia Maps e GoogleMapsMobile. Al momento della stesura di questo documento infatti, esistono poche applicazioni mobili (tra cui la stessa Google Mobile) che prelevano e visualizzano mappe da Google e tutte con licenza commerciale. Il progetto quindi si propone di realizzare una possibile alternativa open-source per un servizio di visualizzazione grafica di mappe su dispositivo mobile, da integrare in una architettura più ampia che realizza l’infrastruttura di gestione di una mobile community. [2] 1 Una mobile community è costituita da un gruppo di utenti dotati di un terminale mobile in grado di connettersi ad un server centrale per scambio di informazioni. 2 Open-source indica un software rilasciato con un tipo di licenza per la quale il codice sorgente è lasciato alla disponibilità di eventuali sviluppatori 3 INDICE 1. INTRODUZIONE....................................................................... 6 1.2. Tempificazione delle attività ................................................ 10 1.3. Definizioni, Acronimi e Abbreviazioni............................... 11 2. DISPOSITIVI MOBILI E GIS ................................................ 13 2.2. Tecnologie e Linguaggi di Programmazione ....................... 15 2.2.1. Java2 Micro Edition ....................................................... 17 Configurazioni, Profili ed Optional-Package ....................... 18 Ambiente di sviluppo............................................................ 23 2.3. Connessioni di rete e Thread ................................................ 25 2.4. Mobile GIS ........................................................................... 31 2.4.1. Google Maps Mobile ..................................................... 34 3. REQUISITI DEL SISTEMA ................................................ 36 3.1. Requisiti funzionali............................................................... 37 3.2. Requisiti non funzionali........................................................ 38 3.3. Modello dei Casi d’uso......................................................... 38 3.3.1. Attori .............................................................................. 39 3.3.2. Diagramma dei casi d’uso.............................................. 40 3.3.3. Descrizione dei Casi d’uso............................................. 41 4. ANALISI DEI REQUISITI E MODELLI DI SISTEMA..... 48 4.1 Dizionario dei dati ................................................................. 48 4.2 Modelli dinamici.................................................................... 52 4.2.1 Sequence diagram ........................................................... 52 5. LA GEOREFERENZIAZIONE DI UTENTI ........................ 55 5.1 PROGETTAZIONE .............................................................. 55 5.2. Interfaccia utente .................................................................. 56 5.2.1. Descrizione dell’interfaccia utente .............................. 56 5.2 IMPLEMENTAZIONE ......................................................... 59 5.2.1 Suddivisione del sistema in componenti........................ 59 4 5.2.2. Descrizione dei sottosistemi ....................................... 59 Package principale ................................................................ 60 Algoritmo di gestione dei tiles.............................................. 67 Algoritmi di gestione delle funzioni del menù. .................... 79 Algoritmi di gestione delle funzioni di messaggistica. ........ 82 Package bluetooth................................................................. 88 Package funzioni................................................................... 89 Librerie matematiche esterne................................................ 91 6. L’ESEMPIO DELLA GIS COMMUNITY............................ 93 7. CONCLUSIONI ........................................................................ 98 8. SVILUPPI FUTURI................................................................ 100 APPENDICE A ........................................................................... 102 WEBGRAFIA.............................................................................. 106 BIBLIOGRAFIA......................................................................... 111 5 1. INTRODUZIONE I sistemi moderni di georeferenziazione ed i navigatori satellitari sono oramai una realtà ben consolidata e fanno parte del vivere quotidiano anche di gran parte degli utenti di telefonia mobile. Gli attuali sistemi di navigazione offrono potenti strumenti per la navigazione tra cui calcoli di percorsi e tracciabilità di flotte (marine e terrestri) commerciali. Ciò nonostante, non sono altrettanto diffusi i sistemi di navigazione in cui al posto di percorsi stradali vengano messe in risalto le informazioni sugli utenti. In questa tesi, infatti, si è concentrata l’attenzione sull’utente e sulla possibilità di fornire servizi, fin ad oggi legati al web ed al personal-computer, che, oltre a mettere in comunicazione gli utenti stessi, consentano anche di fornire informazioni sulla loro posizione geografica. Nasce così GECO MOBILE, un sistema client/server in cui la componente server [rif. Giuseppe] gestisce la logica di back-end, con, ad esempio, funzionalità di registrazione utenti, visualizzazione geografica di una vmobil communty, ecc. La parte client da me sviluppata, invece, consente ad un dispositivo mobile di collegarsi al sistema e di visualizzare una mappa geografica su 6 cui sono indicate le posizioni degli singoli utenti della comunità. tramite “marker3”. Su tale mappa ogni utente può visualizzare la porzione di mappa di maggior interesse grazie alle funzioni di zooming (ingrandimento di un immagine) e panning (scorrimento dell’immagine nelle 4 direzioni). In aggiunta, sono state realizzate le funzioni di base di quella che chiameremo “mobile community” [3] con le quali si possono inviare e ricevere messaggi, conoscere informazioni dettagliate di un utente, avere una lista di utenti che si trovano entro un raggio di azione definito come parametro dall’utilizzatore. Il client quindi è in grado di impersonare uno specifico utente di una community tramite un id assegnatogli durante la fase di registrazione, recuperare mappe su cui georeferenziare utenti, ossia, gestire le informazioni di tipo geografico che riguardano la posizione degli utenti stessi e che fanno parte di una stessa community, e fornire un servizio di localizzazione (LBS4) e di comunicazione integrato. Come server di mappe è stato utilizzato un servizio gratuito di Google che consente di prelevare porzioni di 3 Un marker è un segnaposto grafico molto in uso su mappe geografiche per identificare un punto di interesse 4 Location Based Service 7 mappa sotto forma di immagini (chiamati tiles) di dimensioni ridotte. Il client mobile, quindi, ricompone la mappa da visualizzare utilizzando i tiles richiesti “on-demand” al servizio di Google. I tiles hanno dimensione fissata e si è reso necessario definire un algoritmo per ricomporre la mappa principale e per navigare tale mappa. I servizi che il dispositivo richiede in aggiunta, via http, sono: la visualizzazione degli utenti “attivi” della community, la visualizzazione degli utenti che si trovano ad una certa distanza impostata dall’utente, l’invio delle proprie coordinate, prese dal ricevitore GPS, al database centralizzato. Le coordinate che vengono inviate fanno riferimento alla posizione corrente e vengono acquisite tramite segnale NMEA, opportunamente filtrato, prelevato da dispositivo GPS via protocollo bluetooth.[6] 8 Organizzazione della Tesi Nel capitolo 1 viene illustrato lo scopo del progetto con un resoconto dei tempi impiegati per l’attività di ricerca, studio e implementazione del sistema. Nel capitolo 2 vengono trattati i dispositivi hardware, il linguaggio di programmazione adoperato e il significato di Gis per mobile. Nel capitolo 3 vengono analizzati i requisiti del client mobile ed i suoi use-case. Viene, inoltre, data una prima specifica dell’interfaccia utente. Nel capitolo 4 vengono esplicitati gli use case sotto forma di sequence diagram in modo da dare una visione temporale degli eventi secondo il linguaggio UML. Nel capitolo 5 vengono analizzate le strategie di progettazione e viene fatta una analisi approfondita sull’implementazione passando in rassegna i diversi punti salienti del codice sorgente. Il capitolo 6 mostra una serie di screenshot dell’applicazione e del suo funzionamento per dare un’ idea più visiva della realizzazione. 9 Il capitolo 7 illustra i risultati raggiunti in termini di ricerca di una soluzione open source e in termini di implementazione. Il capitolo 8 infine descrive gli eventuali sviluppi successivi. 1.2. Tempificazione delle attività La progettazione è stata articolata in più fasi con i necessari ricicli, come riportato nel seguente diagramma di Gantt : 10 1.3. Definizioni, Acronimi e Abbreviazioni GECO GeoCoded Community , community geografica Tile unità grafica minima di Google. Singola cella 256x256 contenente una porzione di mappa. Panning Spostamento della mappa in una delle 4 direzioni Zooming Ingrandimento della mappa Georeferenziazione Visualizzazione di oggetti reali su di una mappa geografica. GPS Global Positioning System (sistema di localizzazione satellitare) NMEA Standard Europeo per segnali GPS di latitudine, longitudine, altitudine,.. GIS Geographic Information System 11 J2EE Java 2 Enterprise Editino. Piattaforma di sviluppo software basata su tecnologia java ed orientato ai servizi lato server. J2ME Java 2 micro Editino. Piattaforma di sviluppo software basata su tecnologia java ed orientata ai dispositivi mobili come palmari, PDA e cellulari. 12 2. DISPOSITIVI MOBILI E GIS Col termine GIS (Geografic Information System) si vuol indicare tutto l’insieme delle procedure, dell’hardware, del software, delle banche dati e delle persone che agiscono su dati di tipo spaziale per analisi, interpretazione e produzione di un output. [7] Un GIS interpreta il mondo reale attraverso immagini di vario tipo, ne specifica il significato ed effettua elaborazioni e manipolazioni atte a produrre un ben determinato risultato in output secondo gli schemi e i criteri predeterminati dal sistema stesso. [8] In un GIS vengono combinati strati di informazione in merito ad un determinato luogo geografico per meglio capire le sue caratteristiche ed eventuali correlazioni con altri fenomeni o luoghi. [9] La funzione dei GIS è quindi quella di creare un output che può prendere la forma di MAPPE, DIAGRAMMI e REPORT. Questo output è creato dopo le fasi di cattura, immagazzinamento, query ed analisi di dati spaziali. Un dato geografico, dovendo trattare con macchine e personal-computer, può essere di 3 tipologie diverse: punto, linea o poligono. [10] Il dato geografico è composto da 2 parti: 13 - una parte descrittiva, che rappresenta le caratteristiche del dato stesso (es. nome di un fiume, di una strada, etc) - una parte spaziale, che per sua natura è legata ad altre componenti, e rappresenta il mondo reale. Grazie ai GIS (Biallo, 2005)è possibile analizzare un’area specifica del territorio per conoscerne caratteristiche descrittive, spaziali e, attraverso analisi e sovrapposizione di mappe, fornire ad un utente esperto gli strumenti necessari che sono alla base di un processo decisionale. Esistono ad oggi numerosi software GIS sia opensource che proprietari e in svariati campi applicativi[11]. 14 2.2. Tecnologie e Linguaggi di Programmazione L’evoluzione dei dispositivi mobili e’ in continuo avanzamento. Un tempo un telefono cellulare era adoperato solo per effettuare chiamate e con qualche funzione di messagistica. Oggi i telefoni cellulari stanno divenendo sempre più simili a dei veri e propri microcomputer grazie ai quali sono state realizzate molte altre funzionalità. I telefoni cellulari moderni si sono variegati in base a 3 tipologie principali: 1) Mobile Phone: altresì chiamato cellular phone, e’ il classico dispositivo elettronico per la comunicazione mobile attraverso le reti di telefonia mobile. Solitamente offre pochi servizi aggiuntivi tra cui invio e ricezione SMS, MMS, EMAIL e raramente servizi multimediali come foto e video. 2) Smartphone: è un dispositivo portatile che abbina funzionalità di gestione dei dati personali e di telefono. Può derivare dall’evoluzione di un PDA a cui si aggiungono funzioni di telefono o, viceversa, da un telefono a cui si aggiungono funzioni di un PDA. La loro caratteristica più interessante è la 15 possibilità di installare altri programmi applicativi estendendone le funzionalità. 3) PDA: acronimo di Personal Digital Assistant. E’ un computer di dimensioni contenute in grado di eseguire tutte le funzionalità di uno smartphone e oltre ma non necessariamente quelle di telefonia. [12] Ognuna di queste tipologie si differenzia per il tipo di sistema operativo che adopera e per i servizi di cui e’ dotato. I Mobile Phone sono ovviamente i dispositivi più limitati in termini di risorse di cui dispongono e di potenza di calcolo. Su di essi si e’ basata la nostra attenzione. SmartPhone e PDA sono tecnologicamente più avanzati e offrono maggiore capacità di immagazzinamento e maggiore potenza di calcolo. La capacità di immagazzinamento dei dati e’ data da due fattori: la memoria di base di cui dispone il dispositivo e la memoria aggiuntiva che, se presente, può essere ampliata con memorie di vario tipo. La quasi totalità di dispositivi mobili disponibili delle 3 tipologie consente di eseguire applicazioni java grazie alla cosiddetta “virtual machine” che la SUN MICROSYSTEM realizzato sotto forma di specifiche e requisiti minimi che devono essere soddisfatti. 16 2.2.1. Java2 Micro Edition Nel 1990, Sun Microsystem realizzò un linguaggio di programmazione per i dispositivi elettronici che fu inizialmente chiamato “OAK”. Oggi tale linguaggio è conosciuto come JAVA. Successivamente JAVA fu distinto in 3 diverse piattaforme (Figura 1): J2EE per le soluzioni “enterprise”, J2SE per le soluzioni “desktop” e le applicazioni internet e J2ME per gli “embedded device” Figura 1 Piattaforme Java Purtroppo la grande varietà di dispositivi mobili, le diverse caratteristiche tecnologiche e i diversi sistemi operativi ha reso necessario effettuare una ulteriore differenziazione nell’ambito 17 della stessa J2ME[13]. Allo scopo di specializzare le piattaforma target di sviluppo, nell’ambito mobile, sono state introdotte le definizioni di configurazione, profilo ed optional package. Attraverso quello che viene chiamato JCP (Java Community Process) e le JSR (Java Specification Request), la SUN estende continuamente la piattaforma J2ME e data la veloce evoluzione dei dispositivi attuali è facile prevedere in un futuro non molto lontano una nuova evoluzione anche della piattaforma stessa. [14] Configurazioni, Profili ed Optional-Package Le 3 tipologie si differenziano come detto precedentemente in base a caratteristiche tecnologiche differenti. Per questo motivo SUN ha creato le configurazioni che rappresentano java virtual machine differenti a seconda delle potenzialità del dispositivo. Esistono 2 tipi di Configurazioni: CLDC (Connected Limited Device Configuration) e CDC (Connected Device Configuration). CLDC: Interfaccia utente semplificata, quantità di memoria limitata (da 150kb a 512kb), processori a 16 o 32 bit, 18 CDC: Maggiori interfacce disponibili, maggiore quantità di memoria a disposizione, connettività a diverse tipologie di reti. Figura 2 Configurazioni, profili ed optional-package In particolare la CLDC si occupa di: • definire le caratteristiche del linguaggio Java e della Virtual Machine supportate; • fornire un set minimo di librerie di base; • gestire gli stream di I/O; • sicurezza; • networking; • internazionalizzazione; 19 lasciando ai profili: • la gestione del ciclo di vita delle applicazioni (installazione, lancio, cancellazione); • l'implementazione di interfacce utenti; • la "cattura" e la gestione degli eventi; • l'interazione tra l'utente e l'applicazione; Data la notevole diversità degli apparati elettronici, oltre alle configurazioni son stati introdotti i profili che vanno a ridefinire e a specializzare ulteriormente la categoria cui appartengono (CDC o CLDC). Un profilo quindi completa una configurazione aggiungendo ulteriori informazioni (e quindi classi) per la specifica tipologia di device utilizzata. Entrambe le configurazioni in j2me hanno uno o più profili associati. Profili e Configurazioni definiscono quindi un insieme di JAVA API. Nello specifico, il profilo classico di riferimento per CLDC per dispositivi mobili è MIDP mentre per CDC è il Foundation Profile. 20 Le midlet java sono quindi le applicazioni java per dispositivi mobili basate sul profilo MIDP. Attualmente, la versione di riferimento per MIDP è la 2.1 che definisce, in aggiunta alle classi di CLDC, altri 3 packages: [15] Javax.microedition.lcdui Javax.microedition.midlet Javax.microedition.rms La classe lcdui è quella incaricata di gestire l’interfaccia utente. Essa contiene le api per la grafica di “alto-livello” e di “bassolivello”. La classe midlet è fondamentale per un applicazione midlet la quale deve contenere almeno una classe derivata dalla classe astratta javax.microedition.midlet.MIDlet. la versione 2.1 di MIDP estende le precedenti con un insieme di api per il multimedia ed i giochi. Alcune di esse sono servite per implementare funzioni come panning e grafica nel progetto realizzato. [16] La classe rms si occupa di gestire i meccanismi di memorizzazione e di archiviazione sul dispositivo mobile ed è stata presa in considerazione per eventuali sviluppi futuri. 21 In aggiunta a configurazioni e profili, gli optional-package servono a definire librerie esterne per usi specifici. Essi estendono l’ambiente di runtime ma non sempre sono così universali come configurazioni e profili. Alcuni dispositivi supportano gli optionalpackage mentre altri no ed è per questo che sono definiti “optional”. Nel nostro progetto abbiamo fatto uso di un optional-package appartenente alle specifiche JSR82 (le API Bluetooth) e di due librerie per i calcoli matematici necessari a gestire i tiles e la veste grafica (Sanna, 2007). Di questi parleremo nel dettaglio più avanti. [17] 22 Ambiente di sviluppo Per la scrittura del codice della midlet sono stati presi in considerazione diversi fattori nella scelta dell’ambiente di sviluppo. Trattandosi di un applicazione strettamente legata ai dispositivi mobili, la nostra attenzione si è rivolta a quei tool che mettono a disposizione una serie di utilità configurabili e che allo stesso tempo siano compatibili con la stragrande maggioranza dei dispositivi in commercio. La scelta è caduta su ECLIPSE con il suo add-on ECLIPSE-ME. Per testare la midlet nella fase di pre-rilascio sul dispositivo invece si è utilizzato il classico WTK della SUN MICROSYSTEM. Vediamo a grandi linee gli step del processo produttivo. Innanzitutto, si necessita di una J2SE SDK, ossia la virtual machine standard in versione 6.0 per l’ambiente di base dove eseguire applicazioni JAVA e per poter lanciare il WTK. Fare riferimento alla bibliografia per i link su JAVA SDK. Abbiamo poi scaricato l’IDE open-source ECLIPSE da usare con la suddetta SDK e nella modalità aggiornamento abbiamo inserito il link da cui scaricare e installare automaticamente il plug-in ECLIPSEME che ha aggiunto “features” ad eclipse consentendo lo 23 sviluppo di quella che da questo momento chiameremo MIDLETSUITE. In definitiva, abbiamo scaricato ed installato dal sito SUN il WTK che, dopo averlo opportunamente integrato in Eclipse, ci ha consentito di effettuare i testing necessari come se si utilizzasse un dispositivo reale. Tralasciamo qui di menzionare le modalità di configurazione dei software di sviluppo. 24 2.3. Connessioni di rete e Thread Gestione degli stream : java.io L'input e l'output di Java si basano sul concetto di stream, cioè un generico flusso di byte "in transito" da una sorgente verso una destinazione indipendentemente dal tipo di sorgente, di destinazione e di percorso. Il package java.io non poteva quindi mancare nella CLDC, esso costituisce un sottoinsieme dell'omonimo della Standard Edition. In particolare nella CLDC sono state eliminate tutte le classi riguardanti le operazioni su file, questo perché la maggior parte dei dispositivi che utilizzeranno la CLDC, come già abbiamo detto, non possiedono un vero e proprio file system (i palmari palmOS ne sono un esempio, ma anche i cellulari e gli smart-phone). Le operazioni di I/O da/su file sono comunque garantite dal "Generic Connection Framework". Le due classi, InputStreamReader e OutputStreamWriter, rappresentano l'unico supporto all'internazionalizzazione di cui la CLDC dispone e permettono la conversione di sequenze di byte in caratteri Unicode e vicerversa: InputStreamReader(InputStream is, OutputStreamWriter(OutputStream os, String encoding); String encoding); 25 La CLDC supporta di default la codifica ISO-8859_1 come è possibile vedere "interrogando" le proprietà di sistema (System.getProperty("microedition.encoding")) altri tipi di codifica possono, però essere presenti in implementazioni particolari. Il mancato supporto per una codifica richiesta lancerà, ovviamente, una UnsupportedEncodingException. Tali proprietà son servite nel sistema, come si vedrà successivamente nella parte dell’implementazione, per inviare messaggi e per richiedere i tiles a google il quale deve essere informato del tipo di client che effettua la richiesta. Il "Generic Connection Framework" Come è noto i package java.io e java.net nella Standard Edition forniscono un insieme completo di strumenti per la gestione dell'Input - Output sia per quanto riguarda l'I/O da file sia per quello legato a connessioni di rete. Sfortunatamente però hanno dimensioni tali (circa 200 Kbyte) da impedirne "la completa importazione" nella CLDC, inoltre molte delle funzionalità che garantiscono sono poco (o per nienete) utili in dispositivi embedded e nell'elettronica di consumo in generale. Inoltre molti di questi 26 apparati dispongono di metodi di comunicazione "inusuali" e molto specifici (infrarossi, bluetooth), E’ necessario quindi estrapolare dalla Standard Edition (java.io, java.net) le funzionalità principali e adattarle a questo contesto garantendo. E' stato quindi pensato quello che viene definito "Generic Connection Framework", implementato in un insieme di interfacce che rappresentano vari livelli di astrazione di metodologie di connessione. La decisione di non implementare direttamente, a livello di configurazione, i vari protocolli, ma di lasciare questo compito al livello applicazione (o profilo), rientra nella logica di un approccio generico al problema. In questo modo la configurazione fornisce gli "strumenti generici di base" permettendo il supporto di molti protocolli e l'utilizzo sui più disparati dispositivi. Alla radice della gerarchia, l'interfaccia Connection, rappresenta una generica connessione che può essere aperta e chiusa attraverso i metodi open() (che in realtà non è public ma viene richiamato dal metodo statico open() presente nell’ unica classe Connector) e close(). InputConnection e OutputConnection rappresentano un dispositivo dal quale i dati possono essere rispettivamente letti o scritti, attraverso gli opportuni stream (openInputStream- 27 openDataInputStream / openOutputStream- openDataOutputStream), StreamConnection è la combinazione di Input/Output-Connection e costituisce normalmente il punto di partenza per le classi che implementano le interfacce di comunicazione. La sua estensione ContentConnection dispone di alcuni metodi (getEncoding, getType, getLength) che consentono di ottenere informazioni sui dati trasmessi.[18] Type ed Encoding sono serviti nel progetto per informare Google di quale tipologia di browser effettua la richiesta delle mappe (operazione obbligatoria per prelevare tiles). Figura 1 - Gerarchia delle interfaccie del "Generic Connection Framework". Qualunque tipo connessione viene aperta utilizzando il metodo open() della classe Connector: [19] Connector.open(string_connection); 28 dove string_connection ha il seguente formato: <protocol>:<address>;<parameters> protocol indica il tipo connessione che si intende utilizzare (es. http, datagram, scrittura su file, ecc.), address permette di individuare la destinazione (può essere un indirizzo IP ma anche il nome di un file) , parameters contiene una serie di informazioni aggiuntive che possono essere funzionali per un dato tipo di connessione (ad es. baudrate per comunicazioni su porta seriale). "THREADING" in J2ME J2ME fornisce 2 varianti della classe Thread sottoinsiemi della J2SE. Per CLDC vengono forniti solo i seguenti metodi: activeCount() , currentThread(), getPriority(), isAlive(), join(), run(), setPriority(), sleep(), start(), yield(). Da notare la mancanza dei metodi per fermare o interrompere un thread. Il solo modo che abbiamo avuto per fermare un thread è stato quello di impostare la sua variabile di riferimento a NULL come nell’esempio sottostante: public class AnotherThread implements Runnable { private Thread mostRecent = null; public Thread restart(){ mostRecent = new Thread( this ); 29 mostRecent.start(); } public void run(){ Thread thisThread = Thread.currentThread(); while( mostRecent == thisThread ){ // do something } } public void stopAll(){ mostRecent = null; } } Nella nostra applicazione l’uso dei thread è stato fondamentale poiché l’uso di una connessione o di una richiesta di I/O risulta essere “bloccante” per il sistema. Situazione questa non tollerabile data la natura stessa dei dispositivi e la possibilità del verificarsi di ulteriori eventi come telefonate o la gestione di una eccezione nel funzionamento e la midlet manderebbe irrimediabilmente in blocco tutto il sistema.[20] 30 2.4. Mobile GIS Con mobile-gis facciamo riferimento al GIS per dispositivi elettronici di telecomunicazioni (mobile-phone, smartphone, etc). Il GIS per dispositivi mobile si è sviluppato negli ultimi 10 anni e sta prendendo le forme più disparate: mobile gis sono ad esempio i software commerciali della ESRI come ARCPAD oppure le applicazioni satellitari di navigazione come Tom Tom per dispositivi mobili. L’integrazione tra telecomunicazioni e comunicazione dei dati ha contribuito alla creazione di una infrastruttura di rete globale che sembrerebbe essere disponibile dappertutto, in ogni momento e attraverso una moltitudine di apparecchiature differenti. Assumendo che col passare del tempo questa rete globale sarà via via sempre più disponibile, gli sviluppatori trovano sempre nuove modalità di realizzazione per le applicazioni che sono uniche per questi dispositivi mobili e si differenziano non poco da quelle per workstation classiche. Ecco alcune delle proprietà di un sistema mobile: [21] 1. la stessa applicazione per più devices. In un ambiente fatto da terminali mobili, i servizi devono essere in grado di presentarsi alla maggior parte di essi con funzionalità consistenti e un interfaccia amichevole. 31 2. in un mondo mobile “always on” gli utenti accedono alle informazioni indipendentemente dal luogo e dal tempo. 3. combinare dati reali con dati digitali. Nelle postazioni fisse, il digitale ed il mondo reale sono grosso modo separati. Viceversa, nei sistemi mobili essi devono essere combinati. Avendo a che fare col mondo reale, i dati, come ad esempio la posizione geografica, ci permettono di avere applicazioni realtime. 4. architettura dei dati. Durante la fase di design ed implementazione bisogna fare attenzione anche alle strutture utilizzate. Quando un contesto necessità di essere aggiornato o vengono aggiunte ulteriori informazioni al sistema sottostante, una buona soluzione sarebbe quella di cambiare il minimo possibile nell’architettura. [22] Col termine Mobile-GIS si definisce un sistema integrato di hardware e software per l’accesso ai dati spaziali e ai servizi attraverso un dispositivo mobile via rete wireless. Il Wireless-GIS è una sottocategoria del Mobile-GIS che focalizza la sua attenzione sulla capacità di una rete wireless. Vi sono 2 aree di maggior applicazione per un Mobile-GIS: 32 1. Field-based GIS, che focalizza sulla collezione, validazione e aggiornamento di dati GIS(dati spaziali e attributi). 2. Location-based services (LBS), che focalizza sulle funzioni di localizzazione orientate al business come ad esempio il tracking di flotte marine o terrestri. L’architettura di un Mobile-GIS e’ molto simile a quella di un Internet-based GIS. Utilizza cioè un architettura client/server tipicamente attraverso quella che viene definita come “Three Tiered Architecture” (i.e. MVC). [23] In un sistema LBS [24] vi sono racchiuse 4 importanti tecnologie: mobile phones, acquisizione di locazioni (automatiche o manuali), tecnologia internet wireless e le soluzioni GIS per il wireless. Per acquisizione di locazioni si intende la possibilità di tenere traccia della locazione geografica del dispositivo mobile [25]. Questo è stato utilizzato nel progetto quando vengono storicizzate le posizioni degli utenti a seguito del loro invio delle coordinate. Negli sviluppi futuri un accenno agli eventuali modi di valorizzare queste informazioni. 33 Per tecnologia internet wireless si fa riferimento alla rete italiana 3G, GSM, GPRS, EDGE e così via. Per la nostra applicazione si è fatto largo uso del GPRS (General Racket Radio Services) che è un servizio di comunicazione “always on” che trasferisce informazioni allo stesso modo di internet ossia in pacchetti per poi essere riassemblati al ricevimento dal terminale. 2.4.1. Google Maps Mobile Un esempio [26] di applicazione LBS per mobile viene da qualche anno fornita da un applicazione realizzata dal noto motore di ricerca Google. Si chiama Google Maps Mobile ed e’ giunta gia da Novembre 2007 alla versione 2.x. Google Maps per mobile è un'applicazione scaricabile che consente di visualizzare mappe e immagini satellitari, trovare attività commerciali locali e ottenere indicazioni stradali direttamente sul dispositivo mobile. [27] GoogleMapsMobile offre 2 diverse tipologie di localizzazione della posizione: una puo essere fornita da un GPS esterno o interno mentre in alternativa si può scegliere di adoperare un sistema che sfrutta la triangolazione tra celle. [28] La triangolazione tra celle è una tecnica di rilevamento della posizione che fa uso delle stesse 34 celle usata per la comunicazione voce. [29] Con tale tecnica si riesce ad approssimare un punto in base ai suoi tempi di risposta da 3 diverse celle che formano un triangolo nel quale è contenuto il punto stesso. [30] Tempi di risposta e approssimazione sono però peggiori di quelli forniti da un GPS ma hanno il vantaggio di essere sempre disponibili e di non soffrire dei cosiddetti “luoghi chiusi” come nel GPS. Senza soffermarci troppo sull’applicazione in sè, è da notare che le mappe prelevate da essa si riferiscono, come nella nostra applicazione, ad un indirizzo http diverso da quello a cui ci si è abituati navigando tra le mappe di google da un browser internet. L’indirizzo in questione è di tipo [31] http://mt.google.com/mt?n=404&v=w2.17&x=????&y=????&z oom=?? Il link classico a cui siamo abituati è invece http://maps.google.it ma mentre questo fornisce un reale servizio di localizzazione, il precedente funge da contenitore di tiles e non è funzionalmente adatto ad effettuare alcuna operazione, se non quella di mostrare il tile stesso. 35 3. REQUISITI DEL SISTEMA Lo scopo generale del progetto è quello di realizzare una applicazione J2ME in grado di connettersi ad un server e da questi reperire servizi tipici di una community web. [32] In particolare sull’applicazione mobile realizzata l’utente connesso sarà in grado di visualizzare la lista delle community a cui appartiene , ne potrà selezionare una visualizzandone la posizione degli utenti che in quel momento sono connessi, ed inoltre potrà usufruire di una serie di servizi integrati, tra cui, ad esempio, eseguire una ricerca degli utenti a una certa distanza o mandare un messaggio a un particolare utente. La strategia adoperata e’ di tipo CLIENT/SERVER. Il Server sottostante è preesistente ed è stato implementato secondo il pattern MVC5 (Model View Controller) e si occupa di gestire i servizi lato web e di rispondere alle richieste del client. Il client sviluppato prevede la definizione di una sola tipologia di utente che da questo momento chiameremo utente semplice. L’utente semplice può : 5 Paradigma di programmazione largamente diffuso che tende a scomporre un sistema in tre livelli indipendenti.. 36 • Effettuare Login. • Visualizzare la lista delle community a cui appartiene. • Selezionare una community. • Visualizzare su mappa geografica la posizione degli utenti che in quel momento sono attivi. • Inviare messaggi ad altri utenti “attivi”. • Richiedere una lista di tutti gli utenti che si trovano in un raggio di x metri impostato dall’utente stesso. • Utilizzare un navigatore GPS per le proprie coordinate da inviare al server. 3.1. Requisiti funzionali Per la realizzazione degli obiettivi proposti nel progetto di sviluppo, è necessario realizzare le seguenti funzionalità per l’utente semplice : • Autenticazione dell’utente da dispositivo mobile • Visualizzazione delle community disponibili. • Visualizzazione della mappa e relative funzioni di panning, zoom, ecc. • Invio coordinate GPS (acquisite via Bluetooth) 37 • Invio ricezione messggi • Ricerca utenti a distanza 3.2. Requisiti non funzionali Oltre ai requisiti funzionali, il sistema proposto deve presentare le seguenti caratteristiche: • Tutelare la privacy degli utenti • Minimizzare il traffico di rete L’utente dal proprio dispositivo mobile dopo aver avviato l’applicazione e essersi collegato al GPS inizierà a inviare le sue Coordinate. Definiamo un utente attivo se dall’ultimo invio delle coordinate non è trascorso un certo timeou configurabile , e non attivo in caso contrario. 3.3. Modello dei Casi d’uso I casi che andremo a descrivere prendono in considerazione il punto di vista dell’utente finale ovvero ignora i particolari implementativi focalizzandosi sugli aspetti funzionali del sistema da realizzare. 38 3.3.1. Attori Utente Semplice: è l’utente finale del sistema, che grazie ai servizi realizzati potrà avere a disposizione la posizione geografica esatta degli amici della sua community. In particolare potrà : 1. Autenticarsi da dispositivo mobile. 2. Scegliere una community . 3. Visualizzare la posizione degli altri utenti della community attivi su mappa geografica 4. Chiedere la lista degli utenti che si trovano entro una certa distanza dalla sua posizione 39 Verranno mostrate di seguito le principali funzionalità legate all’utente semplice. 3.3.2. Diagramma dei casi d’uso 40 3.3.3. Descrizione dei Casi d’uso. Use Case Invio/Ricezione Messaggi Permette di inviare un messaggio di testo ad un altor utente della community. Participating Actors 1. utente semplice Preconditions 1. l’utente deve lanciare la midlet e loggarsi nel sistema. Flow of Events 1. L’utente accede alla community tramite la voce VISUALIZZA COMMUNITY che appare nel menu dopo aver effettuato il logging. 2. Il sistema consente di scegliere una delle community a cui ci si è registrati. 3. L’utente effettua la scelta. 4. Il sistema provvede a inviare la richiesta al Server con i dati suddetti e allo stesso tempo carica la mappa iniziale di default. Mostra i marker degli utenti “visibili” . 5. L’utente può visualizzare l’elenco degli altri partecipanti e inviare un messaggio a uno di essi. 6. Se l’operazione va a buon fine compare un messaggio di conferma. 41 Postconditions Viene inviato il messaggio di testo al DB contenente mittente e destinatario. Il destinatario riceve il messaggio dopo un certo tempo prefissato dall’utente. Exceptions Siccome le operazioni avvengono in maniera asincrona, se l’utente destinatario e’ uscito dal sistema prima della ricezione del messaggio quest’ultimo gli sarà recapitato al suo prossimo accesso. Use Case Name Visualizzazione Utenti Permette all’utente di visualizzare oltre ai marker sulla mappa anche una lista completa di tutti gli utenti appartenenti alla community e loggiati in quel momento. Participating Actors 1. utente semplice Preconditions 1. I’utente deve essere loggato 42 Flow of Events 1. l’utente visualizza la mappa. 2. dal menu’ a tendina seleziona la voce VISUALIZZA UTENTI 3. Il sistema fa una richiesta al DB e mostra un elenco di tutti gli utenti loggiati in quel momento. 4. Un ulteriore menù a tendina consente di visualizzare la scheda anagrafica dell’utente selezionato. Post Conditions Non necessarie Exceptions Non necessarie Use Case Name Visualizza Utenti a distaza <= “X metri” Permette all’utente di visualizzare l’elenco degli utenti che si trovano in un raggio di “x” metri da se stesso Participating Actors 43 1. utente semplice Preconditions 1. I’utente deve essere autenticato e deve aver attivato il sistema GPS per il controllo delle coordinate. Flow of Events 1. l’utente seleziona la community a cui è interessato. 2. Il sistema mostra la mappa e conosce gia gli utenti loggiati in quel momento. 3. l’utente attiva il navigatore GPS via Bluetooth. 4. il sistema ora conosce le coordinate dell’utente e inizia a mandarle al DB. 5. l’utente entra nel menù a tendina e seleziona la voce VISUALIZZA UTENTI A DISTANZA. 6. inserisce una distanza in metri nell’apposita form. 7. i sistema visualizza l’elenco ordinato in modo crescente degli utenti a quella distanza. Post Conditions Non necessarie Exceptions Non necessarie 44 Use Case Name Zoom-in/zoom-out Participating Actors 1. utente semplice Precoditions 1. l’utente deve visualizzare correttamente la mappa. Flow of Events 1. L’utente , seleziona il tasto dal menu. 2. il sistema effettua un calcolo per mostrare i nuovi tiles al nuovo livello di zoom. 3. i nuovi tiles prendono il posto dei precedenti e vengono visualizzati. PostConditions Non necessarie Exception Non necessarie 45 Use Case Name Visualizzazione Utenti su Mappa Permette all’utente di visualizzare la posizione geografica degli utenti che appartengono alla community selezionata Participating Actors 1. utente semplice Preconditions 1. I’utente deve essere registrato ed identificato dal sistema. 2. l’utente deve essere iscritto alla mobile communty che vuole visualizzare Flow of Events 1. l’utente accede alla visualizzazione delle community a cui appartiene. 2. Il sistema mostra la lista delle community a cui l’utente4 si è precedentemente iscritto. 3. L’utente selezionala community di cui vuol visualizzare la posizione degli utenti. 4. il Sistema mostra la mappa geografica , indicando con degli omini rossi gli utenti non attivi , e verdi quelli attivi Postconditions Non necessarie Exceptions 46 l’utente potrebbe non visualizzare nessun oggetto se gli utenti non hanno ancora inviato le coordinate al data base. 47 4. ANALISI DEI REQUISITI E MODELLI DI SISTEMA 4.1 Dizionario dei dati I seguenti oggetti sono quelli coinvolti nell’implementazione delle funzionalità che sono messe a disposizione dal sottosistema. Viene data la descrizione del dato e la sua collocazione nei seguenti sequenze in termini di oggetti del dominio (Entità Objects), oggetti di confine (Boundary Objects) e controllori di funzioni (Control Objects). Sequence Diagram Login Operazione di autenticazione iniziale e accesso al sistema Entity Object • login: la stessa creata lato web sul sito di riferimento di GECO SERVER. • password: la stessa creata sul sito di riferimento. Viene visualizzata asteriscata. • user: è l’utente del sistema che effettua l’autenticazione. Boundary Object 48 • Entra: tasto che richiama una form di avvenuto accesso e visualizzazione del corrispettivo id legato a login e password. Control Object Nessun oggetto di controllo. Solo una form di richiesta autenticazione con login e password Sequence Diagram Entra Operazione di accesso al sistema con login e password precedentemente specificate. Entity Object • idutente: la stringa numerica che è strettamente legata alla login e password e viene restituita dal server. • user: è l’utente che visualizza i messaggi di autenticazione e id relativi alla sua login e pass. Boundary Object • vedicommunity: tasto che consente di visualizzare le community legate allo specifico idutente restituito dal server. • Indietro: tasto per ripetere la fase di autenticazione iniziale. 49 Control Object • EffettuaLogin.java: classe di connessione al server che controlla username e password e visualizza relativo messaggio di avvenuta autenticazione in caso positivo o di tipo di errore in caso contrario. Sequence Diagram Vedi Community Operazione di visualizzazione delle community legate allo specifico idutente Entity Object • Lista Community: è la lista delle community associate allo specifico utente. • user: è l’utente che continua nella fase di accesso selezionando una delle community dalla lista delle community. Boundary Object • Scegli: tasto che consente di specificare la community da utilizzare nella fase successiva per mostrare la mappa e i relativi utenti collegati. Control Object 50 • VisualizzaCommunityUtente.java: classe di connessione al server che recupera la lista delle community collegate allo specifico idutente. Sequence Diagram Scegli Community Operazione legata al tasto “Scegli” che seleziona la community e mostra la mappa con i relativi utenti ad essa collegati. Entity Object • Mappa: è la mappa di Google visualizzata con le impostazioni iniziali di default. • Utenti: sono gli utenti collegati in quel momento e che appartengono alla specifica community selezionata nella fase precedente. • user: è l’utente che ha selezionato la community e ne visualizza la mappa e gli utenti ed è in grado di interagire con essi. Boundary Object • Menu: sono le funzioni disponibili una volta ottenuta la visualizzazione grafica della mappa e comprendono lo zoom e le funzioni di interazione con gli altri utenti, oltre alla funzione di uscita dalla midlet. Control Object 51 • MostraMappa.java: funzione di passaggio e controllo dei dati di login, password e selezione della community al visualizzatore principale di mappe MyCanvas. • 4.2 Modelli dinamici 4.2.1 Sequence diagram Possiamo suddividere le sequenze di operazioni in due filoni principali: uno per la fase iniziale di accesso al sistema e visualizzazione mappa e l’altro di utilizzo delle funzioni di interazione con gli utenti della community. Nella prima fase quindi l’utente inserisce i propri dati di accesso, seleziona la community a cui vuole partecipare e inizia a visualizzare le dovute informazioni ossia la mappa e gli utenti collegati in quel momento. Questa fase comporta le connessioni sia al server su cui e’ installato il GECO SERVER sia a Google per il reperimento dei tiles per costruire la mappa. Nella fase di accesso le operazioni sono sequenziali su una linea temporale e sono previste interazioni solo col sistema sottostante per l’autenticazione e la scelta di una community. 52 Accesso e visualizzazione mappa 53 Nella seconda fase si può accedere alle funzioni del menù per interagire con la mappa e con gli altri utenti della community attivi in quel momento. Funzioni del Menu 54 5. LA GEOREFERENZIAZIONE DI UTENTI 5.1 PROGETTAZIONE La progettazione del sistema è stata eseguita considerando i seguenti fattori: • Linguaggio di programmazione • Database • Know-How personali ed aziendali Allo stato attuale i linguaggi di programmazione utili alla realizzazione di un client mobile sono molteplici. Abbiamo deciso di utilizzare JAVA come linguaggio base poiché è facilmente espandibile ed integrabile in diverse altre tecnologie e soprattutto perché è open-source. La scelta del DB è anch’essa orientata all’open-source e ci siamo affidati ad un database di largo uso nella comunità scientifica e che consenta di trattare dati di tipo spaziale. Abbiamo quindi preferito POSTGRESQL con il suo add-on POSTGIS. Ultime ma non meno importanti per la scelta delle strategia da utilizzare sono state le conoscenze personali e quelle 55 messe a disposizione Personalmente il mio dal team di background Unlimited universitario Software. si fonda principalmente su JAVA e quello aziendale, pur avendo a disposizione una più ampia scelta come ad esempio il linguaggio Microsoft Visual Basic, ha una radicata esperienza sulla gestione del database posgresql/postgis in ambito Java. Mettendo insieme le due cose, le conoscenze aziendali e il mio personale background, ci siamo definitivamente orientati a Java come linguaggio di programmazione e Postgis come database. 5.2. Interfaccia utente L’interfaccia proposta dal sistema è stata progettata in maniera tale da garantire all’utente sicurezza e familiarità con l’applicazione. Si e’ utilizzato l’approccio tipico di applicazioni J2ME con utilizzo di menù a tendina e funzioni semplificate. 5.2.1. Descrizione dell’interfaccia utente Possiamo suddividere l’interfaccia utente in due aree principali, 1. l’area in cui visualizza la mappa 56 2. i menù in cui accede alle funzioni del sistema. Descriveremo ora le diverse funzioni del sistema accessibili dal menù: Funzione Zoom-In Vogliamo avere un livello di dettaglio della mappa maggiore di quello attuale. Percorso Navigazione: Menu > Zoom In Funzione Zoom-Out Si richiede al sistema di ritornare ad un livello di zoom meno dettagliato ma che mostri una porzione di mappa più estesa. Percorso Navigazione: Menu > Zoom Out Funzione Visualizza Utenti Si richiede al sistema di visualizzare la lista degli utenti collegati in quel momento. Percorso Navigazione: Menu > Visualizza Utenti Funzione Visualizza Utenti a Distanza 57 Si richiede al sistema di visualizzare la lista degli utenti collegati in quel momento e alla distanza specificata dall’utente. Percorso Navigazione: Menu > Visualizza Utenti a distanza Funzione REFRESH MAPPA Si richiede al sistema di aggiornare le posizioni correnti degli altri utenti effettuando una nuova richiesta di coordinate al server. Percorso Navigazione: Menu > Refresh Mappa Funzione GPS Si richiede al sistema di attivare la procedura di ricerca, identificazione e associazione al sistema di un dispositivo GPS bluetooth. Percorso Navigazione: Menu > GPS 58 5.2 IMPLEMENTAZIONE 5.2.1 Suddivisione del sistema in componenti GECO client e’ suddiviso in 3 package logici: il package midlet, il package funzioni ed il package bluetooth. In ogni package sono raggruppate le funzioni logicamente correlate. Nel package midlet sono contenute 25 classi per l’avvio della midlet stessa e la gestione dei thread della inerenti alla visualizzazione dei dati provenienti dagli altri package. Nel package funzioni sono contenute 10 classi per la gestione delle connessioni e per le operazioni fondamentali su tiles e coordinate geografiche. Nel package bluetooth sono contenute 2 classi per la gestione del dispositivo GPS via bluetooth e per la manipolazione delle informazioni geografiche provenienti dal dispositivo stesso. 5.2.2. Descrizione dei sottosistemi Verranno di seguito descritte le principali classi dei 3 package che realizzano le funzionalità più importanti del progetto. 59 Package principale La prima classe da analizzare e’ la StartMidlet.java. si tratta della classe di avvio della midlet suite. Al suo interno sono stati implementati i principali metodi che una midlet eseguibile deve contenere [33] e in aggiunta sono stati implementati altri metodi che servono alle funzionalità del sistema. Per questa e per tutte le altre classi si è adottato lo schema di implementazione tipico di applicazioni grafiche. In particolare la veste grafica (Muchow, 2002) richiede numerosi thread e listener necessari alle operazioni di base come panning e zooming nonché di invio e ricezione dati tramite connessioni http. Questi sono i metodi che tengono traccia del canvas, dell’id dell’utente, del flag gps e dell’id della community. Avendo a che fare con Servlet e Jsp lato server si è voluti seguire l’approccio tipico di queste applicazioni, ossia la possibilità (specie nei siti di ecommerce) di mantenere attive sessioni e tenere traccia durante tali sessioni dei dati relativi all’acquirente. L’unica differenza è stata che, mentre lato server questa soluzione è intrinseca al modello di implementazione, nel nostro progetto abbiamo dovuto implementare e tenere traccia manualmente di ogni informazione 60 necessaria a realizzare uno specifico “stato” della midlet-suite. L’esempio tipico sono le funzioni get() e set() che vanno prese in considerazione quando durante la navigazione di una mappa si accede ad una funzionalità del menù (cosa particolarmente evidente per la funzione GPS). public void SetMC(MyCanvas m){MC=m;} public void setFlagGPS(){flagGPS=true;} public boolean getFlagGPS(){return flagGPS;} public void setIDUtente(int id){ idutente=id; } public int getIDUtente(){ return idutente; } public MyCanvas getMC(){ return MC; } public void setMC(MyCanvas myc){ MC=myc; } public String getIDCommunity(){ return idcommunity; } public void setIdCommunityy(String s){idcommunity=s;} public Display getDispl(){ return Display.getDisplay(this); } public void startGPS() { Display.getDisplay(this).setCurrent(get_mainForm()); mainForm.addCommand(backCommand); doDiscovery();} 61 Questa è la funzione di attivazione del gps via bluetooth. Il semplice metodo ha dietro tutta una fase di riconoscimento, selezione e associazione (pairing) del dispositivo che viene garantita dal metodo doDiscovery(). private void doDiscovery() { discovery = new Discovery(this); new Thread(new Runnable() { public void run() { try { discovery.performDiscovery(); } catch (Exception ex) { alert(AlertType.ERROR, "discovery", ex); } } }).start(); } E qui invece si vede come si attiva il thread durante la fase di attivazione del gps dal menu del dispositivo. La doDiscovery() è la prima fase di ricerca dei dispositivi bluetooth visibili nel raggio di azione del dispositivo mobile. E’ richiesta la precedente abilitazione del bluetooth da parte dell’utente altrimenti la funzione lancia un messaggio di errore. Tale messaggio è gestito dalla funzione alert(final AlertType type, final String message, final Throwable th) ed è strettamente legate ai metodi di implementazione del bluetooth. Vi è infine un metodo doConnect() che si occupa di eseguire la connessione al dispositivo gps e gestisce in maniera del tutto trasparente 62 all’utente le varie fasi in modo da semplificare al massimo le operazioni di associazione di un dispositivo bluetooth per l’utente. L’unica cosa richiesta all’utente è di abilitare il bluetooth nel dispositivo mobile e di selezionare “GPS” [34] nelle funzioni del menù. public void alert(final AlertType type, final String message, final Throwable th) { alert.setType(type); alert.setTimeout(Alert.FOREVER); final String exMsg = th == null ? null th.getMessage(); final String text = exMsg == null ? message message + ": " + exMsg; alert.setString(text); if (DEBUG) { System.err.println(text); status.setText(text); if (th != null) { th.printStackTrace(); } } Display.getDisplay(this).setCurrent(alert, mainForm); : : } Passiamo ora a esaminare il modo in cui vengono inizializzate le connessioni di rete e la richiesta di tiles. Questa porzione di codice attiva la form iniziale e mette in ascolto la midlet in attesa della digitazione del tasto di login o di uscita. public void startApp() { try { 63 Form f=new Form(""); f.setTicker(title); Image img=Image.createImage("/mondo.gif"); f.append(img); d.setCurrent(f); f.addCommand(cmdCommand3); f.addCommand(cmdCommand4); f.setCommandListener(newCommandActionIniziale(d,this)); } catch(Exception e) { e. printStackTrace(); } } CommandActionIniziale è quindi la seconda classe java da analizzare e di seguito ne mostriamo porzioni di codice: public void commandAction(Command cc, Displayable arg1) { if(cc.getLabel().equals("Login")){ Form form = new Form("Effettua Login"); login = new TextField("Login", null,30,TextField.ANY); password=newTextField("Password",null,15,TextField. PASSWORD); } else{ if(cc.getLabel().equals("Entra")){ if(mm==null){ return; } Thread t = new Thread(new EffettuaLogin( password.getString(), d, mm)); t.start(); } } if(cc.getLabel().equals("Exit")){ mm.exitApp(); } login.getString(), 64 Nel caso in cui l’autenticazione va a buon fine, si passa alla chiamata della classe CommandActionIniziale2(). Vediamola qui di seguito nelle sue parti più importanti: public CommandActionIniziale2(Display dd,StartMidlet m,String login,String password) { vis=new VisualizzaCommunityUtente(login, password, dd); t=new Thread(vis); t.start(); } ………………. if(v.isEmpty()){ Form f=new Form("Errore : "); StringItem str=new StringItem("ATTENZIONE : ","Non ci sono cmmunity Registrate, Riprova dopo Eserti registrato a qualche community"); } else{ l.setTitle("Seleziona La Tua Community :"); Enumeration e=v.elements(); while(e.hasMoreElements()){ Community c=(Community)e.nextElement(); String temp=""+c.getID()+" "+c.getNome(); mm.setIdCommunityy(c.getID()); La classe verifica la disponibilità di community registrate per lo specifico utente attraverso l’esecuzione di un nuovo thread della classe VisualizzaCommunityUtente. Successivamente mostra le community registrare oppure un messaggio di errore. Diamo uno sguardo a questa classe: public VisualizzaCommunityUtente(String password,Display dd) login,String 65 { URL="http://www.us.it/ServerGeco/ServletLoginClient?login="+login+"&password="+p assword+"&comando=visualizzacommunity"; V=new Vector(); } public void run() { try { conn = (HttpConnection)Connector.open(URL); int c; ByteArrayOutputStream baos ByteArrayOutputStream(); is = conn.openInputStream(); = new while ((c = is.read()) != -1) { baos.write(c); } String s = new String(baos.toByteArray()); System.out.println(s); String temp=""; int conta=0; String idcomunity=""; String nomecomunity=""; for(int i=0;i<s.length();i++){ if(s.charAt(i)!=' '){ temp=temp+s.charAt(i); }else{ if(conta==0){ conta++; idcomunity=temp; temp=""; }else{ if(conta==1){ conta++; nomecomunity=temp; temp=""; V.addElement(new Community(idcomunity,nomecomunity)); idcomunity=""; nomecomunity=""; conta=0; } } } } baos.close(); is.close(); conn.close(); } 66 Si può notare che si esegue un thread di connessione al Server Geco e si memorizzano in un Vettore la lista delle community registrate per lo specifico utente. Ritornando alla classe CommandActionIniziale2.java da cui era partita la richiesta, la seguente porzione di codice realizza la visualizzazione della mappa. Da questo momento inizia la parte dell’algoritmo principale di gestione dei tiles: if(cc.getLabel().equals("Scegli")){ idcomunity=l.getString(l.getSelectedIndex()); mostramappa=new MostraMappa(idcomunity,d,mm); mm.setMappa(mostramappa); t=new Thread(mostramappa); t.start(); Algoritmo di gestione dei tiles. Vedremo ora come vengono richiesti i tiles e come vengono gestiti dall’ algoritmo. Passiamo quindi alla rappresentazione grafica e le funzioni di disegno [35]. Per far ciò è necessario analizzare la classe MyCanvas.java: public class MyCanvas extends Canvas implements CommandListener,ActionListener,GPSInfo.Listener {…………. 67 public MyCanvas(StartMidlet exiter,String idcom) throws Exception protected void paint(Graphics g) { try { m_panner.paint(g); } public void performAction() { repaint(); } protected void keyPressed(int keyCode) { m_panner.keyPressed(getGameAction(keyCode)); } protected void keyReleased(int keyCode) { m_panner.keyReleased(getGameAction(keyCode)); } protected void pointerPressed(int x, int y) { m_panner.pointerPressed(x, y); } protected void pointerDragged(int x, int y) { m_panner.pointerDragged(x, y); } public void commandAction(Command c, Displayable d) { if(c == AppExiter.EXIT) { m_updater.cancel(); m_appExiter.exitApp(); } } public static void register(ActionListener obj) { m_updater.register(obj); } private static final ActionUpdater(1000, 25); ActionUpdater m_updater = new Come è facile notare, la classe MyCanvas estende Canvas [36], la classe base per la grafica in J2ME, ed implementa 3 listener. 68 Vi sono poi i thread per le interazioni con l’utente ma soprattutto vi è il sistema che consente di effettuare il panning sui tiles. E’ infatti l’ImagePanner che consente di spostarsi un immagine quando questa risulti essere più ampia delle dimensioni del display in uso. E’ l’ActionListener che “registra” gli spostamenti con i tasti direzione e la funzione paint, che sfrutta tale listener, ridisegna di volta in volta la grafica. Inoltre sono presenti anche (ma solo parzialmente) i metodi per gestire un dispositivo touchscreen sul quale viene comunque garantito il panning dell’immagine. La classe fondamentale quindi che si occupa di gestire le immagini e di effettuare il panning è ImagePanner.java. Vediamo nel dettaglio come funziona: public ImagePanner(Canvas screen,String idcom,StartMidlet ex) throws Exception { latitudine=0.0; longitudine=0.0; idutente=0; threadinserisci=new ThreadInserisciCoordinateGPS(exiter.getIDUtente(),latitudine,lo ngitudine,exiter); idcomunity=idcom; zoom = 9; posizione=new GeoLocation(42, 13); tileDiProva = new TileUtils(posizione.getLatitudine(), posizione.getLongitudine(), zoom); x_tile=tileDiProva.getTileCoord().getX(); y_tile=tileDiProva.getTileCoord().getY(); x_tileA=x_tile; y_tileA=y_tile; x_tileB=x_tile+1; 69 y_tileB=y_tile; x_tileC=x_tile; y_tileC=y_tile+1; x_tileD=x_tile+1; y_tileD=y_tile+1; marker=Image.createImage("/marker.png"); MyCanvas.register(this); m_screenWidth = screen.getWidth(); m_screenHeight = screen.getHeight(); xx=m_screenWidth/2; yy=m_screenHeight/2; int tempDiYY =yy; listaImmagini=new Hashtable(); c=new CalcolaArea(xx,yy,m_screenHeight,m_screenWidth,null); imgA=c.drawRettangoloA(x_tile,y_tile,zoom); imgB=c.drawRettangoloB(x_tile+1,y_tile,zoom); imgC=c.drawRettangoloC(x_tile,y_tile+1,zoom); imgD=c.drawRettangoloD(x_tile+1,y_tile+1,zoom); listaImmagini.put("A",new TileImmagine(imgA,xx256,yy-256,x_tileA,y_tileA,"A")); listaImmagini.put("B",new TileImmagine(imgB,xx,yy256,x_tileB,y_tileB,"B")); listaImmagini.put("C",new TileImmagine(imgC,xx256,yy,x_tileC,y_tileC,"C")); listaImmagini.put("D",new TileImmagine(imgD,xx,yy,x_tileD,y_tileD,"D")); timer=new Timer(); timerricezionesms=new Timer(); con=new HttpConnector(idcomunity); t=new Thread(con); t.start(); } Vengono settate le coordinate iniziali da cui partire, viene settato un determinato livello di zoom iniziale e si passa alla richiesta dei tiles. A tal fine è fondamentale la classe TileUtils.java [37] che analizzeremo nel prossimo package. Da questo momento 70 andiamo a richiedere a Google i 4 tiles che ci serviranno per mostrare la mappa iniziale. Ogni tile è identificato da due coordinate x ed y. Il primo tile (tile A), ad esempio, conterrà i valori x_tileA = 1500 e y_tileA = 1780 entrambi di tipo intero. I restanti tile (tile B, tile C, tile D) sono identificati partendo dalle coordinate del primo tile e aggiungendo +1 alle loro coordinate di riferimento a seconda se si trova a destra, in basso o in basso a destra del tile A. In pratica le mappe di google sono rappresentate come una griglia dove ogni quadrato identifica un tile e ogni tile è identificato dalle sue coordinate x ed y. Questa tecnica di rappresentazione dei tile prende il nome di “raster gerarchico”. E’ un albero (denominato quad-tree) dove ad ogni livello di zoom ci sono dei tile in una griglia. Ogni tile ad un livello z viene suddiviso in 4 tiles nel livello sottostante. La struttura quindi è un albero quando si prende in considerazione il livello di zoom e consiste di 4 tile quando si passa a considerare il livello sottostante [38]. Tornando alla nostra visualizzazione della mappa quindi, ogni tile viene disegnato come un immagine in un rettangolo passandogli la x e la y del tile in questione [39]: 71 imgA=c.drawRettangoloA(x_tile,y_tile,zoom); Precedentemente abbiamo suddiviso il nostro display in 4 parti virtuali: m_screenWidth = screen.getWidth(); m_screenHeight = screen.getHeight(); xx=m_screenWidth/2; yy=m_screenHeight/2; Questo ci servirà poiché xx ed yy sono le coordinate del punto centrale del display del dispositivo grazie al quale potremo agganciare i 4 tiles in modo affiancato (secondo certi criteri che stabiliremo a breve) e contigui l’uno all’altro. [40] Inoltre, con un hastable, teniamo traccia di quali sono i tiles visualizzati. Questo per garantire il caricamento dinamico dei tiles e, in futuro, per realizzare i meccanismi di cache: private Hashtable listaImmagini: listaImmagini.put("A",newTileImmagine(imgA,xx-256,yy256,x_tileA,y_tileA,"A")); Prendiamo in considerazione il punto centrale del display. Se tracciamo due linee, una verticale e una orizzontale, che passano per esso, avremmo suddiviso il display in 4 parti. I nostri tiles andranno a posizionarsi esattamente in queste 4 parti. Nello specifico, il tile A sarà posizionato nel quadrato in alto a sinistra, 72 il tile B in alto a destra, il tile C in basso a sinistra e il tile D in basso a destra. Poiché i nostri tiles hanno dimensione 256x256 [41] ognuno è ovvio domandarsi come essi possano essere piazzati nei suddetti quadrati visto che ogni dispositivo ha dimensioni di schermo differenti e di certo quasi nessuno di essi avrà dimensioni tali da contenere anche un singolo tile. Ebbene, ogni tile verrà posizionato nel rispettivo quadrato andando a far combaciare solo un angolo per ognuno di essi con il punto centrale del display. Quindi, ad esempio, per il tile A solo il suo angolo in basso a destra combacia col punto centrale mentre per il tile B solo il suo angolo in basso a sinistra. La restante porzione di tile non viene visualizzata ma il dispositivo ha comunque conoscenza del fatto che il tile esiste ed è completo. E’ solo una questione di visualizzazione. Grazie a questo meccanismo di gestione dei tiles possiamo effettuare panning su questi primi 4 senza perdere alcuna informazione della mappa. Vediamo ora come si naviga sulla mappa quando ci si sposta oltre il confine di uno dei 4 tiles. Questa strategia di caricamento di 4 tiles e il loro aggiornamento automatico durante lo scrolling della mappa è alla base delll’algoritmo sviluppato in azienda ed 73 è un punto centrale di tutto il progetto, in quanto si presta in modo naturale L’approccio all’integrazione adottato risulta delle altre fondamentale componenti. per i futuri meccanismi che si intendono realizzare e che sono stati ipotizzati nel capitolo degli sviluppi futuri. Supponiamo di spostarci in alto. Il panning consente di scorrere la mappa a velocità selezionabile durante l’implementazione grazie alla seguente riga di codice: m_updater = new ActionUpdater(1000, 25); dove i valori 1000 e 25 indicano rispettivamente la initSleep, ossia il tempo di caricamento iniziale e l’intervallo. In altre parole consente di selezionare la velocità di scorrimento della mappa. Proseguendo verso l’alto quindi e giungendo al margine superiore di un tile (in realtà i margini vengono raggiunti per due tiles alla volta), ossia quando il margine superiore del tile coincide col margine superiore del display, la mappa si blocca, non avendo altre immagini o porzioni di immagini da visualizzare. In questo momento il controllo degli off-set fa scattare la richiesta di altri due tiles: public void performAction() { 74 switch(m_gameAction) { case Canvas.UP: if(yy-256!=0){ yy+=1; } else{ System.out.println("caricati 2 nuovi tile"); this.AggiornaUP(); } La funzione AggiornaUP() effettua un rimescolamento dei 4 tiles come mostrato nel seguente codice: public void AggiornaUP(){ yy=0; Image temp1=imgA; Image temp2=imgB; imgC=null; imgD=null; imgA=null; imgB=null; CalcolaArea c m_screenHeight, = new CalcolaArea(xx, m_screenWidth, null ); yy, y_tile=y_tile-1; x_tileC=x_tileA; y_tileC=y_tileA; x_tileD=x_tileB; y_tileD=y_tileB; x_tileA=x_tile; y_tileA=y_tile; x_tileB=x_tile+1; y_tileB=y_tile; imgA=c.drawRettangoloC(x_tile,y_tile,zoom); imgB=c.drawRettangoloC(x_tile+1,y_tile,zoom); imgC=temp1; imgD=temp2; 75 In altre parole, ci troviamo nel caso in cui siamo giunti ai margini superiori dei tile A e B. Continuando a salire siamo costretti a richiedere i due nuovi tiles della parte superiore. I tiles C e D conterranno adesso quelli che erano A e B mentre questi ultimi verranno aggiornati con i nuovi tiles caricati dalla funzione CalcolaArea della omonima classe del package “funzioni” [42]. Una delle cose che sicuramente andiamo a disegnare oltre ai tiles sono i cosiddetti markers [43]. Distinguiamo ora due diverse tipologie di markers: il marker ke identifica la nostra posizione e i marker prelevati dal server che identificano la posizione degli altri utenti La porzione di codice seguente illustra il funzionamento: public void paint(Graphics g) throws IOException { …….. …………… private TileUtils tileDiProva; SimplePoint punto=tileDiProva.getTileCoordinate(geo.getLatitudine(), geo.getLongitudine(), zoom); if(punto.getX()==A.getTileX() punto.getY()==A.getTileY()){ && 76 myPoint = tileDiProva.getBitmapCoordinate(geo.getLatitudine(),geo.getLong itudine(),zoom); g.drawImage(marker, A.getAngoloX()+(myPoint.getX()%256), A.getAngoloY()+(myPoint.getY()%256), Graphics.TOP|Graphics.LEFT); } if(punto.getX()==B.getTileX() punto.getY()==B.getTileY()){ && myPoint = tileDiProva.getBitmapCoordinate(geo.getLatitudine(),geo.getLong itudine(),zoom); g.drawImage(marker, B.getAngoloX()+(myPoint.getX()%256), B.getAngoloY()+(myPoint.getY()%256), Graphics.TOP|Graphics.LEFT); } if(punto.getX()==C.getTileX() punto.getY()==C.getTileY()){ && myPoint = tileDiProva.getBitmapCoordinate(geo.getLatitudine(),geo.getLong itudine(),zoom); g.drawImage(marker, C.getAngoloX()+(myPoint.getX()%256), C.getAngoloY()+(myPoint.getY()%256), Graphics.TOP|Graphics.LEFT); } if(punto.getX()==D.getTileX() punto.getY()==D.getTileY()){ && myPoint = tileDiProva.getBitmapCoordinate(geo.getLatitudine(),geo.getLong itudine(),zoom); g.drawImage(marker, D.getAngoloX()+(myPoint.getX()%256), D.getAngoloY()+(myPoint.getY()%256), Graphics.TOP|Graphics.LEFT); } Questa prima porzione mostra come disegnare il nostro marker derivato dalle coordinate del dispositivo gps. Per capirne il 77 funzionamento dobbiamo fare alcune considerazioni. Nella nostra classe TileUtils.java del package funzioni riusciamo, avendo coordinate in termini di latitudine e longitudine e avendo un tiles su cui visualizzarle, a posizionare il nostro marker poiché vi sono delle funzioni di trasformazione che convertono coordinate geografiche (LAT/LON) [44] in coordinate grafiche del dispositivo (X e Y) con una approssimazione di uno o due pixel6 al massimo. Sappiamo quindi come rappresentare queste coordinate sul display. Il problema fondamentale però è che dobbiamo anche sapere se un marker (il nostro o quello degli altri utenti) deve essere o meno visualizzato sulla mappa. E inoltre, anche sapendo se deve essere o meno visualizzato, dobbiamo essere certi che appartenga ad uno dei 4 tiles. In altre parole, avendo la nostra posizione geografica, per disegnare un marker sul dispositivo dobbiamo verificare che quella posizione sia “visibile” in quel preciso istante e, in caso affermativo, stabilire quale dei 4 tiles contiene quelle coordinate e quindi quel marker. Nel codice precedente si effettua innanzitutto una trasformazione per conoscere le coordinate del tile che contiene il marker (i.e. le coordinate lat=40 e lon=15 sono contenute, a 6 6 pixel è l’unità minima fondamentale di un display. 78 livello di zoom 6, dal tile x= 1020 e y= 1840) e poi si controllano queste coordinate di tile con le coordinate dei 4 tiles attualmente in uso. Il marker potrà così essere posizionato correttamente sul suo tile di appartenenza [45]. Identica situazione per i marker degli altri utenti. Si recuperano le coordinate degli utenti dal server sotto forma di punti geografici. Si effettua la conversione per sapere le coordinate del tile che contiene quel punto e si controlla se il tile di appartenenza del punto è uno dei 4 tiles del dispositivo e lo si disegna [46]. Algoritmi di gestione delle funzioni del menù. Restando all’interno della classe ImagePanner.java diamo un breve accenno alle restanti funzioni del menù. La porzione di codice seguente richiede una lista di utenti nelle due versioni possibili: utenti della community e utenti a distanza. if(cc.getLabel().equals("VediUtenti")){ Thread t=new Thread(new exiter.getIDCommunity(), exiter.getDispl())); SelezionaUtentiAll( exiter, 79 t.start(); } if(cc.getLabel().equals("VediUtentiADistanza")){ TextField distanza=new TextField("Distanza m.",null,15,TextField.ANY); CommandActionConferma cdd = new CommandActionConferma(exiter.getDispl(), exiter, distanza); f.setCommandListener(cdd); exiter.getDispl().setCurrent(f); } Questa porzione di codice che segue realizza lo zoom-in e lo zoom-out. Per lo zoom-in è da notare la chiara esplicitazione del concetto di raster gerarchico e di quad-tree. x_tile e y_tile vengono moltiplicati per 2 poiché, dato un tile, al livello sottostante esso viene suddiviso in 4 e oguno dei risultanti avrà ovviamente un maggiorelivello di dettaglio.[47] La semplice moltiplicazione fornisce, dei 4, il tile in alto a sinistra. Poiché abbiamo una costruzione basata su offset abbiamo preferito prelevare il tile in basso a destra aggiungendo la quantità di una unità (+1). Questa situazione è ovviamente migliorabile in termini di precisione come si vedrà nel capitolo sugli sviluppi futuri. [48] Stessa situazione per lo zoom-out con l’unica differenza che il processo matematico è inverso. Ossia, dato un tile, esso costituisce la quarta parte del tile che lo contiene al livello 80 superiore. Per reperire il tile di livello superiore si effettua una divisione per 2. [49] if(cc.getLabel().equals("ZoomIn")){ if(zoom>0){ zoom=zoom-1; x_tile=(x_tile*2)+1; y_tile = (y_tile*2)+1; prenditile.setX_tile(x_tile); prenditile.setY_tile(y_tile); prenditile.setZoom(zoom); if(prendiimmagini==null) prendiimmagini=new Thread(prenditile); prendiimmagini.start(); else{ if(cc.getLabel().equals("ZoomOut")){ if(zoom<14){ zoom=zoom+1; x_tile=(x_tile/2); y_tile = (y_tile/2); prenditile.setX_tile(x_tile); prenditile.setY_tile(y_tile); prenditile.setZoom(zoom); if(prendiimmagini==null) prendiimmagini=new Thread(prenditile); prendiimmagini.start(); 81 Algoritmi di gestione delle funzioni di messaggistica. Torniamo alla lista degli utenti (sia completa che degli utenti a distanza). Una volta ottenuto l’elenco degli altri utenti attivi abbiamo detto che è possibile inviare dei messaggi. La clsse che gestisce utenti e messaggi è SelezionaUtentiAll.java. Oltre alle solite procedure di connessione, vediamo come il codice che segue gestisce i messaggi: public SelezionaUtentiAll(String idcommu,StartMidlet m,Display d) { …………………. public void setDisplay(Vector v){ if(V.size()!=0){ f = new Form("Lista utenti :"); List l=new List("Lista UtentiCommunity",List.IMPLICIT); for(int i=0;i<v.size();i++){ Utente u=(Utente)v.elementAt(i); l.append(u.getID(), null); } Command inviamess=new Command("InviaMessaggio",Command.OK,1); Command visualizza=new Command("VisualizzaScheda",Command.OK,1); l.setCommandListener(new CommandActionMessaggi(l,idutente,mm,this)); …………..} else{ Come si può notare, la classe effettua una richiesta al server degli utenti collegati e gestisce la possibilità di visualizzare una scheda utente (che per il momento fornisce solo una anagrafica) e di mandare un messaggio. Questi sono i tipici servizi di una 82 community. La classe CommandActionMessaggi.java è il listener in ascolto alla digitazione del tasto “InviaMessaggio” e di “VisualizzaScheda”. Vediamo come funziona e come è gestito il meccanismo di messaggistica: public CommandActionMessaggi(List l,String idmittente,StartMidlet m,SelezionaUtentiAll selezionautenti) { destinatario=l.getString(l.getSelectedIndex()); mittente=idmittente; lista=l; seleziona=selezionautenti; } public void commandAction(Command cc, Displayable arg1) { ………………………………… if(cc.getLabel().equals("InviaMessaggio")){ t= new TextBox("", "", 10, TextField.URL); destinatario=lista.getString(lista.getSelectedIndex()); Display display=mm.getDispl(); Form f=new Form(""); t.setTitle("Invia Messaggio A "+destinatario); …………………………… } if(cc.getLabel().equals("Invia")){ String mess=""; mess=t.getString(); ThreadInserisciMessaggistica thr=new ThreadInserisciMessaggistica(destinatario,mittente,mess,mm); th=new Thread(thr); th.start(); } Una volta scritto il messaggio da inviare, la classe ThreadInserisciMessaggistica.java si occupa di inoltrare la richiesta. Questa è una fase particolarmente delicata in quanto se non vengono effettuate delle opportune modifiche al messaggio stesso esso non viene interpretato nel modo corretto dalla servlet di 83 GecoServer. Analizziamo la classe ThreadInserisciMessaggistica.java e vediamo cosa si intende per “interpretato”: public ThreadInserisciMessaggistica(String destinatario,String mittente,String text,StartMidlet m){ ……………………………… codifica=new UrlCodec(); messaggio=UrlCodec.encode(messaggio); URL="http://www.us.it/ServerGeco/ServletInviaMessaggio?mittente="+idmittente+"&d estinatario="+iddestinatario+"&msg="+messaggio; } public void run(){ HttpConnection conn = null; InputStream is = null; int rc = -1; try { conn = (HttpConnection)Connector.open(URL); int c; ByteArrayOutputStream baos = new ByteArrayOutputStream(); is = conn.openInputStream(); while ((c = is.read()) != -1) { baos.write(c); } String s = new String(baos.toByteArray()); this.setDisplay(s); } } Nel codice precedente si vede quindi come il messaggio debba essere “codificato” in maniera opportuna per poter essere interpretato lato server. Questa procedura prende il nome di “URL ENCODING” In mancanza di questa codifica, la servlet riceverebbe un messaggio con all’interno dei codici alfanumerici 84 dovuti alla spaziatura tra parole o all’inserimento di caratteri speciali. Lo vediamo nel codice di UrlCodec.java che segue: public class UrlCodec { public static final int[] array ={0x20,0x22,0x23,0x24,0x25,0x26,0x2A,0x2B,0x2C,0x2F,0x3A,0x3B,0 x3C,0x3D,0x3E,0x3F,0x40,0x5b,0x5c,0x5d,0x60,0x7b,0x7c,0x7d,0x7e }; public UrlCodec() { } public static boolean isProtected(char c){ for(int i=0;i<array.length;i++){ if(c==array[i]) return true; } return false; } public static String encode(String input){ StringBuffer buffer=new StringBuffer(); for(int i=0;i<input.length();i++){ if(isProtected(input.charAt(i))){ buffer.append("%"+Integer.toHexString(input.charAt(i))); } else{ buffer.append(input.charAt(i)); } } return buffer.toString(); } A questo punto è quindi possibile inserire spazi e altri caratteri speciali nel testo senza che questo influenzi il buon esito dell’invio. Resta quindi da capire come il destinatario riceve il messaggio. Dobbiamo quindi analizzare la classe ThreadRiceviMessaggio.java che è stata instanziata nel panner la prima volta: 85 public ThreadRiceviMessaggio(int idIN,StartMidlet m) { timerricezionesms=new Timer(); URL="http://www.us.it/ServerGeco/ServletRecapitaMessaggio?id="+id; } public void run(){ …………………….. try { conn = (HttpConnection)Connector.open(URL); int c; ByteArrayOutputStream baos = new ByteArrayOutputStream(); is = conn.openInputStream(); while ((c = is.read()) != -1) { baos.write(c); } String s = new String(baos.toByteArray()); if(!s.equals(null)){ String temp=""; int conta=0; String idmittente=""; String testo=""; for(int i=0;i<s.length();i++){ if(s.charAt(i)!=','){ temp=temp+s.charAt(i); } else{ if(conta==0){ conta++; idmittente=temp; temp=""; } else{ if(conta==1){ conta++; testo=temp; mess=new Messaggio(); mess.setMittente(idmittente); mess.setMessaggio(testo); idmittente=""; }} this.alert(V); ……………………. . . . if(!mes.isEmpty()){ mm.mappa.mc.m_panner.m_gameAction=0; Form f=new Form("Ricevuto "+V.size()+" Messaggi"); this.setFlag(); alert.setTimeout(Alert.FOREVER); alert.setTitle("Hai ricevuto nuovi Messaggi"); String text=""; Enumeration enumerazione=mes.elements(); 86 while(enumerazione.hasMoreElements()) { Messaggio messs=(Messaggio)enumerazione.nextElement(); text =text+"FROM "+messs.getMittente()+":"+messs.getMessaggio()+"\n"; } mes.removeAllElements(); Command cmd =new Command("OK",Command.OK,1); alert.setString(text); alert.addCommand(cmd); alert.setCommandListener(mm); mm.mappa.mc.m_panner.threadricevimessaggio.cancel(); } Da notare come il destinatario, ad intervalli regolari impostati dalla classe timer ed eventualmente parametrizzabile dall’utente, riceva tutti gli eventuali messaggi degli altri utenti. Il sistema in automatico legge dal database ogni x secondi gli eventuali messaggi per l’utente. Se sono presenti messaggi la midlet blocca il panning e provvede a gestirli. Ad ogni intervallo, il sistema richiede i nuovi messaggi e l’architettura sottostante si preoccupa di marcare suddetti messaggi come “gia letti” per evitare un secondo invio degli stessi. Anche nel caso in cui vi fossero più messaggi da parte di più utenti, la suddetta classe mostra una “pop-up7” per ognuno di essi visualizzando per primo il messaggio più recente. L’utente quindi visualizza il testo del messaggio accompagnato dall’id del mittente e, una volta letto, può digitare il tasto “OK” e procedere alla lettura della prossima pop-up. Terminati tutti i messaggi, 7 Messaggio istantaneo visualizzato in un apposito riquadro solitamente più piccolo del display in uso 87 l’utente può proseguire nell’utilizzo dell’applicazione. Da notare che i messaggi risiedono sul server e che, siccome gli eventi si susseguono in modo asincrono nella community, potrebbe capitare che un utente esca dal sistema prima di ricevere un messaggio inviatogli da un altro utente attivo. Il mittente quindi non riesce ad accorgersi in tempo che il destinatario non risulta più collegato e procede all’invio del messaggio. Questa situazione non desiderata comporterebbe ovviamente la perdita del messaggio se non fosse presente il flag di lettura dello stesso. In tal modo, il destinatario scollegatosi appena pochi secondi prima, riuscirà a visualizzare il messaggio al suo prossimo login nel sistema. Ovviamente, un timestamp sul messaggio avviserà il destinatario del giorno e dell’ora esatta in cui gli è stato inviato. Package bluetooth Del package bluetooth da notare solo la classe GPSInfo.java che effettua il parsing delle stringhe inviate dal dispositivo GPS. Mostriamo solo i metodi relativi alla gestione dei dati: 88 public String getUTC() { return utc; } public double getLatitude() { return lat; } public double getLongitude() { return lon; } public int getSatelliteCount() { return nsat; } public double getAccuracy() { return accuracy; } public double getAltitude() { return alt; } La classe quindi lavora sui dati del gps e opera delle opportune scomposizioni della stringa ricevuta in maniera tale da poter fornire i singoli dati attraverso i suddetti metodi. Package funzioni Del package funzioni invece sono da notare le classi TileUtils.java e CaricaImmagine.java. Iniziamo ad analizzare la classe CaricaImmagine: public CaricaImmagine(int xx,int yy,int z){ x=xx; y=yy; zoom=z; 89 } public Image getImmagine() { String utl="http://mt1.google.com/mt?n=404&x="+x+"&y="+y+"&zoom="+zoom ; Come gia detto all’inizio del documento la modalità di visione mappe è completamente diversa dal servizio di mappe fornito da Google. Questo url nel codice in alto, opportunamente modificato in modo da inserire valori al posto delle variabili, fornisce la visualizzazione di un solo tile. Uno studio approfondito è stato effettuato su questo url e sul tile da esso fornito. L’url in questione, d’altra parte, non è unico. Siamo giunti alla conclusione che Google gestisce diversi server su cui tiene memorizzate le mappe e per di più ha anche diverse versioni di mappe che differiscono, ad un rapido sguardo, per colore e informazioni presenti. try { conn=(HttpConnection)Connector.open(utl); conn.setRequestProperty("UserAgent","Profile/MIDP-2.0 Configuration/CLDC-1.1"); Inoltre, dopo aver lavorato per circa due mesi all’applicazione, non era più possibile visualizzare mappe. Dopo un attento studio abbiamo trovato soluzione con la porzione di codice di cui sopra. Facciamo un passo indietro. L’url dal quale preleviamo tiles poteva essere aperto in un qualsivoglia browser, sia esso un web-browser o 90 un mobile-browser. Dopo oltre due mesi di sviluppo, google, senza alcun preavviso ne documentazione a riguardo, ha impostato i suoi server in maniera tale che ad ogni richiesta di tile dovesse essere esplicito il tipo di browser che la sta effettuando. La difficoltà di interpretazione di questo meccanismo è stato soprattutto il fatto che sembrava scontato che un browser desse informazioni di se stesso ma, mentre questo può essere vero per un web-browser, non lo è di sicuro per il client emulato dal WTK della SUN. Su un dispositivo reale, invece, il problema sembrava non porsi Librerie matematiche esterne Per realizzare le trasformazioni da coordinate geografiche in coordinate grafiche sul display, per posizionare correttamente un marker sul tile di riferimento avendo le sue coordinate e per sapere le coordinate x ed y del tile che contiene uno specifico punto identificato dalle sue coordinate geografiche è stato necessario utilizzare la classe TileUtils.java.[50] Questa classe utilizza due librerie esterne, MatC e MatFP per poter calcolare 91 funzioni matematiche che non sono presenti nella libreria di base di J2ME. In particolar modo si è dovuta implementare la funzione logaritmo poiché essa, pur essendo presente nelle suddette librerie, necessitava di una opportuna correzione in quanto il risultato del logaritmo non era corretto. Abbiamo quindi in parte riscritto la libreria MathC affinché fornisse il corretto valore del calcolo dei logaritmi. La libreria MathFP invece contiene le funzioni di seno e coseno, anch’esse non presenti nella libreria di base. La funzione atan (arctangente) di suddetta classe infatti viene utilizzata in TileUtils.java assieme alle altre per il corretto posizionamento del punto sul display. [51] 92 6. L’ESEMPIO DELLA GIS COMMUNITY Vediamo, schermata per schermata come si presenta la midlet all’utente. A sinistra la schermata di avvio. A destra la prima schermata di autenticazione con login e password. 93 L’avvenuta autenticazione con la scelta della community a cui ci si è registrati. Lesempio mostra solo una community ma ve ne potrebbero essere diverse. 94 La visualizzazione della mappa di default con i relativi marker degli utenti attivi nella community scelta. 95 Esempio di uso delle funzioni. A sinistra la funzione di attivazione del gps. A destra un esempio di zoom-in sulla mappa di default. 96 Esempio di zoom-out a sinistra ed a destra l’uso della funzione di ricerca di utenti a distanza con inserimento parametro in metri. 97 7. CONCLUSIONI Lo svolgimento del lavoro ha portato alla realizzazione di un sistema concreto ed utilizzabile a tutti gli effetti. Il sistema è stato realizzato rispettando in pieno le premesse iniziali, legate all’utilizzo di software open source. Sono state realizzate le principali funzioni e servizi previsti che consentono la gestione base di una mobile community, e soprattutto, è stata trovata una soluzione software che ha consentito la visualizzazione di mappe avanzate, come quelle fornite dal servizo di Google Maps, sui dispositivi mobili di utilizzo comune e con capacità limitate. In aprticolare la soluzione software proposta, basata sull’ algoritmo descritto nel capitol 5, può essere facilmente riutilizzata in altri contesti applicativi, in virtù del fatto che la classi sviluppate sono state progettate ed organizzate come una libreria indipendente. Il capitolo 6 mostra chiaramente con degli esempi il livello operativo raggiunto nello sviluppo del progetto, in termini di fruizione di servizi, usabilità dell’interfaccia, ecc. Il sistema è stato testato con successo nella pratica, tramite l’utilizzo di dispositivi mobili e supporti hardware illustrati in una scheda tecnica sintetica presentata nell’appendice A. Una opportuna configurazione dei 98 tempi (timeout) di aggiornamento dei servizi di localizzazione, ha inoltre evidenziato, come l’uso di questo sistema, per un utente, possa anche essere considerato relativamente economico, rispetto ai costi di traffico dati su canale GPRS, calcolati sulle tariffe medie dei principali operatori di telefonia. 99 8. SVILUPPI FUTURI J2ME mette a disposizione un sistema di memorizzazione dati sul dispositivo detto RMS8 attraverso il quale sarebbe possibile, in maniera ottimizzata, tenere traccia dei tiles scaricati, sia per evitare un ulteriore download degli stessi e quindi velocizzare il processo di visualizzazione della mappa e sia per ottimizzare il traffico dati sulla rete GPRS. In altre parole, un meccanismo per mantenere, in un database del dispositivo, dati persistenti garantirebbe la fruizione di mappe già scaricate anche in assenza di connessione. Con l’evoluzione al WEB2.0 è possibile ipotizzare l’integrazione con altre tecnologie di sviluppo per Java come JAVAFX MOBILE. JavaFx mobile è un framework progettato per realizzare applicazioni mobili ricche di contenuti multimediali, di maggior impatto sull’utente finale ed abilita molte altre funzionalità del sistema di reti wireless. Con JavaFx quindi sarebbe possibile realizzare nuove funzionalità avanzate ad uso delle community, come esecuzione di file audio e video. Completamente basata sulle 8 Record Management Store. Il sistema di j2me per la memorizzazione dei dati su dispositivi mobili. 100 pre-esistenti API di Java Micro Edition, il framework JAVAFX consentirebbe maggiore rapidità di sviluppo e maggiori contenuti. Attualmente il progetto Geco Client è installabile anche su dispositivi PDA. Purtroppo, non essendo stati implementati i metodi del touchscreen, è possibile scorrere la mappa in maniera limitata al classico joystick presente sui dispositivi. Sarebbe quindi interessante realizzare una interfaccia per PDA per migliorarne l’usabilità. La struttura stessa del PDA consentirebbe anche un’ evoluzione dei marker: il Touch Pen9 (o stilo) consente infatti un rapido ed immediato accesso all’interfaccia grafica e, inoltre, l’uso della stilo faciliterebbe la possibilità di selezionare aree di interesse (tramite dragging) e garantirebbe una migliore interazione. 9 La penna classica con cui sono dotati i dispositivi a touchscreen 101 APPENDICE A L’applicazione è stata testata su diverse tipologie di cellulari, ed in particolare test esaustivi sono stati fatti per: • smartphone nokia E65 • palmare nokia 6630 • smartphone HTC P3300 con le seguenti antenne gps: • Antenna GPS Bluetooth blumax Sirf Star 3 • Antenna GPS Blutooth RoyalTek RBT 2010 Sirf Star 3 Caratteristiche tecniche: Nokia E65: Caratteristiche Reti Dimensione display [pixel] Colore del display Funzione palmare Connessioni internet Connessioni pc Browser web Altre informazioni Sistema operativo Memoria Memoria ram disponibile [mb] Dual mode umts/gsm (900/1800/1900) 352 x 416 16 milioni di colori tft Si Gprs,edge Wifi,bluetooth,infrarossi,cavo usb Wap Symbian 9.1 - serie 60 3rd edition 70 102 Nokia 6630: Caratteristiche Dual mode umts/gsm (900/1800/1900) Dimensione display [pixel] 176 x 208 Colore del display 65000 colori tft Funzione palmare Si Connessioni internet Gprs,edge Connessioni pc bluetooth,cavo usb Browser web Wap Altre informazioni Symbian 8.0 - serie Sistema operativo 60 3rd edition Memoria Memoria ram disponibile [mb] 10 Reti HTC P3300: Caratteristiche Reti Dimensione display [pixel] Colore del display Funzione palmare Connessioni internet Connessioni pc Browser web Altre informazioni Sistema operativo Memoria Memoria rom Dual mode gsm (900/1800/1900) 2.8” matrice attiva TFT 65000 colori tft Si Gprs, Edge WI-FI, bluetooth,cavo usb Wap Windows Mobile 5.0 128 103 disponibile [mb] Memoria ram disponibile [mb] 64 Antenna GPS Bluetooth blumax Sirf Star 3: *Chipset Sirf Star III *Frequenza: L1, 1.575,42 Mhz * Canali: 20 * DGPS: SBAS (WAAS, EGNOS) * Posizione: 10m 90% * Velocita: 0.1 metri/secondo, senza SA' * Tempo: 1 microsecondo sincronizzato al riferimento GPS * Riacquisizione: 0.1 sec * Cold Start : 42 sec * Warm Start: 35 sec * Hot Start : 1 sec * Altitudine: <18,000 metri; Velocita': <515 metri/sec; * Collegamento Bluetooth (classe 2) SPP - Serial Port Profile * Protocollo:NMEA GGA, GLL, GSA, GSV; RMC, VTG, 57600 bps * Autonomia: 17 ore di funzionamento continuo Antenna GPS Blutooth RoyalTek RBT 2010 Sirf Star 3: * Chipset Sirf Star III * Frequenza: L1, 1.575,42 Mhz * Canali: 20 * DGPS: SBAS (WAAS, EGNOS) * Sensibilita': -159dBm * Posizione: 10m 90% * Velocita: 0.1 metri/secondo, senza SA' * Tempo: 1 microsecondo sincronizzato al riferimento GPS * Riacquisizione: 0.1 sec * Cold Start : 42 sec 104 * Warm Start: 35 sec * Hot Start : 1 sec * Altitudine: <18,000 metri; Velocita': <515 metri/sec; * Protocollo:NMEA GGA, GLL, GSA, GSV; RMC, VTG, 57600 bps * Autonomia: 17 ore di funzionamento continuo * Dimensioni 70 x 41 x 30 mm; Peso: 85gr Guida all’istallazione e configurazione del sistema: Requisiti software CLDC/MIDP 1.1/2.0 o superiore. Requisiti hardware • Il dispositivo mobile deve avere capacità di calcolo sufficiente (smartphone o palmare). • Il dispositivo deve essere dotato di antenna GPS esterna o interna (per navigazione con sistema di coordinate LAT/LON). Passi da compiere per l’installazione: 1. scaricare la midlet da sito (es. www.u-s.it). 2. eseguire il deploy della midlet sul dispositivo mobile 3. lanciare la midlet. Modi per effettuare il deploy della midlet: 1. via cavo usb con nokia tool (solo per dispositivi nokia) 2. via OTA (Over The Air) con bluetooth 105 WEBGRAFIA (i link di seguito riportati sono stati visitati nel periodo che va da ottobre 2007 a febbraio 2008) [1] http://j2memap.8motions.com/ [2] http://www.easywms.com/easywms/?q=en/suas-mapserver-mobile- client-ii [3] http://developers.sun.com/mobility/midp/articles/bluetooth2/ [4] https://meapplicationdevelopers.dev.java.net/ [5] http://www.substanceofcode.com/software/mobile-trail-explorer/ [6] http://www.metah.ch/blog/?p=178 [7] http://rilievo.poliba.it/fotosat/convegno2003.html [8] http://en.wikipedia.org/wiki/Geocoding [9] http://it.wikipedia.org/wiki/Wikipedia:Bar/Google_Maps [10] http://www.secondarydata.com/software/mrslgeo.asp [11] http://www.slideshare.net/mra1124/geo-mapping/ [12] ] http://forums.java.net/jive/forum.jspa?forumID=111 [13] http://j2me.javastaff.com/ 106 [14] http://www.cs.sjsu.edu/faculty/pearce/j2me/J2ME%20Programming.htm [15]http://www.massimocarli.it/site/index.php?option=com_content&task =category§ionid=5&id=35&Itemid=32 [16] http://www.jcp.org/en/jsr/tech?listBy=1&listByType=platform [17] http://mobile.html.it/guide/leggi/124/guida-j2me/ [18] http://today.java.net/pub/a/today/2004/10/08/J2ME-2.html [19] http://www.mokabyte.it/2002/07/j2me-6.htm [20] http://www.java2s.com/Code/Java/J2ME/HttpConnection.htm [21]http://www2.mokabyte.it/cms/article.run?articleId=Y72-YYX-A2UODE_7f000001_30480431_a21c5804 [22] http://www.giuseppesicari.it/articoli/java-2-micro-edition/location- api/ [23] http://www.javaportal.it/rw/24746/editorial.html [24] http://www.ddj.com/mobile/184406388 [25] http://today.java.net/pub/a/today/2004/04/01/gis.html [26]http://www.mobileutopia.com/Code/0emq1a0y6_Info+on+the+JSR+179+-+Location+API 107 [27]http://www.forum.nokia.com/info/sw.nokia.com/id/175bf8e6-a1f54d3d-a5916fc936506a6b/MIDP_Location_API_Developers_Guide_v2_0_en.pdf.html [28] http://www2.mokabyte.it/cms/article.run?articleId=Y72-YYX-A2UODE_7f000001_30480431_a21c5804 [29] http://mapki.com/wiki/Satellite_Tile_Layout [30] http://blog.grimpoteuthis.org/2005/02/mapping-google.html [31] http://it.wikipedia.org/wiki/Keyhole_Markup_Language [32]http://www.java2s.com/Code/Java/J2ME/UseGETorPOSTtocommuni catewith aJavaservlet.htm [33] http://www.developer.com/java/j2me/article.php/10934_1561591_4 [34] http://www.ros-softair.net/Uso_GPS.html [35] http://www.microjava.com/articles/techtalk/midp2_games [36] http://www.wmlscript.it/j2me_pro/locationapi.php [37] http://www.mgmaps.com/cache/MapTileCacher.perl [38] http://www.cse.buffalo.edu/~ajay/googlemaps.html [39] http://mapki.com/wiki/Lat/Lon_To_Tile [40]http://maps.google.com/mapdata?latitude_e6=40803210&longitude_e6 =14197070&zm=340000&w=800&h=600&cc=us&min_priority=2 108 [41]http://dunck.us/collab/Simple_20Analysis_20of_20Google_20Map_20a nd_20Satellite_20Tiles [42] http://googlemapsapi.blogspot.com/2006/08/draggable-markers- and.html [43] http://mapki.com/index.php?title=Icon_Image_Sets [44] http://mapki.com/index.php?title=Lat/Lon_To_Tile [45] http://snippets.dzone.com/posts/show/531 [46] http://mapki.com/wiki/Automatic_Tile_Cutter [47] http://mapki.com/wiki/Tile_utility_code_in_Java [48]http://code.djangoproject.com/browser/django/branches/gis/django/co ntrib/gis/maps/google/zoom.py [49]http://it.wikipedia.org/wiki/Wikipedia:Mappa_dei_wikipediani [50] http://www.nabble.com/Re:-Logaritmo-em-JavaME-p13355848.html [51] http://home.rochester.rr.com/ohommes/MathFP/index.html [52] http://www.faunalia.it/pdf/Mondogis_2005_49.pdf [53] http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_tu t01 109 [54] http://www.bostongis.com/postgis_quickguide.bqg?outputformat=PDF 110 BIBLIOGRAFIA Giuseppe Balzano (2007/2008) GECO MOBILE:un’infrastruttura java di utenti di una mobile community, Salerno, Università degli Studi. H. Bergsten (2004) Java Server Pages 2nd Editino, O'Reilly. Giovanni Biallo (2005) Introduzione ai Sistemi Informativi Geografici, I quaderni di MondoGis. Martin C. Brown (2006) Hacking Google Maps and Google Earth, Wiley Publishing. D. Crane, E. Pascarello (2006) Ajax in Action, Manning. Bruce Eckel (2006) Thinking in Java 3rd Edition. Schuyler Erle, Rich Gibson (2006) Google Maps Hacks, O'Reilly. B. Hopkins, R. Antony (2003) Bluetooth for Java, Apress. B. Momjian (2001) PostgreSQL Introduction and Concept, Addison Wesley. John W. Muchow (2002) J2ME: guida pratica alla programmazione dei dispositivi wireless, Mc Graw Hill. Stefano Sanna (2007) Java Micro Edition: sviluppare applicazioni networkoriented per telefoni cellulari e PDA, HOEPLI. 111