Progettazione e Realizzazione di una Library per Agenti Context-Aware

Dimensione: px
Iniziare la visualizzazioe della pagina:

Download "Progettazione e Realizzazione di una Library per Agenti Context-Aware"

Transcript

1 UNIVERSITÀ DEGLI STUDI DI PARMA Dipartimento di Matematica e Informatica Corso di Laurea in Informatica Progettazione e Realizzazione di una Library per Agenti Context-Aware Design and Implementation of a Library for Context-Aware Agents Relatore: Chiar.mo Prof. Federico Bergenti Candidato: Serri Cristiano Anno Accademico 2012/2013

2 Ai miei genitori ai miei zii e ai miei colleghi di studio che mi hanno sostenuto e supportato in questi anni

3 Indice 1 Introduzione 1 2 Introduzione a Jade Creazione di Piattaforme e Container Creazione di Agenti e Agenti Speciali Inizializzazione degli Agenti Gestione Eccezioni e Terminazione Agente I Behaviour Scambio di Messaggi tra gli Agenti Creare una Ontology e i suoi Componenti Programmazione su Android Ambiente di Sviluppo: ADT Creare ed Eseguire un Android Project Importare Progetti e Librerie Activity e Intent Manifest della Applicazione Costanti di Stringa usate dalla Applicazione Descrizione del Menu di una Activity Descrizione della Videata di una Activity La Library Dave Le Informazioni Geografiche La Posizione: EarthPoint Aggiungiamo la Direzione: EarthVector Il Punto di Vista: EarthPartialCircle Classe Helper per Jade Gli Agenti di Dave DaveClientAgent FixedAgent RandomAgent AndroidRealAgent DaveServerAgent

4 INDICE iii 4.4 UpdatePlanner NeverUpdatePlanner Riduzione del Carico Computazionale LevelAccessRule AccessRules QualityOfService NoService Esempio di Creazione e Configurazione Client Struttura Dati del Server ClientMatrix ClientRow OtherClient Levels Following Visualizzazione Agenti sulle GoogleMaps DaveReceiver IntentFilter Azioni compiute Esempio Applicazione Dave Le Fasi del gioco Fase di Posizionamento dei Tesori Fase di Ricerca dei Tesori Fine del Gioco Gli Agenti di DaveTreasureHunt TreasureAgent ExplorerAgent PirateAgent GameStorage ExplorerMatrix ExplorerRecord Screenshot del Gioco Conclusioni 64 Bibliografia 66

5 Capitolo 1 Introduzione Dave (Discover Agents Viewed on Earth) è una libreria scritta in Java che permette ai dispositivi Android che la utilizzano di acquisire la propria posizione geografica (tramite WiFi o GPS) e la direzione in cui sono rivolti (tramite Giroscopio), elaborare tali informazioni (per vedere se ci sono stati cambiamenti significativi) e trasmetterle. Le informazioni geografiche dei vari dispositivi vengono ricevute, memorizzate e rese disponibili da un processo Server che risiede su un pc il cui indirizzo ip è raggiungibile dai vari dispositivi Client. Queste operazioni consentono ad ogni dispositivo Android di individuare (e visualizzare opportunamente su una mappa con cui l utente del dispositivo può interagire) quali altri dispositivi si trovano nel suo punto di vista. Dave è stata sviluppata utilizzando le funzionalità e i concetti della libreria Jade, sviluppata da Telecom Italia. Jade (Java Agent DEvelopment framework) è un framework che permette di costruire applicazioni Java basate sul concetto di Agente. Gli Agenti si distringuono dai normali oggetti Java (che possiedono solo attributi e metodi) perchè possiedono dei comportamenti (Behaviour) che vengono eseguiti e prendono decisioni in modo autonomo, eseguiti in modo concorrente da uno Scheduler (di tipo Round Robin senza prelazione) interno all Agente stesso. Gli Agenti che fanno parte di una stessa Piattaforma possono comunicare tramite scambio di messaggi. Questa comunicazione è asincrona poichè i messaggi inviati vengono depositati nelle mailbox dei destinatari, ciascuno dei quali deciderà in modo autonomo se e quando leggerli. Utilizzando Jade in particolare si semplificano le comunicazioni via rete nelle applicazioni multi-utente. In Dave, sia i vari Client (Android) sia il Server (PC) sono implementati come Agenti. Inoltre ci sono alcuni Agenti Client che possono essere creati su PC. Questi Agenti non potranno ovviamente rilevare la propria posizione e direzione, la quale potrà essere definita all inizio e rimanere costante (op-

6 2 pure cambiare in modo rotatorio o random). La prima fase del mio lavoro di Tesi consiste nello studio e nell utilizzo della libreria Jade e nell allestimento dell Ambiente di Sviluppo per Android, comprendendo la struttura dei progetti e i principi alla base della programmazione su tale piattaforma. Le nozioni che ho appreso durante questa fase sono trattate (con un approccio di tipo operativo) rispettivamente nei capitoli 2 e 3. La seconda fase consiste nello sviluppo e nel test della libreria Dave (capitolo 4), e di un gioco (DaveTreasureHunt, una caccia al tesoro) che si appoggi su tale libreria (capitolo 5).

7 Capitolo 2 Introduzione a Jade Questo capitolo ha lo scopo di illustrare il funzionamento e i concetti base della libreria Jade (Java Agent DEvelopment framework), evidenziando principalmente le sue parti che sono state utili alla costruzione della libreria Dave. La guida completa, e il download della versione aggiornata della libreria (comprensiva anche di esempi), è possibile scaricarla dal sito ufficiale di Jade, ovvero jade.tilab.com. Come anticipato nell introduzione, Jade consente di creare applicazioni basate sul concetto di Agente. Verrà descritto come allestire il luogo (la Piattaforma e i vari Container) dove creare gli Agenti, e per ciascuno di questi come definire i vari comportamenti autonomi e come interagire con gli altri Agenti. Nel corso della trattazione di questa sezione riguardante Jade, verrà utilizzato il classico esempio nel quale gli Agenti sono venditori e compratori di Libri (BookTrading): Ciascun venditore inizia avendo in suo possesso un certo insieme di libri, ciascuno dei quali ha un nome e un prezzo. I venditori vengono contattati dai compratori per sapere se posseggono un determinato libro, i venditori rispondono in modo opportuno, comunicando il prezzo in caso affermativo. Inoltre i venditori vengono contattati dai compratori anche in caso di acquisto, dove forniscono il libro al compratore rimuovendolo dai libri posseduti. I compratori hanno lo scopo di acquistare un singolo libro, al prezzo minore tra quelli di tutti i venditori che posseggono il libro richiesto, poi terminano. Durante il lavoro di tesi, per integrare lo studio delle funzionalità di Jade con una prova pratica, è stato esteso l esempio base, ovvero quello presente nella directory examples/booktrading (scaricando il pacchetto completo di Jade). Le principali modifiche consistono:

8 2.1 Creazione di Piattaforme e Container 4 Nell utilizzo di un automa a stati finiti (FSMBehaviour) come Behaviour principale del compratore. Nell aggiunta di una Ontology specifica per i Libri, in modo tale che lo scambio di messaggi non sia più string-based ma costituito da Concetti e Predicati ad hoc. Usufruendo dell interfaccia grafica per creare e rimuovere compratori o venditori in momenti arbitrari, dello standard output per capire che cosa sta facendo ciascun Agente e come avviene la loro comunicazione, e degli strumenti messi a disposizione da Jade stesso, quali l Rma e lo Sniffer, questo esempio BookTrading può essere utilizzato come ottimo strumento di studio per i programmatori che si avvicinano a Jade. 2.1 Creazione di Piattaforme e Container Quando avviamo Jade (tramite la procedura descritta in seguito) dobbiamo decidere se creare una nuova Piattaforma con un Container Principale (Main) oppure se connetterci ad una Piattaforma già esistente tramite un Container Periferico. I Container sono il luogo dove gli agenti di Jade sono in esecuzione. Solo gli Agenti che vivono nella stessa Piattaforma (all interno dello stesso container o di container differenti) possono interagire (ovvero comunicare tramite scambi di messaggi). Di seguito vengono descritte le principali caratteristiche delle due tipologie di Container: Il Main Container deve esistere ed essere unico in ciascuna Piattaforma di Jade. La creazione di un Main Container coincide con la creazione di una Piattaforma. Tale operazione di creazione è possibile effettuarla solo da PC, e non da dispositivo Android. Non ci sono limiti al numero di Container Periferici che una Piattaforma può avere. Quando si crea un Container Periferico bisogna indicare una Piattaforma già esistente (nella quale in particolare si trova già il Main Contaiber) alla quale tale Container si registrerà. I Container Periferici possono essere creati indifferentemente da Android o da PC. Per poter creare una nuova Piattaforma è necessario che non ci sia alcun servizio attivo sulla porta 1099 (è quella che di default Jade usa, se non specificato diversamente). La porta 1099 può essere occupata ad esempio da vecchie istanze di Jade non terminate correttamente. L eccezione che tipicamente viene lanciata quando la porta è già in uso è: jade.core.imtpexception: No ICP active at jade.imtp.leap.leapimtpmanager.initialize(leapimtpmanager.java:138) at jade.core.agentcontainerimpl.init(agentcontainerimpl.java:319) at jade.core.agentcontainerimpl.joinplatform(agentcontainerimpl.java:489) at jade.core.runtime.createmaincontainer(runtime.java:166)

9 2.1 Creazione di Piattaforme e Container 5 Inoltre, per consentire ai Container Periferici di connettersi al Main Container su questa Piattaforma bisogna controllare che la porta non sia bloccata dal Firewall del sistema operativo. Per sbloccarla occorre aggiungere nel Firewall una nuova regola che consenta le connessioni in ingresso su tale porta da parte di qualsiasi applicazione (in Windows è possibile farlo nelle Impostazioni Avanzate del Windows Firewall, accessibile dal Pannello di Controllo nella scheda Sistema e Sicurezza). Queste istruzioni consentono di creare un Main Container su PC: import jade.core.profile; import jade.core.profileimpl; import jade.core.runtime;... Profile profile = new ProfileImpl(); AgentContainer container = Runtime.instance().createMainContainer(profile); Supponiamo di avere creato una Piattaforma su un pc con indirizzo Ip nella porta di default (1099), ovvero di avere eseguito su tale pc un programma che contenga le istruzioni soprastanti (il costruttore di default di ProfileImpl imposta come indirizzo ip localhost e come porta la 1099). Se questo punto vogliamo creare da un altro PC un Container Periferico facente parte della stessa piattaforma, utilizziamo il codice seguente: import jade.core.profile; import jade.core.profileimpl; import jade.core.runtime;... Profile profile = new ProfileImpl(" ", 1099, null, false); AgentContainer container = Runtime.instance().createAgentContainer(profile); Abbiamo usato il costruttore più generico di ProfileImpl. Il terzo parametro è l etichetta da applicare al container (null significa di usare quella di default), e il quarto parametro impostato a false significa che il container che vogliamo creare non è Main. Creare un Container Periferico da Android è più complesso, poichè bisogna connettere (bindservice) il servizio di Jade per Android (MicroRuntimeService) all Activity (il concetto di Activity, così come quello di Intent, verranno trattati nel capitolo riguardante Android). La ServiceConnection e la CallBack contengono codice che viene eseguito rispettivamente al completamento dell operazione di bind e di creazione del Container Periferico (tali operazioni non vengono fatte istantaneamente, quindi questo procedimento è necessario).

10 2.2 Creazione di Agenti e Agenti Speciali 6 Properties properties = new Properties(); properties.setproperty(profile.main_host, " "); properties.setproperty(profile.main_port, "1099")); properties.setproperty(profile.main, "false"); properties.setproperty(profile.jvm, Profile.ANDROID); properties.setproperty(profile.local_host, AndroidHelper.getLocalIPAddress()); properties.setproperty(profile.local_port, "1099"); ContainerStartupCallback contcallback = new RuntimeCallback<Void>() public void onsuccess(void thisisnull) { // Container Creato public void onfailure(throwable throwable) { // Fallimento nella creazione del Container ServiceConnection ServiceConnection = new ServiceConnection() public void onserviceconnected(componentname name, IBinder service) { microruntimeservicebinder = (MicroRuntimeServiceBinder) service; if (!MicroRuntime.isRunning()) { microruntimeservicebinder.startagentcontainer( properties, contcallback ); public void onservicedisconnected(componentname name) { microruntimeservicebinder = null; //Suppongo che activity sia il puntatore all Activity che invoca questo codice activity.bindservice( new Intent(activity, MicroRuntimeService.class), this.serviceconnection, Context.BIND_AUTO_CREATE ); 2.2 Creazione di Agenti e Agenti Speciali Quando il Container (Main o Periferico) è pronto, possiamo creare gli agenti e collocarli in tale Container. L istruzione seguente consente (in modo compatto) di creare ed eseguire 1 Agente da PC: container.createnewagent(nome, classe, args).start();

11 2.2 Creazione di Agenti e Agenti Speciali 7 Di seguito descrivo lo scopo di ciascuno dei parametri: Il nome verrà usato come nome locale del nuovo Agente deve essere univoco all interno della Piattaforma (quindi non si può scegliere come nome quello di un altro Agente presente nello stesso Container o in un altro) La classe (comprensiva di package) è una qualsiasi classe che estende jade.core.agent, usata per creare e personalizzare il nuovo Agente. Il terzo parametro, args è un array di Object che verrà passato al nuovo Agente una volta creato, che può essere usato per personalizzarlo. Se all Agente non servono argomenti, è possibile usare null. Prima di vedere come eseguire la stessa operazione su Android, presentiamo un Agente molto comodo, contenuto nella classe jade.tools.rma.rma. Possiamo crearlo con il codice sopradescritto, ovvero: container.createnewagent("rma","jade.tools.rma.rma", null).start(); L rma è provvisto di una interfaccia grafica, che offre molte comodità e funzionalità, tra cui: Possiamo vedere i vari Container presenti nella Piattaforma e per ciascuno di essi gli Agenti contenuti. E possibile effettuare le operazioni di creazione o distruzione di utenti e containers. Nella barra del titolo è presente l indirizzo Ip e la porta della Piattaforma in uso Possiamo avviare gli altri Tools di Jade, ad esempio l utile Sniffer, che consente di catturare e leggere tutti i messaggi inviati tra gli Agenti.

12 2.3 Inizializzazione degli Agenti 8 Notiamo subito che oltre all Agente che abbiamo appena creato (l rma), nel Main Container erano già presenti due Agenti (creati insieme alla Piattaforma stessa): L ams registra i nomi di tutti gli Agenti che vengono creati, e assicura che ciascuno abbia un nome univoco. Inoltre rappresenta l autorità all interno della piattaforma, ovvero è l Agente al quale gli altri Agenti devono rivolgersi per compiere determinate operazioni. E in grado di fornire l elenco dei nomi degli Agenti a coloro che lo richiedono, ovvero offre un servizio di Pagine Bianche. Il df fornisce invece un servizio di Pagine Gialle, ovvero è in grado di fornire su richiesta la lista degli Agenti che rispecchiano determinate caratteristiche (che offrono determinati servizi). Una differenza importante rispetto all ams è che gli Agenti presenti nella Piattaforma non sono automaticamente riconosciuti dal df, ma devono registrarsi per poter essere trovati con le ricerche fatte dagli altri Agenti. Per concludere la sezione, il codice seguente consente di fare l operazione di creazione di un Agente da Android. Anche qui dobbiamo ricorrere ad una Callback: agentstartupcallback = new RuntimeCallback<Void>() public void onsuccess(void thisisnull) { // Agente creato correttamente public void onfailure(throwable throwable) { // Creazione fallita microruntimeservicebinder.startagent(nome, classe, args, agentstartupcallback); 2.3 Inizializzazione degli Agenti Una volta che un Agente è stato creato, ha assunto un regolare nome univoco e un indirizzo, e l ams è venuto a conoscenza della sua presenza, allora il corrispondente Thread può cominciare la sua esecuzione. Il primo metodo dell Agente che viene invocato è il setup(), nel quale solitamente si effettuano le seguenti operazioni: si recuperano i parametri passati all Agente al momento della sua creazione, che serviranno per personalizzarlo. ci si registra con il DF (fornendo l elenco dei Servizi offerti) se si desidera essere trovati tramite il servizio di Pagine Gialle

13 2.3 Inizializzazione degli Agenti 9 si aggiungono tutte le Ontology che l Agente deve conoscere e gestire (il concetto di Ontology sarà trattato in seguito) si aggiungono i codec che verranno utilizzati per codificare e decodificare il contenuto degli ACLMessage nella forma appropriata (tra cui Stringhe o sequenze di byte). si definiscono e si aggiungono all Agente i suoi comportamenti autonomi (Behaviour) si creano e inizializzano le strutture dati che servono all Agente per memorizzare informazioni e prendere così le proprie decisioni. public class BookSellerAgent extends Agent{ // Place where the Books owned by this Seller Agent are stored private Books library; // Codec for the SL Language (ACLMessages) private SLCodec protected void setup(){ codec = new SLCodec(); super.getcontentmanager().registerlanguage(codec); super.getcontentmanager().registerontology(bookontology.getinstance()); this.library = new Books(); for (Object o: super.getarguments()) if (o instanceof Book){ this.library.add((book) o); DFAgentDescription agentdescription = new DFAgentDescription(); agentdescription.setname(super.getaid()); ServiceDescription servicedescription = new ServiceDescription(); servicedescription.setname("book Selling"); servicedescription.settype("book Selling"); agentdescription.addservices(servicedescription); try { DFService.register(this, agentdescription); catch (FIPAException e) { e.printstacktrace(); super.dodelete();... // Creation and addition of Behaviours to the scheduler super.addbehaviour(new ReceiveQueriesBehaviour()); super.addbehaviour(new SellBookBehaviour());

14 2.4 Gestione Eccezioni e Terminazione Agente Gestione Eccezioni e Terminazione Agente Nel metodo setup() del venditore di libri illustrato nella sezione precedente notiamo che se la registrazione con il DF fallisce viene lanciata una Eccezione (di classe FIPAException). Il comportamento che dobbiamo adottare nella gestione delle Eccezioni all interno di un Agente varia a seconda della categoria: Per quanto riguarda le Eccezioni che estendono RuntimeException, il linguaggio Java stesso ci permette di non gestirle (ovvero il compilatore non segnala errori se non dichiariamo l eccezione dell intestazione del metodo o non allestiamo un blocco try-catch). Esempi di queste Eccezioni sono IllegalArgumentException, NullPointerException, StringIndexOutOfBoundsException... Le eccezioni non catturate in Jade vengono stampate nella console (con printstacktrace) e innescano la terminazione dell agente, tramite la chiamata al metodo dodelete() dell Agente, che inizia la transizione verso lo stato Dead. Le Eccezioni che non estendono RuntimeException (ad esempio FI- PAException) devono essere gestite dal programmatore. In particolare dovremo (se non lo facciamo il compilatore segnerà errore) catturarle tramite try-catch, poichè i metodi della classe Agent che abbiamo sovrascritto (tra cui setup) non ci permettono di dichiarare eccezioni tramite la clausola throws. Nel mio caso ho gestito la FIPAException con la stessa strategia di Jade, ovvero stampare l eccezione e far terminare l Agente. Durante la transizione di stato verso Dead (ovvero poco prima di terminare) viene invocato il metodo speculare di setup(), ovvero takedown(), che possiamo sovrascrivere allo scopo di effettuare tutte le operazioni di cleanup necessarie, tra cui solitamente è presente la deregistrazione al DF se nel setup è stata fatta la registrazione. Ha lo stesso compito del distruttore delle classi del C++. Mentre l Agente esegue il metodo takedown è ancora in grado di inviare messaggi agli altri public void takedown(){ // When this Agent terminates, he has to remove himself from the Yellow Page Service (DF) // Otherwise he will still considered a valid result even dead try { DFService.deregister(this); System.out.println(getLocalName()+": Taking down..."); catch (FIPAException e) { e.printstacktrace();

15 2.5 I Behaviour I Behaviour Le operazioni che l Agente compie durante la sua vita e le decisioni che vengono compiute in autonomia dall Agente in risposta a determinati eventi sono contenute all interno di uno o più Behaviour. Ciascun Agente può avere un numero arbitrario di Behaviour, che può anche cambiare durante l esecuzione, tramite addbehaviour(behaviour) e removebehaviour(behaviour) dell Agente. Tuttavia solo un Behaviour per volta è in esecuzione, infatti la classe Agent implementa (in modo automatico e invisibile all esterno) un meccanismo di Scheduling Round Robin senza Prelazione. Ciò significa che se uno dei Behaviour entra in un ciclo infinito (o svolge operazioni molto pesanti), gli altri non avranno possibilità di essere eseguiti, poichè l intero Thread dedicato all Agente in questione sarà bloccato. E quindi una buona norma costruire i Behaviour in modo tale da compiere operazioni leggere e brevi, o comunque interrompibili in uno o più punti (e essere in grado di riprendere da dove ci si era interrotti) per lasciare spazio anche agli altri. I metodi che possiamo (o dobbiamo, a seconda dei casi) sovrascrivere quando definiamo un nostro Behaviour sono: action(), nel quale definiamo le azioni che vengono compiute quando lo Scheduler manda in esecuzione questo Behaviour. Se abbiamo progettato il Behaviour come interrompibile, dobbiamo gestire in modo adeguato i casi in cui il Behaviour ha iniziato il suo lavoro o lo ha ripreso dal punto in cui si era interrotto. Quando il metodo action() termina viene invocato il metodo done(). done(), nel possiamo distinguere i casi di terminazione di action(). Se action() è terminato perchè il Behaviour ha concluso il suo lavoro allora restituiamo true (in questo caso il Behaviour verrà rimosso dalla coda dello Scheduler). Se invece action() è terminato per interrompersi e riprendere in seguito, allora restituiamo false. Ciò che succede in quest ultimo caso dipende dal fatto che il programmatore abbia invocato o meno il metodo block() del behaviour. Normalmente (ovvero se block non è stato invocato), il Behaviour torna in fondo alla coda dello Scheduler. onend(), il quale viene invocato quando done() restituisce true, possiamo usarlo per definire un valore di ritorno (intero) per il Behaviour, oltre ad eventuali operazioni di cleanup. onbegin(), che è speculare rispetto a onend(), viene invocato solo una volta, prima di eseguire per la prima volta il metodo action(). I Behaviour possono decidere di portarsi in stato di sleep, qualora stiano aspettando il verificarsi di un determinato evento per proseguire con il loro

16 2.5 I Behaviour 12 lavoro (ad esempio lo scadere di un certo timeout o la ricezione di un messaggio con determinate caratteristiche). Per spostarsi nello stato di sleep, i Behaviour (dentro il metodo action) devono invocare il metodo block() oppure block(timeout) e fare in modo che done() restituisca false (in caso contrario il Behaviour verrebbe eliminato). I Behaviour che si trovano nello stato di sleep non vengono più considerati dallo Scheduler, il quale farà proseguire altri Behaviour. Un Behaviour esce dallo stato di sleep (e torna quindi nella coda dello Scheduler) quando: Il timeout associato alla chiamata di sleep è scaduto (ovviamente se si è utilizzato il metodo block con 1 parametro). Un altro Behaviour (che non si trova a sua volta nello stato di sleep) decide esplicitamente di risvegliarlo con il metodo restart(). L Agente ha ricevuto un nuovo messaggio. In questo caso tutti i Behaviour vengono risvegliati. Ciascuno di questi, quando verrà rimandato in esecuzione dallo Scheduler, dovrà verificare che il nuovo messaggio non sia già stato letto da un Behaviour mandato in esecuzione prima di lui, e di essere interessato a quel tipo di messaggio. Nel caso che queste condizioni non siano verificate il Behaviour potrà decidere di tornare nello stato di sleep. Quando definiamo i nostri Behaviour, oltre a poter estendere la classe base Behaviour (in questo modo dobbiamo definire action e done), possiamo anche adottare alcune scorciatoie andando ad estendere alcune sottoclassi (intese nella gerarchia) di Behaviour: OneShotBehaviour modella un Behaviour che non ha bisogno di tornare nella coda dello Scheduler poichè gli basta una sola esecuzione per compiere il leggero carico di lavoro ad esso assegnato. In particolare il metodo done() restituisce sempre true, quindi non è necessario farne l override. CyclicBehaviour modella un Behaviour che deve essere sempre presente durante la vita dell Agente (in esecuzione, nella coda o in stato di sleep), vengono utilizzati solitamente per gestire i vari tipi di messaggi che l Agente può ricevere, o per fornire i servizi che ha specificato quando si è registrato al DF. Il metodo done() restituisce sempre false. TickerBehaviour è un particolare Behaviour che non segue il normale funzionamento della coda. Infatti viene selezionato dello Scheduler e portato in esecuzione solo ed esclusivamente ogni X millisecondi (dove X è stato specificato dal Behaviour stesso), molto utile per effettuare operazioni periodiche (ad esempio la ricerca sul DF di un determinato Agente, effettuata ogni 10 secondi fino a che non viene trovato). Il

17 2.5 I Behaviour 13 metodo done() restituisce sempre false come per le CyclicBehaviour, quindi per terminare l esecuzione si deve esplicitamente invocare il metodo removebehaviour() dell Agente. WakerBehaviour è un Behaviour temporizzato come TickerBehaviour. E possibile specificare una data superata la quale (o un timeout preciso trascorso il quale) il Behaviour si sveglia e esegue (in una unica soluzione) le istruzioni nel suo metodo onwake(). FsmBehaviour modella un Behaviour interrompibile che può trovarsi in uno stato (che definisce le azioni da compiere quando lo Scheduler lo rimette in esecuzione) appartenente ad un certo insieme. Ogni volta che il metodo action() termina lo stato del Behaviour può cambiare (o rimanere lo stesso), a seconda delle transizioni che vengono definite. In altre parole il Behaviour è un Automa a Stati Finiti Deterministico (DFA). Il metodo done() restituisce true solo quando il Behaviour è giunto in uno stato finale. SequentialBehaviour è un DFA semplificato che non necessita di definire le transizioni, perchè per ogni stato è presente solo una transizione, che è verso il successivo, mentre l ultimo è lo stato finale (quindi conta solo l ordine nel quale gli stati vengono aggiunti). A titolo di esempio, la seguente immagine rappresenta il Behaviour principale degli Agenti Buyer, si tratta di un Behaviour complesso implementato con un Automa a Stati Finiti Deterministico (ovvero FSMBehaviour).

18 2.6 Scambio di Messaggi tra gli Agenti Scambio di Messaggi tra gli Agenti Per identificare univocamente un Agente all interno della Piattaforma (e quindi poter interagire con esso) si utilizza il suo nome completo (AID - Agent IDentifier), che unisce il nome locale dell agente (univoco, come anticipato nella sezione dedicata alla creazione degli Agenti), la piattaforma di appartenenza e in container in cui trovarlo. Ciascun Agente ottiene il proprio AID appena dopo la sua creazione, che può essere recuperato con il metodo getaid() dell Agente. Gli Agenti che vivono nella stessa Piattaforma possono comunicare scambiandosi messaggi modellati dalla classe ACLMessage (dove ACL sta per Agent Communication Language). Il messaggio consta di vari campi, accessibili con i metodi getter e setter: Sender è l AID dell Agente che ha creato e che spedirà il messaggio (viene impostato in automatico con il costruttore di ACLMessage). Receivers è una lista di AID ai quali il messaggio verrà recapitato. Inizialmente la lista di destinatari è vuota, è necessario aggiungerne almeno uno (con il metodo addreceiver) per poter inviare il messaggio. Performative è l intento con il quale il messaggio viene inviato, è possibile anche definirlo nel costruttore. La classe ACLMessage prevede alcune costanti che possono essere usate in questo ambito, quali Propose, Refuse, Inform, QueryIf... ConversationID (facoltativo) può essere utile per raggruppare logicamente messaggi e risposte facenti parte di una stessa conversazione. Language indica la codifica del contenuto del messaggio (il mittente e i destinatari devono essere in grado di codificare e decodificare il linguaggio scelto), quello di default è SLCodec (che trasferisce stringhe leggibili dall essere umano), possibili alternative prevedono il trasferimento di sequenze di bytes. Ontology è un insieme di simboli, concetti, predicati e azioni che hanno senso per il mittente e i destinatari. Di default nessuna Ontology è usata, quindi il contenuto dovrà essere interpretato dai destinatari. Content è il contenuto del messaggio, ovvero ciò che si vuole comunicare ai destinatari. Deve rispettare il Linguaggio e la Ontology scelte. In particolare per conversazioni poco articolate e monotematiche si può pensare di non utilizzare nessuna Ontology e di lasciare il Language di default, ovvero la conversazione è basata su scambi di Stringhe, in questo caso è possibile specificare il contenuto normalmente con setcontent(string). Se invece si utilizzano Language e

19 2.6 Scambio di Messaggi tra gli Agenti 15 Ontology, quindi la conversazione è più articolata e strutturata, bisogna usare il metodo getcontentmanager.fillcontent(aclmessage, ContentElement) che in automatico effettua la conversione di ContentElement (che è un Predicato o una Azione che fa parte della Ontology scelta) nel formato specificato dalla Language e lo inserisce nel messaggio come contenuto. Per inviare il messaggio (dopo averlo creato e riempito i campi desiderati) è sufficente invocare il metodo send(aclmessage) dell Agente. In questo modo il messaggio sarà recapitato nella mailbox dei destinatari dopo avere individuato il Container nel quale vivono. L arrivo di un nuovo messaggio nella mailbox di un Agente fà si (come abbiamo visto in precedenza) che tutti i behaviours dell Agente stesso che avevano invocato il metodo block() vengano risvegliati dallo stato di sleep e posizionati nuovamente nella coda dello Scheduler. Il messaggio verrà gestito da uno solo di questi Behaviour (o di quelli che non erano in sleep), quello che è interessato a quel tipo di messaggio. Ciascun behaviour può definire quali sono i messaggi al quale è interessato mediante la classe MessageTemplate, che definisce dei filtri (combinabili con le operazioni logiche) sui campi dell ACLMessage. Quando un Behaviour trova un messaggio di suo interesse dentro la mailbox, questo viene rimosso dalla mailbox, e quindi agli eventuali altri Behaviour la mailbox risponderà che non ci sono più nuovi messaggi. Un Agente (o meglio i Behaviour dell Agente) può accedere alla propria mailbox per prelevare messaggi, con due strategie differenti: receive, che ritorna null se nessun nuovo messaggio è presente nella mailbox. Se invece ci sono uno o più nuovi messaggi, il metodo restituisce uno di questi (in un oggetto di classe ACLMessage). E possibile utilizzare un MessageTemplate per fare sì che il metodo restituisca null anche quando i nuovi messaggi presenti nella mailbox non sono di nostro interesse. blockingreceive, che funziona esattamente come il precedente, ma quando quest ultimo restituirebbe null, invece questo manda tutti i behaviour in stato di sleep.

20 2.6 Scambio di Messaggi tra gli Agenti 16 private class ReceiveQueriesBehaviour extends CyclicBehaviour{ private MessageTemplate t; public ReceiveQueriesBehaviour(){ // Accepting only queries about Books decodable with the SL Codec t = MessageTemplate.and( MessageTemplate.MatchPerformative(ACLMessage.QUERY_IF), MessageTemplate.and( MessageTemplate.MatchOntology(BookOntology.INSTANCE.getName()), MessageTemplate.MatchLanguage(codec.getName()) ) public void action() { try{ ACLMessage message = myagent.receive(t); if (message == null){ // If no message respecting template arrived super.block(); // The Behaviour goes into the Sleep State return; // If a message has arrived, I decode the content ContentElement c = getcontentmanager().extractcontent(message); // Creating the reply ACLMessage (Reply receiver = Message sender) ACLMessage reply = message.createreply(); if (c instanceof Own){ // An Agent is asking me if I own a book Own own = (Own) contentelement; // Searching the requested book in the library Book book = library.getbook(own.getbookname()); if (book == null){ // If not found, i reply with a No AbsPredicate not = new AbsPredicate(SLVocabulary.NOT); not.set(slvocabulary.not_what, BookOntology.INSTANCE.fromObject(own)); reply.setperformative(aclmessage.failure); myagent.getcontentmanager().fillcontent(reply, not); else{ // If found, i reply with the price of the book reply.setperformative(aclmessage.propose); Costs costs = new Costs(book.getBookName(), book.getprice()); myagent.getcontentmanager().fillcontent(reply, costs); myagent.send(reply); catch(exception e){ e.printstacktrace(); myagent.dodelete();

21 2.7 Creare una Ontology e i suoi Componenti Creare una Ontology e i suoi Componenti Come anticipato nelle sezioni precedenti, una Ontology è un insieme di Concetti, Predicati (affermazioni sui concetti che possono avere un valore di verità) e Azioni che hanno senso per una certa categoria di Agenti. Prima di creare la Ontology dobbiamo costruire i singoli componenti, implementando rispettivamente le interfacce Concept, Predicate o AgentAction. Non ci sono metodi dei quali dobbiamo fare l override, tuttavia la classe implementante deve soddisfare i seguenti requisiti: Deve avere il costruttore di default pubblico e accessibile. In particolare ricordiamo che se non specifichiamo nessun costruttore il compilatore in automatico ci fornisce il costruttore senza parametri che non fa nulla. Nel caso che invece abbiamo dichiarato un costruttore che prevede parametri, il compilatore non ci fornisce nulla, quindi dobbiamo dichiarare a mano anche quello senza parametri. Per ogni attributo Attr bisogna fornire i metodi getter (per leggere il contenuto della variabile) e setter (per impostare il contenuto della variabile), pubblici e accessibili, nella forma canonica getattr e setattr. public class Costs implements Predicate{ private static final long serialversionuid = L; private Price price; private BookName bookname; public Costs(){ public Costs(BookName bookname, Price price){ this.bookname = bookname; this.price = price; public Price getprice() { return price; public void setprice(price price) { this.price = price; public BookName getbookname() { return bookname; public void setbookname(bookname bookname) { this.bookname = bookname;

22 2.7 Creare una Ontology e i suoi Componenti 18 Una volta creati tutti i Concept, Predicate e AgentAction implementando l interfaccia adeguata e soddisfando i requisiti richiesti (non ci sono particolari differenze nel codice che si va a scrivere nei 3 casi), possiamo creare la Ontology. Le Ontology di Jade si distinguono tra di loro per il nome che viene assegnato a ciascuna. In generale non è necessario creare più oggetti di un particolare tipo di Ontology, pertanto si sfrutta il design pattern Singleton (rendendo il costruttore privato e fornendo una sola istanza accessibile staticamente). public class BookOntology extends Ontology{ public static final String ONTOLOGY_NAME = "BookOntology"; // The Ontology should always be a singleton public static final BookOntology INSTANCE = new BookOntology(); public static final BookOntology getinstance(){ return INSTANCE;... Per ciascuna classe che implementa Concept, Predicate o AgentAction che desideriamo inserire nella Ontology e per ciascun attributo di quelle classi definiamo una costante di tipo String. Valorizziamo le costanti associate alle classi con il nome delle classi stesse, e le costanti associati agli attributi con lo stesso nome (case-sensitive) con cui sono chiamati gli stessi attributi dentro le rispettive classi. public class BookOntology extends Ontology{... // Class COSTS (Predicate) public static final String COSTS = "Costs"; // Attributes public static final String COSTS_PRICE = "price"; public static final String COSTS_BOOKNAME = "bookname";... Una volta create le costanti di Stringa per ciascuna classe e ciascun attributo andiamo ad implementare il costruttore della BookOntology. Innanzitutto dobbiamo dichiarare qual è la Ontology che stiamo estendendo. Infatti potremmo decidere di sfruttare l ereditarietà creando ad esempio una TradingOntology che definisce i concetti alla base del commercio di beni e servizi, in modo tale da riciclare tali concetti nella BookOntology. Se non si desidera sfruttare questa funzionalità, la Ontology che si deve estendere è quella di base. A questo punto dobbiamo aggiungere alla BookOntology tutti i concetti, i predicati e le azioni creati precedentemente, andando a specificare

23 2.7 Creare una Ontology e i suoi Componenti 19 in quale classe trovarle e qual è il nome che desideriamo associare al nuovo componente (sfruttando le costanti di stringa definite prima). private BookOntology() { super(ontology_name, BasicOntology.getInstance()); try { super.add(new ConceptSchema(PRICE), Price.class); super.add(new ConceptSchema(BOOK), Book.class); super.add(new PredicateSchema(COSTS), Costs.class); super.add(new PredicateSchema(OWN), Own.class); super.add(new AgentActionSchema(BUYACTION), BuyAction.class);... catch (OntologyException e) { e.printstacktrace(); Per concludere il costruttore dobbiamo recuperare uno per uno tutti gli Schemi appena aggiunti alla Ontology, tramite il metodo getschema(string) e descrivere nel dettaglio ciascuno di essi, aggiungendo tutti gli attributi che li compongono. Quando aggiungiamo un attributo dobbiamo descrivere: Che nome assume l attributo all interno dello Schema (utilizzando la corrispondente costante di Stringa definita prima). Che tipo di dato è: è uno Schema che è stato precedentemente aggiunto nella BookOntology o è un tipo di dato primitivo? Questo attributo può anche essere null (ObjectSchema.OPTIONAL) all interno dello Schema senza invalidarlo, oppure no? Se l attributo è una lista di oggetti di un determinato tipo, dobbiamo definire le cardinalità minima e massima. try {... ConceptSchema c = (ConceptSchema) super.getschema(book); c.add( BOOK_PRICE, (ConceptSchema) getschema(price), ObjectSchema.MANDATORY ); c.add( );... BOOK_NUMBEROFPAGES, (PrimitiveSchema) getschema(basicontology.integer), ObjectSchema.MANDATORY catch (OntologyException e) { e.printstacktrace();

24 Capitolo 3 Programmazione su Android Questo capitolo descrive la struttura di un Progetto Android e i concetti alla base della programmazione su tale piattaforma. Viene inoltre illustrato come procedere per arrivare ad eseguire la classica applicazione Hello, world!. La guida completa (che è stata usata come riferimento nel lavoro di tesi) su tutto ciò che riguarda lo sviluppo e la pubblicazione di applicazioni Android è possibile trovarla su developer.android.com. 3.1 Ambiente di Sviluppo: ADT Per poter sviluppare applicazioni Android dobbiamo procurarci un apposito ambiente di sviluppo, una possibile scelta è ADT (Android Developer Tools). Si tratta dell usuale ambiente di sviluppo Java, ovvero Eclipse, munito di un plug-in che consente di generare il codice per applicazioni Android (che, come vedremo, saranno costituite da files.java e da files.xml), e di compilarle producendo files.apk che il dispositivo Android è in grado di installare. Inoltre questo plug-in consente di installare ed aggiornare i pacchetti relativi ad Android (window -> android SDK manager) e di simulare una vasta gamma di dispositivi Android stessi. Ogni volta che eseguiamo un Android Project via ADT possiamo infatti scegliere se fare l upload e l installazione del file.apk in un dispositivo Android reale connesso via USB, oppure se utilizzare l emulatore di ADT stesso. Tuttavia l emulatore non si presta ai nostri scopi, poichè (oltre all intrinseca lentezza) non presenta sensori di alcun tipo. Possiamo procurarci Android Developer Tools su developer.android.com/sdk/index.html. 3.2 Creare ed Eseguire un Android Project Per creare una nuova applicazione nel nostro ambiente di sviluppo ADT andiamo su File -> New -> Android Application Project. Nella prima finestra che ci viene proposta dobbiamo scegliere il nome dell applicazione che

25 3.2 Creare ed Eseguire un Android Project 21 comparirà in Android (quindi è meglio sceglierlo corto in modo tale che non venga tagliato), il nome del progetto (dentro ADT) e il nome del package (composto da almeno due parti, che deve rimanere immutato, quindi è meglio pensarci bene prima di sceglierlo). Nelle finestre successive solitamente non abbiamo la necessità di cambiare nulla. Una volta completata la procedura concentriamo la nostra attenzione sulla struttura di files e directory generate: La directory src contiene il codice Java da noi scritto per la nostra applicazione. Se non abbiamo cambiato nulla nella procedura di creazione del progetto, notiamo che nel package che abbiamo specificato è già presente una Activity, di nome MainActivity, che attualmente è la prima ad essere eseguita quando la applicazione Android viene lanciata. La directory gen contiene altro codice Java che fa parte della nostra applicazione. Questo codice è generato e/o modificato automaticamente dal compilatore ogni volta che creiamo o modifichiamo i file.xml dell applicazione stessa. Nella directory libs possiamo collocare le librerie (gli archivi.jar) della quale l applicazione ha bisogno. Attualmente contiene android-supportv4.jar che consiste in un insieme di utility per le operazioni più comuni in Android. La questione di importazione di librerie e/o progetti Java/Android è molto delicata, perchè è facile sbagliarsi e perdere tempo, pertanto sarà trattata più nello specifico. La directory res (resources) è quella più importante, perchè ci consente di creare e configurare la parte statica della nostra applicazione. In particolare all interno di res troviamo diverse directory drawable, in tali directory andremo a posizionare tutte le immagini, che potranno ad esempio essere utilizzate come sfondo o come icone nella nostra applicazione. Le varie directory dovranno contenere le stesse immagini (ovvero files con gli stessi nomi) con dimensioni diverse (low, medium, high, extra-high, extra-extra-high), in modo tale che se l applicazione deve disegnare una immagine (ad esempio ic_launcher.png che dovremmo già avere all interno di queste directory) può scegliere tra diverse alternative, a seconda dello spazio a disposizione sullo specifico dispositivo Android sulla quale è in esecuzione. E stato definito un insieme di immagini standard per le azioni più comuni, che è bene utilizzare per il principio di familiarità nell ambito dell usabilità del software. Dentro res inoltre troviamo le directory layout, menu e values, che contengono files.xml riguardanti rispettivamente gli oggetti contenuti nelle videate, le scelte presenti nei menu, e le costanti (di stringa, di colore o di dimensione) utilizzate nell ambito dell interfaccia grafica. Ciascuna di queste tre categorie sarà affrontata singolarmente.

26 3.3 Importare Progetti e Librerie 22 Nel file AndroidManifest.xml possiamo configurare l applicazione Android sotto diversi aspetti, che saranno trattati nella sezione apposita. Per lanciare l applicazione andiamo nel menu run, scegliamo Android Application, e successivamente il device sul quale eseguirla (o l emulatore, che per questa semplice applicazione può essere usato). Se il dispositivo Android presenta la schermata di blocco (o lo schermo si è spento), passiamo il dito sullo schermo stesso per sbloccarlo. Solitamente è meglio disattivare l oscuramento dello schermo (e la conseguente schermata di blocco) mentre si sta programmando, andando nel menu Impostazioni del dispositivo Android, nella sezione Opzioni Sviluppatore. Se tutto è andato a buon fine, dovremmo vedere una applicazione con il nome che abbiamo scelto (in quella che si chiama Action Bar), e la scritta hello world! nella videata. Inoltre ora capiamo a cosa è stata utilizzata la ic_launcher che abbiamo trovato nelle directory Drawable. La applicazione che abbiamo appena lanciato è stata inoltre installata sul dispositivo, quindi potrà essere individuata e lanciata anche dal dispositivo Android stesso. 3.3 Importare Progetti e Librerie Per costruire un Android Project possiamo avere bisogno di importare librerie (ovvero file.jar), altri Android Project, oppure normali progetti Java. Le risorse linkate in modo errato non presentano problemi in fase di stesura del codice (ovvero il compilatore inline di Eclipse non notifica alcun errore), tuttavia poi i problemi si presentano quando la applicazione è in esecuzione su Android, al primo uso di una classe non riconosciuta. Per specificare le risorse che uno specifico progetto deve importare lo selezioniamo e scegliamo Properties nel menu Project. Le schede che ci interessano sono due: 1. Nella scheda Android possiamo aggiungere (tramite il pulsante Add) altri Android Project che si trovano dentro lo stesso Workspace di questo. Possiamo aggiungere solo ed esclusivamente gli Android Project che hanno spuntato il flag Is Library, che vediamo nella scheda Android stessa. Gli Android Project settati con Is Library non possono essere installati (e quindi nemmeno eseguiti). I progetti aggiunti in questo modo non devono più essere considerati nel punto successivo. 2. Nella scheda JavaBuild Path possiamo aggiungere i progetti Java (dentro lo stesso workspace) e le librerie (interne o esterne al workspace). E importante ricordarsi di spuntare tutti i progetti e le librerie aggiunte in Order and Export per fare si che tali risorse finiscano del file.apk.

27 3.4 Activity e Intent 23 E importante fare attenzione a non importare più volte Android Support v4.jar, errore che mi è capitato spesso facendo gerarchie complesse di progetti. E sconsigliabile creare i.jar dei propri Android Project mentre si sta programmando (per importarli negli altri progetti al posto di importare gli Android Project stessi), perchè si creano altri problemi (tra cui dover fare il refresh di tutti i progetti ogni volta che viene fatta una modifica, e problemi di dipendenze). In particolare se vogliamo creare un progetto Android che si appoggi sulle funzionalità offerte da Dave (descritte nel relativo capitolo) dobbiamo importare gli Android Library Project Dave Android e GooglePlayServicesLib. Quest ultima libreria consente di utilizzare le Google Maps all interno della propria applicazione. Possiamo ottenerla istallandola con l SDK Manager del nostro ambiente di sviluppo, seguendo le semplici istruzioni che troviamo qui. 3.4 Activity e Intent Una applicazione Android è composta da una o più Activity, ciascuna delle quali fornisce una interfaccia grafica (che, nella maggior parte dei casi, copre tutto lo schermo) con la quale l utente Android può interagire. Una delle Activity deve essere la launch Activity, che è quella di partenza della applicazione. Le Activity che fanno parte di una singola applicazione sono collegate tra di loro, ovvero ciascuna Activity ha la possibilità di iniziarne un altra allo scopo di compiere specifiche operazioni. In questo caso la nuova Activity viene messa in foreground, mentre quella precedente viene messa in stato di pausa (vengono compiute le operazioni di scrittura su memoria persistente rimaste in sospeso, interrotte animazioni e rilasciate risorse). Tutte le Activity, ovvero quella in foreground e quelle in background rimangono memorizzate in una struttura dati a pila, la quale permette di riportare velocemente in foreground (tramite l operazione pop) l Activity più recente. Le Activity presenti nella pila (tranne quella in foreground) possono essere distrutte per necessità di memoria, in tale caso lo stato della istanza della Activity (che viene salvato ogni volta che la Activity va in stato di pausa) deve essere ripristinato qualora l utente ritorni sulla Activity (se l Activity invece è rimasta nella pila l operazione di ripristino non è necessaria). La Activity ha un ciclo di vita composto da diversi stati (lo stato di pausa ne fa parte), ciascuna transizione verso uno stato corrisponde all invocazione del corrispondente metodo (ad esempio onpause), che il programmatore può sovrascrivere per effettuare le proprie operazioni (di cleanup, salvataggio, ripristino...).

28 3.4 Activity e Intent 24 package it.unipr.informatica.prova; import android.os.bundle; import android.app.activity; import android.view.menu; public class MainActivity extends Activity protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); public boolean oncreateoptionsmenu(menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getmenuinflater().inflate(r.menu.main, menu); return true; Quando costruiamo una Activity possiamo sovrascrivere alcuni metodi, per definire i comportamenti che la Activity deve seguire nelle transizioni di stato citate poco fa o al verificarsi di determinati eventi: oncreate: questo metodo viene invocato quando l Activity viene creata (savedinstancestate == null) oppure viene ricreata da un istanza precedentemente salvata. Bundle è una struttura dati che associa a chiavi di tipo String valori di tipo arbitrario. Tramite il metodo setcontentview(int) facciamo in modo che il contenuto della videata sia quello definito nel file xml oppotuno. onpause: questo metodo viene invocato quando l Activity non è più in primo piano (ovvero quando l utente passa ad un altra applicazione/activity lasciando aperta questa). Di solito si fa l override di questo metodo se è possibile rilasciare risorse e/o servizi al fine di ridurre il consumo di batteria. onresume: speculare di onpause, invocato quando l Activity torna in primo piano. ondestroy: speculare di oncreate, invocato quando l Activity sta per essere distrutta. E possibile effettuare operazioni di clean-up aggiuntive (perchè il metodo onpause viene invocato prima di ondestroy). onsaveinstancestate: metodo invocato prima di ondestroy che consente di creare e riempire un oggetto di tipo Bundle con i dati necessari ad una successiva ricreazione della Activity.

29 3.5 Manifest della Applicazione 25 oncreateoptionsmenu: invocato quando il menu sta per essere creato, consentendoci di associare il file.xml che contiene quello desiderato. onoptionsitemselected: metodo invocato quando uno degli oggetti del menu viene selezionato. Ci viene fornito l id dell oggetto che ha innescato l evento, in modo tale che con costrutti if o switch possiamo gestirlo in modo appropriato. Un Intent è un messaggio che viene inviato per richiedere una azione da parte di un altro componente della applicazione. L Intent contiene principalmente: L azione che si desidera che il/i riceventi del messaggio compiano. Le informazioni delle quali necessitano il/i riceventi per compiere l azione. Si tratta di una mappa <chiave, valore>, chiamata Extra dell Intent. Gli intent possono essere usati in particolare per iniziare un altra Activity, o per instaurare una dialogo tra diverse Activity. Per definire i tipi di Intent che ciascuna Activity supporta (ovvero le azioni supportate), si costruisce un IntentFilter, del quale discuteremo più avanti. Questa meccanica del filtro è necessaria, poichè tipicamente gli Intent vengono mandati in Broadcast. 3.5 Manifest della Applicazione Nel file Manifest vengono elencate tutte le caratteristiche della applicazione Android, tra cui: L icona (nome della immagine dentro la directory Drawable), il nome della applicazione (quello che abbiamo specificato nella procedura di creazione dell applicazione stessa) e il package di appartenenza. I dispositivi Android supportati dalla applicazione, stabilendo un range di versioni SDK. Solo i dispositivi che hanno una versione compresa nel range specificato possono eseguire la applicazione. I permessi che la applicazione deve ottenere per poter funzionare correttamente. I permessi elencati nel manifest sono gli stessi che vengono esposti all utente al momento del download di una applicazione da Google Play. Possono riguardare l accesso a Internet, l uso della Rubrica, la necessità di impedire lo Stand-By... I servizi di cui l applicazione ha bisogno. I servizi sono attivi a tempo continuato e lavorano in background rispetto alle Activity, le quali possono contattare (tramite l operazione di bind) il servizio stesso per poterne usufruire.

30 3.5 Manifest della Applicazione 26 L elenco delle varie Activity che compongono la applicazione, le loro caratteristiche (se è la Launch Activity, se è necessaria una specifica orientazione del telefono...) e la loro gerarchia. Se ad esempio vogliamo fare sì che la nostra applicazione possa accedere ad Internet per poter scaricare e visualizzare le Google Maps, e ricevere i dati relativi alla posizione tramite GPS e WiFi, dobbiamo aggiungere i seguenti permessi nel file manifest (prima del tag <application>). <uses-permission android:name="android.permission.internet" /> <uses-permission android:name="android.permission.access_network_state" /> <uses-permission android:name="com.google.android.providers.gsf.permission.read_gservices" /> <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_fine_location" /> Tuttavia per poter usufruire delle Google Maps per Android dobbiamo anche richiedere il servizio a Google. Dopo aver fatto il login su Google andiamo su https://code.google.com/apis/console. Dobbiamo creare un nuovo progetto (ci verrà proposto dalla pagina stessa di farlo) con lo stesso nome della applicazione Android che stiamo sviluppando. Il nostro obiettivo è abilitare il servizio Google Maps Android API v2 per il progetto che abbiamo creato, le operazioni da svolgere dipendono dall interfaccia grafica che vi presenterà Google. Una volta abilitato il servizio, dobbiamo associare il progetto creato in remoto con quello locale in ADT, creando una nuova Android Key. Ci verrà richiesto di inserire l impronta SHA1 del nostro progetto dentro ADT e il relativo package che avevamo scelto al momento della creazione (ora disponibile nel manifest). Per ottenere l impronta SHA1 dobbiamo selezionare il progetto nel Package Explorer di ADT, poi andare in Window - > Preferences -> Android -> Build. Una volta inserite queste informazioni (separate da un punto e virgola), Google genererà una Android Key, che dobbiamo aggiungere nel file Manifest (prima del tag <activity>) nel seguente modo: <meta-data /> android:name="com.google.android.maps.v2.api_key" android:value="aizasyatcq0jixahtofu-u89f9xnfiohbckq0lq" Se la nostra applicazione necessita di servizi (ad esempio Jade per Android), anche questi vanno specificati in questo punto del file manifest (ovvero prima del tag <activity>): <service android:name="jade.android.microruntimeservice" />

31 3.6 Costanti di Stringa usate dalla Applicazione Costanti di Stringa usate dalla Applicazione Nel file strings.xml (che troviamo nella directory values) vengono memorizzate tutte le costanti di Stringa che vengono usate dall applicazione. In particolare al suo interno troviamo la costante di stringa app_name, che è valorizzata con il nome della Applicazione. Possiamo utilizzare questa (o un altra) costante ovunque, ovvero: all interno degli altri file.xml (in particolare app_name viene usata nel manifest), nel seguente nei file.java all interno della directory src, nel seguente modo: R.string.app_name // la classe R si trova all interno dei file java generati, ovvero dentro la directory gen Anche dimens e styles seguono lo stesso principio sopradescritto, ma sono di raro utilizzo. 3.7 Descrizione del Menu di una Activity Ad ogni Activity (ad esempio MainActivity) è associato un file xml (ad esempio main.xml) dove viene descritto il suo menu. Il menu è composto da oggetti che possono trovarsi nella Action Bar (ovvero la barra sotto quella delle notifiche, dove è presente anche il nome della Activity), oppure che possono comparire premendo il tasto menu del dispositivo Android. Ogni oggetto del menu possiede i seguenti attributi: id: utilizzato dall applicazione per identificare l oggetto quando deve gestire gli eventi dell interfaccia e le loro sorgenti. title: visualizzato su schermo se l oggetto non si trova nella Action Bar icon: immagine visualizzata su schermo se l oggetto si trova nella Action Bar showasaction: determina se e quando l oggetto deve finire nella Action Bar, possibili scelte sono always, never, o ifroom (se c è spazio)

32 3.8 Descrizione della Videata di una Activity Descrizione della Videata di una Activity Ad ogni Activity (ad esempio MainActivity) è associato un file xml (ad esempio activity_main.xml) dove viene descritto il contenuto della videata. Innanzitutto dobbiamo definire un layout, ovvero come gli oggetti devono essere disposti, i più usati sono: RelativeLayout, in cui per ogni oggetto si può specificare la posizione rispetto ad un altro oggetto (sotto a, a fianco di...), cercando di non fare riferimenti circolari. LinearLayout, che dispone gli oggetti sempre nella stessa direzione (verticale o orizzontale, che possiamo specificare tramite l attributo android:orientation). Tra gli oggetti che possiamo inserire abbiamo pulsanti (ai quali possiamo rispondere all evento onclick), campi di testo, checkbox, radio button, pulsanti on/off, menu a tendina, selezionatori (di data e ora ad esempio). Questi oggetti, insieme alle voci del menu trattate nella sezione precedente, costituiscono la principale modalità di interazione dell utente con la Activity corrente.

33 Capitolo 4 La Library Dave Questo capitolo descrive la libreria Dave (Discover Agents Viewed on Earth) facendo una panoramica sulle principali classi delle quali è composta. Per ciascuna classe verrà spiegato il funzionamento in termini di operazioni effettuate, lo scopo all interno della libreria, ed eventuali esempi di utilizzo. Verranno utilizzati nella spiegazione alcuni concetti quali Agente, Behaviour, Activity, Intent che sono stati trattati nei capitoli precedenti. Come anticipato nell introduzione, la libreria Dave consente di creare una architettura Client-Server basata sul concetto di Agente di Jade. Ciascun Agente Client ricava ad intervalli regolari la propria posizione e direzione corrente, creando un oggetto di classe EarthPartialCircle, che viene inviato al Server se il cambiamento rispetto a quello precedente è significativo (secondo il giudizio dell UpdatePlanner). Il Server ad intervalli regolari fornisce ad un certo numero di Client (in accordo alla QualityOfService che tali Client hanno richiesto) gli altri Agenti che tali Client vedono, qualora questi siano cambiati. Le operazioni svolte da Client e Server saranno trattate nello specifico nel capitolo riguardante gli Agenti di Dave. E stata anche dedicata una sezione apposita per il Server, per parlare del suo carico computazionale, e delle soluzioni adottate per attenuarlo. La parte finale del capitolo è dedicata alle classi specifiche per Android. Il codice sorgente completo di Dave si articola in tre progetti Java: Il Progetto Dave Base include la parte di Dave che è necessaria sia su PC che su Android, contenente i concetti e le azioni base. Il Progetto Dave Pc include le classi specifiche su PC, tra cui gli Agenti dotati di interfaccia grafica Swing. Deve aggiungere come sorgente il Progetto Dave Base. Il Progetto Dave Android include le classi specifiche per Android, che andranno a gestire gli Intent, i sensori e le GoogleMaps. Deve aggiungere come sorgente il progetto Dave Base.

34 4.1 Le Informazioni Geografiche Le Informazioni Geografiche In questa sezione vengono descritte le classi che descrivono le entità geometriche in ambito terrestre, finalizzate alla rappresentazione (e alla trasmissione) della posizione e del punto di vista degli Agenti. Sono contenute nel package dave.onto.concepts.earth La Posizione: EarthPoint Per identificare univocamente un punto sulla superficie 2D della Terra è sufficiente fornire la corrispondente coppia <latitudine, longitudine>. La latitudine indica l angolo formato dalla retta che passa per il centro della terra e il punto rispetto al piano equatoriale. Due punti che hanno la stessa latitudine si trovano sullo stesso parallelo (in particolare l equatore è il parallelo fondamentale, con latitudine 0). Il polo Nord e il polo Sud formano un angolo retto, ovvero hanno rispettivamente la massima (+90) e la minima latitudine (-90). La longitudine è la distanza angolare di un punto rispetto al meridiano fondamentale, quello che passa per l Osservatorio di Greenwich in Inghilterra (che ha quindi longitudine 0). La longitudine varia da +180 a Due punti che hanno la stessa longitudine si trovano sullo stesso meridiano. Il 180-esimo meridiano est (o ovest) è la linea internazionale del cambio di data, situata nell Oceano Pacifico. La classe EarthPoint, che modella questo concetto, è quindi semplicemente una coppia di reali. Come abbiamo visto sopra, sia la latitudine che la longitudine hanno un range di valori accettati, ma la classe EarthPoint accetta qualsiasi valore per entrambe, effettuando l operazione di modulo 90 per la latitudine e di modulo 180 per la longitudine.

35 4.1 Le Informazioni Geografiche Aggiungiamo la Direzione: EarthVector Gli EarthVector sono segmenti orientati (ovvero vettori) sulla superficie 2D della Terra che congiungono due EarthPoint (quello di partenza è il first- Point, quello di arrivo è il SecondPoint). E possibile costruire un EarthVector in due modi: Specificando il punto di partenza e il punto di arrivo. Specificando il punto di partenza, la direzione (comprensiva di verso) e il modulo. Per calcolare la direzione dobbiamo prendere come sistema di riferimento quello costituito dai paralleli e dai meridiani (ad esempio scegliamo come asse x l equatore e come asse y il meridiano di Greenwich). Troviamo l intersezione della retta su cui giace l EarthVector con l asse x e tracciamo un asse y parallela a y e passante per quel punto. Abbiamo così individuato due angoli. Per ottenere univocamente la direzione dobbiamo includere anche il verso. Nell immagine sottostante, la direzione del vettore AB è di 30 gradi se il vettore va da A a B, mentre è di 210 gradi se va da B ad A. Il modulo (o lunghezza) è la distanza in linea d aria tra i due estremi del vettore. Esistono alcune formule trigonometriche che consentono di calcolare la distanza e la direzione tra due EarthPoint, implementate nella classe EarthGeometry. Queste formule (e le relative nozioni) sono state tratte dai siti sunearthtools.com e movable-type.co.uk, che offrono anche una utile prova interattiva.

36 4.1 Le Informazioni Geografiche Il Punto di Vista: EarthPartialCircle Un EarthPartialCircle è un cerchio (parziale), ottenuto facendo ruotare sul piano terrestre di un uguale angolo (che non deve superare i 180 gradi) sia in senso antiorario (leftangle) che in senso orario (rightangle) un Earth- Vector attorno al suo firstpoint (che diventa quindi il centro del cerchio parziale). Conoscendo il totalangle (che è il doppio del rightangle o del leftangle, visto che sono uguali) e l EarthVector è possibile ricavare tutte le altre informazioni, tra cui area e perimetro ad esempio. Questa classe include alcuni metodi di fondamentale importanza per il funzionamento della libreria: contains(earthpoint) è in grado di determinare per ogni EarthPoint se cade all interno della superficie dell EarthPartialCircle oppure no. Questo metodo ci consente di sapere se un Agente è contenuto nel punto di vista di un altro oppure no. getremotenessratio(earthpoint) è in grado di determinare per ogni EarthPoint quante volte il raggio dell EarthPartialCircle è contenuto nella distanza tra il centro e l EarthPoint stesso, fornendoci una informazione sul suo grado di lontananza. getfrontierpoint(double, double, int) restituisce un determinato punto appartenente alla frontiera dell EarthPartialCircle (ovvero sulla circonferenza). Questo metodo (chiamato più volte) ci consentirà di disegnare la circonferenza sulla GoogleMap.

37 4.2 Classe Helper per Jade 33 Ponendo il centro di un EarthPartialCircle nella posizione corrente di un Agente, e la maindirection (ovvero quella dell EarthVector) nella direzione in cui il suo disposivo Android è rivolto, siamo in grado di rappresentare il suo punto di vista. Un agente in Dave è quindi descritto dall EarthPartialCircle corrente, in aggiunta al suo AID, come i normali Agenti di Jade. Le classi che modellano i concetti di descrittore di Agente e di lista di Agenti sono contenute nel package dave.onto.concepts.agent 4.2 Classe Helper per Jade Nel capitolo riguardante Jade abbiamo notato che spesso le istruzioni da utilizzare per le operazioni di creazione di container e agenti sono più di una e cambiano a seconda di trovarci su PC o su Android. Lo scopo è invece avere un unico modo, più compatto ma comunque versatile, per fare queste comuni operazioni. La classe EasyJade definisce le operazioni possibili e la loro struttura, tali operazioni vengono poi implementate in modo diverso dalle classi PcJade e AndroidJade, che estendono EasyJade. Per creare un oggetto PcJade possiamo usare il costruttore con 3 parametri, che sono rispettivamente l Object che intende creare il PcJade (può anche essere null se non serve tenerlo memorizzato dentro a PcJade), l host al quale si vuole connettersi (è possibile specificare indifferentemente l indirizzo Ip oppure il nome), e la porta (è possibile utilizzare la costante EasyJade.DEFAULT_PORT per indicare 1099). Questo costruttore consente di creare un Container Periferico. Notiamo che ci vengono proposti alcuni metodi eventualmente da sovrascrivere: PcJade pcjade = new PcJade(Object caller, String host, int port) { // Invocato quando il servizio di Jade per Android viene disconnesso // Invocato dopo le operazioni di cleanup innescate da public void onfinish() public void oncontainerready() { // Fallimento nella creazione (o nella connessione) al public void oncontainerfailure(throwable throwable) { // Agente creato con public void onagentstartupsuccess() { ; // Fallimento nella creazione di un public void onagentstartupfailure(throwable throwable) {

38 4.3 Gli Agenti di Dave 34 I metodi oncontainerfailure() e onagentstartupfailure() potranno eventualmente essere utilizzati per stampare l eccezione nella console e presentare un appropriato messaggio di errore all utente. Il metodo onagentstartupsuccess può essere utilizzato solo a scopo di debug, visto che non è presente il nome dell Agente creato. Infatti per interagire con il nuovo Agente, si usa invece il Communicator. Il metodo più importante è oncontainerready, invocato (come dice il nome) quando il container (main o periferico) è pronto per creare Agenti. Per creare un Agente (sia usando PcJade che AndroidJade), usiamo uno di questi metodi di EasyJade: createnewagent(string agentname, String classname, Object args); createnewagent(string agentname, String classname, Object[] args); createnewagent(string agentname, String classname); // usiamo questo se l Agente non necessita di argomenti per il setup Per costruire un AndroidJade, abbiamo lo stesso identico costruttore, e gli stessi metodi eventualmente da sovrascrivere. L unica differenza è che l Object caller deve essere non null e instanceof Activity, perchè necessaria per fare il bind e l unbind del servizio di Jade per Android. Infine per quanto riguarda PcJade abbiamo ovviamente anche il diritto di creare Main Container locali ( localhost, sulla porta 1099), usufruendo del costruttore con 1 parametro (anche qui è opzionale, quindi si può usare null): PcJade pcjade = new PcJade(Object caller){ Gli Agenti di Dave DaveClientAgent E la classe base astratta che consente di definire tutti gli Agenti lato client. E astratta perchè i metodi che restituiscono la posizione corrente (getcurrentposition) e la direzione corrente (getcurrentdirection) sono astratti, in modo tale che le classi che estendono DaveClientAgent siano tenute a restituire ad ogni loro chiamata un valore numerico valido, ottenuto in modo diverso per ciascuna. Questo fa sì che si possano creare Client non dipendenti dai sensori di Android. Un DaveClientAgent dopo essere nato (ovvero quando comincia la sua esecuzione nel metodo setup) si aspetta di trovare un oggetto che sia in-

39 4.3 Gli Agenti di Dave 35 stanceof DAVEClientArguments nei suoi argomenti. Un oggetto di classe DAVEClientArguments contiene 4 informazioni: La distanza massima alla quale l Agente potrà vedere. Sarà utilizzato come raggio degli EarthPartialCircle. L ampiezza angolare del suo punto di vista. Sarà utilizzato come totalangle degli EarthPartialCircle. Questo vincolo e quello soprastante sono necessari, perchè erano gradi di libertà nella costruzione dell EarthPartialCircle, ovvero non era univocamente determinato solo dalla posizione e direzione corrente. Un UpdatePlanner, che è un oggetto (che sarà descritto più avanti) che può essere usato per definire quando un cambiamento della direzione o posizione dell Agente è significativo, e che quindi deve essere comunicato al Server. Una QualityOfService (anch essa descritta più avanti), che serve per definire la qualità del servizio che il Server ci deve offrire. Un Communicator (contenuto nel package dave) svolge il ruolo di mediatore tra l Agente e il suo creatore, consentendo a ciascuno di dialogare con l altro. In altre parole un Communicator possiede (e può restituire su richiesta) sia il puntatore all Object che il puntatore all Agente. Communicator può anche essere null, se questa funzionalità non è necessaria. Quando il metodo setup() termina, il DaveClientAgent si mette a cercare un Agente che offra il servizio di Server, tramite un Behaviour (SearchServerBehaviour) eseguito periodicamente ogni secondo. Quando il Server verrà trovato, tale Behaviour verrà sostituito dai seguenti: PresentationBehaviour: il Client deve informare il Server della sua presenza. Le informazioni che deve fornire includono la QualityOf- Service richiesta (che è disponibile, visto che era un argomento), e la sua identità, composta da AID e dall EarthPartialCircle corrente. Per l AID non ci sono problemi, visto che il Server può ricavare il mittente del messaggio, mentre l EarthPartialCircle deve essere costruito con il raggio e il totalangle (che sono costanti che abbiamo specificato negli argomenti d ingresso), e con getcurrentposition() e getcurrentdirection(). Questi ultimi metodi possono anche non essere ancora pronti a fornire tale informazione, magari perchè fanno uso di sensori che sono ancora in fase di inizializzazione. In questo caso la presentazione deve essere rimandata fintanto che tali informazioni non sono disponibili (ovvero anche PresentationBehaviour è eseguita periodicamente fino al suo successo). Se tutte le informazioni

40 4.3 Gli Agenti di Dave 36 sono pronte, viene mandato un messaggio al Server (il cui contenuto include tali informazioni, è una AgentAction definita nella classe dave.onto.concepts.actions.clientsubmission), e viene comunicato all UpdatePlanner che l EarthPartialCircle iniziale è quello usato nella presentazione. ServerMessagesHandlerBehaviour: è sempre in coda o in esecuzione (CyclicBehaviour) quando si conosce il Server o ci si è presentati con esso. Il suo compito è ricevere i messaggi provenienti dal Server, e smistarli nei vari handler a seconda della AgentAction presente nel contenuto. Le possibilità includono ServerUpdate, ServerExit, FollowedUpdate e FollowedExit (che si trovano tutte nello stesso package dave.onto.concepts.actions). Il meccanismo di Following verrà descritto più avanti, vediamo le altre due AgentAction. ServerUpdate contiene le identità (AID + EarthPartialCircle) di tutti gli altri Agenti che si trovano dentro il nostro punto di vista (il centro del loro EarthPartialCircle è contenuto nella superficie del nostro), lo riceviamo quando: La nostra presentazione ha avuto successo, e quindi il Server ci fornisce come risposta la lista iniziale di Agenti che vediamo. Il Server ci ha mandato una nuova lista poichè è cambiata (in accordo alla QualityOfService che abbiamo richiesto al Server) rispetto a quella precedente. Quando riceviamo la AgentAction ServerExit (invocato dal Server quando desidera terminare la sua esecuzione) il comportamento di default è invocare la dodelete() e quindi terminare anche il Client (si potrebbe invece decidere che, invece di morire, il DaveClientAgent vada in stato di sleep e poi provi a cercare un nuovo Server). Il metodo takedown(), invocato durante il processo innescato da dodelete(), consiste nel mandare una AgentAction (ClientExitRequest) al Server, con lo scopo di far dimenticare il Server della nostra presenza (ciò significa che non siamo più visti, non vediamo più nessuno, e tutti i meccanismi di Following che ci riguardano terminano). L ultimo Behaviour del quale è provvisto il DaveClientAgent è il MovingBehaviour, che sostituisce il PresentationBehaviour dopo che la presentazione ha avuto successo. Il suo semplice compito è quello di invocare periodicamente getcurrentposition() e getcurrentdirection() e fornire tali valori all UpdatePlanner, che decide se è il caso di informare il Server. In caso affermativo viene creato e spedito un messaggio che come contenuto ha la AgentAction ClientUpdate (che contiene la nuova identità dell Agente).

41 4.3 Gli Agenti di Dave FixedAgent E un DaveClientAgent che fornisce sempre lo stesso EarthPoint ogni volta che viene invocato il metodo getcurrentposition(). Per quanto riguarda il metodo getcurrentdirection(), possiamo decidere invece: di fargli restituire sempre la stessa direzione (DO_NOT_ROTATE) di fargli restituire una direzione che varia ogni volta con passo costante in senso orario o antiorario. Questi parametri aggiuntivi (EarthPoint fisso, direzione iniziale, e rotazione) si devono specificare fornendo come argomento al FixedAgent i FixedAgentArguments, che estendono i DaveClientArguments. E disponibile anche la versione FixedAgentWithGUI, che estende FixedAgent e fornisce una interfaccia grafica usufruendo della libreria swing (quindi FixedAgentWithGUI è specifico per PC e pertanto non si può creare su Android) RandomAgent E un DaveClientAgent che restituisce valori random (ma comunque validi) ad ogni chiamata di getcurrentposition() o getcurrentdirection(). Non ha bisogno di parametri aggiuntivi, quindi lo si può creare usando i DaveClientArguments. Come per il FixedAgent, esiste la versione specifica per pc (RandomAgentWithGUI) con interfaccia grafica swing AndroidRealAgent E un DaveClientAgent specifico per Android. In questo Agente i metodi getcurrentposition() e getcurrentdirection() interrogano rispettivamente il provider di localizzazione (GPS o Wi-Fi) e il Giroscopio. Questo Agente si aspetta di trovare come argomento un oggetto di classe RealAgentArguments, la quale estende DaveClientArguments, e impone come vincolo aggiuntivo che il Communicator non sia null e sia instanceof AACommunicator. L AACommunicator (Activity-to-Agent Communicator) estende il Communicator e impone che l oggetto chiamante sia una Activity. Inoltre fornisce ad entrambi un rapido accesso al Giroscopio e al Network Provider (preferibile rispetto al GPS provider che funziona bene solo all aperto), permettendo di leggere i valori forniti da questi strumenti (a questo sarà interessato l Agente) o metterli in pausa al fine di risparmiare energia (a questo sarà interessata la Activity).

42 4.4 UpdatePlanner DaveServerAgent La struttura interna di questo Agente è più semplice rispetto a quella del Client. Infatti non necessita di argomenti in ingresso e ha solo due Behaviour: ClientMessageHandlerBehaviour è sempre in esecuzione o in coda (CyclicBehaviour) e ha il compito di ricevere i messaggi provenienti dai Client, e smistarli nei vari handler a seconda della AgentAction presente nel contenuto. Le possibilità includono ClientSubmission, ClientUpdate, ClientExitRequest, StartFollow e StopFollow. Il meccanismo di Following sarà trattato più avanti, vediamo ora la gestione degli altri tipi di AgentAction: ClientSubmission è la AgentAction usata da un nuovo Client quando si presenta al Server, come abbiamo visto nella sottosezione dedicata al DaveClientAgent. Quando viene ricevuta il Server deve aggiungere nella propria struttura dati (che approfondiremo in seguito) le informazioni riguardanti il nuovo Client, e rispondere con un ServerUpdate indicando gli Agent inizialmente visti da quello nuovo (dopo averli trovati). ClientUpdate viene ricevuto quando uno dei Client ha cambiato in modo significativo (rispetto al proprio UpdatePlanner) il proprio EarthPartialCircle. Il Server deve semplicemente riconoscere il Client (in tempo O(1), in seguito vedremo come) e aggiornare questo dato. ClientExitRequest viene ricevuto quando uno dei Client ha intenzione di terminare la propria esecuzione. Il Server, dopo averlo riconosciuto, deve rimuovere tale Client dalla propria struttura dati. UpdateBehaviour è una procedura che il Server esegue ogni secondo. Per ciascuno dei Client, l obiettivo è aggiornare gli Agenti che questo Client vede, e, se sono cambiati rispetto alla precedente esecuzione di UpdateBehaviour, mandare un messaggio al Client con la lista aggiornata. I cambiamenti sono ovviamente dovuti allo spostamento del Client stesso o allo spostamento di uno o più altri Agenti, che sono entrati (o usciti) dal suo punto di vista. Questa procedura viene fatta in accordo alla QualityOfService che ciascun Client ha richiesto. 4.4 UpdatePlanner L UpdatePlanner (contenuto nel package dave.update) si occupa di stabilire quando un cambiamento nell EarthPartialCircle di un Client (in seguito ad una nuova lettura di posizione e direzione) è significativo (e in quanto tale, il Server deve venirne a conoscenza). I criteri sono i seguenti:

43 4.5 Riduzione del Carico Computazionale Deve essere passato abbastanza tempo (maggiore del parametro UpdatePeriod, che possiamo specificare nel costruttore) dalla precedente lettura. In caso contrario, la lettura viene considerata non significativa. UpdatePeriod, per questo motivo, viene quindi anche utilizzato per temporizzare il MovingBehaviour del Client. 2. La distanza tra i centri dei due EarthPartialCircle (ovvero la differenza di posizione) deve essere superiore di un altro parametro (minimum_delta_position) che possiamo impostare nel costruttore. 3. La differenza di direzione deve essere superiore di un terzo parametro (minimum_delta_direction), anche questo impostabile a nostro piacimento. L UpdatePlanner non si limita a memorizzare i criteri, è anche in grado di memorizzare le letture e fornire le risposte, infatti: Il metodo start(earthpartialcircle) memorizza dentro l Update- Planner l EarthPartialCircle iniziale e il currenttimemillis. Il metodo needtoupdate(earthpartialcircle) analizza l EarthPartialCircle passato come parametro e il currenttimemillis confrontando questi dati con quelli precedentemente memorizzati. Secondo i criteri che abbiamo stabilito, il metodo restituisce una risposta booleana in merito alla significatività del cambiamento. Che il cambiamento sia significativo o meno, i dati precedentemente memorizzati vengono sostituiti da quelli nuovi, in modo tale da essere pronto per la successiva chiamata NeverUpdatePlanner Il NeverUpdatePlanner (contenuto nel package dave.update) è un Update- Planner che risponde sempre di no, ovvero il suo metodo needtoupdate restituisce sempre false. I criteri non vengono quindi utilizzati, e le letture non vengono memorizzate. Può essere utile se usato dai FixedAgent che non ruotano o da Agenti che non vogliono informare il Server dei propri spostamenti, facendogli credere di trovarsi sempre nella posizione iniziale. 4.5 Riduzione del Carico Computazionale Sebbene la struttura interna del DaveServerAgent sia molto semplice, il lavoro che questo Agente deve svolgere, se non si adottano strategie per ridurlo, è molto costoso in termini di operazioni. Infatti ogni volta che UpdateBehaviour è in esecuzione (ogni secondo) dovrebbe controllare per ciascuno degli N Client connessi se vede o meno ciascuno degli N - 1 altri Client, con un

44 4.5 Riduzione del Carico Computazionale 40 costo quadratico. Le semplificazioni che adottiamo per ridurre questo costo sono le seguenti: Alcuni Client possono accontentarsi di ricevere aggiornamenti meno frequentemente. Se un Client è interessato agli update ogni 5 secondi, allora UpdateBehaviour (che viene eseguito ogni secondo) dopo averlo servito 1 volta lo ignorerà per le 4 volte successive. Non è necessario ogni volta ricontrollare tutti gli altri N - 1 Client. Se ad esempio un Agente X è a Milano, e il raggio del suo Earth- PartialCircle è di 1 Km, che bisogno c è di controllare se ora vede l Agente Y che si trovava a Roma quando è stato fatto l ultimo aggiornamento? Al contrario un Agente Z che si trovava a 2 Km da X o un Agente W che si trovava a 500m da X ma alle sue spalle avranno bisogno di essere controllati più spesso. Qui entra in gioco il concetto di RemotenessRatio che è stato introdotto nella sezione dedicata agli EarthPartialCircle. L idea è definire una serie di Regole che associano alla RemotenessRatio una frequenza di aggiornamento. Le Regole saranno utilizzate dal Server per creare dei Livelli nei quali posizionare gli N - 1 altri Agenti. Gli Agenti facenti parti di un Livello vengono controllati tutti insieme (in rispetto alla Regola associata al Livello) ed eventualmente spostati in altri Livelli a seconda della loro variazione di RemotenessRatio. Per quanto riguarda il ClientMessagesHandlerBehaviour, il suo compito prevalente è riconoscere ciascun Client che ha inviato un messaggio per poter accedere alla struttura dati del Server nel punto opportuno. Se il riconoscimento del Client fosse solo tramite AID, il Server dovrebbe confrontarlo uno per uno con tutti gli N AID dei Client connessi, quindi con un costo di N confronti nel caso pessimo. Per ridurre questo costo viene introdotto un numero intero (Cookie) che identifica univocamente ciascun Client. Ogni volta che un nuovo Client X si connette viene posto in fondo alla lista del Server e gli viene associato il Cookie CX, dove CX è il numero di Client precedentemente presenti nella lista (quindi X escluso). Tale Cookie corrisponde esattamente all indice della lista in cui si trovano i dati di quel Client. Ogni volta che X manda un messaggio al Server deve presentare il proprio Cookie CX, in modo tale che l accesso ai suoi dati avvenga in tempo O(1) utilizzando il Cookie come indice nella lista. Che cosa succede quando un Client Y con Cookie CY manda una ClientExitRequest al Server? In questo caso il Client Y viene eliminato dalla lista e tutti i client che avevano Cookies (ovvero posizione all interno della lista) maggiori di CY vengono shiftati di una posizione verso sinistra, mentre tutti i Client che avevano Cookies minori di CY rimangono nella posizione in cui erano (quindi i loro Cookies rimangono funzionanti). Se un client X è stato

45 4.5 Riduzione del Carico Computazionale 41 shiftato il suo cookie CX non è più valido, però i suoi dati si trovano nella lista in una posizione sicuramente minore di CX (in particolare in quella precedente se è stato eliminato solo un Client con cookie < CX dall ultima volta in cui CX ha mandato un messaggio al Server). Tuttavia questo non è un grosso problema, poichè: Non tutti i Cookies perdono di validità Le operazioni di eliminazione sono sicuramente meno frequenti rispetto alle operazioni di accesso e modifica ai propri dati Qualora un Cookie CX diventasse invalido, il riconoscimento del Client X viene fatto tramite il suo AID, andando a ritroso nella lista a partire dalla posizione CX (quindi al più CX confronti vengono fatti). Una volta trovati i dati, il Cookie viene corretto e rimandato al Client, così le successive operazioni torneranno ad essere servite in tempo O(1) LevelAccessRule La classe LevelAccessRule implementa il concetto di Regola che abbiamo introdotto parlando di riduzione del carico di lavoro del Server. E ciascun Client che decide quante e quali Regole creare, a seconda delle proprie esigenze (o meglio di quelle dell applicazione). Per creare una Regola dobbiamo semplicemente specificare una coppia di valori interi: Limite: solo gli Agenti che hanno RemotenessRatio < Limite vengono considerati da questa regola. E possibile fornire anche il valore speciale NO_LIMIT per indicare che la RemotenessRatio può essere qualsiasi. UpdatePeriod: ogni quanti secondi gli Agenti considerati da questa regola vengono controllati per verificare gli eventuali cambiamenti AccessRules Questa classe modella il concetto di insieme di regole. Possiamo aggiungere tutte le LevelAccessRule che vogliamo, in un qualsiasi ordine, e quando siamo soddisfatti, invocare il metodo checkandnormalize() che ordina le regole e controlla che non ci siano regole discordanti, di troppo o mancanti: Le Regole non possono essere zero (viene lanciata una EmptyRulesException). Deve esistere una regola con UpdatePeriod = 1. Non ci possono essere due regole uguali (viene lanciata una EqualRulesException). Due regole sono uguali quando hanno lo stesso Limite o lo stesso UpdatePeriod. Come conseguenza può esistere al più una sola regola con NO_LIMIT.

46 4.5 Riduzione del Carico Computazionale 42 Non ci possono essere due regole discordanti. Se il Limite di R 1 è maggiore del Limite di R 2 (quindi la regola R 1 prende in considerazione Agenti più distanti) allora deve valere che anche l UpdatePeriod di R 1 è maggiore di quello di R 2 (ovvero che la regola R 1 triggera meno frequentemente della regola R 2 ). In caso contrario R 1 e R 2 sono discordanti (e viene lanciata una DiscordantRulesException). Le regole sono quindi ordinate per UpdatePeriod (o equivalentemente per limite, visti i vincoli soprastanti). In questo modo sappiamo che se i > k allora il Limite e l UpdatePeriod di R i sono maggiori rispettivamente del Limite e dell UpdatePeriod di R k. Un Client A risponde alla regola R k del Client B (si parla delle regole ordinate come descritto sopra) se e solo se: 1. la RemotenessRatio di A rispetto a B è minore del limite specificato nella regola R k 2. tra tutte le regole di B che soddisfano il punto precedente, R k è quella con il Limite minore. Se nelle AccessRules di B è presente una regola con NO_LIMIT, allora tutti i Client A diversi da B rispondono a una e una sola delle regole. Nel caso non sia presente, invece, qualora la RemotenessRatio di un client A rispetto a B diventasse maggiore di tutti i Limiti di tutte le Regole, A non sarà mai più considerato da B QualityOfService Con questa classe ciascun Client può indicare al Server le AccessRules di cui necessita, e un ulteriore parametro intero, updatefrequency, che indica ogni quanti secondi il Server deve aggiornare gli Agenti che tale Client vede. Se un Client desidera aggiornamenti ogni N secondi, allora il Server manterrà un contatore inizializzato ad N. UpdateBehaviour viene eseguito nel Server ogni secondo, e decrementa in ciascuna esecuzione tutti i contatori dei Client. Se un contatore arriva a zero, allora UpdateBehaviour deve controllare (seguendo ora le AccessRules) gli Agenti visti dal Client associato a quel contatore, e poi ripristinare il contatore al valore iniziale NoService Se un Client invia NoService (invece di QualityOfService) al Server, significa che non desidera ricevere aggiornamenti di Agenti visti. In questo caso tale Client riceverà solamente un ServerUpdate, quello di risposta alla ClientSubmission, contenente gli Agenti visti inizialmente. Non ricevendo altri aggiornamenti, il Client non saprà se tali Agenti sono usciti dal suo punto di vista, o se ne sono entrati altri.

47 4.6 Esempio di Creazione e Configurazione Client Esempio di Creazione e Configurazione Client new AndroidJade(activity, " ", public void oncontainerready() { AACommunicator communicator = new AACommunicator(activity) { public void onagentlinked() { doresume(); QualityOfService qualityofservice = new QualityOfService( AccessRules.DEFAULT_ACCESS_RULES, 5 );... AndroidRealAgentArguments arguments = new AndroidRealAgentArguments( 3.0, // Raggio 90.0, // TotalAngle new UpdatePlanner(), qualityofservice, communicator ); createnewagent( "Luca", "dave.android.agent.androidrealagent", arguments ); In questo esempio viene creato un Agente di classe AndroidRealAgent, di nome Luca, i cui EarthPartialCircle avranno un raggio di 3 Km e un ampiezza angolare totale di 90 gradi. Luca usa l UpdatePlanner di Default, cioè quello fornito dal costruttore di default di UpdatePlanner, che in particolare ha: Mininum_Delta_Direction = 10, ovvero vengono considerate significative solo le rotazioni di almeno 10 gradi. Mininum_Distance = 0.01, ovvero vengono considerati significativi solo gli spostamenti di almeno 10 metri. Update_Period = 2000, ovvero devono passare 2 secondi tra una lettura dell EarthPartialCircle e la successiva. La QualityOfService specificata da Luca impone che Luca deve essere aggiornato (degli Agenti che vede) dall UpdateBehaviour del Server ogni 5 secondi, con le AccessRules di default, che sono queste:

48 4.7 Struttura Dati del Server 44 public static final AccessRules DEFAULT_ACCESS_RULES = new AccessRules().addRule(new LevelAccessRule(1, 1)).addRule(new LevelAccessRule(20, 2)).addRule(new LevelAccessRule(40, 4)).addRule(new LevelAccessRule(80, 8)).addRule(new LevelAccessRule(100, LevelAccessRule.NO_LIMIT)); Tutto ciò significa: Ogni 5 secondi (5 * 1) vengono controllati gli Agenti che, al momento dell ultimo aggiornamento, distavano al più 3 * 1 = 3 Km da Luca. Ogni 100 secondi (5 * 20) vengono controllati gli Agenti che, al momento dell ultimo aggiornamento, distavano al più 3 * 2 = 6 Km. Ogni 200 secondi (5 * 40) vengono controllati gli Agenti che, al momento dell ultimo aggiornamento, distavano al più 3 * 4 = 12 Km. Ogni 400 secondi (5 * 80) vengono controllati gli Agenti che, al momento dell ultimo aggiornamento, distavano al più 3 * 8 = 24 Km. Gli agenti che, al momento dell ultimo aggiornamento, distavano più di 24 Km da Luca vengono controllati ogni 5 * 100 = 500 secondi. Se eliminassimo l ultima regola, otterremmo che se un Agente in un qualsiasi momento viene a distare più di 24 Km da Luca, allora tale Agente non sarà mai più considerato da Luca, nemmeno se la loro distanza dovesse successivamente ridursi a meno di 24 Km. Infine, viene fornito un AACommunicator per far comunicare Luca con la Activity che l ha creato. In particolare, quando Luca avrà fatto sapere all AACommunicator che la sua creazione ha avuto successo, verrà invocato il metodo doresume() dell AACommunicator, che ha l effetto di iniziare la lettura del giroscopio e del Network Provider. 4.7 Struttura Dati del Server ClientMatrix ClientMatrix è la struttura dati dove il Server contiene tutte le informazioni riguardanti gli Agenti che gli hanno inviato ClientSubmission. E semplicemente una lista di oggetti di tipo ClientRow, che gestiscono le informazioni di un singolo Client. Le operazioni che il Server deve svolgere sulla ClientMatrix sono: Aggiungere una ClientRow ogni volta che riceve una ClientSubmission da parte di un agente B. Per ciascuno dei Client X già presenti nella ClientMatrix deve confrontare l EarthPartialCircle di X con quello di

49 4.7 Struttura Dati del Server 45 B, e viceversa, calcolando così le rispettive RemotenessRatio per poter quindi posizionare nel Level corretto B nei confronti dei vari Client X, e i vari Client X nei confronti di B. In particolare così il Server ha ottenuto gli Agenti che B vede, e li può mandare a B come risposta alla ClientSubmission. Rimuovere una ClientRow ogni volta che riceve una ClientExitRequest da parte di un agente B. Per ciascuno dei Client X rimanenti, deve rimuovere B dal Level di X dove si trovava. Inoltre deve terminare tutte le operazioni di Following da e verso B. Riconoscere un Client attraverso AID o attraverso AID e Cookie, e verificarne l esistenza nella ClientMatrix, restituendo la corrispondente ClientRow. Nel caso venga fornito un Cookie non più valido, deve correggerlo e restituirlo corretto al Client ClientRow ClientRow contiene tutte le informazioni riguardanti un singolo Client B all interno della ClientMatrix. Le informazioni che vengono memorizzate sono: Il descrittore (DaveAgent) di B. L EarthPartialCircle contenuto nel descrittore viene modificato ogni volta che B manda un ClientUpdate. I Levels costruiti e governati dalle AccessRules che B ha richiesto. In particolare l oggetto di classe Levels conterrà tanti oggetti di classe Level pari al numero di regole (size di AccessRules), e assegnerà a ciascun Level una di queste. Un contatore (Counter) che serve all UpdateBehaviour per sapere se B deve essere servito (qualora il Counter dopo essere stato decrementato diventa zero) o ignorato (dopo il decremento rimane positivo) nella esecuzione corrente. Il Counter viene resettato al valore iniziale ogni volta che UpdateBehaviour serve B L UpdatePeriod, quello della QualityOfService che B ha richiesto, che serve per inizializzare e resettare il Counter. Gli Agenti che B vede, ricalcolati ogni volta che UpdateBehaviour controlla i Livelli di B. I Followers di B (descritti più avanti), con la possibilità di aggiungerli, rimuoverli e ottenerne la lista.

50 4.7 Struttura Dati del Server OtherClient OtherClient è una piccola struttura dati di appoggio riferita ad una coppia di Client <A, B> presenti nella ClientMatrix. Il primo Client (A) assume il ruolo di straniero, mentre il secondo Client (B) il ruolo di locale. Dentro questa struttura dati viene memorizzato l ultimo (nel senso l ultimo che è stato calcolato, visto che può cambiare con il tempo) rango assegnato al Client straniero da parte del Client locale. Se A risponde alla regola R k di B, allora il rango di A è k (che corrisponde all indice dell oggetto Level in cui trovare A). Se A non risponde a nessuna delle regole di B, allora il rango assume il valore speciale IGNORED. Inizialmente (quando Other- Client viene costruito) il rango memorizzato dentro OtherClient assume il valore speciale NO_PREVIOUS_RANK. Gli oggetti di tipo OtherClient vengono creati ogni volta che un nuovo Client C si presenta al Server tramite ClientSubmission, in particolare per ogni Client X già presente viene creato un OtherClient per la coppia <C, X> e un altro per la coppia <X, C> Levels I Levels di B sono una lista ordinata di oggetti di tipo Level, ciascuno dei quali è associato ad una delle regole specificate dal Client B con AccessRules (l ordinamento dei Level corrisponde all ordinamento dei LevelAccessRule). I vari Level di B contengono tutti gli OtherClient riferiti alle coppie <X, B> tali che: 1. X è un Agente diverso da B 2. Il rango contenuto nell oggetto OtherClient è diverso da IGNORED Ogni volta che l Agente X (o meglio l oggetto OtherClient riferito alla coppia <X, B>) deve essere posizionato in uno dei Livelli di B (questo accade quando X e B si conoscono oppure quando UpdateBehaviour agisce sul Livello di B in cui si trova attualmente X), bisogna calcolare il rango di X rispetto a B e confrontarlo con quello precedentemente salvato dentro l oggetto OtherClient: Se sono uguali, vuol dire l Agente X non deve essere spostato dal Level in cui si trova. Se il rango precedente era NO_PREVIOUS_RANK, allora X deve essere posizionato nel Level di indice corrispondente al nuovo rango. Se il nuovo rango è IGNORED, allora X deve essere rimosso dal Level in cui si trova (dato dal rango precedente). In questo modo l oggetto OtherClient riferito alla coppia <X, B> non sarà più puntato da nessuno dei Level, e verrà automaticamente eliminato dalla memoria. X non sarà mai più inserito in uno dei Level di B.

51 4.8 Following 47 Altrimenti il rango precedente e quello nuovo sono diversi e non sono i valori speciali sopra elencati. L oggetto OtherClient dovrà essere eliminato dal Level dato dal rango precedente, e inserito nel Level dato dal nuovo rango. Dopo avere compiuto l eventuale spostamento, il rango precedente dentro l oggetto OtherClient viene sostituito con quello nuovo. Ciascun Level ha inoltre un proprio contatore (inizializzato al valore di UpdatePeriod della regola a cui il Livello si riferisce), che viene usato per determinare (con lo stesso funzionamento del Counter di ClientRow) se gli OtherClient presenti nel Livello devono essere analizzati nella corrente esecuzione di UpdateBehaviour oppure no. Ovviamente questo controllo viene fatto per ciascun Livello solo nel caso in cui UpdateBehaviour stia servendo il Client. 4.8 Following E un meccanismo che consente ad un Agente A (il follower ) di ricevere dal Server le notifiche riguardanti gli spostamenti di un Agente B (il followed ). Non ci sono limiti riguardanti il numero di Agenti che si può seguire o il numero di Agenti dal quale si può essere seguiti. Questo meccanismo è del tutto slegato dall aggiornamento degli Agenti che A vede, infatti anche se A sta seguendo B, continuerà a ricevere gli usuali messaggi contenenti la AgentAction ServerUpdate, nei quali potrà essere presente anche B. 1. L Agente A decide di voler seguire l Agente B, quello che deve fare è mandare un messaggio al Server contenente la AgentAction StartFollow, dove può specificare l AID di B. 2. Il Server ricava A come mittente del messaggio, e B all interno della StartFollow contenuta nel messaggio, e fa alcuni controlli (di conoscere sia A che B, che A sia diverso da B, che A non stia già seguendo B). Se tutti i controlli vengono superati, l Agente A viene aggiunto alla lista dei Followers dentro la ClientRow di B. Infine il Server manda un messaggio di risposta ad A comunicandogli l EarthPartialCircle iniziale di B (e il suo AID, visto che A potrebbe stare seguendo più Agenti contemporaneamente) tramite una AgentAction FollowedUpdate. 3. Ogni volta che B manda un ClientUpdate al Server, oltre ad aggiornare l EarthPartialCircle contenuto nella ClientRow di B, il Server deve anche mandare un messaggio (contenente la AgentAction FollowedUpdate) a tutti gli Agenti che fanno parte della lista dei Followers di B (A è uno di questi). 4. Se B decide di mandare una ClientExitRequest al Server, quest ultimo deve mandare un messaggio a tutti i Followers, contenente la Agen-

52 4.9 Visualizzazione Agenti sulle GoogleMaps 48 taction FollowedExit. Dalla ricezione di questo messaggio, A non riceverà più FollowedUpdate riguardanti B (in particolare neanche le ServerUpdate conterranno B, visto che B non c è più). 5. Anche l Agente A può far terminare l operazione di Following, qualora decidesse di inviare a sua volta una ClientExitRequest, oppure la AgentAction StopFollow, che ha l effetto di terminare solamente l invio delle FollowedUpdate riguardanti B senza causare la terminazione di A. 4.9 Visualizzazione Agenti sulle GoogleMaps Le mappe di Google sono uno strumento molto comodo e versatile, poichè: Possiamo visualizzare ciascun luogo con tre modalità diverse: stradale, terreno, oppure ibrida. Possiamo visualizzare ciascun luogo a diversi livelli di zoom (fornendo un parametro tra 1 e 20) E possibile spostare la telecamera in una qualsiasi posizione e con una qualsiasi angolazione (e possiamo animare o meno gli spostamenti) E possibile posizionare marcatori nei punti di interesse, e associare a ciascuno un nome e un colore E possibile gestire tramite handler personalizzati gli eventi touch o drag-and-drop sui marcatori DaveMap è una sovrastruttura della GoogleMap che le consente di interagire con gli Agenti di Dave. Funziona in modo simile a quanto previsto dal Design Pattern Adapter, ovvero i metodi di DaveMap internamente si appoggiano ai metodi della GoogleMap. I Marcatori (Marker) che la GoogleMap è in grado di posizionare (in un punto qualsiasi) e visualizzare su se stessa verranno utilizzati per rappresentare gli Agenti. Anche i Marcatori dovranno avere una opportuna sovrastruttura (DaveMarker), che consentirà loro di contenere più informazioni. In particolare, per ciascun DaveMarker abbiamo bisogno di memorizzare: L AID dell Agente a cui il marcatore si riferisce. In questo modo si stabilisce una corrispondenza biunivoca tra l Agente e il suo DaveMarker. Vogliamo sapere se l Agente a cui questo marcatore si riferisce è quello locale (quello che vive nel dispositivo Android che sta visualizzando la mappa), oppure se è visto e/o seguito da quello locale. Questa informazione sarà utilizzata per scegliere il colore con cui disegnare il marcatore (se non specificato esplicitamente dal programmatore nel

53 4.9 Visualizzazione Agenti sulle GoogleMaps 49 costruttore), e se disegnare o meno l EarthPartialCircle associato all Agente. Un EarthPartialCircle può essere disegnato (con una certa precisione che influenzerà le prestazioni) con una poligonale (data una lista di N+1 punti, la poligonale consiste negli N segmenti ciascuno dei quali ha come estremi due punti consecutivi nella lista). Di seguito un esempio di codice che consente di creare una DaveMap a partire da una GoogleMap: MapFragment m = (MapFragment) getfragmentmanager().findfragmentbyid(r.id.map); GoogleMap g = m.getmap(); g.setmaptype(googlemap.map_type_hybrid); DaveMap davemap = new DaveMap(g) public void onagentselected(davemarker davemarker) { public boolean accepttoviewagent(daveagent daveagent) { return public Float onagentcolorrequested(daveagent daveagent) { Agent a = androidjade.getcommunicator().getagent(); AndroidPirateAgent p = (AndroidPirateAgent) a; TreasureList treasures = p.getgamestorage().gettreasurelist(); ; if (treasures.contains(daveagent.getaid())){ return DaveMarker.getHue(Color.YELLOW); return null; Il codice soprastante fa parte della PirateActivity del gioco DaveTreasureHunt, trattato nel capitolo 5. Le prime due istruzioni consentono di recuperare (tramite identificatore) dal file xml contenente la descrizione della videata della PirateActivity (ovvero pirate.xml) il Fragment contentente la GoogleMap, e estrarre quest ultima. Nel file pirate.xml troviamo infatti: <fragment android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.mapfragment" /> Il FragmentManager è così in grado di riconoscere la GoogleMap corretta e restituirla. Dopo aver impostato il tipo di mappa nella linea successiva, notiamo che quando creiamo la DaveMap ci viene chiesto di implementare tre metodi:

54 4.9 Visualizzazione Agenti sulle GoogleMaps 50 onagentselected viene invocato quando l Utente tocca un Marcatore sulla GoogleMap. L argomento del metodo è il DaveMarker che l utente ha toccato. In questo modo possiamo estrarre l Agente a cui il marcatore si riferisce e compiere le azioni appropriate a seconda della sua identità. accepttoviewagent viene invocato quando l Agente che troviamo come argomento è visto dall Agente locale. Dobbiamo restituire true se desideriamo che tale Agente venga visualizzato sulla mappa, o false se vogliamo nasconderlo. Anche qui possiamo fare azioni diverse a seconda dell identità dell Agente stesso. Da notare che gli Agenti che nascondiamo rimangono comunque nella memoria della DaveMap, quindi è possibile decidere di disegnarli in un secondo momento. Gli Agent che possiamo nascondere sono solo quelli visti, infatti questo metodo non viene invocato per l Agenti locale e quelli seguiti. onagentcolorrequested viene invocato quando l Agente che troviamo come argomento ha superato il test dato da accepttoviewagent e sta per essere disegnato. Dobbiamo scegliere il colore da associare a tale Agente. Nell esempio esposto sopra viene controllato che l Agente sia un Tesoro, in tale caso viene colorato in giallo, altrimenti vengono usati i colori di default (blu per quello locale, verde per quelli seguiti, rosso per quelli visti). Le aggiunte apportate alla GoogleMap grazie alla DaveMap riguardano principalmente un maggior supporto ai Marcatori: I DaveMarker rimangono memorizzati in due liste (una per quelli visualizzati sulla mappa, una per quelli nascosti) all interno della Dave- Map stessa. In un qualsiasi momento è possibile usare il metodo refresh() che riunisce le due liste in una sola, e innesca nuovamente accepttoviewagent e onagentcolorrequested su ciascuno dei DaveMarker, per dividerli nuovamente nelle due liste (eventualmente in modo diverso da prima). Ogni volta che un nuovo DaveMarker viene aggiunto alla mappa, prima ancora di invocare i metodi accepttoviewagent e onagentcolor- Requested, viene verificato che non esista già in una delle due liste un altro DaveMarker associato allo stesso Agente. In caso esista viene deciso quale dei due DaveMarker cancellare, così da mantenere la corrispondenza biunivoca tra Agente e DaveMarker. E possibile ottenere uno specifico DaveMarker all interno di una delle due liste con il metodo getmarker(aid). E possibile ottenere anche quello locale, con getmymarker().

55 4.10 DaveReceiver 51 E possibile cancellare i DaveMarker, in modo selettivo (sempre per AID), tutti quelli presenti (con il metodo clear), o solo quelli visti DaveReceiver Il compito di DaveReceiver è ricevere gli Intent che vengono inviati dagli Agenti di classe AndroidRealAgent (o sottoclassi). In particolare ogni volta che riceve un Intent deve ricavarne l azione (tra tutte quelle che il DaveReceiver può gestire), estrarne gli eventuali Extra, per poter così compiere l azione appropriata sulla DaveMap e/o sulla Activity (tipicamente visualizzare delle notifiche) IntentFilter Per definire le azioni che il DaveReceiver è in grado di gestire è stato costruito un IntentFilter (memorizzato all interno del DaveReceiver stesso): IntentFilter intentfilter = new IntentFilter(); intentfilter.addaction(display_my_position); intentfilter.addaction(display_near_agents); intentfilter.addaction(go_to_my_position); intentfilter.addaction(agent_dead); intentfilter.addaction(followed_add); intentfilter.addaction(followed_changed); intentfilter.addaction(followed_removed); intentfilter.addaction(presentated); intentfilter.addaction(server_exit); Questo intentfilter deve essere utilizzato per registrare il DaveReceiver alla Activity (una Activity può avere uno o più BroadcastReceiver che catturano gli Intent diretti a quest ultima). Pertanto, dopo aver creato un oggetto (this.receiver) di classe DaveReceiver nel metodo onstart della Activity, dovremo anche effettuare l operazione di registrazione del corrispondente IntentFilter in questo protected void onresume() { super.onresume();... super.registerreceiver(this.receiver, this.receiver.getintentfilter()); ; La speculare operazione di de-registrazione serve per consumare meno batteria quando non ci si aspetta di ricevere Intent su quella public void onpause(){ super.onpause();... super.unregisterreceiver(this.receiver);

56 4.10 DaveReceiver Azioni compiute Visto che abbiamo utilizzato l IntentFilter sappiamo che tutti gli Intent catturati dal DaveReceiver (viene invocato il metodo onreceive quando ne arriva uno nuovo) hanno come action una di quelle sopra elencate. Gli Extra sono invece un insieme di coppie <chiave, valore> che l Intent può portare con sè. A seconda della action dell Intent sappiamo se aspettarci degli Extra oppure no. Di seguito elenco le operazioni compiute a seconda della action dell Intent. Tali operazioni sono contenute in metodi handler (ad esempio followedadd). Al termine di ciascuno di questi metodi (ad esempio followedadd), viene invocato un ulteriore metodo astratto (ad esempio on- FollowedAdd), del quale possiamo fornire una implementazione per compiere azioni aggiuntive. DISPLAY_MY_POSITION: L AndroidRealAgent avvisa la Activity che ha calcolato un (nuovo) EarthPartialCircle riferito a se stesso. Il DaveReceiver accede all Agente (tramite il suo puntatore), recupera il nuovo valore dell EarthPartialCircle, e fà si che la DaveMap aggiorni il DaveMarker locale. DISPLAY_NEAR_AGENTS: L AndroidRealAgent avvisa la Activity della ricezione di un ServerUpdate. Come nel caso precedente, il DaveReceiver accede all Agente per recuperare le informazioni sugli Agenti visti. Dopodichè tutti i DaveMarker che si riferivano ad Agenti visti vengono cancellati dalla DaveMap e sostituiti con quelli nuovi. GO_TO_MY_POSITION: L AndroidRealAgent chiede che la Dave- Map della Activity venga centrata nella propria posizione. Per fare questo il DaveReceiver accede all Agente per ricavare l EarthVector dal suo EarthPartialCircle corrente. L EarthVector viene utilizzato per calcolare lo zoom (lunghezza dell EarthVector), il bearing (direzione dell EarthVector) e la posizione (firstpoint dell EarthVector) della telecamera della GoogleMap. FOLLOWED_ADD: L AndroidRealAgent avvisa la Activity del fatto che ha richiesto al Server di seguire un Agente. Non vengono compiute operazioni, visto che non abbiamo ancora la posizione dell Agente seguito. Tuttavia viene ricavato dagli Extra il nome dell Agente seguito, in modo tale che sovrascrivendo onfollowedadd potremmo eventualmente visualizzare una notifica a schermo. FOLLOWED_CHANGED: L AndroidRealAgent ci avvisa di aver ricevuto una FollowedUpdate dal Server. Dopo aver ricavato (dagli Extra) il nome dell Agente a cui si riferisce l aggiornamento, il Dave- Receiver deve sostituire nella DaveMap il DaveMarker relativo a tale Agente.

57 4.10 DaveReceiver 53 FOLLOWED_REMOVED: L AndroidRealAgent ci avvisa di aver ricevuto una FollowedExit dal Server. Dopo aver ricavato (dagli Extra) il nome dell Agente del quale la FollowedExit si riferisce, il DaveReceiver deve rimuoverlo dalla DaveMap. Dopo averlo rimosso controlla se l Agente (non più seguito) è però visto da quello locale, in tal caso deve ri-aggiungerlo (verrà colorato diversamente). I metodi che gestiscono tutte le altre action definite nell intentfilter invocano semplicemente il metodo astratto corrispondente. Con AGENT_DEAD l AndroidRealAgent comunica all Activity che sta per terminare la sua esecuzione (ad esempio in seguito ad una eccezione), quindi potremmo decidere di far terminare anche la Activity. Con PRESENTATED l AndroidRealAgent comunica alla Activity che ha mandato il messaggio di presentazione al Server. Infine con SERVER_EXIT l AndroidRealAgent comunica alla Activity di avere ricevuto l ononimo messaggio dal Server.

58 Capitolo 5 Esempio Applicazione Dave Questo capitolo descrive il primo gioco tratto dalla libreria Dave, ovvero DaveTreasureHunt. Si tratta di una caccia al tesoro, nella quale gli Esploratori devono trovare tutti gli oggetti nascosti dal Pirata in una certa area di gioco, prima dello scadere del tempo fissato dal Pirata stesso. Il gioco può essere fruito in diverse modalità a seconda del numero dei giocatori: cooperativo: una squadra di persone collabora per trovare i tesori e sconfiggere così il Pirata (uno solo di questi è l Esploratore, e ha il gioco attivo sul telefono, gli altri lo aiutano) competitivo: gli Esploratori sono persone che cercano individualmente i tesori, cercando di trovarli prima degli altri (e prima dello scadere del tempo) competitivo a squadre: come competitivo, ma ciascun Esploratore ha i propri collaboratori. Verranno in seguito descritte le regole e lo svolgimento del gioco, e come il gioco stesso è stato costruito. 5.1 Le Fasi del gioco Fase di Posizionamento dei Tesori Il giocatore che assumerà il ruolo di Pirata avvierà l Applicazione Dave Treasure Hunt Pirate sul proprio dispositivo Android, immettendo il proprio nome e l indirizzo Ip (pubblico) del PC dove il Main Container di Jade è in esecuzione. A questo punto, mantenendo la connessione 3G attiva, si muoverà nella zona prestabilita per il gioco (una città, un bosco...). Ogni volta che giunge in una posizione nella quale desidera nascondere un tesoro, deve:

59 5.1 Le Fasi del gioco Scrivere su un foglio di carta o un cartoncino un codice alfanumerico da associare all oggetto che si vuole nascondere, e incollarlo all oggetto stesso. 2. Collocare l oggetto nella posizione nascosta scelta. 3. Posizionandosi il più vicino possibile all oggetto appena nascosto, toccare l icona del GamePad nella ActionBar dell applicazione, e scegliere l opzione Place Treasure, fornendo i dati richiesti, ovvero: nome del tesoro (univoco all interno del Container Jade), codice di sblocco (il codice alfanumerico che abbiamo associato all oggetto), e indizio per trovarlo. Lo scopo dell indizio è quello di far giungere gli Esploratori in prossimità di questo tesoro (e non nel punto esatto nel quale è nascosto), e può essere (a discrezione del Pirata, per rendere più o meno difficile il gioco) scritto in forma enigmatica, può essere un indovinello, può essere correlato al ritrovamento di tesori precedenti Una volta inserite queste 3 informazioni, il Pirata può allontanarsi dal tesoro, e verificare che nella mappa è comparso un marcatore di colore giallo nella posizione in cui l ha collocato. Il Pirata procede così fino a mettere un numero adeguato di Tesori sulla mappa. Quando è soddisfatto, torna alla Base, cioè dove si trovano gli altri giocatori, e li avvisa verbalmente che il gioco sta per iniziare. A questo punto il Pirata deve scegliere l opzione Start Game, e impostare la data e l ora di fine del gioco (se nessuno trova tutti i tesori entro quel limite, il Pirata vince) Fase di Ricerca dei Tesori Gli Esploratori che concorrono (o i capitani delle loro squadra/e) avviano l applicazione Dave Treasure Hunt Explorer sul proprio dispositivo Android, e immettono il loro nome (o quello della squadra) e lo stesso indirizzo Ip e Porta immessi precedentemente dal Pirata. A questo punto possono toccare l icona del GamePad, che ha l effetto di ricercare il Pirata. Se il Pirata non ha ancora fatto Start Game, questa operazione fallirà, e verranno fatti nuovi tentativi periodicamente. Non appena il Pirata farà Start Game, l operazione avrà successo, e l Esploratore entrerà nel gioco. Gli Esploratori possono entrare nel gioco in momenti arbitrari, purchè nessuno degli altri Esploratori abbia già vinto e il tempo limite non sia già stato superato (ovviamente arrivando in ritardo si è comunque svantaggiati). Quando un Esploratore è in partita ha a disposizione la lista dei Tesori nascosti dal pirata (la trova nel menu accessibile toccando l icona del GamePad), e per ciascuno può accedere all indizio che gli consente di avvicinarsi ad esso. Una volta giunto in prossimità del tesoro (ovvero nel luogo in cui l indizio porta, se interpretato correttamente), l Esploratore dovrebbe vedere il marcatore

60 5.2 Gli Agenti di DaveTreasureHunt 56 giallo del tesoro sulla mappa della propria applicazione. Una volta giunto sul posto indicato dal marcatore, l Esploratore cerca il tesoro guardando nei possibili nascondigli locali. Quando l avrà trovato, l Esploratore dovrà leggere il codice di sblocco sul tesoro stesso, e selezionare l opzione UNBLOCK dal menu contestuale del tesoro. Se il codice inserito è quello corretto, arriverà una notifica di successo, e il tesoro stesso scomparirà dalla mappa. Nel caso il gioco sia cooperativo, il tesoro trovato può essere raccolto e portato con sè nelle successive ricerche, in caso invece che ci siano altri Esploratori (o altre Squadre), il tesoro va rimesso esattamente dove lo si ha trovato, nascosto nello stesso modo (è il Pirata che alla fine del gioco raccoglie tutti i tesori e controlla che nessuno abbia barato) Fine del Gioco Il gioco può terminare per uno dei seguenti motivi: Il Pirata annulla il gioco dalla propria applicazione. Gli esploratori possono attendere la creazione di una nuova partita Il tempo limite fissato all inizio del gioco viene superato, in questo caso il Pirata vince. Gli esploratori possono comunque continuare le proprie ricerche fino a quando il Pirata non annulla il gioco. Uno degli Esploratori ha trovato tutti i tesori nascosti dal Pirata. In questo caso il Pirata e tutti gli altri Esploratori perdono. Gli Esploratori che hanno perso possono comunque continuare le proprie ricerche, fino a quando il Pirata non annulla il gioco. Il fatto che un Esploratore, o tutti quelli presenti, decidano di abbandonare il gioco, non comporta il termine dello stesso. Infatti finchè il tempo limite non viene superato, altri Esploratori possono entrare in partita. 5.2 Gli Agenti di DaveTreasureHunt TreasureAgent Questo Agente rappresenta 1 singolo Tesoro di quelli nascosti dal Pirata, ed è un FixedAgent, visto che il Tesoro rimane fermo nella posizione in cui era il Pirata quando l ha creato, per tutta la durata del gioco. Si aspetta di ricevere come arguments[0] un oggetto che sia instanceof TreasureAgentArguments, nel quale vengono specificati, tra le altre cose, l indizio e l unblock code associati al Tesoro, e l AID del Pirata. La sua struttura interna è molto semplice, visto che consiste in un unico Behaviour che ha il compito di ricevere e gestire messaggi contenenti una di queste AgentAction:

61 5.2 Gli Agenti di DaveTreasureHunt 57 HintRequest: Uno degli Esploratori ha richiesto l indizio associato al Tesoro. La risposta viene fornita al mittente tramite la AgentAction HintResponse. Unblock: Uno degli Esploratori ha inviato un codice di sblocco. Tale codice deve essere confrontato con quello esatto. Il TreasureAgent deve mandare una AgentAction UnblockDone al Pirata in caso di successo, oppure una UnblockFailed all Esploratore in caso di fallimento. GameCanceled: il Pirata ha deciso di annullare il gioco (questo può succedere sia prima dell inizio, sia durante il gioco, sia dopo la fine dello stesso), comportando il dodelete() di tutti i Tesori ExplorerAgent Questo Agente ha una struttura più complessa rispetto al TreasureAgent, poichè deve interagire sia con il Pirata, sia con i Tesori, sia con la Activity (e quindi con l Utente Android Stesso). Non ha bisogno di argomenti in ingresso aggiuntivi, vengono utilizzati quelli della superclasse (estende AndroidRealAgent). Di seguito entro nel merito di ciascuna di queste interazioni: L ExplorerAgent possiede alcuni metodi pubblici (startgame, unblock, askhint e askremainingtime) che la Activity può invocare e rendere disponibili all Utente Android attraverso la propria interfaccia grafica (in particolare sono tutte le azioni che si possono compiere dal menu identificato dall icona GamePad e dai suoi sottomenu). Per quanto riguarda la comunicazione nel senso opposto, l Agente può visualizzare o cambiare informazioni sull interfaccia grafica mandando all Activity degli Intent con un determinato tipo e i corrispondenti Extra. L ExplorerAgent conosce l AID di tutti i tesori che deve cercare (la lista dei tesori è fornita dal Pirata). Ogni volta che la Activity invoca askhint(aid), questo Agente manda un messaggio al tesoro corrispondente, contenente la AgentAction HintRequest. I messaggi in arrivo (dai Tesori o dal Pirata) vengono catturati e gestiti, come per gli altri Agenti finora visti, tramite un apposito Behaviour (quindi in particolare viene catturato il messaggio contenente la HintResponse). L altro tipo di interazione con i Tesori è tentare di sbloccarli mandando una Unblock, in questo caso l ExplorerAgent non si aspetta una risposta da parte del Tesoro (a meno che lo sbloccaggio fallisca), ma dal Pirata. Quando la Activity invoca il metodo startgame, l ExplorerAgent aggiunge a se stesso un Behaviour (PirateFinderBehaviour), che ha lo scopo di effettuare una ricerca periodica di un Agente che fornisca il

62 5.2 Gli Agenti di DaveTreasureHunt 58 servizio di Pirata e che abbia già avviato la partita (tutti i tesori siano già stati collocati, e il tempo limite sia già stato impostato). Il Behaviour terminerà la propria esecuzione quando la ricerca avrà successo, dopo aver mandato una JoinGameRequest al Pirata, così da entrare nella partita e ricevere dal Pirata la lista dei tesori da cercare (JoinGameResponse). L ExplorerAgent può interagire direttamente con il Pirata chiedendogli il tempo mancante alla fine del gioco (Time- Request), che viene mantenuto e restituito (TimeResponse) dal Pirata, per evitare eventuali differenze tra gli orologi dei vari ExplorerAgent. Gli ExplorerAgent possono ricevere dal Pirata messaggi relativi ai loro successi nello sbloccaggio dei Tesori, e un ulteriore messaggio alla fine della partita, il cui contenuto dipende dall esito della stessa (GameWin, GameLost, GameCanceled) PirateAgent Questo Agente svolge sia il ruolo di Pirata (nasconde i tesori), sia il ruolo di Server (accoglie e mantiene informazioni dei vari ExplorerAgent durante la partita). Il Servizio che questo Agente offre, PirateService, viene registrato al DF per permettere ai vari ExplorerAgent di trovarlo. Di questo Agente è stata fatta sia una versione per Android, sia per PC. Siccome Java non permette l ereditarietà multipla (AndroidPirateAgent estende già AndroidRealAgent, quindi non posso costruire un altra classe base con le operazioni comuni), il codice di questi due Agenti (Pirata per PC e Pirata per Android) si riduce ad un copia-incolla. Per ridurre il problema della doppia manutenzione, alcune parti imporanti, tra cui GameBehaviour (il Behaviour principale di AndroidPirateAgent e PcPirateAgent) sono stati isolati in classi a sè stanti. GameBehaviour riceve i messaggi da parte degli Explorer e dei Treasure e li gestisce in modo appropriato: JoinGameRequest: è inviato da un Explorer, quando vuole unirsi alla partita. Viene controllato che realmente sia un Explorer (e non un Treasure), che non stia già partecipando alla partita, e che quest ultima sia già iniziata ma non ancora finita. Se uno di questi controlli fallisce, viene mandata una JoinGameRefuse al mittente del messaggio. Altrimenti la struttura dati del Pirata (GameStorage) viene aggiornata con i dati del nuovo Explorer, e viene risposto all Explorer con una Join- GameResponse, nella quale è presente la lista dei tesori (che il Pirata conserva all interno del GameStorage). UnblockDone: viene inviato da un Treasure quando un Explorer è riuscito a sbloccarlo. L AID del Tesoro è il mittente del messaggio, mentre l AID dell Explorer è contenuto all interno dell UnblockDone. Anche in questo caso vengono fatti alcuni controlli di validità, che se non superati fanno sì che il messaggio venga ignorato. Il GameStorage viene

63 5.3 GameStorage 59 aggiornato (in seguito vedremo come), e l Explorer viene avvisato con un UnblockConfirm del successo dell operazione. Inoltre se quel tesoro era l ultimo che mancava a tale Explorer (ovvero con quello li ha sbloccati tutti), allora è il vincitore. In questo caso il Pirata manda un GameWin a costui, e un GameLost a tutti gli altri Explorer. Anche il Pirata stesso ha perso in questo caso, quindi deve mandare un Intent appropriato alla propria Activity. TimeRequest: uno degli Explorer ha richiesto il tempo rimanente alla fine del gioco. Viene calcolata la differenza tra il tempo limite del gioco e il currenttimemillis, e inclusa in un messaggio TimeResponse, spedito come risposta al mittente. ExplorerExit: uno degli Explorer vuole abbandonare il gioco. Tale Explorer e tutti i dati riferiti a quest ultimo vengono rimossi dal Game- Storage. L altro Behaviour di cui dispone il Pirata è il TimerBehaviour, che viene innescato solo una volta, al raggiungimento del tempo limite fissato all inizio del gioco. Il suo compito è sancire la vittoria del Pirata, ovvero mandare un GameLost a tutti gli Explorer, e un Intent alla activity del Pirata così da visualizzare la notifica della propria vittoria. 5.3 GameStorage Questa struttura dati è mantenuta dal Pirata, e contiene tutte le informazioni relative: allo stato del gioco, ovvero se è iniziato e/o è finito (informazioni booleane), qual è il tempo limite (in millisecondi), e se è finito chi è l eventuale vincitore (l Explorer che ha trovato tutti i tesori). Come informazione aggiuntiva abbiamo il tempo mancante alla fine della partita, ricavabile dal tempo limite e da quello corrente. Quando GameStorage viene creato il gioco non è iniziato e neanche finito. Per iniziare il gioco si deve invocare il metodo startgame(long endtime), che imposta gamestarted a true dopo aver controllato che non lo era già, e che l endtime fornito sia nel futuro. Per terminare il gioco si deve invocare stopgame(aid winneraid), dove si può fornire l AID dell Explorer che ha trovato tutti i tesori, oppure null per indicare che è il Pirata ad aver vinto. Lo stesso oggetto GameStorage si può riutilizzare per un altra partita, usufruendo del metodo reset() che ripristina l oggetto così com era dopo essere stato costruito. ai tesori, ovvero viene mantenuta la lista degli AID dei TreasureAgent che il Pirata ha creato. Con questa lista possiamo:

64 5.4 Screenshot del Gioco 60 aggiungere nuovi tesori (nella prima fase del gioco) copiarla dentro un ACLMessage e spedirla agli Explorer (nella seconda fase del gioco) spedire GameCanceled ai TreasureAgent stabilire se un determinato AID corrisponde ad uno dei Tesori oppure no, con il metodo istreasure(aid) usare il puntatore alla lista all interno di ExplorerMatrix, per mantenere i punteggi. agli esploratori, all interno di una ulteriore struttura dati (ExplorerMatrix) contenuta dentro GameStorage stesso. GameStorage può interrogare ExplorerMatrix per sapere se un determinato AID corrisponde ad uno degli Explorer che stanno attualmente partecipando alla partita, con il metodo isplayer(aid) ExplorerMatrix L ExplorerMatrix ha una struttura molto simile alla ClientMatrix, ovvero possiede un oggetto di classe ExplorerRecord per ciascuno dei partecipanti alla partita. Questi ExplorerRecord possono essere aggiunti, rimossi o selezionati dalla lista (con i relativi metodi di ExplorerMatrix), rispettivamente quando un Explorer entra nel gioco, esce dal gioco o trova un Tesoro ExplorerRecord In questa classe vengono mantenute tutte le informazioni riguardanti un singolo Explorer B che sta partecipando al gioco, ovvero il suo AID, e i punteggi (incapsulati in un oggetto di classe Scores) ottenuti durante la partita stessa. Dentro Scores viene memorizzata una informazione booleana trovato per ciascuno dei Tesori nascosti dal Pirata, in questo modo è possibile: verificare se B ha trovato tutti i tesori (ovvero se tutti i flag sono true). verificare, dato un tesoro T, se B ha già trovato T oppure no. gestire l operazione B ora ha trovato T, impostando a true l opportuno flag trovato. 5.4 Screenshot del Gioco Nelle pagine successive verranno esposte alcune delle schemate facenti parte delle applicazioni Pirate ed Explorer che costituiscono il gioco.

65 5.4 Screenshot del Gioco 61 (a) Dati per Creazione Agente. (b) Schermata di Attesa Iniziale. (c) Azioni Pirata. (d) Inserimento Nome del Nuovo Tesoro. Figura 5.1: Alcuni Screenshot della Applicazione Pirate

66 5.4 Screenshot del Gioco 62 (a) Indizio per trovare il Tesoro. (b) Tesoro Posizionato Correttamente. (c) Inserimento Data Fine Gioco. (d) Inserimento Ora Fine Gioco. Figura 5.2: Alcuni Screenshot della Applicazione Pirate

67 5.4 Screenshot del Gioco 63 (a) Messaggio di Inizio Ricerca Pirata. (b) Messaggio di Benvenuto in Partita. (c) Azioni Esploratore. (d) Menu Tesori. Figura 5.3: Alcuni Screenshot della Applicazione Explorer

Introduzione a JADE. Francesco Di Giunta

Introduzione a JADE. Francesco Di Giunta Introduzione a JADE Francesco Di Giunta SOMMARIO Introduzione Architettura generale di un sistema multiagente (MAS) in JADE Architettura e implementazione di un agente JADE Comunicazione e interazione

Dettagli

Programmazione in ambiente

Programmazione in ambiente Università Politecnica delle Marche Dipartimento di Ingegneria dell Informazione Programmazione in ambiente Android Laura Montanini - laura.montanini@univpm.it Corso di Tecnologie per le TLC 2013-2014

Dettagli

ANDROID 4.2 JELLY BEAN Installazione e configurazione dell ambiente

ANDROID 4.2 JELLY BEAN Installazione e configurazione dell ambiente INTRODUZIONE Per sviluppare applicazioni in grado di girare su sistemi Android servono tre cose: il Java JDK (Java Development Kit), che contiene tutti gli strumenti necessari a sviluppare nel linguaggio

Dettagli

La geolocalizzazione

La geolocalizzazione La geolocalizzazione La maggior parte dei dispositivi mobili di ultima generazione è dotata di un antenna GPS che permette di conoscere, in breve tempo e con la precisione di qualche metro, la propria

Dettagli

L ambiente di sviluppo Android Studio

L ambiente di sviluppo Android Studio L ambiente di sviluppo Android Studio Android Studio è un ambiente di sviluppo integrato (IDE, Integrated Development Environment) per la programmazione di app con Android. È un alternativa all utilizzo

Dettagli

[AD.AGIO] ANDROID SDK

[AD.AGIO] ANDROID SDK [AD.AGIO] ANDROID SDK 2013.06 Pag. 1 1. PREMESSA Il presente documento riporta informazioni riservate il cui utilizzo è confidenziale e permesso esclusivamente nell'ambito del rapporto di fornitura in

Dettagli

Lezione 3 Le attività

Lezione 3 Le attività A cura di Carlo Pelliccia Le applicazioni Android, come si è accennato durante la prima lezione, si compongono di quattro mattoni fondamentali: le attività (activity), i servizi (service), i broadcast

Dettagli

MOBILE WEB DESIGN TUTORIAL ANDROID METAIO AUGMENTED REALITY

MOBILE WEB DESIGN TUTORIAL ANDROID METAIO AUGMENTED REALITY MOBILE WEB DESIGN TUTORIAL ANDROID METAIO AUGMENTED REALITY 1 Sommario 1. INTRODUZIONE... 3 2. GET METAIO... 4 2.1. PREREQUISITI... 4 2.2. INTALLAZIONE... 4 2.3. PROGETTI ESEMPLIFICATIVI... 4 3. USARE

Dettagli

SimpleFeedReader App

SimpleFeedReader App SimpleFeedReader App Realizzazione di un semplice feed reader Android. Introduzione Programmiamo una semplice applicazione Android. La nostra applicazione dovrà essere in grado di scaricare un feed RSS

Dettagli

Sistemi Mobili e Wireless Android Primi passi

Sistemi Mobili e Wireless Android Primi passi Sistemi Mobili e Wireless Android Primi passi Stefano Burigat Dipartimento di Matematica e Informatica Università di Udine www.dimi.uniud.it/burigat stefano.burigat@uniud.it Ambiente di sviluppo L'ambiente

Dettagli

Caratteristiche principali. la struttura open source (escluse alcune versioni intermedie) il suo basarsi su kernel Linux.

Caratteristiche principali. la struttura open source (escluse alcune versioni intermedie) il suo basarsi su kernel Linux. Android s.o. Androidè un sistema operativo per dispositivi mobili costituito da uno stack software che include: un sistema operativo di base, i middleware per le comunicazioni le applicazioni di base.

Dettagli

La prima applicazione Java con NetBeans IDE. Dott. Ing. M. Banci, PhD

La prima applicazione Java con NetBeans IDE. Dott. Ing. M. Banci, PhD La prima applicazione Java con NetBeans IDE Dott. Ing. M. Banci, PhD Creare la prima applicazione 1. Creare un progetto: Quando si crea un progetto IDE occorre creare un ambiente nel quale costruire e

Dettagli

QUEUE : considerazioni. QUEUE : considerazioni. QUEUE : esempio. QUEUE : esempio

QUEUE : considerazioni. QUEUE : considerazioni. QUEUE : esempio. QUEUE : esempio QUEUE : considerazioni QUEUE : considerazioni Si è realizzata una struttura dati complessa utilizzandone una primitiva, l array. Il pregio di tale implementazione è il basso costo computazionale, mentre

Dettagli

MagiCum S.r.l. Progetto Inno-School

MagiCum S.r.l. Progetto Inno-School MagiCum S.r.l. Progetto Inno-School Area Sviluppo Software Autore: Sergio Gandola Revisione: 2 Data: 07/06/13 Titolo: Documentazione Tecnica Diario File:Documentazione Tecnica.pdf Sito: http://inno-school.netsons.org/

Dettagli

Java Agent DEvelopment Framework. Jade è una piattaforma per la realizzazione di sistemi distribuiti multi-agente

Java Agent DEvelopment Framework. Jade è una piattaforma per la realizzazione di sistemi distribuiti multi-agente JADE Java Agent DEvelopment Framework Cos è JADE Jade è una piattaforma per la realizzazione di sistemi distribuiti multi-agente E interamente realizzato in Java da Telecom Italia Lab. Può essere scaricato

Dettagli

Tecniche di progettazione e sviluppo di applicazioni mobile

Tecniche di progettazione e sviluppo di applicazioni mobile Slide del corso FSE Tecniche di progettazione e sviluppo di applicazioni mobile svolto presso AREA Science Park Padriciano - Trieste - Italy diegozabot@yahoo.it Android Introduzione diegozabot@yahoo.it

Dettagli

Indice: Introduzione 1 Strumenti di lavoro 2 Istallare Eclipse e SDK 3 Istallare l ADT in eclipse 4. Powered by: Vincenzo Acinapura

Indice: Introduzione 1 Strumenti di lavoro 2 Istallare Eclipse e SDK 3 Istallare l ADT in eclipse 4. Powered by: Vincenzo Acinapura Indice: Introduzione 1 Strumenti di lavoro 2 Istallare Eclipse e SDK 3 Istallare l ADT in eclipse 4 Introduzione Salve a tuttiù Mi presento mi chiamo Vincenzo Acinapura e studio ingegneria informatica,

Dettagli

Tale attività non è descritta in questa dispensa

Tale attività non è descritta in questa dispensa Fondamenti di informatica Oggetti e Java ottobre 2014 1 Nota preliminare L installazione e l uso di Eclipse richiede di aver preliminarmente installato Java SE SDK Tale attività non è descritta in questa

Dettagli

Activation In sintesi: è inutile avere attivi degli oggetti se non vengono utilizzati

Activation In sintesi: è inutile avere attivi degli oggetti se non vengono utilizzati Activation In generale i Sistemi ad oggetti distribuiti sono progettati per lavorare con oggetti persistenti. Dato che questi sistemi saranno composti da migliaia (forse milioni) di tali oggetti, sarebbe

Dettagli

Strumenti per lo sviluppo del software

Strumenti per lo sviluppo del software Lo sviluppo del software Strumenti per lo sviluppo del software Lo sviluppo del software è l attività centrale del progetto e ha lo scopo di produrre il codice sorgente che, una volta compilato e messo

Dettagli

Guida all uso dell ambiente di sviluppo 1 integrato o IDE. JCreator LE 4.50

Guida all uso dell ambiente di sviluppo 1 integrato o IDE. JCreator LE 4.50 Guida all uso dell ambiente di sviluppo 1 integrato o IDE JCreator LE 4.50 Inizializzazione: creazione del nuovo progetto e del file sorgente in ambiente JCreator Al lancio del programma si apre la finestra

Dettagli

Sviluppo di un applicazione mobile per la gestione degli interventi tecnici tramite geolocalizzazione

Sviluppo di un applicazione mobile per la gestione degli interventi tecnici tramite geolocalizzazione UNIVERSITA DEGLI STUDI DI FERRARA Corso di Laurea in informatica Anno Accademico 2011-2012 Sviluppo di un applicazione mobile per la gestione degli interventi tecnici tramite geolocalizzazione Relatore:

Dettagli

INDICE. DATEX il manuale edizione aprile 2011

INDICE. DATEX il manuale edizione aprile 2011 DATEX MANUALE INDICE INDICE... 1 INTRODUZIONE... 2 PRINCIPALI CARATTERISTICHE... 3 IL PRIMO COLLEGAMENTO... 4 INTERFACCIA... 5 DEFINIZIONE DELLE OPERAZIONI E DEI PROFILI... 6 INGRESSO CON PASSWORD NEL

Dettagli

Corso Eclipse. Prerequisiti. 1 Introduzione

Corso Eclipse. Prerequisiti. 1 Introduzione Corso Eclipse 1 Introduzione 1 Prerequisiti Uso elementare del pc Esecuzione ricerche su Internet Esecuzione download Conoscenza elementare della programmazione 2 1 Cos è Eclipse Eclipse è un IDE (Integrated

Dettagli

Pannello controllo Web www.smsdaweb.com. Il Manuale

Pannello controllo Web www.smsdaweb.com. Il Manuale Pannello controllo Web www.smsdaweb.com Il Manuale Accesso alla piattaforma Accesso all area di spedizione del programma smsdaweb.com avviene tramite ingresso nel sistema via web come se una qualsiasi

Dettagli

Android. Android. Sviluppo di applicazioni. Dalvik 19/03/2011. A. Ferrari

Android. Android. Sviluppo di applicazioni. Dalvik 19/03/2011. A. Ferrari Android Android A. Ferrari Android è un sistema opera8vo per disposi8vi mobili. Inizialmente sviluppato da Startup Android Inc. acquisita poi nel 2005 da Google Inc. Il cuore di Android è un kernel Linux.

Dettagli

Concetti Base Eccezioni Eccezioni e Metodi Gerarchia di Eccezioni. Java: Eccezioni. Damiano Macedonio

Concetti Base Eccezioni Eccezioni e Metodi Gerarchia di Eccezioni. Java: Eccezioni. Damiano Macedonio Dipartimento di Informatica, Università degli Studi di Verona Corso di Programmazione per Bioformatica lezione del 30 maggio 2014 Introduzione Un programma diviso in sezioni distinte Un approccio alla

Dettagli

BIMPublisher Manuale Tecnico

BIMPublisher Manuale Tecnico Manuale Tecnico Sommario 1 Cos è BIMPublisher...3 2 BIM Services Console...4 3 Installazione e prima configurazione...5 3.1 Configurazione...5 3.2 File di amministrazione...7 3.3 Database...7 3.4 Altre

Dettagli

Migrazione di HRD da un computer ad un altro

Migrazione di HRD da un computer ad un altro HRD : MIGRAZIONE DA UN VECCHIO PC A QUELLO NUOVO By Rick iw1awh Speso la situazione è la seguente : Ho passato diverso tempo a impostare HRD e a personalizzare i comandi verso la radio, le frequenze preferite,

Dettagli

Android development. Sviluppo di Mobile Apps sul sistema operativo di Google

Android development. Sviluppo di Mobile Apps sul sistema operativo di Google Android development Sviluppo di Mobile Apps sul sistema operativo di Google Agenda Giorni: Gio 14/04/2011 Ven 15/04/2011 Gio 21/04/2011 Ven 22/04/2011 Suddivisione: Mattina: teoria Pomeriggio: pratica

Dettagli

Ciclo di vita delle aevità Android Mobile Programming Prof. R. De Prisco

Ciclo di vita delle aevità Android Mobile Programming Prof. R. De Prisco Ciclo di vita delle aevità Ogni AcHvity ha dei metodi standard A(vità non esiste 1. oncreate() 2. onstart() 3. onresume() A(vità in esecuzione 4. onpause() 5. onstop() 6. ondestroy() A(vità non esiste

Dettagli

Sistemi Mobili e Wireless Android Activity

Sistemi Mobili e Wireless Android Activity Sistemi Mobili e Wireless Android Activity Stefano Burigat Dipartimento di Matematica e Informatica Università di Udine www.dimi.uniud.it/burigat stefano.burigat@uniud.it Activity Tipicamente, un'activity

Dettagli

PROGETTO DI UN MIDDLEWARE PER L ACCESSO REMOTO A UN REPOSITORY

PROGETTO DI UN MIDDLEWARE PER L ACCESSO REMOTO A UN REPOSITORY Giampiero Allamprese 0000260193 PROGETTO DI UN MIDDLEWARE PER L ACCESSO REMOTO A UN REPOSITORY Reti di Calcolatori LS prof. Antonio Corradi A.A. 2007/2008 ABSTRACT L obiettivo di questo progetto è la realizzazione

Dettagli

Gestione delle eccezioni in Java

Gestione delle eccezioni in Java Gestione delle eccezioni in Java - Introduzione al concetto di eccezioni E possibile definire un eccezione come un situazione imprevista che il flusso di un applicazione può incontrare. È possibile gestire

Dettagli

Laurea Specialistica in Informatica, Tecnologie Informatiche Anno Accademico 2008/2009 Reti Applicazioni e Servizi

Laurea Specialistica in Informatica, Tecnologie Informatiche Anno Accademico 2008/2009 Reti Applicazioni e Servizi Laurea Specialistica in Informatica, Tecnologie Informatiche Anno Accademico 2008/2009 Reti Applicazioni e Servizi Implementazione di una MIDlet che realizza un sistema di voto Christian Tiralosi Sviluppatori:

Dettagli

Corso di programmazione di sistemi mobile 1. Android. Google Cloud Messaging

Corso di programmazione di sistemi mobile 1. Android. Google Cloud Messaging Corso di programmazione di sistemi mobile 1 Android Google Cloud Messaging Corso di programmazione di sistemi mobile 2 Cos è Il Google Cloud Messaging o GCM è un servizio di Google che permette di inviare

Dettagli

Esercitazione n 4. Obiettivi

Esercitazione n 4. Obiettivi Esercitazione n 4 Obiettivi Progettare e implementare per intero un componente software in Java Linguaggio Java: Classi astratte Utilizzo di costruttori e metodi di superclasse Polimorfismo Esempio guida:

Dettagli

Synchronized (ancora)

Synchronized (ancora) Synchronized (ancora) Riscriviamo l esempio di prima. Usiamo una struttura modulare, con una classe Notificatore che ha opportuni metodi. La classe ha due campi privati, la lista buftext e un suo thread.

Dettagli

19. Introduzione al multi-threading

19. Introduzione al multi-threading 19. Introduzione al multi-threading Marco Faella Dip. Ing. Elettrica e Tecnologie dell'informazione Università di Napoli Federico II Corso di Linguaggi di Programmazione II I thread I thread, o processi

Dettagli

ARGO PRESENZE LEGGIMI DEGLI AGGIORNAMENTI. Argo Presenze. Leggimi Aggiornamento 3.2.0. Data Pubblicazione 15-10-2013.

ARGO PRESENZE LEGGIMI DEGLI AGGIORNAMENTI. Argo Presenze. Leggimi Aggiornamento 3.2.0. Data Pubblicazione 15-10-2013. Argo Presenze Leggimi Aggiornamento 3.2.0 Data Pubblicazione 15-10-2013 Pagina 1 di 18 Aggiornamento 3.2.0 Variazioni Con la release 3.2.0 viene introdotto un nuovo driver per lo scarico delle transazioni

Dettagli

Configurare TPTP in Eclipse e testare un applicazione

Configurare TPTP in Eclipse e testare un applicazione Configurare TPTP in Eclipse e testare un applicazione Questa guida concentra la sua attenzione sul tool TPTP (Test & Performance Tools Platform) presente nell ambiente di sviluppo Eclipse. Verrà descritta

Dettagli

20 - Input/Output su File

20 - Input/Output su File 20 - Input/Output su File Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo Dipartimento di Informatica, Università di Pisa http://www.di.unipi.it/ milazzo milazzo di.unipi.it

Dettagli

Funzioni principali di Dropbox

Funzioni principali di Dropbox ICT Rete Lecco Generazione Web - Progetto FARO Dropbox "Un luogo per tutti i tuoi file, ovunque ti trovi" Dropbox è il servizio di cloud storage più popolare, uno tra i primi a fare la sua comparsa nel

Dettagli

Gestione di errori e situazioni eccezionali. Gestione delle eccezioni. Gestione tradizionale di errori e situazioni eccezionali (2)

Gestione di errori e situazioni eccezionali. Gestione delle eccezioni. Gestione tradizionale di errori e situazioni eccezionali (2) Gestione di errori e situazioni eccezionali Gestione delle eccezioni Una procedura (utente o di libreria) deve poter segnalare l impossibilità di produrre un risultato significativo o la propria terminazione

Dettagli

SMS-GPS MANAGER. Software per la gestione remota ed automatizzata dei telecontrolli gsm con e senza gps

SMS-GPS MANAGER. Software per la gestione remota ed automatizzata dei telecontrolli gsm con e senza gps SOFTWARE PER LA GESTIONE DEI TELECONTROLLI SMS-GPS MANAGER Software per la gestione remota ed automatizzata dei telecontrolli gsm con e senza gps Rev.1009 Pag.1 di 10 www.carrideo.it INDICE 1. DESCRIZIONE

Dettagli

TESTARE E CREARE APPLICAZIONI TESTUALI JAVA PER ANDROID CON ANDROID

TESTARE E CREARE APPLICAZIONI TESTUALI JAVA PER ANDROID CON ANDROID TESTARE E CREARE APPLICAZIONI TESTUALI JAVA PER ANDROID CON ANDROID Ho deciso di scrivere questa guida per tre motivi principali: 1) Avendo un tablet che ha la possibilità di essere usato per programmare,

Dettagli

Lezione 3 Le attività

Lezione 3 Le attività A cura di Carlo Pelliccia Le applicazioni Android, come si è accennato durante la prima lezione, si compongono di quattro mattoni fondamentali: le attività (activity), i servizi (service), i broadcast

Dettagli

Blue s One CTI Enterpris Blue s Attendant Pro/Enterprise SDK - plugin creating tools

Blue s One CTI Enterpris Blue s Attendant Pro/Enterprise SDK - plugin creating tools Blue s One CTI Enterpris Blue s Attendant Pro/Enterprise SDK - plugin creating tools rel. 1.2 ITA 01-06-2012 Introduzione alla creazione del plug-in Questo documento ha lo scopo di illustrare come creare

Dettagli

Prova d Esame 07.04.2006 Compito B

Prova d Esame 07.04.2006 Compito B DOMANDA 1 (6 punti) Si analizzi il codice seguente e si scriva l output prodotto dai metodi main public class General { public static String s1 = "ciao"; protected int n; public General() { n = 3; public

Dettagli

CAPITOLO 27 SCAMBIO DI MESSAGGI

CAPITOLO 27 SCAMBIO DI MESSAGGI CAPITOLO 27 SCAMBIO DI MESSAGGI SCAMBIO DI MESSAGGI Sia che si guardi al microkernel, sia a SMP, sia ai sistemi distribuiti, Quando i processi interagiscono fra loro, devono soddisfare due requisiti fondamentali:

Dettagli

Programmazione Android A cura di Carlo Pelliccia. Lezione 7 Menù

Programmazione Android A cura di Carlo Pelliccia. Lezione 7 Menù A cura di Carlo Pelliccia I menù sono una parte importante di qualsiasi applicazione moderna. Da anni gli utenti sono abituati ad avere a che fare con questi strumenti, ai quali si rivolgono ogni volta

Dettagli

SISTEMI OPERATIVI. Sincronizzazione dei processi. Domande di verifica. Luca Orrù Centro Multimediale Montiferru 30/05/2007

SISTEMI OPERATIVI. Sincronizzazione dei processi. Domande di verifica. Luca Orrù Centro Multimediale Montiferru 30/05/2007 2007 SISTEMI OPERATIVI Sincronizzazione dei processi Domande di verifica Luca Orrù Centro Multimediale Montiferru 30/05/2007 Sincronizzazione dei processi 1. Si descrivano i tipi di interazione tra processi?

Dettagli

SOFTWARE GESTIONE SMS DA INTERFACCE CL MANUALE D INSTALLAZIONE ED USO

SOFTWARE GESTIONE SMS DA INTERFACCE CL MANUALE D INSTALLAZIONE ED USO CLSMS SOFTWARE GESTIONE SMS DA INTERFACCE CL MANUALE D INSTALLAZIONE ED USO Sommario e introduzione CLSMS SOMMARIO INSTALLAZIONE E CONFIGURAZIONE... 3 Parametri di configurazione... 4 Attivazione Software...

Dettagli

Fondamenti di Informatica T-1 CdS Ingegneria Informatica a.a. 2011/2012. Introduzione a Visual Studio 2005/2008/2010

Fondamenti di Informatica T-1 CdS Ingegneria Informatica a.a. 2011/2012. Introduzione a Visual Studio 2005/2008/2010 Fondamenti di Informatica T-1 CdS Ingegneria Informatica a.a. 2011/2012 Introduzione a Visual Studio 2005/2008/2010 1 Outline Solution e Project Visual Studio e linguaggio C Visual Studio schermata principale

Dettagli

Introduzione alla programmazione in Java

Introduzione alla programmazione in Java Introduzione alla programmazione in Java 1 Programmare ad oggetti La programmazione come attività di creazione di modelli. I concetti di classe, oggetto e scambio di messaggi. Un primo esempio di programma

Dettagli

Android. Android03: Ciclo di vita di una Activity. diegozabot@yahoo.it

Android. Android03: Ciclo di vita di una Activity. diegozabot@yahoo.it Android Android03: Ciclo di vita di una Activity diegozabot@yahoo.it Ciclo di vita Ciclo di vita La classe Activity gestisce i propri stati definendo una serie di eventi che ne governano il ciclo. Spetta

Dettagli

Lezione 11 Accesso al file system

Lezione 11 Accesso al file system A cura di Carlo Pelliccia Qualunque applicazione Android può leggere e scrivere file dalla memoria interna del telefono o da una scheda esterna inserita nel dispositivo. I principi da osservare per compiere

Dettagli

Servers Activatable. Massimo Merro Programmazione di Rete 166 / 193

Servers Activatable. Massimo Merro Programmazione di Rete 166 / 193 Servers Activatable Nelle lezioni precedenti abbiamo detto che una referenza remota ad un server di tipo UnicastRemoteObject rimane valida finchè il server è in esecuzione. Quando il server termina, o

Dettagli

Lezione 19 Blackberry. Dr. Paolo Casoto, Ph.D - 2012

Lezione 19 Blackberry. Dr. Paolo Casoto, Ph.D - 2012 + Lezione 19 Blackberry + Credits I lucidi di questa lezione sono stati redatti dal Dr. Paolo Casoto nel 2012. Sono rilasciati con licenza Creative Commons Attribuzione, non commerciale e non opere derivate.

Dettagli

Introduzione a Visual Studio 2005

Introduzione a Visual Studio 2005 Fondamenti di Informatica e Laboratorio T-AB Ingengeria Elettronica e Telecomunicazioni a.a. 2008/2009 Introduzione a Visual Studio 2005 Outline Solutions e Projects Visual Studio e il linguaggio C Visual

Dettagli

UN CLONE IN CLIKE C-LIKE DI SEGUIVISIONE

UN CLONE IN CLIKE C-LIKE DI SEGUIVISIONE IDROID 86 LAB pagg 12-13 23-04-2007 14:57 Pagina 12 I-D01 LAB UN CLONE IN CLIKE C-LIKE DI SEGUIVISIONE PROGRAMMAZIONE Alcuni comportamenti predefiniti attivabili su I-Droid01 sono facilmente riproducibili

Dettagli

Lezione 2 Gestione delle risorse

Lezione 2 Gestione delle risorse A cura di Carlo Pelliccia Se c è un aspetto di Android dal quale si evince la modernità di questo sistema, è la sua maniera di gestire le risorse ed i dati. Nelle piattaforme di sviluppo meno moderne,

Dettagli

PRESENTAZIONE di WP-Office

PRESENTAZIONE di WP-Office PRESENTAZIONE di WP-Office WP-Office è uno dei moduli del prodotto WebProfessional ed utilizza il framework di WebProfessional (versione 3.4 e superiori), un concetto indirizzato all integrazione degli

Dettagli

Eclipse. Avviare un progetto e compilare un semplice programma

Eclipse. Avviare un progetto e compilare un semplice programma Eclipse Avviare un progetto e compilare un semplice programma Descrizione di Eclipse Eclipse è un ambiente di sviluppo che facilita la scrittura ed il debug di programmi java Permette di: Scrivere il codice

Dettagli

Android. Anatomia di una applicazione

Android. Anatomia di una applicazione Android Anatomia di una applicazione Elementi di base Gli elementi di base per costruire una applicazione Android sono cinque: Activity Intent Broadcast Receiver Service Content Provider 2 Activity (1/3)

Dettagli

Programmazione Android. Luca Morettoni http://www.morettoni.net

Programmazione Android. Luca Morettoni <luca@morettoni.net> http://www.morettoni.net Programmazione Android Luca Morettoni http://www.morettoni.net Android Programming Cos'è Android; Concetti di base sulla programmazione: Q&A AndroidManifest; Activities; Services;

Dettagli

Corso Android New Edition Corso Online Programmatore Android New Edition

Corso Android New Edition Corso Online Programmatore Android New Edition Corso Android New Edition Corso Online Programmatore Android New Edition Accademia Domani Via Pietro Blaserna, 101-00146 ROMA (RM) info@accademiadomani.it Programma Generale del Corso di Programmatore

Dettagli

Linguaggio Java. Robusto. Orientato agli oggetti. Protegge e gestisce dagli errori. Non permette costrutti pericolosi

Linguaggio Java. Robusto. Orientato agli oggetti. Protegge e gestisce dagli errori. Non permette costrutti pericolosi Linguaggio Java Robusto Non permette costrutti pericolosi Eredità Multipla Gestione della Memoria Orientato agli oggetti Ogni cosa ha un tipo Ogni tipo è un oggetto (quasi) Protegge e gestisce dagli errori

Dettagli

Guida Utente PS Contact Manager GUIDA UTENTE

Guida Utente PS Contact Manager GUIDA UTENTE GUIDA UTENTE Installazione...2 Prima esecuzione...5 Login...7 Registrazione del programma...8 Inserimento clienti...9 Gestione contatti...11 Agenti...15 Archivi di base...16 Installazione in rete...16

Dettagli

Lezione 13 Content Provider

Lezione 13 Content Provider A cura di Carlo Pelliccia Come si è visto nelle due lezioni precedenti, secondi i meccanismi di gestione della sicurezza di Android, sia i file che i database sono solitamente di esclusiva proprietà dell

Dettagli

Sistemi Mobili e Wireless Android Localizzazione utente

Sistemi Mobili e Wireless Android Localizzazione utente Sistemi Mobili e Wireless Android Localizzazione utente Stefano Burigat Dipartimento di Matematica e Informatica Università di Udine www.dimi.uniud.it/burigat stefano.burigat@uniud.it Localizzazione utente

Dettagli

Un Sistema Location-based per la mappatura degli Access Point

Un Sistema Location-based per la mappatura degli Access Point 1 Un Sistema Location-based per la mappatura degli Access Point Pasquale Cautela pasquale.cautela@studio.unibo.it Marco Peca marco.peca@studio.unibo.it Rosario Salpietro rosario.salpietro@studio.unibo.it

Dettagli

Introduzione all uso di Eclipse

Introduzione all uso di Eclipse Introduzione all uso di Eclipse Daniela Micucci Programmazione Outline Eclipse: concetti generali Definire un workspace Creare un project Importare un file Utilizzo 1 Introduzione Eclipse è un ambiente

Dettagli

Laboratorio di Ingegneria del Software A.A 2009/2010 Programmazione su Android A cura di Carlo Pelliccia. Lezione 7 Menù

Laboratorio di Ingegneria del Software A.A 2009/2010 Programmazione su Android A cura di Carlo Pelliccia. Lezione 7 Menù A cura di Carlo Pelliccia I menù sono una parte importante di qualsiasi applicazione moderna. Da anni gli utenti sono abituati ad avere a che fare con il concetto di menù, al quale si rivolgono ogni volta

Dettagli

Lab. Programmazione Sistemi Mobili e Tablets

Lab. Programmazione Sistemi Mobili e Tablets Lab. Programmazione Sistemi Mobili e Tablets Anno Accademico : 2011-2012 Matricola Studente: De Guidi Enrico 156464 Titolo del Progetto: Let s go Data:04/09/12 Introduction: Let s go è un applicazione

Dettagli

Quando si sa chiaramente come si deve comportare l applicazione si può analizzare una possibile soluzione applicativa.

Quando si sa chiaramente come si deve comportare l applicazione si può analizzare una possibile soluzione applicativa. Introduzione alla tecnologia JMX 1 Viene analizzata l architettura sottostante le Java Managment Extensions (JMX) mostrandone un utilizzo applicativo e analizzando altri possibili scenari d uso di Ivan

Dettagli

IL COMPUTER NEL TASCHINO, IL NUOVO MONDO DELLE APP

IL COMPUTER NEL TASCHINO, IL NUOVO MONDO DELLE APP FACOLTÀ DI SCIENZE DELLA COMUNICAZIONE CORSO DI LAUREA IN MANAGEMENT E COMUNICAZIONE D IMPRESA INDIRIZZO PUBBLICITÀ E MARKETING Tesi di laurea in Programmazione e scrittura del web IL COMPUTER NEL TASCHINO,

Dettagli

Un primo programma Java. Introduzione alla programmazione in Java. Programmi e mondo reale. Programmare ad oggetti. I programmi come modelli

Un primo programma Java. Introduzione alla programmazione in Java. Programmi e mondo reale. Programmare ad oggetti. I programmi come modelli 4 Un primo programma Java Introduzione alla programmazione in Java class Program1 { System.out.println("Benvenuti al corso"); 1 5 Programmi e mondo reale Programmare ad oggetti Il codice di un programma

Dettagli

UNIVERSITÀ DEGLI STUDI DI FIRENZE FACOLTA DI INGEGNERIA DIPARTIMENTO DI SISTEMI E INFORMATICA. Elaborato di Tecnologie del Software per Internet

UNIVERSITÀ DEGLI STUDI DI FIRENZE FACOLTA DI INGEGNERIA DIPARTIMENTO DI SISTEMI E INFORMATICA. Elaborato di Tecnologie del Software per Internet UNIVERSITÀ DEGLI STUDI DI FIRENZE FACOLTA DI INGEGNERIA DIPARTIMENTO DI SISTEMI E INFORMATICA Elaborato di Tecnologie del Software per Internet JMSWEB 2 SISTEMA PER LO SCAMBIO DI MESSAGGI TRA APPLICAZIONI

Dettagli

Manuale EacqCE. Versione manuale 3.0.2. Copyright 2011 MMS Srl. Manuale EacqCE Pagina 1

Manuale EacqCE. Versione manuale 3.0.2. Copyright 2011 MMS Srl. Manuale EacqCE Pagina 1 Manuale EacqCE Versione manuale 3.0.2 Copyright 2011 MMS Srl Manuale EacqCE Pagina 1 Sommario Sommario... 2 Informazioni generali... 3 Introduzione... 3 Installazione del programma... 4 Primo avvio del

Dettagli

1 http://desvino.altervista.org JSPDynPage, componenti portale e Java Server Pages

1 http://desvino.altervista.org JSPDynPage, componenti portale e Java Server Pages 1 http://desvino.altervista.org JSPDynPage, componenti portale e Java Server Pages Le JSP DynPages sono un utile strumento, fornito da SAP Netweaver, per una gestione più evoluta di event handling e session

Dettagli

GESTIONE DEI PROCESSI

GESTIONE DEI PROCESSI Sistemi Operativi GESTIONE DEI PROCESSI Processi Concetto di Processo Scheduling di Processi Operazioni su Processi Processi Cooperanti Concetto di Thread Modelli Multithread I thread in Java Concetto

Dettagli

RMI. Java RMI RMI. G. Prencipe prencipe@di.unipi.it

RMI. Java RMI RMI. G. Prencipe prencipe@di.unipi.it Java Remote Method Invocation -- RMI G. Prencipe prencipe@di.unipi.it RMI RMI è una tecnologia JAVA che permette a una JVM di comunicare con un altra JVM per farle eseguire metodi È possibile che oggetti

Dettagli

RECS 101: UN WEB SERVER EMBEDDED PER APPLICAZIONI DI CONTROLLO REMOTO TRAMITE TCP/IP

RECS 101: UN WEB SERVER EMBEDDED PER APPLICAZIONI DI CONTROLLO REMOTO TRAMITE TCP/IP RECS 101: UN WEB SERVER EMBEDDED PER APPLICAZIONI DI CONTROLLO REMOTO TRAMITE TCP/IP seconda parte di Cristian Randieri randieri@intellisystem.it In questa seconda parte della presentazione del dispositivo

Dettagli

Esercizi lezione 7. Esercizio A Progettate un'applicazione Android che consenta di fare una telefonata. Pag. 1/9

Esercizi lezione 7. Esercizio A Progettate un'applicazione Android che consenta di fare una telefonata. Pag. 1/9 Pag. 1/9 Esercizi lezione 7 Esercizio A Progettate un'applicazione Android che consenta di fare una telefonata. Suggerimenti: si può usare un intent e il metodo startactivity(), seguendo il frammento di

Dettagli

Programmazione Fondi Strutturali 2007/2013 P.O.N. FSE A.S. 2013/2014 SCHEDA PROGETTUALE MODULO. Obiettivo: C Azione: 1 Riferimento interno:

Programmazione Fondi Strutturali 2007/2013 P.O.N. FSE A.S. 2013/2014 SCHEDA PROGETTUALE MODULO. Obiettivo: C Azione: 1 Riferimento interno: ISTITUTO ISTRUZIONE SECONDARIA SUPERIORE GUGLIELMO MARCONI Piazza Poerio 2, 70126 Bari - Tel.080-5534450 Fax.080-5559037 - www.marconibari.it - info@marconibari.it Programmazione Fondi Strutturali 2007/2013

Dettagli

Supporto On Line Allegato FAQ

Supporto On Line Allegato FAQ Supporto On Line Allegato FAQ FAQ n.ro MAN-7VS9N245045 Data ultima modifica 08/04/20 Prodotto Tutti Modulo Tutti Oggetto Distribuzione aggiornamenti software in modalità Live Update In giallo sono evidenziate

Dettagli

Configurazione moduli I/O serie EX

Configurazione moduli I/O serie EX Configurazione moduli I/O serie EX aggiornamento: 20-12-2014 IEC-line by OVERDIGIT overdigit.com Tabella dei contenuti 1. Moduli di I/O con protocollo Modbus... 3 1.1. Parametri di comunicazione... 4 1.2.

Dettagli

Università degli Studi di Napoli Federico II. FACOLTÀ DI INGEGNERIA Corso di Laurea in Ingegneria Informatica LM. Progetto di un applicazione Android

Università degli Studi di Napoli Federico II. FACOLTÀ DI INGEGNERIA Corso di Laurea in Ingegneria Informatica LM. Progetto di un applicazione Android Università degli Studi di Napoli Federico II FACOLTÀ DI INGEGNERIA Corso di Laurea in Ingegneria Informatica LM Progetto di un applicazione Android Briscola bluetooth Candidati: Giuliano Formato Daniele

Dettagli

RMI: metodi equals e hashcode

RMI: metodi equals e hashcode RMI: metodi equals e hashcode Per verificare se due oggetti remoti contengono gli stessi dati, la chiamata indirizzata al metodo equals() avrebbe bisogno di contattare i server dove si trovano gli oggetti

Dettagli

Prova d Esame 07.04.2006 Compito A

Prova d Esame 07.04.2006 Compito A DOMANDA 1 (6 punti) Si analizzi il codice seguente e si scriva l output prodotto dai metodi main public class General { public static String s1 = "Ciao"; protected int n; public General() { n = 1; public

Dettagli

Il linguaggio C# Eventi ed eccezioni

Il linguaggio C# Eventi ed eccezioni Tecniche di Programmazione avanzata Corso di Laurea Specialistica in Ingegneria Telematica Università Kore Enna A.A. 2009-2010 Alessandro Longheu http://www.diit.unict.it/users/alongheu alessandro.longheu@diit.unict.it

Dettagli

Scrivere un programma in Java

Scrivere un programma in Java Programmare in JAVA Leonardo Rigutini Dipartimento Ingegneria dell Informazione Università di Siena Via Roma 56 53100 SIENA uff. 0577 234850 - interno: 7102 Stanza 119 rigutini@dii.unisi.it http://www.dii.unisi.it/~rigutini/

Dettagli

SMS-GPS MANAGER. Software per la gestione remota ed automatizzata dei telecontrolli gsm con e senza gps

SMS-GPS MANAGER. Software per la gestione remota ed automatizzata dei telecontrolli gsm con e senza gps SOFTWARE PER LA GESTIONE DEI TELECONTROLLI SMS-GPS MANAGER Software per la gestione remota ed automatizzata dei telecontrolli gsm con e senza gps Rev.0911 Pag.1 di 8 www.carrideo.it INDICE 1. DESCRIZIONE

Dettagli

Basi Android. Android si definisce open. Con8ene tecnologie open source. Il codice di Android è open. Licenza Open Source Apache 2.

Basi Android. Android si definisce open. Con8ene tecnologie open source. Il codice di Android è open. Licenza Open Source Apache 2. Basi Android 1 Android Cosa è Android? Android è un insieme di strumen8 e librerie per sviluppare applicazioni mobili è più di un SO Android si definisce open Con8ene tecnologie open source Linux Il codice

Dettagli

Lezione 15 Location e mappe

Lezione 15 Location e mappe A cura di Carlo Pelliccia La diffusione delle applicazioni location-based è certamente uno dei maggiori contributi resi dalle piattaforme mobili alla storia dell informatica. Un applicazione o un servizio

Dettagli

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP)

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP) 12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP) Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo Dipartimento di Informatica,

Dettagli

Guida all uso. Instant Cloud Platform As A Service

Guida all uso. Instant Cloud Platform As A Service Guida all uso Instant Cloud Platform As A Service Prima edizione maggio 2014 Instant Cloud Platform As A Service Sommario Instant Cloud - Platform As A Service... 4 1 Introduzione... 4 2 Instant Cloud...

Dettagli

Java? Sì, grazie. Scopo del corso

Java? Sì, grazie. Scopo del corso Modulo di Java? Sì, grazie Il linguaggio di Internet? Portabilità su qualunque piattaforma (non solo calcolatori): It works everywhere Supporto e disponibilità di strumenti, librerie e documentazione garantiti

Dettagli