Citation preview
Agostino LORENZI
Andrea RIZZI
PRO.TECH Informatica per Istituti Tecnici Tecnologici
B Linguaggio Java Programmazione ad oggetti Web e applicazioni Android
Ulteriori Contenuti digitali integrativi sono disponibili sul sito della Casa Editrice www.edatlas.it
Agostino LORENZI
Andrea RIZZI
PRO.TECH Informatica per Istituti Tecnici Tecnologici
ATTIVA IL TUO
1
Vai sul sito www.scuolabook.it e ACCEDI con e-mail e password (o iscriviti se è la prima volta che usi la piattaforma). TITOLO
3
Inserisci il codice COUPON che trovi sul bollino bianco in questa pagina.
ATLAS 1234
kmti02vibtderpdz
DEL LIBRO
2
Vai sul webreader, clicca sulla copertina e usa il libro online oppure scarica la app di Scuolabook e usa tutti i tuoi libri anche offline.
B Linguaggio Java Programmazione ad oggetti Web e applicazioni Android © Istituto Italiano Edizioni Atlas
Coordinamento redazionale: Bianca Rossi Redattore responsabile: Marta Bianchetti Redazione ed editing: Claudia Dalle Mura Coordinamento grafico: Massimiliano Micheletti Progetto grafico: Massimiliano Micheletti Copertina: Appears s.r.l. Videoimpaginazione: IN PAGINA sas, Arezzo Coordinamento iconografico: Marco Cattaneo Ricerca iconografica: Claudia Dalle Mura Coordinamento digitale: Silvia Gadda Disegni: Vavassori & Vavassori In copertina: © AndSus – Fotolia Autore: Prof. Agostino Lorenzi Autore: Prof. Andrea Rizzi Consulenza didattica: prof.ssa Piera Zolli
Referenze fotografiche del volume: Dreamstime: a p. 123 © Czbrat (in alto), © Piotr Adamowicz (in basso); a p. 169 © Vladimir Timofeev; a p. 209 © Adam36; a p. 281 © Scanrail; a p. 282 © Dny3dcom; a p. 304 © One Photo; a p. 357 © Oleksandr Delyk; a p. 393 © Tiagoz; alle pp. 45, 121, 177, 207, 279, 303, 355, 391, 357 © Antonio Guillem. iStock: a p. 2 © kukutubQ; a p. 5 © izusek; a p. 7 © OksanaOO; a p. 57 © Farknot_Architect; a p. 270 © Eshma; a p. 308 (stampante in basso a sinistra) © Nerthuz. Archivio Atlas.
Il marchio Libro in Chiaro mette in evidenza le qualità del libro di testo e con la Carta d’Identità – in modo semplice, immediato e trasparente – indica gli elementi di cui è composto, descrivendone gli aspetti qualitativi e quantitativi, la validazione del processo produttivo, le modalità di rapporto con l’utente e l’osservanza delle norme di legge etico-comportamentali. Scopri, con la Carta d’Identità, la storia di ogni libro visitando il sito della Casa Editrice. L’accesso a tutti i contenuti digitali è riservato all’utente registrato, che ha accettato le relative condizioni generali di licenza d’uso riportate sul sito della Casa Editrice. Tale licenza non è trasferibile a terzi. Il presente volume è conforme alle Linee Guida e alle disposizioni ministeriali in merito alle caratteristiche tecniche e tecnologiche dei libri di testo. Per fini esclusivamente didattici, nei volumi a stampa e relativi supporti vengono indicati link a siti internet di terze parti. I diritti di traduzione, di memorizzazione elettronica, di riproduzione e di adattamento totale o parziale, con qualsiasi mezzo (compreso i microfilm e le copie fotostatiche) sono riservati per tutti i Paesi. Informazioni per studenti non vedenti, ipovedenti, disabili motori o con disturbi specifici dell’apprendimento sul sito www.edatlas.it/it/supporto/domande-frequenti Le fotocopie per uso personale del lettore possono essere effettuate nei limiti del 15% di ciascun volume/fascicolo di periodico dietro pagamento alla SIAE del compenso previsto dall’art. 68, commi 4 e 5 della legge 22 aprile 1941, n. 633. Le riproduzioni diverse da quelle sopra indicate (per uso non personale - cioè, a titolo esemplificativo, commerciale, economico o professionale - e/o oltre il limite del 15%) potranno avvenire solo a seguito di specifica autorizzazione rilasciata da EDISER Srl, società di servizi dell’Associazione Italiana Editori, attraverso il marchio CLEARedi Centro Licenze e Autorizzazioni Riproduzioni Editoriali. Informazioni: www.clearedi.org Proprietà letteraria riservata.
La casa editrice ATLAS opera con il Sistema Qualità conforme alla nuova norma UNI EN ISO 9001:2015 certificato da IIP CERTICARGRAF © Copyright 2019 - Istituto Italiano Edizioni Atlas Via Crescenzi, 88 – 24123 Bergamo – Tel. 035.249711 – Fax 035.216047 – www.edatlas.it
Stampa: Vincenzo Bona (Torino) Prima edizione: Gennaio 2019 Ristampa 2 3 4 5 6 7 8 9 10
II
Anno 19 20 21 22 23 24
Questo libro è stampato su carta che rispetta le foreste
© Istituto Italiano Edizioni Atlas
STRUTTURA DELL’OPERA
1
ci. Questi gli elementi grafi usando soltanto ata lizz schermo; rea lo ere sul lizzate fica non può ess e vengono visua Un’interfaccia gra e. Occorre lorate, scritte ch ess co n co ee e lin gir re, era gu fi int o tiera per rappresentano sol terfaccia. il mouse o la tas e tra l’utente e l’in Il volume si divide in sezioni, che sono ere e può usare gestita l’interazion ne l’utente le può ved vie ali qu le n le modalità co aperte da attività di flipped classroom però aggiungere Il concetto di classe che, usa la
o richia-
gestit (classe capovolta), per attivare la didattica le interfacce grafi che deve essere per gestir OOP, gio dinee de ociato un evento Il lingLaauag ll’utente viene ass e smuovere l’interesse. zio era int ogni one mm e appropriata. progra ’azion o unazi mand ettare risp nifestarsi senza ATTIVITÀ 1
a oggetti e di classe nella programmazione Obiettivo: comprendere il concetto rammazione codifi care la classe nel linguaggio di prog A CASA
è un avvenimento
In generale un tempi prefissati.
fi ca ione della classe Cerchio e sulla codi Guarda il video tutoriale sulla creaz Parte1\Attività1). in Java ( la il calcolo proposto nel video, scrivendo Svolgi la creazione della classe e rsonale. omputer pe con il tuo c codifi ca nel linguaggio di programmazione
ò ma
asincrono, cioè pu IN CLASSE
CAPIT
OLO Chiarisci i tuoi dubbi li aspetti che non ti sono chiari; – fai domande all’insegnante su tutti g ni e prova a rispondere. – ascolta le domande dei tuoi compag Metti in pratica el lavoro svolto a casa, create e – a gruppi di tre, seguendo la traccia d nendo gli attributi e i metodi per il codifi cate le classi Cilindro e Cubo, defi e rivete poi il programma per il calcolo calcolo del volume dei due solidi. Sc n tutta la classe le soluzioni trovate. validate l’esecuzione. Confrontate co
IO
MP Le classiESE e gli oggetti
2
CLASSE CAPOVOLTA
ssia, mentre non po fero sono eventi ertura del frigori verifica a una l’ap si o é e rch sor pe COMPETE evi , NzE tel na l perso L’accensione de mpleanno di una come evento il co documentazione con javadoc mo considerare La generazione automatica della scadenza precisa. dell’utente: 1 Il linguaggio Java o all’interazione si verifica in seguit r, ute oppure la mp nte co Java lsa in o sul pu svilupp I CONOSCE un NzE Gli ambienti di a una GU INSERTO A a finestra, il clic su Un evento, riferito o la chiusura di un ura ert ti l’ap ogget o gli e son classi 2 Le possibili eventi . fici. Questidi dati e i file gene- i un tasto del mouse re nto gli elementi gra L’evenfito 3 Le struttu o; pressione di ll’utente.nti Quest erm sch lo ettuatatoda gra ci.rat sul ’azionendeff gli eleame o un a da un no visualizzate 4 Le interfarre cce grafiche o soltan lta genesch causatrea è vo usa Un e. ata ermo; co on ABILITÀ lizz Oc azi a lo est ere sul esse. qu n ess ate ò co nti e lizz pu . rda n gir ua ua no vis era rig ca i int no eventi fi on scritte che vengo dagli er afac gra azi guidat cia ione orm mmaz inf progra ter un La le . ’in a te cia 5 Un indi tutgure, linee colorate, , che viene demandataeragire con esse. Occorre e l’interfac ene qusol conti fi ratseo con int ne o r zione tra l’utente pe stio o ge ra tie tan JDBC sua tas sen la alla rappre deve provvedere ò usare il mouse o IOcia. fac MP ter 6 L’accesso ai databa ESE l’utente e l’in eventotesi le può vedere e pu a l’interazione tra stit ge ne l’uten vie ali qu premendo le modalità con le azione compiuta però aggiungere stito richiarato in seguito all’ che si attiva viene gene he deve essere ge e, sor evi tel l la da a hia fiche, usanto viene gestit accaeagra L’evento essere gestito ric interfost questo eve stire le Ogni capitolo sirrege apre evento che deve La rispl’esplicitazione o un La OOP, pe iatsiv ocevi tasto.con asstel neale o. tetovie un particola ten ll’u de ne to can zio ven era na ll’e a ogni int are arecompetenze, un determi atae. abilità ed conoscenze za rispettdi la generazione de per visualizz’az e appropri associate aare del mouse causa uò manifestarsi sen uncheion operazioni mandonte preme un tasto insieme di nif un do en arsi senza rispett Un uteche gu est esercizi saggiano i prerequisiti. ese ma stito ò ge pu è ne cio vie o, o ron ess : asinc ESEMPIO è un avvenimento tente nerale un ll’interazione dell’u ge Inqu MPIO ESEott ssono nascere da ell’evento. ti. po aa ssi nti po rid eve n a, gli no I ius e ch GU ntr fissamma che usa una viene pi pre tem ono eventi, me gra e eventi quando pro rar un a ne i. In ssiaun ge ess po a ò n di ca pu no ifi su a e ver str clic ntr si ne fa fi é me si , La rch nti se ci. pe fi eve nto a, o gra on eve son ers fero un oriran nntigli elementi gene eve ntil frig lsade ura ifica a una pu 1 Glico ert i ver l’ap si ltre o é e ino rch a; sor pe dit evi , ran l tel deing personagli esempi Moltissimi puere opon cce nansi ico nno di una sono aL’a mplea come evento il co mo considerare di quanto spiegato affinché si te: ten zione dell’u seguito all’intera scadenza precisa. re la pu op abbia un’idea pratica nte zione dell’utente: lsa pu eracome o all’intdi ra, il clic su un la verifica in seguit si r, ute mp co pulsante oppure poter utilizzare clic su un viene a una GUI sul a finestra, ilquanto Un evento, riferito la chiusura di un o ura ert l’ap o esposto a livello teorico. possibili eventi son te. L’evento gene ettuata dall’uten ? to del mouse. eve unne o un ratnto cos L’evento geneChaevo lta’ège pressione di un tas Un e. on uata dall’uten azi a est Delle parole colorate in te. blu effett . di ev generato un sata da un’azione re lta cau sto è vo a ge Un un e. a on esta azi demandata nti qu . uardanel i rig si offre colonnino laterale on azi orm inf un le a ndata indi tutte ESEMPIO , che viene dema rato contiene qu ne stio ge sua la traduzione inglese perché ESEMPIO vvedere alla evento si deve pro iuta premendo uito all’azione comp ormai entrata nel gergo tecnico. iva att si iuta premendo e, che uito all’azione comp gestita dal televisor generato in seg e si attiva viene e, ch sor evi Domande in itinere aiutano tel l te dichiarata. a da stit ge ne vie nto L’evento viene esplicitamen eve nti o eve est gli qu a de to a ne ven ost stio te, dall’altro la re tasto. La risp agetestare la comprensione ola generazione dell’e destinata allaale e dell’utendi rticun padi sivo. unrte evisat telcau ’applicazioneter a dall’interazion to can vento pa nagli zioni associate a ll’e La mi è de era e nti op de ion di eve e un raz ne iem are de n ins causa la ge spiegato. zioni associate a per visualizz generazione tasto del quanto mouse nti. appena Se da un lato la insieme di opera che premea un un gestore di eve nte Ungeute tente o eseguendo un ne è affidataess ll’u stit de stio ge e ne on o vie azi lor o ter : re una risposta nascere dall’in occupa di da a tware che si pre azione dell’utente ne chiusa, ridott sof ter vie ne ll’in do da zio an re lica qu sce . pp ti na ll’a nto ven no a quell’eve è la parte de essi. I gli eventi posso ne chiusa, ridott si fa clic su di a che usa una GU handler to. eventi quando vie no un evento se un prograomm di evento ricevu su di essi. a può generare str clic ne fa fi inInbase al tipme si La se ci. fi nto gra nerano un eve con gli ele nti 210 ze i pulsanti ge dita;sino cenltre re ingran e cono a icona oppu ifica le tu
PEr INIzIArE
• Conoscere i concetti di base e la metodologia della programma zione ad oggetti • Definire le classi con attributi e met ATTIVITÀ 2 odi e fornire la loro rappresentazione tico le attraverso diagrammi vadoc per generare in modo automa Obiettivo: utilizzare lo strumento ja • Applicare i principi della programma mentazione del software zione ad oggetti utilizzando il pagine in formato HTML per la docu linguaggio Java
1 Considera un tablet come oggetto descrivono l’oggetto e le azioni
dimensioni display
A CASA
to javadoc Leggi il testo che spiega lo strumen Parte1\Attività2\javadoc.pdf). ( Parte1\Attività2). ( Guarda il video tutoriale su javadoc
..................................................... .....................................................
• Concetti di base della programma zione ad oggetti • Classi e oggetti IN CLASSE • Information hiding Chiarisci i tuoi dubbi • Ereditarietà chiari; non ti sono li aspetti che – fai domande all’insegnante su tutti g • Polimorfismo rispondere. ni e prova a uoi compag – ascolta le domande dei t
..................................................... Azioni accendere spegnere
Metti in pratica scenze acquisite con il lavoro a casa, – a gruppi di due, utilizzando le cono re ava per calcolare la media delle statu scrivete il codice di un programma J di del programma i commenti e i tag di n persone e inserite nel testo c. ntazione usando lo strumento javado • Definire le classi con attributi e met commento. Generate poi la docume odi luzioni trovate. • Disegnare i diagrammi di classe Confrontate con tutta la classe le so • Creare e utilizzare gli oggetti • Applicare i principi della programma zione ad oggetti utilizzando il linguaggio Java
ti grafici. Questi soltanto gli elemen schermo; realizzata usando o visualizzate sullo ca non può essere Un’interfaccia grafi e, scritte che vengon Occorre figure, linee colorat interagire con esse. o la tastiera per rappresentano solo e l’interfaccia. e può usare il mouse zione tra l’utente l’intera gestita l’utente le può vedere quali viene le modalità con le però aggiungere eventi: dagli a mmazione guidat richiache, usa la progra grafi gestito ce essere interfac le che deve La OOP, per gestire associato un evento dell’utente viene a ogni interazione appropriata. re mando un’azione starsi senza rispetta no, cioè può manife asincro ento è un avvenim In generale un evento ESEMPIO tempi prefissati. possianon sono eventi, mentre ra del frigorifero ca a una a, perché si verifi televisore o l’apertu L’accensione del anno di una person come evento il comple mo considerare . scadenza precisa nte: all’interazione dell’ute seguito in ca ter, si verifi te oppure la a una GUI sul compu il clic su un pulsan a di una finestra, Un evento, riferito l’apertura o la chiusur possibili eventi sono del mouse. o geneChe cos’è un evento? pressione di un tasto ata dall’utente. L’event effettu ne da un’azio generato un azione. Una volta di un evento è causata La generazione riguardanti questa e di eventi. tutte le informazioni data a un gestor e, che viene deman rato contiene quindi dere alla sua gestion ESEMPIO evento si deve provve do ne compiuta premen all’azio seguito in generato si attiva del televisore viene dal televisore, che L’evento accensione evento viene gestita La risposta a questo un particolare tasto. ne televisivo. pressio canale nto inato determ la generazione dell’eve per visualizzare un associate a del mouse causa ioni tasto un operaz di e un insiem Un utente che preme gestito eseguendo mouse: esso viene del tasto del mouse nte dall’interazione dell’ute nascere o posson quell’evento. ridotta eventi che usa una GUI gli quando viene chiusa, In un programma essi. può generare eventi se si fa clic su di grafici. La finestra ti generano un evento con gli elementi dita; inoltre i pulsan a icona oppure ingran La generazione di
un evento
..................................................... .....................................................
2 Collega a ciascun termine il corrisponde
I paragrafi di profilo sono inframmezzati ad attività di laboratorio, volte a far mettere subito in pratica quanto studiato, intitolate “Proviamo insieme”. Il percorso proposto si rivela quindi ricchissimo di esercitazioni in itinere da svolgere con la guida dell’insegnante in laboratorio.
gestore
amente dichiarata. eventi viene esplicit Il gestore di eventi alla gestione degli nte, dall’altro la licazione destinata erazione dell’ute La parte di un’app è causata dall’int zione degli eventi Se da un lato la genera di eventi. data a un gestore loro gestione è affi una risposta dare di upa software che si preocc dell’applicazione parte la è e Un gestor evento ricevuto. in base al tipo di
• IL LINGUAGGIO DI PROGRAM
Ver
•
1. Struttura di dati dello stesso tipo 2. Programma che traduce il codice sorgente in codice bytecode 3. Metodo di partenza nell’esecuzio ne di un programma Java 4. Insieme di classi e metodi per lo sviluppo di applicazioni
57
MAZIONE
PARTE PRIMA
nte significato.
a. Main b. Array c. Libreria d. Compilatore
utente
gestione
handler
ruotare
azione
generazione evento
reale. Completa lo schema inserendo le proprietà che che possono essere fatte su di esso.
Proprietà nome prodotto
etenze Sviluppa le tue comp
PROVIAMO INSIEME
1 L’ISCRIZIONE A UN SERVIZ
IO
WEB Creare un modulo per raccogliere i dati di un utente che desidera iscriversi nome, password e indirizzo a un servizio Web (cognom email) e, Il modulo è formato da quattro caselle di testo per: • cognome; • nome; • password; • indirizzo email.
Inoltre sono presenti due pulsanti di comando Invia e Annulla. Il modulo è rappresentato in HTML con il seguente codice. Pagina Web (Richiesta
.html)
Inserimento dati
chiamata alla pagina
invio di 4 parametri JSP con Iscrizione al servizio Web
(F) Cognome O FALSA rA (V) | |
etti Nome | to agli ogg DE tabili orienta | PEr orma lizzare Java è llocazio DI UN PrOGrAMM uaggio la piattaf tte di rea ne e dea TUrA GENErALE versiola ling il tipo password per la zio me per STrUT Il uare LA o F E oca per individ i sol (all 1 V .html per Java PrOGETTAr testo della password casella di gramm memoria uaggio hnetwork/java/index ard Edition), fai il download era pro visualizzare i carattericonsente di non Password omaticam sezione Java SE mento al sito http:// uaggio a | | un progra ice portab ne più recente del con il nome sul computer. F Il ling salvalo 1 Dati il lazione e zione di è un cod i l’instal 4 V numer pila non prezzo di due com di un prodotto e
del JDK ed esegui la somma ecode e o della la percentuale di F Il byt mma che calcola ttament il risultat 5 V sconto, calcola e guito , il seguente progra Email | guito dire visualizza il prezzo ecode è ere ese usando Blocco Note, F Il byt 2 Scrivi, 2 Avend scontato. a per ess essere ese to 6 V Jav può o la | o metri, centimetri guita aut rmazione ecode dev nei file sci un programma tralasciando gli eventu F Il byt viene ese
dita di info per convertire contenuto 8 V ali millimetri residui tipo int class Somma ta una per ecode è float al . 3 Dato F Il byt compor float al tipo int in ore, minuti e versione void main(String ata pro Per esempio 5 ore, | | ott 18564 fl
con { si ting secondi. F La cas un int dal tipo 11 V ta con il int per int a = 3;
versione 4 Nella di tipo ne esegui trasmissione di dati F La con numero float vie 12 V tramite reti di calcola int b = 8;
ente ting ndo un numero indicante int al tipo + b; tori, l’unità di misura F Divide omaticam i bit ere il cas dal tipo int somma = a
13 V utilizzata è il bit. a richied Per esempio 84.054 trasmessi, calcola a quanti byte, guito aut (somma); versione Ricevuto in input pre ese KB, MB, GB corrisp .321 bit = 10.506 mmatore F La con System.out.println un un altro a è sem onde. .790 byte = 10.260 14 V il progra dato in ,5 KB = 10,02 MB ting in Jav e essere tipo di } un dev i F Il cas = 0,0098 tire V cas ni GB. 5 Suppo ver 15 nendo che una rete per con a in alcu casting } F In Jav televisiva abbia La pagina Web viene salvata strumento errori di gramma per conver 16 V trasmesso 5.876 nella sottodirectory: eventuali tire il valore nel ting è uno minuti di docum omatico F Il cas formato giorni, entari in un anno, individua vieneore, minuti. ente. 17 V int è aut scrivi un proverifica quale errore pilazione il programma preced C:\Programmi\Tomcat\weba ne ble al tipo variabile intera e 3 Compila ed esegui F La com 6 Dato di una pps\esempiJSP di selezio tipo dou 18 V un elenco di 10 dichiarazione con il nome Richiesta.html. prodotti con descriz ting dal struttura ente la seguente F Il cas ione e prezzo, visualiz ne {…} è una un programma conten zio 19 V 4 Scrivi else sele . za il prezzo massim ) {...} di compilazione ttura di F if (… o. ne 7 Scrivi La pagina viene poi aperta generato in fase 20 V un programma che è una stru iterazio ne } di {… azio nel ) ra browser scrivendo nella consenta di inserire di iter struttu F for (… mente deve restitu casella dell’indirizzo: 5 nomi di città con 21 V } è una struttura ne ire {… 15.0; zio il ) = una nome il rispett è il ecu (… ne della ca volume ivo città maggio int modifi numero di abitant e l’es http://localhost:8080/esemp F while iterazio rmente popolata. …break;} i. SuccessivaSuccessivamente si durant 22 V iJSP/Richiesta.html ttura di il mes(…) {case: il cui valore è 22. verificar 8PERC_ è una stru venga visualizzato UnaIVA F switch scuola è compo la che può (…) {…} il progra i una costante intera 23 V stamma, da N classi. Per compilando } catch mma che dichiar ne anoma ca che,Calcola a ogni classe, viene 5 Scrivi un progra quanti studenti freque F try {… zione situazio il valore 21. Verifi gramm inserito da tastier 24 V ntano la scuola e IVA assegnando e PERC_IVA”. di compila ione è una a il numero di studen ne del pro valore di PERC_ 340 in 140. in fase value to final variabl F L’eccez minazio ti. PARTE SECONDA • IL WEB E L’INFORMATICA MOBILE a alla variabile il valoremedia quanti studenti ci sono per “cannot assign a 25 V si verifica sa la ter tipo byte. Assegn 9 lunghe classe. saggio di errore on”. zza e di cezione catch … precisi Si tita, cau introdu of … L’ec loss ges le ce F nome da di try non variabile cco errorea“possib un elenco di libri 26 V ditastier ione, se totale il messag A mma che dichiari una formato da autore con il blo zato il 4%gio progra in più per le spese unETT 6 Scrivi F L’eccez , titolo e prezzo trollata COrr mma, venga visualiz di spedizione. 27 V . Calcola il totale inilèprogra POSTAVerifica che, compiloando ione è con e applica sul tod ma A LA rIS F L’eccez EzION 28 V e del me s) seguenti variabili: 10 Esamina le inform NI, SEL hiarazion (Str byte occupano le ing arg azioni MAzIO in quanti retta dic 7 dCalcola AFFEr sono le prove sufficie sulle verifiche che uno studen 3 La cor voi ma UENTI te ha fatto durant float; nti. args[]) è li di tipo lic static in (Str ing cio variabi e l’anno scolastico LLE SEG 5 • pub s[]) ili, DE a. arg e conta quante void ma SCUNA (String o portab li di tipo short; e, • 7invariabi d ma PEr CIA b. public 11 I dati Java son forme divers voi ; in tic double di sta tipo () un’indagine di mercat i scritti su piatta d •ma4invariabili di c. public o sono stati raccolt gramm Il questionario era difiche static voi • 4 variabili di tipo long; i attraverso un questio 1 I pro composto da A rativa di aè senza mo d. public nario di domande domande e ciascun stionari compilati tipo int; di Jav eseguibili la modalità ope a risposta chiusa. genteli di a domanda preved variabi al termine dell’ind • 10 sor o eva al massimo agine sono stati manda il conteg un file tipo char. attravers B risposte. I quein totale N. Elabor gio delle rispost sione di • 10 variabili di etazione. e date e calcolando a video: a i dati evidenziando 4 L’esten la struttu output a. interpr . ra dati più adatta la percentuale per ogni doisca il seguente per la soluzione mma che restitu a. .class di riga corrisponde del problema è l’array delle risposte sul totale. Sugge b. editing zione. 8 Scrivi un progra al rimento: numero di doman a due dimensioni dia” pila b. .txt da e l’indice di colonn (matrice), dove l’indice c. com “La divina comme : o a corrisp p TITOLO risultat ing. il .cp endo ugg onde c. ri al numero di rispost ne restitu Iè d. deb esegua la divisio imo AP a. AUTORE: D. Alighie di tipo double ed d. .java dell’acron due valori LEMI tastiera PrOB MATEMATICI nificato mma che legga da retto sig sing Interface. com9 Scrivi un progra nome il 2 Il cor sul video Proces 12 Stabilis Institute. una persona e stampi ci se due sullo schermo. e dirette a. Active Programming te. cognom il a e titu x+b nome y+c Ins =0 e a x+b y+c 1 1 da tastiera il 1 cessing =0 sono perpen 2 b. Active rface. 2 mma che legga 2 JAVA 35 ation Pro ing Inte 10 Scrivi un progra UAGGIO o è pari o dispa- dicolari. 13 Scrivi gramm c. Applic 1 • IL LING un programma un messaggio se il numer ation Pro pleto. CAPITOLO o e comunichi conche produc a a video la tavola d. Applic tastiera un numer pitagorica. isce 0. mma che legga da divisione per 2 restitu 11 Scrivi un progra 14 Dopo to. il resto della aver ottenuto da tro di un quadra numero è pari se e ilaperime tastier ri. Ricorda che un un numero decima calcoli l’area e sistem lato del a binario le, calcola la rappre . da tastiera la misura sentazione dello mma che legga stesso numero nel 12 Scrivi un progra JAVA 39 IL LINGUAGGIO CAPITOLO 1 • 15 Un’urn a contiene 20 palline numerate da 1 dall’urna e che consid a 20. Crea un progra eri come vittoria mma che simuli l’estrazione di un un’estrazione casuale numero pari. 16 Data la velocità espres sa in km/h, calcola la conversione in m/s. zIONI,
FErMA
NTI AF
UE LLE SEG
STUDIO DI CASI REA
LI
La rubrica “Verifica le tue conoscenze“ dichiarata. presenta licitamentenumerosi egli eventi viene esp ll’altro la da te, ten ll’u de e esercizi suddivisi per a dall’interazion tipologia. una risposta dare“Sviluppa di In
le tue competenze” si esercitano le competenze enunciate in apertura di ogni capitolo. •
e che si preoccupa
dichiarata. ne esplicitamente ne degli eventi vie stio ll’altro la ge da alla te, ata ten stin ll’u de cazione de a dall’interazione sat cau La parte di un’appli è nti eve nerazione degli Se da un lato la ge di eventi. data a un gestore affi è ne stio ge o lor risposta cupa di dare una tware che si preoc sof ne zio lica pp è la parte dell’a evento ricevuto. in base al tipo di
42
PARTE PRIMA
La rubrica “Studio di casi reali” presenta numerose proposte per compiti di realtà.
• IL LINGUAGGIO DI PROGRAM
MAZIONE
© Istituto Italiano Edizioni Atlas
Struttura dell’OPera
III
IN DIGITALE PRO.TECH è un’opera mista: la versione a stampa si integra con la versione digitale eBook+ per approfondire, sperimentare e imparare con l’interazione e la multimedialità.
+ MULTIMEDIALE
1
APPROFONDIMENTI
VIDEO
QUIZ INTERATTIVI
La tecnologia JDBC
comune costituire una base di lavoro di archivi integrati che possono relazionale Il database è un insieme costruiti secondo il modello ioni diverse. I database riga corrisponde per utenti diversi con applicaz nelle quali a ciascuna organizzano i dati in tabelle, (database relazionali) tabella. della campi che sono le colonne dei database. e un record formato da Richiami sui databas che consentono la gestione ment System)) sono software e il linguaggio SQL I DBMS (DataBase Manage di classi a disposizione una libreria ivity)) è un software che mette SQL (Structured JDBC (Java DataBase Connect usano il linguaggio standard che database ai relazionali. Java per interfacciare l’accesso di accesso ai database o di fornire un’uniformità La classe dichiarata in questo modo contiene il solo metodo main. Questo Query Language),), con l’obiettiv per metodo raggruppa base le la o dichiarazioni di variabili e le istruzioni fornend SQL direttamente, che compongono l’applicazione e richiamare comandi Java. Esso viene dichiarato usando le Attraverso JDBC è possibil parole chiave public, static e void e. ion tion che specificano alcune Applicat per l’accesso ai databas (Applica ioni API proprietà una del metodo: applicaz come costruire è classificato di Java il software JDBC offerta dall’API • public quella a indica che il metodo analoga Secondo la terminologia è pubblico ed è visibile; faccia ), perché fornisce un’inter e), • static indica che il metodo è associato Programming Interfac alla classe e non può essere richiamato moderni. dai singoli oggetti della classe (vedi pag. 79); A che cosa serve per i sistemi operativi nel JDK di Oracle. • void indica che non ci sono valori il software JDBC? L’API JDBC è contenuta di ritorno. pe- il nome e a una Dopo del metodo, tra parentesi, sono indicati I driver per database , un programma che consent i parametri. Il metodo main possiede driver parametro driver indica, in generale ma termine program il come il tica er: un array di stringhe (indicato con In informa di un comput args[]) che corrisponde ai parametri are con l’unità centrale passati dalla riga di comando quando riferica hardware di comunic ma richiedente. viene eseguita l’applicazione. li trasferisce al program ritrova i dati richiesti e parentesi graffe {…} sono usate per pree i datiLe individuare un blocco, che può essere che consente di trasferir una classe, un metodo oppure un insieme di istruzioni. con è un programma standard All’interno di un blocco possono e a un database creato Il driver per database acceder vuole ma essere presenti altri blocchi in modo annidato. Per un program poter meglio distinguere questi blocchi senti in un database: quando database. conviene seguire e usare una tecnica di indentazion utilizzare il driver per quel e: anche se un programma Java potrebbe un altro applicativo, deve essere scritto ((Oracle,una sola riga, è utile disporre prodotti DBMS usando ordinatamente le varie istruzioni e creati con i più diffusi e gli databas elementi i per sintattici per migliorare driver la leggibilità del codice. JDBC interagisce con i ecc.). MySQL, PostgreSQL, SQLite, Le righe che iniziano con // indicano frasi di commento. In Java ogni istruzione deve terminare JDBC e con Java databas il punto ione ai o e virgola Applicaz L’access (;). Questo terminatore va inserito alla fine di tutte le istruzioni e di tutte le dichiarazioni.
Un libro di testo digitale arricchito da audio, video, approfondimenti, gallerie di immagini e link.
+ INTERATTIVO Integra gli esercizi interattivi direttamente nel testo digitale, per un’immediata verifica.
classe Domanda
DATABASE
Aiuta a comprendere e approfondire il testo, rendendo l’apprendimento più attivo e divertente.
282
PARTE
Come si distingue un blocco?
ESEMPIO Basandosi su questa struttura è possibile scrivere un semplice programma che stampa sul video un messaggio.
Driver
+ COINVOLGENTE
Come si dichiara il metodo main?
il metodo main è formato da un’unica istruzione
class Domanda DBMS { Database Conl’oggetto System.out indica public static void main(Strin ano i driver ODBC (Open g args[]) lo standard output (video) in modo recenti di Java si utilizzav { te Windows per scrivere Nelle versioni meno ambien in d standar ccia software System.out.println("Quanti nectivity), che è l’interfa e. anni hai?"); che si connettono ai databas } dalle aziende che produsemplice le applicazioni il metodo println scrive utilizzare i driver forniti devono si 8 JDK } sullo standard output i suoi A partire dalla versione argomenti e torna a capo da terze parti. cono i DBMS oppure usaredell’esecuzione di questo Il risultato di Access si può programma è la visualizzazione della I driver per i database con Microsoft Access scritta “Quanti e a un database creato hai?”; poi il programma termina. Web: e indirizzoanni In particolare per acceder scaricabile dal seguent JDBC per urce open-so UCanAccess, un driver rojects/ucanaccess/ https://sourceforge.net/p nell’aputilizzare il driver NOTA BENE per rie necessa Java è un linguaggio case-sensit e i file .jar con le librerie ive. Questo significa che vi è differenza Il file zip fornito contien nello scrivere unasoftware lettera maiuscola o minuscola. Per esempio l’identificatore System plicazione Java. essere aggiunte al progetto è diverso da system. Un errore nella digitazione NetBeans le librerie possono comporta la segnalazione di un errore Nell’ambiente di sviluppo di compilazione. in questo modo: a sinistra (Projects); del progetto nel riquadro • tasto destro sul nome Le fasi di realizzazione di un program ma • scelta Properties; Per realizzare un programma e renderlo selezionare Libraries; eseguibile si devono compiere i seguenti • nella finestra che si apre, passi: 1. editare il codice sorgente; 2. compilare il codice sorgente; 3. eseguire il codice compilato. IO DI PROGRAMMAZIONE LINGUAGG IL • PRIMA
Compilazione esecuzione
Quali sono i passi per realizzare un programma?
Per editare il codice Java è possibile usare il programma Blocco note di 14/01/19 14:55 Windows o qualsiasi altro editor di testi. Il codice sorgente deve essere salvato in un file con estensione .java. Il nome da dare al file corrisponde al nome della classe, cioè al nome inserito dopo la parola chiave class. ESEMPIO Il programma dell’esempio precedente Se il programma è composto da deve essere più classi, conviene mesalvato in un file chiamato Domanda.ja morizzare ogni classe in un file diverso. va.
CAPITOLO
1 • IL LINGUAGGIO JAVA
9
2188_PRO.TECH_B_002_045_cap1.i
ndd 9
1
ATTIVA IL TUO
SEI UN INSEGNANTE?
Vai sul sito www.scuolabook.it e ACCEDI con e-mail e password (o iscriviti se è la prima volta che usi la piattaforma).
Il nostro agente di zona è a tua disposizione. Chiedi! saggio digitale
2
3
IV
Inserisci il codice COUPON che trovi sul bollino bianco nel frontespizio del volume.
ATLAS 1234
Vai sul webreader, clicca sulla copertina e usa il libro online oppure scarica la app di Scuolabook e usa tutti i tuoi libri anche offline.
in diGitale
kmti02vibtderpdz
TITOLO DEL LIBRO
Chiedi il saggio digitale al nostro agente, quindi vai sul sito www.scuolabook.it, registrati/accedi come insegnante, usa l’eBook+ online e offline. RISORSE RISERVATE
Vai su www.edatlas.it, accedi con la tua e-mail e il codice di attivazione ricevuto dal nostro agente, scarica le risorse riservate all’insegnante. Sul sito, inoltre, sono disponibili a studenti e docenti i materiali aggiuntivi presenti nel DVD.
© Istituto Italiano Edizioni Atlas
Un libro accessibile a tutti L’intero corso è disponibile nella versione ad Alta Accessibilità: puoi ascoltare i testi, scorrerli in formato liquido e visualizzarli ad alta leggibilità. Apri il libro con la app di Scuolabook, scegli il pulsante alta accessibilità nella barra degli strumenti e usa tutti i servizi. 1. Visualizzare il solo testo liquido (reflowable).
2. Azionare l’audiolettura (sintesi vocale text to speech TTS) di tutto il testo.
3. Selezionare un carattere speciale ad alta leggibilità.
4. Cambiare la modalità di lettura, la font e il corpo del testo.
edatlas.it PRO.TECH Informatica per Istituti Tecnici Tecnologici
Agostino LORENZI
Andrea RIZZI
PRO.TECH Informatica per Istituti Tecnici Tecnologici
Autori: A. Lorenzi – V. Moriggia – A. Rizzi – E. Cavalli
con DVD
B
Linguaggio Java Programmazione ad oggetti Web e applicazioni Android
A. LO
Cerca sul sito www.edatlas.it le ulteriori risorse libere da scaricare per ogni singola opera. Per trovare il libro e i contenuti digitali abbinati, inserisci il titolo (o le ultime cifre del codice ISBN) nel campo di ricerca presente nella home page del sito, oppure sfoglia il catalogo selezionando ordine di scuola, ambito disciplinare e titolo. Trovata la copertina del libro, cerca e clicca il tasto Contenuti digitali per accedere ai contenuti dedicati.
Agostino LORENZI
Andrea RIZZI
PRO.TECH Informatica per Istituti Tecnici Tecnologici
con DVD
B
Linguaggio Java Programmazione ad oggetti Web e applicazioni Android
© Istituto Italiano Edizioni Atlas
in diGitale
V
INDICE PARTE PRIMA
IL LINGUAGGIO DI PROGRAMMAZIONE 1
Studio di casi reali
Il linguaggio Java
44
CLIL
1
Le caratteristiche generali di Java
6
Scheda di autovalutazione
2
L’ambiente di programmazione
7
INSERTO
3
La struttura dei programmi Le fasi di realizzazione di un programma
8
A
4
Gli identificatori e le parole chiave
10
5
Le variabili e le costanti La visibilità delle variabili
11
6
I tipi di dato: primitivi e riferimento I tipi numerici I tipi carattere I tipi booleani
12
7
Il casting per la conversione di tipo
14
8
Gli operatori
16
PER APPROFONDIRE
La notazione prefissata e postfissata
I commenti e la documentazione
18
10
La gestione dell’input/output
18
11
PROVIAMO INSIEME
Variabili di tipo diverso
19
PROVIAMO INSIEME
La media delle età
21
Le strutture di controllo: sequenza PROVIAMO INSIEME
12 13
14
Le strutture di controllo: selezione Le strutture di controllo: ripetizione
16
PROVIAMO INSIEME
indice
Le classi e gli oggetti
1
L’orientamento agli aggetti
58
2
Gli oggetti e le classi
59
3
La dichiarazione e l’utilizzo di una classe
62
PROVIAMO INSIEME
L’area del cerchio
62
65
23 25
6
28
7
31
I dati anagrafici
PROVIAMO INSIEME
Le operazioni sul conto corrente 70
La creazione degli oggetti
8
72
I riferimenti nulli
74
PER APPROFONDIRE
L’uguaglianza tra oggetti
75
L’utilizzo degli oggetti
76
La circonferenza e l’area del cerchio
77
Gli attributi e i metodi static
79
Il mascheramento dell’informazione nelle classi 80 PROVIAMO INSIEME
9
68
PER APPROFONDIRE
PER APPROFONDIRE
33 34 35 39
PROVIAMO INSIEME
PROVIAMO INSIEME
31
32
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze
2
La dichiarazione dei metodi
I parametri forniti al programma 30
Dividere per zero
51
5
27
Le eccezioni
NetBeans I passi per la creazione del programma Il collaudo del programma Il debug L’applicazione con più classi La chiusura del progetto Le cartelle build e dist
22
I cicli interrotti e i cicli infiniti
La matrice trasposta
2
64
PER APPROFONDIRE
PROVIAMO INSIEME
46
La dichiarazione degli attributi
26
Gli array multidimensionali
Eclipse I passi per la creazione del programma I passi per l’esecuzione del programma
4
Le votazioni dello studente
La struttura di dati array
Gli ambienti di sviluppo in Java
22
PROVIAMO INSIEME
PROVIAMO INSIEME
15
Ore, minuti e secondi
45
1
17
9
VI
42
La semplificazione della frazione 83
La realizzazione di programmi object-oriented 86 PROVIAMO INSIEME
La gestione della fatturazione © Istituto Italiano Edizioni Atlas
87
10
Gli array di oggetti PROVIAMO INSIEME
La valutazione dei modelli di hard disk
89
6
L’albero PROVIAMO INSIEME
90
145 L’implementazione dell’albero binario 147
11
L’ereditarietà
93
7
I flussi di input/output
154
12
La dichiarazione e l’utilizzo di una sottoclasse 97
8
I file strutturati
157
PROVIAMO INSIEME
13
La gerarchia delle classi PER APPROFONDIRE
14
Il volume del cilindro
PROVIAMO INSIEME
Il programma di scrittura
158
100
PROVIAMO INSIEME
Il programma di lettura
160
Le ultime classi della gerarchia 101
Il polimorfismo L’overriding L’overloading PROVIAMO INSIEME
98
I file di testo
101
Il controllo sulle operazioni del conto corrente
103
15
Le librerie La API
106
16
Le stringhe
109
PROVIAMO INSIEME
9
Le vocali e gli spazi in una frase
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali Scheda di autovalutazione
PROVIAMO INSIEME
L’agenda dei contatti
162
PER APPROFONDIRE
La classe StringTokenizer
165
PROVIAMO INSIEME
La stampa dei contatti
166
PROVIAMO INSIEME
La copia di backup
168
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali
110 113 114 117 119
121
Le strutture di dati e i file
4
Le strutture di dati dinamiche
124
2
Gli array dinamici
124
PROVIAMO INSIEME
I vertici di un poligono
PROVIAMO INSIEME
La rubrica telefonica in un array 128
3
La pila PROVIAMO INSIEME PROVIAMO INSIEME
4
5
La gestione automatica della memoria
126
131 133
Un modello generico di pila
134
Una pila di numeri casuali
135
La coda
136
PROVIAMO INSIEME
Un modello generico di coda
137
PROVIAMO INSIEME
Le ordinazioni al bar
138
La lista concatenata
140
PROVIAMO INSIEME
Una lista di parole
141
PROVIAMO INSIEME
Stampare i dati di una lista
145
© Istituto Italiano Edizioni Atlas
177
Le interfacce grafiche
1
L’interfaccia per l’utente
180
2
Gli elementi dell’interfaccia grafica
181
3
1
PER APPROFONDIRE
176
Scheda di autovalutazione
PER APPROFONDIRE
3
170 171 173 175
CLIL
120
CLIL
161
Gli elementi grafici come oggetti della OOP
183
Le librerie grafiche AWT e Swing PROVIAMO INSIEME
183
Una finestra grafica
185
4
L’ambiente di programmazione
187
5
La creazione di applicazioni in NetBeans
189
PROVIAMO INSIEME
La somma di due numeri
189
6
Le etichette
192
7
I pulsanti
193
8
Le caselle e le aree di testo
194
9
PROVIAMO INSIEME
L’input dei dati con caselle di testo 194
PROVIAMO INSIEME
L’area di testo
196
Le caselle combinate e le caselle di controllo 196 PER APPROFONDIRE
Il layout degli elementi grafici 197
PROVIAMO INSIEME
La scelta nel menu di piatti
199
PROVIAMO INSIEME
Il layout tabellare
200
Mappa concettuale Verifica le tue conoscenze
201 202 indice
VII
Sviluppa le tue competenze Studio di casi reali CLIL Scheda di autovalutazione
5
204 205
L’avviso sonoro in caso di errore 264
PROVIAMO INSIEME
La riproduzione di suoni
266
207
PROVIAMO INSIEME
La tastiera musicale
269
Gli eventi
210
2
La gestione degli eventi
211
Gli eventi su una finestra
213
PROVIAMO INSIEME
Gli eventi su un pulsante
214
PROVIAMO INSIEME
Il convertitore di gradi
216
La scelta con una casella combinata
218
PROVIAMO INSIEME
PROVIAMO INSIEME
4
6
Le fotografie delle città
223
L’editor di testi
Le liste e le gerarchie di dati
1 2 3
4
233
PROVIAMO INSIEME
I promemoria
237
La tecnologia JDBC
282
La connessione al database
283
La manipolazione dei dati
284
PROVIAMO INSIEME
L’operazione di inserimento
285
PROVIAMO INSIEME
L’operazione di cancellazione
287
PROVIAMO INSIEME
L’operazione di aggiornamento 288
Le interrogazioni PROVIAMO INSIEME
PROVIAMO INSIEME
5 243
I disegni e la grafica 2D
245 249
PROVIAMO INSIEME
L’area di disegno
249
PROVIAMO INSIEME
La didascalia delle immagini
254
PROVIAMO INSIEME
Il disegno di schemi elettrici
258
290
Le persone della provincia di Milano
291
Le persone di una provincia richiesta da tastiera
293
I metadati PROVIAMO INSIEME
La scelta del film
279
L’accesso ai database con JDBC
232
I servizi di autolavaggio
Il drag and drop
6
273 274 275 277 278
Scheda di autovalutazione
227
PROVIAMO INSIEME
PROVIAMO INSIEME
7
221
226
PROVIAMO INSIEME
5
220
L’input obbligatorio dei dati anagrafici
I menu
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali CLIL
PROVIAMO INSIEME
Le finestre di dialogo
263
206
1
3
I suoni PROVIAMO INSIEME
La programmazione guidata dagli eventi
PROVIAMO INSIEME
8
295 La struttura della tabella
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali
295 297 298 300 301 302
CLIL Scheda di autovalutazione
303
PARTE SECONDA
IL WEB E L’INFORMATICA MOBILE 7 1
Le servlet e le pagine JSP
L’architettura Client/Server PER APPROFONDIRE
2
Le servlet PROVIAMO INSIEME
VIII
L’estensione del server Web
indice
PER APPROFONDIRE
308 311 312
Una fotografia con il titolo
3
314
La compilazione e l’esecuzione della servlet PROVIAMO INSIEME
4
L’ambiente di esecuzione delle servlet Le visite a una pagina Web
L’interazione con il client PROVIAMO INSIEME
La media dei voti
315 317 319 320 321
© Istituto Italiano Edizioni Atlas
5
L’accesso ai database in rete
323
PROVIAMO INSIEME
6
Le servlet per la connessione ai database
324
PROVIAMO INSIEME
PROVIAMO INSIEME PROVIAMO INSIEME
PROVIAMO INSIEME
La gestione degli utenti
La visualizzazione degli utenti registrati 326 La registrazione di un nuovo utente
Lo scambio di dati in JSON
7
PROVIAMO INSIEME
324
La pizzeria più vicina
331 331
Le pagine JSP
335
9
L’attivazione di una pagina JSP
337
PROVIAMO INSIEME
La data e l’ora
337
PROVIAMO INSIEME
La tavola pitagorica
338
Il passaggio di parametri alla pagina JSP PROVIAMO INSIEME
11 12
L’accesso ai database con JSP L’elenco degli utenti registrati
PROVIAMO INSIEME
L’operazione di inserimento
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali Scheda di autovalutazione
PROVIAMO INSIEME
Il consumo di carburante
380
PER APPROFONDIRE
Avviare una telefonata
384
9 1
PROVIAMO INSIEME
2 3
PER APPROFONDIRE
355
Android e l’ambiente di sviluppo
L’informatica mobile
358
2
Il sistema operativo Android e le applicazioni
359
PER APPROFONDIRE
3
L’ambiente di sviluppo Android Studio PER APPROFONDIRE
4
Realizzare un’applicazione per Android PROVIAMO INSIEME
5
Gli emulatori di dispositivi Che ora è?
Le etichette, le caselle di testo e i pulsanti di comando © Istituto Italiano Edizioni Atlas
362 363 364 365
371
La lista della spesa
396 400
I numeri di cellulare
401 407
Il menu di scelte per la lista della spesa
411
La condivisione di contenuti tra le applicazioni
416
Le immagini e la fotocamera
418
PROVIAMO INSIEME
Un’immagine personalizzata
420
PROVIAMO INSIEME
Disegnare con il dito
424
PROVIAMO INSIEME
Un bordo per le immagini
429
A che ora ho scattato la fotografia?
435
5
La distribuzione delle applicazioni
440
6
Le applicazioni per smartwatch
442
La gara di corsa
442
PROVIAMO INSIEME
Gli elementi base dell’interfaccia Android 360
394
Il menu e i file PROVIAMO INSIEME
4
391
L’accesso ai contatti
345
1
390
Le liste dinamiche
PROVIAMO INSIEME
8
385 386 388 389
Le app per l’informatica mobile
PROVIAMO INSIEME
348 349 351 353
379
Scheda di autovalutazione
354
CLIL
La classe Activity
343
Le operazioni di manipolazione sul database con JSP 345
La localizzazione del software 378
CLIL
340
343
Un messaggio di avvertimento per l’utente 376
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali
339
Il passaggio di parametri con l’indirizzo URL 342
PROVIAMO INSIEME
13
L’iscrizione a un servizio Web
6
328
8
10
PER APPROFONDIRE
I megapixel di una fotocamera 373
Mappa concettuale Verifica le tue conoscenze Sviluppa le tue competenze Studio di casi reali
451 452 454 455 456
CLIL Scheda di autovalutazione
457
Quick reference
458
Acronimi
464
Indice analitico
465 indice
IX
INDICE DEI MATERIALI MULTIMEDIALI Nell’eBook e nel DVD sono presenti i seguenti materiali Classe capovolta Parte 1 Attività 1: Il concetto di classe Attività 2: La generazione automatica della documentazione con javadoc Parte 2 Attività 1: Una panoramica sul linguaggio XML Attività 2: L’ambiente di sviluppo e di collaudo con Tomcat
Capitolo 4 Le interfacce grafiche I contenitori in AWT La palette delle componenti Swing e AWT Il codice generato automaticamente da NetBeans La componente per gestire un’area di disegno I contenitori ScrollPane e TabbedPane Quiz Interattivo - Quiz CLIL
Capitolo 1 Il linguaggio Java Java Development Kit (JDK): installazione e modalità operative Editing, compilazione ed esecuzione di un programma Java in Windows Operatori logici per le operazioni sui dati bit a bit Operatore di selezione ternario L’array args[] per i valori passati da linea di comando Valutazione di un polinomio di terzo grado Quiz Interattivo - Quiz CLIL
Capitolo 5 La programmazione guidata dagli eventi Evento sulla modifica delle caselle di testo Simulatore di un miscelatore di acqua Rilevazione di dati in una stazione meteorologica La visualizzazione dei dati in tabella La dimensione del testo nelle aree grafiche Quiz Interattivo - Quiz CLIL
Capitolo 2 Le classi e gli oggetti L’astrazione nella programmazione ad oggetti Le specifiche di rappresentazione in UML Dichiarazione e utilizzo di un metodo static Singleton: le classi con una sola istanza I metodi della classe Object Collegamento statico e collegamento dinamico Le classi astratte Le interfacce e la clausola Implements Casting tra le classi Documentazione delle librerie Java Quiz Interattivo - Quiz CLIL Capitolo 3 Le strutture di dati e i file Accesso alle strutture dinamiche usando gli iteratori Struttura di dati dinamica per gestire le Hash Table La classe Stack e l’interfaccia Queue nel package Java.util Il Java Collections Framework per gestire gli insiemi di dati Lettura dei dati da tastiera con la classe Console Gestione dei file ad accesso casuale Operazioni sulle directory e sui file Quiz Interattivo - Quiz CLIL
X
indice dei materiali multimediali
Capitolo 6 L’accesso ai database con JDBC Richiami sui database e il linguaggio SQL Quiz Interattivo - Quiz CLIL Capitolo 7 Le servlet e le pagine JSP Installare e configurare Apache Web Server Creare le servlet con l’ambiente di sviluppo NetBeans Application Server per sviluppare applicazioni Java Enterprise Gestire le sessioni con le servlet Creare i pacchetti per le applicazioni Web (JAR, WAR, EAR) Quiz Interattivo - Quiz CLIL Capitolo 8 Android e l’ambiente di sviluppo Versioni del sistema operativo Android L’ambiente di sviluppo Eclipse Aggiornare ed estendere l’Android SDK Il ciclo di vita delle Activity Quiz Interattivo - Quiz CLIL Capitolo 9 Le app per l’informatica mobile Le componenti grafiche di Android Il layout degli oggetti La geolocalizzazione Quiz Interattivo - Quiz CLIL
© Istituto Italiano Edizioni Atlas
Video Tutoriali Classe capovolta javadoc Linguaggio XML Capitolo 1 Struttura programma Compilazione esecuzione Eccezioni Inserto A Eclipse NetBeans Capitolo 2 Dichiarazione classe Ereditarietà Polimorfismo
Capitolo 4 Interfaccia grafica (1) Interfaccia grafica (2) Interfaccia grafica (3) Interfaccia grafica (4) Interfaccia grafica (5) Capitolo 7 Emulatori Test e debug Consumi Capitolo 9 Lista della spesa Bordo dell’immagine Pubblicazione
In aggiunta nel DVD
Informati
ca per Isti tu
Il
ti Tecnici
Andrea RIZ ZI
H
Tecnologic
i
uppor to f un z i o nal e e in te g r a ti v o d el v o
Richiami sugli elementi del linguaggio HTML Quick reference di HTML Tabella dei colori Entità Carattere
B
lum
Pagine Web
PRO.TEC ZI
un s
Quick reference Codici Caratteri Linguaggio SQL Java e Android Gesti touch
Agostino LO REN
DVD è
Software e note operative NotePad++ Guida di Adobe Reader Editor XML NetBeans UCanAccess Tomcat Installazione Opzioni di configurazione
eP
RO
Lingu Programm aggio Java a Web e app zione ad oggetti licazioni A ndroid
.T E CH
B
Acronimi DVD info
rmatica. indd Scuola-Lavoro Percorso per le competenze trasversali e per l’orientamento
2
edatlas.it Sul sito di Atlas si trovano gran parte degli approfondimenti presenti anche nel DVD.
© Istituto Italiano Edizioni Atlas
indice dei materiali multimediali
XI
1
Il linguaggio di programmazione
1 Il linguaggio Java INSERTO
A
Gli ambienti di sviluppo in Java
2 Le classi e gli oggetti 3 Le strutture di dati e i file 4 Le interfacce grafiche 5 La programmazione guidata dagli eventi 6 L’accesso ai database con JDBC © Istituto Italiano Edizioni Atlas
ATTIVITÀ 1
Il concetto di classe
Obiettivo: comprendere il concetto di classe nella programmazione a oggetti e codifi care la classe nel linguaggio di programmazione A CASA
Guarda il video tutoriale sulla creazione della classe Cerchio e sulla codifi ca Parte1\Attività1). in Java ( Svolgi la creazione della classe e il calcolo proposto nel video, scrivendo la codifi ca nel linguaggio di programmazione con il tuo computer personale.
CLASSE CAPOVOLTA
IN CLASSE
Chiarisci i tuoi dubbi – fai domande all’insegnante su tutti gli aspetti che non ti sono chiari; – ascolta le domande dei tuoi compagni e prova a rispondere. Metti in pratica – a gruppi di tre, seguendo la traccia del lavoro svolto a casa, create e codifi cate le classi Cilindro e Cubo, defi nendo gli attributi e i metodi per il calcolo del volume dei due solidi. Scrivete poi il programma per il calcolo e validate l’esecuzione. Confrontate con tutta la classe le soluzioni trovate.
ATTIVITÀ 2
La generazione automatica della documentazione con javadoc
Obiettivo: utilizzare lo strumento javadoc per generare in modo automatico le pagine in formato HTML per la documentazione del software A CASA
Leggi il testo che spiega lo strumento javadoc Parte1\Attività2\javadoc.pdf). ( Parte1\Attività2). Guarda il video tutoriale su javadoc ( IN CLASSE
Chiarisci i tuoi dubbi – fai domande all’insegnante su tutti gli aspetti che non ti sono chiari; – ascolta le domande dei tuoi compagni e prova a rispondere. Metti in pratica – a gruppi di due, utilizzando le conoscenze acquisite con il lavoro a casa, scrivete il codice di un programma Java per calcolare la media delle stature di n persone e inserite nel testo del programma i commenti e i tag di commento. Generate poi la documentazione usando lo strumento javadoc. Confrontate con tutta la classe le soluzioni trovate.
© Istituto Italiano Edizioni Atlas
CAPITOLO
1
Il linguaggio Java COMPETENZE • Progettare la struttura generale di un programma Java • Utilizzare correttamente la sintassi del linguaggio e le strutture di controllo • Organizzare i dati in array
CONOSCENZE • Struttura generale di un programma in linguaggio Java • Caratteristiche principali dei dati, delle istruzioni e degli operatori • Elementi di documentazione • Istruzioni di input/output e codifica delle strutture di controllo • Struttura di dati di tipo array
ABILITÀ • Scrivere i programmi utilizzando in modo corretto la sintassi del linguaggio • Riconoscere le diverse fasi del lavoro di programmazione per codificare e validare gli algoritmi • Definire le strutture per dati dello stesso tipo • Gestire le eccezioni
© Istituto Italiano Edizioni Atlas
Per iniziare 1 Quali delle seguenti affermazioni riferite alla struttura iterativa sono vere (V) e quali false (F)? a.
V
F
b.
V
F
c.
V
F
d.
V
F
È un elenco di istruzioni che deve essere ripetuto un certo numero di volte
È un elenco di istruzioni che deve essere ripetuto fino a che non si verifica una fissata condizione È una serie di percorsi alternativi tra cui scegliere
È un elenco di istruzioni da eseguire una dopo l’altra
2 Che cosa produce il seguente algoritmo in pseudocodifica? inizio assegna somma = 0 per k = 1 fino a 10 calcola somma = somma + k ripeti scrivi somma fine a. Scrive i primi 10 numeri interi.
b. Scrive la somma dei primi 10 numeri interi.
c. Scrive la somma dei 10 numeri interi inseriti.
d. Scrive 10 volte la somma dei valori del contatore k.
3 Qual è il valore di b alla fine dell’esecuzione delle seguenti istruzioni in pseudocodifica?
Utilizza la tabella per tenere traccia dell’esecuzione e per determinare il valore finale di b.
a = -3; b = 4; esegui mentre a java Domanda il risultato che si ottiene è il seguente: Editing, compilazione ed esecuzione di un programma Java in Windows
Quanti anni hai?
4
Gli identificatori e le parole chiave
Un programma scritto in Java si compone di parole che si possono classificare in due gruppi: • gli identificatori; • le parole chiave del linguaggio. Gli identificatori sono i nomi che il programmatore assegna alle specifiche componenti del suo programma, per identificare le variabili, i metodi e le classi. Che cosa sono gli identificatori?
Un identificatore è composto da una sequenza di lettere e di numeri. Il primo carattere deve essere una lettera. È anche possibile usare il carattere di sottolineatura _. NOTA BENE Bisogna fare molta attenzione alla scrittura degli identificatori perché Java distingue le lettere maiuscole e minuscole. Per esempio, i seguenti identificatori: Nome NOME sono considerati diversi.
10
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Gli identificatori assumono un ruolo fondamentale per la leggibilità e la comprensione di un programma. Utilizzare identificatori significativi da associare ad attributi, metodi e classi rende il programma autodocumentato. Solitamente si rispettano le seguenti convenzioni: • gli identificatori che si riferiscono al nome di attributi, di metodi e di oggetti cominciano con la prima lettera minuscola (per esempio, nome, voto, aggiorna, auto); • gli identificatori che specificano il nome delle classi iniziano con la lettera maiuscola (per esempio, Libro, Automobile, Rettangolo); • se gli identificatori sono formati da più parole, queste vengono unite e ogni parola successiva alla prima ha l’iniziale maiuscola (per esempio, totFattura, contaSecondi, calcolaMedia). Le parole chiave sono un insieme di parole riservate di Java che non possono essere usate come identificatori.
Parole chiave del linguaggio Java abstract
continue
goto
package
this
assert
default
if
private
throw
boolean
do
implements
protected
throws
break
double
import
public
transient
byte
else
instanceof
return
try
case
enum
int
short
void
catch
extends
interface
static
volatile
char
final
long
super
while
class
finally
native
switch
const
for
new
synchronized
Che cosa sono le parole chiave?
I programmi Java devono essere scritti seguendo le regole dalla sintassi del linguaggio che specifica come combinare tra loro le parole chiave e gli identificatori in modo corretto.
5
Le variabili e le costanti Le variabili sono i contenitori con i quali è possibile memorizzare i dati. Le variabili possono cambiare valore durante l’esecuzione del programma. Gli elementi che caratterizzano una variabile sono il tipo, il nome e la sua visibilità.
In Java la dichiarazione di una variabile assume la seguente forma: tipo nomevariabile; ESEMPIO Se si vuole dichiarare una variabile che deve contenere un valore numerico, si deve scrivere: int prezzo;
Durante la dichiarazione delle variabili è possibile inserire il valore iniziale da assegnare. L’assegnamento di un valore di inizializzazione a una variabile si ottiene usando il segno uguale (=). tipo nomevariabile = valoreiniziale; © Istituto Italiano Edizioni Atlas
CAPITOLO
Come si assegna un valore a una variabile?
1 • IL LINGUAGGIO JAVA
11
ESEMPIO Per assegnare il valore dell’altezza si deve scrivere: double altezza = 1.83;
Una costante, a differenza delle variabili, può assumere un solo valore durante tutta l’esecuzione del programma. Come si dichiara una costante?
Per dichiarare una costante, bisogna far precedere alla dichiarazione la parola chiave final. ESEMPIO Il valore di conversione tra la yard (0.914 metri) e il metro può essere espresso con la costante: final double YARD_METRO = 0.914; Se si tenta di modificare il valore della costante, viene generato un errore di compilazione. NOTA BENE Per convenzione, il nome delle costanti viene indicato tutto in lettere maiuscole. Se si compone di più parole, queste vengono unite con un simbolo di sottolineatura.
La visibilità delle variabili
scope
Non esiste un punto preciso del programma dove dichiarare le variabili. Per comodità e leggibilità del codice conviene raggruppare le dichiarazioni di tutte le variabili nella parte iniziale del blocco di programma in cui verranno utilizzate. In linea di principio ogni variabile può essere dichiarata in qualsiasi punto ma, a seconda della posizione, cambia la sua visibilità. Il campo di visibilità di una variabile è costituito dal blocco dentro al quale è stata dichiarata. All’esterno di questo blocco non viene riconosciuta. Inoltre, dopo la dichiarazione di una variabile, non è possibile dichiarare altre variabili con lo stesso nome, anche all’interno di blocchi annidati. In pratica non si possono verificare situazioni come la seguente: { int a; . . . { int a; } . . .
Qual è il campo di visibilità di una variabile?
}
6
I tipi di dato: primitivi e riferimento
Il tipo di dato stabilisce qual è l’insieme di valori e operazioni accettabili da una variabile. In Java si distinguono due tipi di dato: • tipi primitivi; • tipi riferimento. Come possono essere i dati primitivi? E quelli riferimento?
12
PARTE PRIMA
I tipi di dato primitivi sono analoghi a quelli offerti da tutti i linguaggi di programmazione. Possono essere raggruppati in tre categorie: numerici, carattere e booleani. I tipi di dato riferimento sono gli array (vedi pag. 28) e le classi.
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
I tipi di dato in Java
TIPI DI DATO
primitivi
numerici
interi
carattere
riferimento
booleani
array
classi
virgola mobile
I tipi numerici I tipi numerici sono usati per dichiarare le variabili che possono contenere numeri. Questi tipi si possono distinguere a loro volta in tipi interi e tipi non interi in virgola mobile (o numeri in notazione esponenziale).
Quanti generi di tipi numerici esistono?
I tipi interi, a seconda della loro occupazione di memoria (dimensione), identificano l’intervallo di valori interi che una variabile può assumere. Tipo
Dimensione
Valori
byte
8 bit
da -128 a 127
short
16 bit
da -32.768 a 32.767
int
32 bit
da -2.147.483.648 a 2.147.483.647
long
64 bit
da - 263 a 263-1 ESEMPIO
byte numeroLotto; I valori che può assumere la variabile numeroLotto sono compresi nell’intervallo -128..127. Questo perché il tipo byte, come è indicato nella tabella, richiede un’occupazione di memoria di 8 bit. Con 8 bit è possibile identificare 256 numeri differenti (28 = 256). In generale l’intervallo di valori ammissibile per un tipo intero varia da -2n-1 a 2n-1-1, avendo indicato con n il numero di bit occupati dal tipo. In Java non esistono i tipi unsigned, cioè tipi che contengono solo valori positivi. Esistono due tipi numerici a virgola mobile: usando float si definiscono numeri a singola precisione (con 7 cifre decimali), usando double i numeri sono a doppia precisione (con 16 cifre decimali). Tipo
Dimensione
Precisione
float
32 bit
singola
double
64 bit
doppia ESEMPIO
double peso = 8.573; Si noti che il numero è stato scritto usando anche il valore dei decimali. Indicare un numero in questo modo fa capire al compilatore che si tratta di un numero a doppia precisione. Per indicare un numero a singola precisione si deve aggiungere, dopo il numero, la lettera f (per esempio: 8.573f). © Istituto Italiano Edizioni Atlas
CAPITOLO
1 • IL LINGUAGGIO JAVA
13
I tipi carattere Il tipo di dato carattere è indicato con la parola chiave char. È definito usando 16 bit e la codifica Unicode. Java non utilizza la codifica ASCII per rappresentare i caratteri. ESEMPIO char lettera = 'N';
La codifica Unicode definisce un insieme di caratteri usando due byte. I primi 128 caratteri dell’insieme Unicode sono equivalenti ai caratteri nel codice ASCII. Alcuni caratteri, che non possono essere digitati, vengono rappresentati attraverso le sequenze di escape. Queste sono formate da un backslash (\) seguito da una lettera o da un simbolo. Alcuni esempi di sequenze di escape sono: • \n ritorno a capo; • \t tabulazione; • \\ backslash; • \” doppio apice. Le stringhe sono un tipo di dato che raggruppa un insieme di caratteri. Le stringhe non sono un tipo predefinito, ma sono definite da una apposita classe (String, vedi Capitolo 2 pag. 109). Le sequenze di escape possono essere usate all’interno di una stringa per stampare dei caratteri speciali. ESEMPIO System.out.println("prima riga \n\t seconda riga indentata");
I tipi booleani Il tipo di dato booleano è indicato con la parola chiave boolean. Le variabili dichiarate in questo modo possono assumere due soli valori: true o false. ESEMPIO boolean trovato = true;
Questo tipo di dato non può essere convertito in un tipo di dato numerico.
7
Che cosa si intende per promozione?
14
PARTE PRIMA
Il casting per la conversione di tipo
Il linguaggio Java richiede molta attenzione nell’uso dei tipi di dato: il compilatore controlla che gli assegnamenti vengano effettuati tra variabili dello stesso tipo o di un tipo compatibile. Quasi tutti questi controlli di correttezza di tipo vengono eseguiti durante la fase di compilazione. Si dice anche che Java è fortemente tipizzato. Se per esempio si vuole assegnare un valore intero a una variabile di tipo float, Java effettua automaticamente la conversione perché il tipo float è più grande del tipo intero. Questa conversione, chiamata anche promozione, è permessa perché solitamente non si ha perdita di dati.
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
ESEMPIO int intNum; float floatNum; intNum = 32; floatNum = intNum; La variabile floatNum può ricevere un valore int che viene automaticamente convertito in float. La conversione da float a intero, invece, non viene eseguita automaticamente. Quando invece si tenta di effettuare assegnamenti tra variabili ed espressioni con tipi che sono in conflitto, viene generato un errore. ESEMPIO Usando in un programma le variabili precedenti: floatNum = 13.278f; intNum = floatNum; il secondo assegnamento, durante la fase di compilazione, restituisce un errore: non viene eseguita automaticamente la conversione tra float e int. Se si vuole eseguire l’assegnamento, il programmatore deve indicare esplicitamente la sua volontà, forzando la conversione. Il casting è il meccanismo che consente al programmatore di indicare la conversione da un tipo di dato a un altro tipo. Il casting si effettua in pratica anteponendo al valore da convertire, tra parentesi tonde, il tipo di dato in cui sarà convertito.
Che cos’è e come si esegue il casting?
ESEMPIO Nell’esempio precedente, il casting viene effettuato aggiungendo (int) prima della variabile floatNum. floatNum = 13.278f; intNum = (int) floatNum; In questo caso la conversione produce le perdita di tutte le cifre decimali. Nella variabile intNum resta memorizzato solo il valore intero 13. Il casting esplicito è previsto per evitare la perdita di dati nella conversione tra tipi. Java non consente la conversione automatica tra tipi che comportano una perdita di dati, ma lascia la possibilità di effettuare la conversione se viene esplicitamente richiesta. Il casting è uno strumento utile anche quando all’interno di un’espressione si usano tipi di dato diversi. ESEMPIO Se si dividono due numeri interi, il risultato della divisione è un numero intero. Quindi eseguendo 20/6 il risultato è 3, che è un risultato non corretto. int numeratore = 20; int denominatore = 6; double risultato; risultato = numeratore / denominatore;
© Istituto Italiano Edizioni Atlas
CAPITOLO
1 • IL LINGUAGGIO JAVA
15
La variabile risultato contiene il valore 3.0. Per ottenere il risultato corretto, con le cifre decimali, si deve effettuare un casting del numeratore prima di fare la divisione. risultato = (double) numeratore / denominatore; Con questa modifica, alla variabile risultato viene assegnato il valore 3.3333333333333335.
8
Gli operatori Gli operatori sono i caratteri speciali che identificano particolari operazioni sui dati. Per esempio si possono usare gli operatori matematici per le operazioni tra i numeri oppure l’operatore di concatenazione tra le stringhe. Operatori del linguaggio Java
=
>
>>>
+=
-=
*=
/=
&=
|=
^=
%=
=
>>>=
Le operazioni aritmetiche di base possono essere eseguite con i quattro operatori fondamentali: +, -, *, /. L’operatore % è usato per calcolare il resto della divisione tra due numeri. ESEMPIO int num1 = 25; int num2 = 7; int modulo; modulo = num1 % num2;
A che cosa servono le parentesi tonde?
alla variabile modulo viene assegnato il valore 4
Se la formula da implementare si compone di più fattori è consigliabile l’utilizzo delle parentesi tonde per rendere chiaro e non ambiguo l’ordine di esecuzione dei vari operatori aritmetici. ESEMPIO risultato = ((a + b) / (c – d)) * e;
Ci sono due operatori di incremento e di decremento che aggiungono o tolgono 1 al valore della variabile: ++ e – –. L’istruzione: i++; corrisponde all’istruzione: i = i + 1; In Java l’assegnamento di un valore a una variabile viene eseguito usando l’operatore di assegnamento =.
16
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Oltre a questo operatore esistono altri operatori di assegnamento. Sono tutti caratterizzati dal segno = preceduto da un altro operatore. Tra gli operatori composti di assegnamento ci sono: +=, –=, *=, /=, %=. Questi operatori rappresentano la combinazione di un’operazione di calcolo e di un assegnamento. ESEMPIO
Quali sono gli operatori di assegnamento?
L’istruzione: totale *= 10; corrisponde all’abbreviazione della seguente: totale = totale * 10; Le stringhe possono essere concatenate tra loro usando l’operatore di concatenazione +. Esso consente anche di concatenare una stringa con un numero, eseguendo automaticamente la conversione del numero in stringa. Questa possibilità è molto utile con il metodo println per l’output dei risultati (vedi pag. 18), perché permette di stampare sia testo che numeri. ESEMPIO int sco = 20; System.out.println("sconto = " + sco + "%");
PER APPROFONDIRE
LA NOTAZIONE PREFISSATA E POSTFISSATA Gli operatori di incremento e di decremento possono essere posizionati dopo il nome della variabile (postfissi) oppure prima del nome della variabile (prefissi). La diversa posizione modifica il comportamento dell’operatore: specifica se l’incremento o decremento di una variabile deve essere fatto prima o dopo il suo impiego nell’espressione di calcolo. ESEMPIO Nel caso seguente l’operatore è postfisso: int num; int risultato;
la variabile risultato assume il valore 7, num diventa 11
num = 10; risultato = (num++) - 3; L’ultima istruzione è equivalente alle seguenti istruzioni: risultato = num - 3; num = num + 1; Di seguito viene mostrato l’esempio con l’operatore prefisso: num = 10; risultato = (++num) - 3
la variabile risultato assume il valore 8, num il valore 11
L’ultima istruzione è equivalente alle seguenti istruzioni: num = num + 1; risultato = num - 3;
© Istituto Italiano Edizioni Atlas
CAPITOLO
1 • IL LINGUAGGIO JAVA
17
9
I commenti e la documentazione
All’interno dei programmi Java possono essere inserite frasi contenenti commenti o annotazioni del programmatore, con cui è possibile documentare il significato delle variabili o delle costanti utilizzate oppure la funzione svolta da una parte del programma. In Java ci sono tre forme per rappresentare i commenti. • La prima forma (commento di riga) utilizza i caratteri //. Tutto quello che viene scritto dopo questi caratteri e sulla stessa riga è considerato un commento. Questa modalità è usata per i commenti brevi. ESEMPIO int eta; // dichiarazione di una variabile intera • La seconda forma di commento è /* … */. Tutto il testo compreso tra i caratteri di inizio /* e quelli di termine */ viene considerato un commento. Questa forma consente di dividere il commento su più righe. ESEMPIO /* commento che occupa più righe */ • La terza forma è /** … */, dove al posto dei puntini va inserito un commento. Funziona come il commento su più righe. Rappresenta un commento di documentazione e può essere usata prima di dichiarare una classe o un metodo. Questa particolare forma di commento è importante perché viene riconosciuta dagli strumenti per la generazione automatica della documentazione dei programmi.
Quali forme vengono usate per indicare i commenti?
ESEMPIO /** Funzione per calcolare il MCD tra due numeri */ public void calcolaMCD(int a, int b) { // istruzioni }
Operatori logici per le operazioni sui dati bit a bit
L’uso frequente delle frasi di commento deve diventare un’abitudine del programmatore fin dai primi semplici esercizi: in questo modo possono essere costruiti programmi che si autodocumentano e che possono essere compresi e letti facilmente a distanza di tempo, anche da persone diverse dal programmatore che ha scritto il programma.
10
La gestione dell’input/output
Le operazioni di input e output possono essere eseguite utilizzando un’interfaccia a caratteri.
Le operazioni di output In alcuni esempi precedenti è già stata presentata la modalità per scrivere sul video con istruzioni come la seguente: System.out.println("messaggio da visualizzare"); System.out rappresenta un oggetto associato allo standard output. Esiste anche un oggetto associato allo standard error, che è System.err. Entrambi fanno riferimento, in assenza di una diversa specifica (cioè per default), allo schermo.
18
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Sull’oggetto System.out viene invocato il metodo println, con un parametro che rappresenta il valore da visualizzare. Il parametro può essere una stringa, un numero intero o reale, un carattere o un booleano. Quando il metodo println viene richiamato, esso stampa sul video il parametro e inserisce un ritorno a capo. Con l’oggetto System.out è possibile utilizzare anche il metodo print: esso stampa il parametro passato, ma non stampa il ritorno a capo. I metodi print e println ricevono un unico parametro, ma utilizzando l’operatore + è possibile concatenare stringhe e numeri.
Qual è la differenza tra i metodi printIn e print?
PROVIAMO INSIEME
1 VARIABILI DI TIPO DIVERSO Scrivere un programma che consenta di stampare il valore di 3 variabili: un numero intero, un numero reale e un booleano Il programma dichiara 3 variabili di tipo diverso, alle quali vengono assegnati 3 valori. L’operazione di stampa visualizza i valori assegnati. Programma Java (Stampa.java) /** * Programma per la stampa di tre variabili. */ class Stampa { public static void main(String args[]) { // dichiarazione delle variabili int intero = 5; float reale = 25.68f; boolean trovato = false;
CODIFICA
// operazioni di stampa System.out.println("Numero intero = " + intero); System.out.println("Numero reale = " + reale); System.out.println("Trovato = " + trovato); } } Nella dichiarazione del numero reale è stata aggiunta la lettera f dopo il numero: infatti il solo numero sarebbe interpretato come un numero di tipo double, che non può essere assegnato a una variabile di tipo float. L’aggiunta della lettera f equivale a effettuare un casting. In alternativa si può svolgere la dichiarazione anche in questo modo: float reale = (float) 25.68; Il risultato dell’esecuzione di questo programma è: Numero intero = 5 Numero reale = 25.68 Trovato = false
Le operazioni di input Per le operazioni di input esiste un oggetto analogo System.in che gestisce il flusso di dati inseriti da tastiera. L’oggetto System.in, in pratica, viene mascherato con altri oggetti più potenti che forniscono maggiori funzionalità. © Istituto Italiano Edizioni Atlas
CAPITOLO
1 • IL LINGUAGGIO JAVA
19
Si utilizza la classe BufferedReader nel seguente modo: InputStreamReader input = new InputStreamReader(System.in); BufferedReader tastiera = new BufferedReader(input); Con queste dichiarazioni viene definito un oggetto tastiera, di classe BufferedReader, usando l’operatore new che crea un nuovo oggetto (vedi pag. 62). La classe BufferedReader mette a disposizione il metodo readLine che consente di leggere, in questo caso da standard input, una riga per volta. Una linea viene considerata terminata quando viene premuto il tasto di Invio. Questo metodo restituisce solo stringhe, quindi se si vogliono acquisire valori numerici si deve effettuare la conversione tra stringhe e numeri. Per effettuare la lettura di una stringa occorre dichiarare una variabile stringa e poi usare il metodo readLine con l’oggetto tastiera che è stato definito in precedenza: String nome; nome = tastiera.readLine(); L’operazione deve essere completata considerando le eccezioni che possono essere generate dal metodo readLine. L’eccezione segnala una situazione anomala: quando si verifica un’eccezione, bisogna prevedere un blocco di istruzioni per gestire questa situazione. Il costrutto try ... catch ... (vedi pag. 32) raggruppa le istruzioni da controllare e dichiara il nome dell’eccezione che si vuole gestire; in particolare la classe Exception indica un’eccezione generica. Quindi la lettura di una stringa si effettua correttamente nel seguente modo:
Come si esegue la lettura di una stringa?
String nome; try { nome = tastiera.readLine(); } catch(Exception e) {}
il segmento di codice stabilisce che, al verificarsi dell’eccezione, non deve essere effettuata alcuna operazione
Per effettuare la lettura di numeri, occorre convertire la stringa ottenuta dall’operazione di input nel seguente modo: String leggiNumero; int num; try { leggiNumero = tastiera.readLine(); num = Integer.valueOf(leggiNumero).intValue(); } catch(Exception e) { System.out.println("\nNumero non corretto!"); return; } L’istruzione aggiuntiva consente di convertire una stringa in un numero intero, attraverso due metodi della classe Integer: valueOf converte il parametro stringa in un oggetto di classe Integer, mentre intValue restituisce un valore intero. In questo caso, l’eccezione che può essere generata si verifica quando i caratteri inseriti non corrispondono a cifre numeriche. ESEMPIO Se si inseriscono i valori 34f5 oppure 45.45, essi non vengono riconosciuti come interi e quindi provocano un’eccezione che causa la terminazione del programma.
20
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Per leggere un numero a virgola mobile, occorre cambiare il modo di conversione. ESEMPIO Come si esegue la lettura di numeri?
Se si vuole ottenere un valore float, si deve scrivere: numFloat = Float.valueOf(leggiNumero).floatValue(); In modo del tutto analogo, per ottenere un valore double: numDouble = Double.valueOf(leggiNumero).doubleValue();
PROVIAMO INSIEME
1 LA MEDIA DELLE ETÀ Leggere da tastiera l’età di tre persone e calcolare l’età media Il programma acquisisce da tastiera le età con tre operazioni di input. Viene poi calcolata la media sommando i 3 numeri e dividendo per 3. Alla fine si visualizza il risultato del calcolo. Algoritmo in pseudocodifica inizio immetti eta1 immetti eta2 immetti eta3 calcola media = (eta1 + eta2 + eta3) /3 scrivi media fine Programma Java (Media.java) import java.io.*;
CODIFICA
class Media richiama la libreria java.io, che { contiene le classi InputStreamReader public static void main(String args[]) e BufferedReader usate per leggere dallo standard input { // impostazione dello standard input InputStreamReader input = new InputStreamReader(System.in); BufferedReader tastiera = new BufferedReader(input); // dichiarazione delle variabili int eta1, eta2, eta3; int media; System.out.println("Persona 1 ***************"); System.out.print("eta': "); try { String numeroLetto = tastiera.readLine(); eta1 = Integer.valueOf(numeroLetto).intValue(); } catch(Exception e) { System.out.println("\nNumero non corretto!"); return; }
quando si verifica un’eccezione durante la lettura, viene mostrato un messaggio di errore e l’istruzione return interrompe l’esecuzione del metodo main, causando la fine del programma
System.out.println("Persona 2 ***************"); System.out.print("eta': "); try { String numeroLetto = tastiera.readLine();
© Istituto Italiano Edizioni Atlas
CAPITOLO
1 • IL LINGUAGGIO JAVA
21
eta2 = Integer.valueOf(numeroLetto).intValue(); } catch(Exception e) { System.out.println("\nNumero non corretto!"); return; } System.out.println("Persona 3 ***************"); System.out.print("eta': "); try { String numeroLetto = tastiera.readLine(); eta3 = Integer.valueOf(numeroLetto).intValue(); } catch(Exception e) { System.out.println("\nNumero non corretto!"); return; } media = (eta1 + eta2 + eta3) / 3; System.out.println("\nEta' media: " + media);
quando si verifica un’eccezione durante la lettura, viene mostrato un messaggio di errore e l’istruzione return interrompe l’esecuzione del metodo main, causando la fine del programma
calcolo e output del risultato
} }
11 Come si indica la struttura di sequenza?
Le strutture di controllo: sequenza
La struttura di sequenza viene realizzata posizionando le istruzioni una di seguito all’altra e separandole con il punto e virgola. Ogni dichiarazione e istruzione deve terminare con il punto e virgola.
PROVIAMO INSIEME
1 ORE, MINUTI E SECONDI Costruire un programma che, dopo aver acquisito l’ora del giorno espressa come numero di secondi, converta il valore dai secondi al formato ore:minuti:secondi Un’ora si compone di 60 minuti e ogni minuto è composto da 60 secondi. Un’ora contiene quindi 3600 secondi. Le ore 8:00 possono essere espresse in secondi con il valore 28800, ottenuto moltiplicando 8 x 60 x 60. Avendo il totale dei secondi, per ottenere le ore si procede per divisioni successive, sfruttando l’operatore / per la divisione intera e l’operatore % per calcolare il resto della divisione. Algoritmo in pseudocodifica inizio immetti orario calcola ore = orario / 3600 calcola minuti = (orario % 3600) / 60 calcola secondi = orario % 60 scrivi orario H:M:S fine
22
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Programma Java (Orario.java) class Orario { public static void main(String args[]) { // dati di input int orario = 41345;
CODIFICA valore di inizializzazione per la variabile orario
// dati di output int ore, minuti, secondi; // calcolo sequenziale ore = orario / 3600; minuti = (orario % 3600) / 60; secondi = orario % 60; // stampa orario System.out.println("Orario: "
operatore / per la divisione intera; operatore % per il resto della divisione
+ ore + ":" + minuti + ":" + secondi);
} }
12
Le strutture di controllo: selezione
La struttura di selezione consente di far eseguire particolari istruzioni in alternativa ad altre sulla base del risultato di una condizione. Se la condizione è vera viene eseguito un blocco di istruzioni, altrimenti ne viene eseguito un altro. I blocchi sono indicati con le parentesi graffe. In Java la selezione è realizzata con il seguente costrutto: if (condizione) { // istruzioni eseguite se la condizione è vera } else { // istruzioni eseguite se la condizione è falsa }
Come si rappresenta la struttura di selezione?
Il blocco indicato da else può non essere presente. Se il blocco è formato da una sola istruzione, si può evitare di mettere le parentesi graffe. Comunque l’uso delle parentesi, anche in presenza di una sola istruzione, serve per ottenere una maggiore leggibilità ed evitare possibili errori di interpretazione. La condizione che segue l’if può essere una variabile di tipo boolean oppure un’espressione che contiene gli operatori di confronto o gli operatori booleani. ESEMPIO Gli operatori di confronto L’operatore di uguaglianza è rappresentato da due simboli di uguale (==). La disuguaglianza (diverso da) è espressa usando l’operatore !=. Gli altri operatori di confronto sono =. © Istituto Italiano Edizioni Atlas
Con la seguente struttura di selezione, sul video viene scritto il messaggio sufficiente se il voto è uguale a 6. if (voto == 6) { System.out.println("sufficiente"); }
CAPITOLO
NOTA BENE L’operatore di uguaglianza non deve essere confuso con l’operatore di assegnamento =, che usa un solo segno di uguale.
1 • IL LINGUAGGIO JAVA
23
Gli operatori booleani Gli operatori booleani vengono applicati a due valori booleani e restituiscono il risultato in base alle regole dell’algebra booleana: • l’operatore && (oppure &) indica l’operazione di AND; • l’operatore || (oppure |) indica l’operazione di OR; • l’operatore ! esprime la negazione NOT.
Quali sono gli operatori di confronto? E quelli booleani?
I due operatori di AND e i due di OR forniscono gli stessi risultati. La differenza, tuttavia, si nota in termini di efficienza. L’espressione (cond1 && cond2) è equivalente a (cond1 & cond2): è vera solo se entrambe cond1 e cond2 sono vere, mentre basta che una condizione sia falsa per rendere falsa l’espressione. Tuttavia l’uso di && è più efficiente perché, durante la valutazione, se cond1 è falsa, cond2 non viene valutata, dato che comunque l’espressione è sicuramente falsa. Al contrario l’operatore & valuta sempre entrambe le condizioni. È quindi utile usare come operatori booleani && e ||. ESEMPIO if ((ora >= 12) && (ora 0) { return false; } else { return true; } }
}
public int size() { return elementi.size(); }
continua nell’esercizio seguente
2 UNA PILA DI NUMERI CASUALI Popolare una pila con dieci numeri casuali e svuotarla mostrando che l’ordine degli elementi viene invertito, dall’ultimo al primo Si utilizza la classe precedentemente definita all’interno di un semplice programma che mostra come vengono inseriti ed eliminati gli elementi di una pila. I numeri interi non possono essere inseriti direttamente nella pila perché quest’ultima accetta solo gli oggetti. Per superare questo problema si deve creare un’istanza della classe Integer che incorpora il valore di un numero intero all’interno di un oggetto: numObj = new Integer(num); A questo punto si può utilizzare questo oggetto per le operazioni con la pila. Nel momento in cui l’oggetto viene prelevato dalla pila, tramite l’operazione pop, bisogna effettuare il casting dell’oggetto verso la classe originaria, che in questo caso è la classe Integer. numObj = (Integer) pila.pop();
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
135
Programma Java (ProgPila.java) class ProgPila { public static void main(String args[]) { // crea una pila vuota Pila pila = new Pila();
CODIFICA
int num; Integer numObj; genera un numero // aggiunge elementi alla pila casuale for(int i=0; i
© Istituto Italiano Edizioni Atlas
togli()
gli elementi aggiunti alla coda vengono posizionati nel vettore dopo l’ultimo elemento inserito
= null; elementi.size(); 0)
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
137
{ obj = elementi.elementAt(0); elementi.removeElementAt(0);
}
} return obj;
public boolean vuota() { if (elementi.size() > 0) { return false; } else { return true; } } public int size() { return elementi.size(); }
}
gli elementi vengono tolti dalla coda sempre dalla posizione 0
controlla se la coda non contiene elementi
restituisce il numero di elementi presenti nella coda
continua nell’esercizio seguente
2 LE ORDINAZIONI AL BAR
Creare un programma che simuli il funzionamento di un bar. Può essere inclusa la precedente classe in un programma Java che utilizza le code Un bar può essere immaginato in modo semplificato come un servizio in cui i clienti generano delle ordinazioni e i gestori soddisfano queste ordinazioni. Ogni ordinazione è rappresentata dal numero del tavolo e dal contenuto dell’ordine e può essere descritta con il seguente diagramma di classe: Ordine tavolo ordine stampa
Implementazione della classe (Ordine.java) class Ordine { private String tavolo; private String ordine;
CODIFICA
public Ordine(String tav, String ord) { tavolo = tav; ordine = ord; }
138
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
}
public void stampa() { System.out.println("Tavolo: " + tavolo); System.out.println("Ordine: " + ordine); }
Programma Java (ProgBar.java) class ProgBar { public static void main(String args[]) { Coda codaOrdinazioni = new Coda(); Ordine ord;
le ordinazioni vengono organizzate in una coda, dichiarata come un oggetto di classe Coda
ord = new Ordine("05", "4 caffe'"); codaOrdinazioni.aggiungi(ord); System.out.println("––Aggiunto ordine");
}
CODIFICA
un ordine viene aggiunto alla coda delle ordinazioni nel momento in cui viene generato dal cliente ordina
ord = new Ordine("03", "2 bibite"); codaOrdinazioni.aggiungi(ord); System.out.println("––Aggiunto ordine");
ordina
ord = new Ordine("11", "1 caffe' e 2 bibite"); codaOrdinazioni.aggiungi(ord); System.out.println("––Aggiunto ordine");
ordina
ord = (Ordine) codaOrdinazioni.togli(); System.out.println("Soddisfatto ordine:"); ord.stampa();
soddisfa
ord = new Ordine("15", "1 cappuccino"); codaOrdinazioni.aggiungi(ord); System.out.println("––Aggiunto ordine");
ordina
ord = (Ordine) codaOrdinazioni.togli(); System.out.println("Soddisfatto ordine:"); ord.stampa();
soddisfa
ord = (Ordine) codaOrdinazioni.togli(); System.out.println("Soddisfatto ordine:"); ord.stampa();
soddisfa
ord = (Ordine) codaOrdinazioni.togli(); System.out.println("Soddisfatto ordine:"); ord.stampa();
soddisfa
i gestori del bar prelevano le ordinazioni dalla coda e le soddisfano
}
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
139
La classe Stack e l’interfaccia Queue nel package Java.util
Nel precedente Proviamo insieme viene usata un’unica variabile ord per creare e riferirsi a vari oggetti di classe Ordine. Il riutilizzo della stessa variabile non comporta l’eliminazione dell’oggetto precedentemente creato, in quanto la variabile contiene solo il riferimento all’oggetto. Quando l’oggetto viene inserito nella coda, viene generato un duplicato di questo riferimento all’interno del vettore che gestisce la coda. Diventa così possibile riutilizzare la variabile ord per referenziare altri oggetti senza che l’ordine precedente venga perso.
5 linked list
La lista concatenata La lista concatenata è una struttura di dati in cui gli elementi sono organizzati in sequenza. Ogni elemento conosce qual è il suo successore e in questo modo, a partire dal primo elemento, è possibile ricostruire tutti gli elementi presenti nella lista.
Oltre a gestire strutture ordinate, la lista ha il vantaggio di inserire e cancellare i dati in modo più veloce rispetto ad altre soluzioni. Con le liste concatenate, dopo che è stata trovata la posizione, l’inserimento è immediato. La stessa operazione eseguita con un array risulta molto più costosa in quanto, per fare spazio al nuovo elemento, si devono spostare tutti gli elementi di un posto.
Come è composta una lista concatenata?
Una lista può essere vista come una successione di nodi, in cui ogni nodo è costituito dai dati relativi all’elemento stesso più un riferimento al nodo successivo. Per tenere traccia di questa successione è necessario conoscere il riferimento al primo elemento della lista (testa) e all’ultimo elemento (coda). Il riferimento alla testa è utile perché, partendo da questo, è possibile scorrere l’intera lista eseguendo un’operazione chiamata di attraversamento. Il riferimento alla coda è utile per aggiungere rapidamente un elemento in fondo alla lista senza doverla scorrere per recuperare l’ultimo nodo. Graficamente, una lista concatenata può essere rappresentata nel seguente modo: LISTA
Il funzionamento della lista concatenata
testa coda
null NODO
NODO
NODO
Nel linguaggio C++ le liste concatenate vengono gestite utilizzando i puntatori. In Java vengono invece utilizzati i riferimenti agli oggetti che in pratica svolgono lo stesso ruolo dei puntatori, ma la cui gestione è in buona parte demandata al modulo run-time di Java. La lista concatenata viene schematizzata con il seguente diagramma di classe: Lista concatenata testa coda inserisci elimina contiene
Le operazioni di modifica sono: • inserisci: inserisce un elemento nella lista; • elimina: preleva un elemento specifico dalla lista.
140
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
L’operazione di inserimento può essere a sua volta di vari tipi a seconda di come si vuole aggiungere l’elemento alla lista. Gli elementi potrebbero essere aggiunti in testa, in coda oppure all’interno della lista, se occorre rispettare un particolare ordine nella generazione della lista. Ogni operazione di inserimento deve essere implementata con un metodo diverso. L’operazione di interrogazione è contiene: controlla se nella lista è presente un particolare elemento. Esistono anche altre operazioni minori di interrogazione, per esempio un’operazione che controlla se la lista è vuota o un’operazione che conta gli elementi nella lista.
Quali operazioni possono essere svolte in una lista concatenata?
PROVIAMO INSIEME
1 UNA LISTA DI PAROLE
Costruire una lista di parole organizzate in ordine alfabetico Deve essere costruita una lista concatenata i cui elementi contengono un dato di tipo stringa. Il nodo della lista contiene due attributi: • dato è l’informazione che viene memorizzata nel nodo (in questo caso si tratta di una parola); • successivo è un riferimento al nodo successivo; l’ultimo nodo della lista assegna il valore null all’attributo successivo. Nodo dato successivo setSuccessivo getSuccessivo getDato
Le operazioni set e get sono utilizzate per accedere e modificare gli attributi del nodo che sono dichiarati con il modificatore private. La lista che si vuole realizzare consente le seguenti operazioni: • inserimento di un nuovo elemento in ordine alfabetico; • eliminazione di un elemento specificato; • controllo circa la presenza di un elemento specificato nella lista; • stampa della lista in ordine alfabetico. Lista testa coda inserisci elimina contiene stampa
Gli attributi testa e coda sono oggetti di classe Nodo che vengono dichiarati e inizializzati nel seguente modo: private Nodo testa = null; private Nodo coda = null; Il metodo inserisci viene implementato considerando quattro situazioni: 1. il nuovo elemento viene aggiunto in testa e la lista è vuota; 2. il nuovo elemento viene aggiunto in testa e la lista contiene elementi; 3. il nuovo elemento viene aggiunto all’interno della lista; 4. il nuovo elemento viene aggiunto in coda alla lista. © Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
141
La prima istruzione contenuta nel metodo inserisci è la creazione di un nuovo nodo, poi in base alla situazione si effettuano altre operazioni. L’inserimento in ordine alfabetico viene gestito utilizzando il metodo compareTo contenuto nella classe String. Questo metodo esegue un confronto lessicografico tra due stringhe; la prima è quella da cui viene invocato il metodo, mentre la seconda stringa è indicata dal parametro. Il metodo compareTo restituisce il valore zero se le stringhe sono uguali, un valore minore di zero se la prima stringa è minore della seconda in senso lessicografico, un valore maggiore di zero se la prima stringa è maggiore della seconda. Il metodo elimina viene implementato considerando tre situazioni: 1. l’elemento da eliminare si trova in testa alla lista; 2. l’elemento da eliminare si trova all’interno della lista; 3. l’elemento da eliminare si trova in coda alla lista. Nella situazione 1 viene modificato il riferimento dell’attributo testa facendolo puntare al secondo elemento della lista. Nella situazione 2 viene modificato il riferimento dell’attributo successivo relativo al nodo che precede l’elemento da eliminare. Nella situazione 3 si ripete l’operazione effettuata nella situazione 2 e in più si aggiorna il riferimento dell’attributo coda facendolo puntare al penultimo elemento della lista. Il metodo contiene scorre la lista partendo dalla testa e si ferma quando trova l’elemento cercato oppure quando termina la lista. Il metodo stampa scorre la lista dalla testa fino alla coda visualizzando tutti gli elementi. Entrambi questi metodi si basano su un ciclo che possiede la seguente struttura: Nodo temp = testa; while (temp != null) { // operazioni sull'elemento temp
}
temp = temp.getSuccessivo();
Il programma completo per la gestione della lista concatenata viene riportato di seguito. Implementazione della classe (Nodo.java) class Nodo { private String dato; private Nodo successivo;
CODIFICA
public Nodo(String dato) { this.dato = dato; successivo = null; } public void setSuccessivo(Nodo succ) { successivo = succ; } public Nodo getSuccessivo() { return successivo; }
142
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
}
public String getDato() { return dato; }
Implementazione della classe (Lista.java) class Lista { private Nodo testa = null; private Nodo coda = null;
CODIFICA dichiarazione e inizializzazione
// costruttore vuoto public Lista() {} public void inserisci(String str) { Nodo n = new Nodo(str); Nodo temp, succ; boolean aggiunto;
creazione di un nuovo nodo
if (testa == null) { testa = coda = n; } else { // controlla se va inserito in testa if (str.compareTo(testa.getDato()) < 0) { n.setSuccessivo(testa); testa = n; } else { // controlla all'interno della lista aggiunto = false; temp = testa; succ = testa.getSuccessivo(); while (succ != null) { if (str.compareTo(succ.getDato()) < 0) { temp.setSuccessivo(n); n.setSuccessivo(succ); aggiunto = true; break; } temp = succ; succ = succ.getSuccessivo(); } // controlla se va inserito in coda if (!aggiunto) {
© Istituto Italiano Edizioni Atlas
il nuovo elemento viene aggiunto in testa se la lista è vuota
il nuovo elemento viene aggiunto in testa se la lista contiene elementi e se è minore, in senso lessicografico, dell’attuale elemento in testa
il nuovo elemento viene aggiunto all’interno della lista
il nuovo elemento viene aggiunto in coda alla lista
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
143
}
}
}
}
coda.setSuccessivo(n); coda = n;
public void elimina(String str) { Nodo temp, succ; if (testa == null) return; l’elemento da eliminare si
trova in testa alla lista if (str.equals(testa.getDato())) { // elimina l'elemento in testa testa = testa.getSuccessivo(); } else { temp = testa; l’elemento da eliminare si trova all’interno della lista succ = testa.getSuccessivo(); while (succ != null) { if (str.equals(succ.getDato())) { temp.setSuccessivo(succ.getSuccessivo()); break; } temp = succ; succ = succ.getSuccessivo(); }
}
}
// controlla se e' stata modificata la coda della lista if (temp.getSuccessivo() == null) { coda = temp; }
public boolean contiene(String str) { Nodo temp;
scorre la lista partendo dalla testa: si arresta quando trova l’elemento cercato oppure quando termina la lista
temp = testa; while (temp != null) { if (str.equals(temp.getDato())) { return true; } temp = temp.getSuccessivo(); } return false; }
144
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
public void stampa() { Nodo temp;
}
}
visualizza tutti gli elementi della lista
System.out.println("Contenuto lista:"); temp = testa; while (temp != null) { System.out.println(temp.getDato()); temp = temp.getSuccessivo(); }
continua nell’esercizio seguente
2 STAMPARE I DATI DI UNA LISTA
Inserire nella lista cinque parole e stampare l’elenco in ordine alfabetico
Avendo a disposizione la classe Lista, il programma risulta molto conciso e utilizza le operazioni inserisci e stampa implementate nella stessa classe. Programma Java (ProgLista.java) class ProgLista { public static void main(String args[]) { Lista l = new Lista(); l.inserisci("rosso"); l.inserisci("indaco"); l.inserisci("nero"); l.inserisci("azzurro"); l.inserisci("verde"); l.stampa(); } }
6
CODIFICA
L’albero L’albero è una struttura di dati dinamica definita come un insieme di nodi connessi tra loro in modo che non esistano cicli. Questo significa che non ci sono percorsi chiusi che permettono, partendo da un nodo, di tornare allo stesso senza ripercorrere lo stesso tratto due volte.
Tra i nodi che compongono un albero si distinguono: • la radice: è il nodo da cui partono le connessioni che generano l’albero; • le foglie: sono i nodi esterni che non hanno nodi figli; • i nodi interni: sono i nodi che non sono né radice né foglie. © Istituto Italiano Edizioni Atlas
Che cos’è un albero? Da quali elementi è formato?
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
145
ESEMPIO Un esempio di albero è l’organizzazione dei file su disco gestita dal file system del sistema operativo. La radice è la directory principale, i nodi interni sono le altre directory e le foglie sono i file. root \ temp
studenti program
utenti Giulio fisica
relaz.doc
Mario
AZ
matem
primo.doc
Aldo
contab
curva.txt
cli.dat
movim.dat
Un caso particolare di albero è costituito dall’albero binario, nel quale ogni nodo ha al massimo due nodi figli chiamati sottoalbero sinistro e sottoalbero destro. I due sottoalberi sono ancora alberi binari e quindi potranno essere vuoti oppure essere costituiti da nodi con due sottoalberi. La definizione di albero binario può essere espressa in modo sintetico con la ricorsione, cioè usando il concetto di albero binario per spiegare che cos’è l’albero binario stesso. Che cosa contraddistingue un albero binario?
Un albero binario è un insieme vuoto oppure è costituito da un nodo, detto radice, a cui sono collegati al massimo due alberi binari.
L’albero binario
NODO
Sottoalbero sinistro
Sottoalbero destro
L’albero binario viene schematizzato con il seguente diagramma di classe: Albero radice inserisci elimina contiene
Le operazioni di modifica sono: • inserisci: inserisce un elemento nell’albero; • elimina: preleva un elemento specifico dall’albero. L’operazione di interrogazione è contiene: controlla se nell’albero è presente un particolare elemento. Esistono anche altre operazioni di interrogazione, per esempio quella che stampa il contenuto dell’albero. Un albero binario di ricerca è un particolare albero binario in cui i nodi sono ordinati per valore e in cui le operazioni di ricerca e modifica risultano efficienti. Come sono organizzati i nodi di un albero binario di ricerca?
146
PARTE PRIMA
Nell’albero binario di ricerca i nodi vengono organizzati seguendo questo criterio: dato un nodo con un certo valore, tutti i nodi con un valore inferiore sono inseriti nel suo sottoalbero sinistro, mentre i nodi con un valore maggiore sono inseriti nel suo sottoalbero destro.
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
PROVIAMO INSIEME
1 L’IMPLEMENTAZIONE DELL’ALBERO BINARIO
Costruire il programma per gestire le operazioni di modifica e interrogazione su un albero binario È possibile usare un albero binario per gestire i dati che possono essere ordinati attraverso un codice numerico. Il nodo dell’albero contiene cinque attributi: • codice, descrizione: rappresentano l’informazione associata al singolo nodo dell’albero; • eliminato: è un attributo booleano che specifica se il nodo è stato eliminato; • sinistro, destro: sono i riferimenti ai nodi che identificano il sottoalbero di sinistra e il sottoalbero di destra.
L’operazione stampa visualizza sullo schermo il codice e la descrizione, indicando anche se il nodo è stato eliminato. I riferimenti al sottoalbero sinistro e destro sono dichiarati come oggetti pubblici di classe Nodo nel seguente modo: NOTA BENE public Nodo sinistro; public Nodo destro;
Questa modalità di dichiarazione introduce una situazione ricorsiva, in cui gli attributi della classe Nodo fanno riferimento alla classe che stanno definendo.
Il diagramma della classe Nodo è il seguente: Nodo codice descrizione eliminato sinistro destro stampa
Le operazioni previste per la classe Albero consentono di aggiungere e togliere nodi, ricercare un nodo all’interno dell’albero e visualizzare i dati contenuti nella struttura. Albero radice inserisci elimina contiene stampaInordine stampaPreordine stampaPostordine
L’albero ha un unico attributo radice che fa riferimento al nodo radice dell’albero e viene dichiarato con l’istruzione: public Nodo radice; Oltre alle classiche operazioni di inserimento (inserisci), eliminazione (elimina) e ricerca (contiene) sono presenti tre tipi di operazioni di stampa. Essi rappresentano i tre modi in cui un albero può essere attraversato (o visitato): • stampaInordine: l’attraversamento è eseguito in ordine simmetrico (prima il sottoalbero di sinistra, poi la radice, poi il sottoalbero di destra); • stampaPreordine: l’attraversamento è eseguito in ordine anticipato (prima la radice, poi il sottoalbero di sinistra e il sottoalbero di destra); • stampaPostordine: l’attraversamento è eseguito in ordine posticipato (prima il sottoalbero di sinistra e il sottoalbero di destra, poi la radice). Se si vuole ottenere una stampa in ordine di codice si deve utilizzare l’operazione stampaInordine. Tutti i metodi della classe Albero sono presenti in doppia versione: una pubblica e una privata. In questa implementazione, i metodi privati sono metodi ricorsivi, infatti al loro interno è contenuta una chiamata al metodo stesso. Questi metodi vengono attivati dai metodi pubblici e alla prima chiamata ricevono come parametro il riferimento radice. © Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
147
L’eliminazione di un nodo avviene impostando a true il valore dell’attributo eliminato. Si parla in questo caso di eliminazione logica, perché il nodo è ancora presente nell’albero; al contrario si indica con eliminazione fisica la rimozione del nodo dalla struttura. La presenza di nodi eliminati logicamente va tenuta in considerazione durante la stampa degli elementi dell’albero e durante l’inserimento di un nuovo nodo che ha lo stesso codice di quello eliminato. Implementazione della classe (Nodo.java) class Nodo { // informazioni del nodo public int codice; public String descrizione; public boolean eliminato;
CODIFICA
// sottoalberi public Nodo sinistro; public Nodo destro; public Nodo(int codice, String descrizione) { this.codice = codice; this.descrizione = descrizione;
}
}
eliminato = false; sinistro = null; destro = null;
public void stampa() { System.out.print("-" + codice + "- " + descrizione); if (eliminato) { System.out.print(" (eliminato)"); } System.out.println(); }
Implementazione della classe (Albero.java) class Albero { public Nodo radice;
CODIFICA
public Albero() { radice = null; } public void inserisci(Nodo nuovo) { if (radice == null) { radice = nuovo; } else { inserisci(nuovo, radice); } }
148
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
private void inserisci(Nodo nuovo, Nodo n) { if (nuovo.codice == n.codice) { n.eliminato = false; } else if (nuovo.codice < n.codice) { if (n.sinistro == null) { n.sinistro = nuovo; } else { inserisci(nuovo, n.sinistro); } } else { if (n.destro == null) { n.destro = nuovo; } else { inserisci(nuovo, n.destro); } } }
i nodi con codice minore sono inseriti nel sottoalbero sinistro
i nodi con codice maggiore sono inseriti nel sottoalbero destro
public void elimina(int elim) { elimina(elim, radice); } private void elimina(int elim, Nodo n) { if (n != null) { if (elim == n.codice) { n.eliminato = true; System.out.println("Nodo eliminato."); } else if (elim < n.codice) { elimina(elim, n.sinistro); } else { elimina(elim, n.destro); } } else {
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
149
}
}
System.out.println("Nodo non trovato!");
public Nodo contiene(int cerca) { return contiene(cerca, radice); } private Nodo contiene(int cerca, Nodo n) { if (n != null) { if (cerca == n.codice) { if (n.eliminato) { return null; } else { return n; } } else if (cerca < n.codice) { return contiene(cerca, n.sinistro); } else { return contiene(cerca, n.destro); } } else { return null; } } public void stampaInordine() { stampaInordine(radice); } private void stampaInordine(Nodo n) { if (n != null) { stampaInordine(n.sinistro); n.stampa(); stampaInordine(n.destro); } }
150
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
attraversamento in ordine simmetrico o attraversamento inordine (prima il sottoalbero di sinistra, poi la radice, poi il sottoalbero di destra)
© Istituto Italiano Edizioni Atlas
public void stampaPreordine() { stampaPreordine(radice); } private void stampaPreordine(Nodo n) { if (n != null) { n.stampa(); stampaPreordine(n.sinistro); stampaPreordine(n.destro); } }
attraversamento in ordine anticipato o attraversamento preordine (prima la radice, poi il sottoalbero di sinistra e il sottoalbero di destra)
public void stampaPostordine() { stampaPostordine(radice); }
}
private void stampaPostordine(Nodo n) { if (n != null) { stampaPostordine(n.sinistro); stampaPostordine(n.destro); n.stampa(); } }
attraversamento in ordine posticipato o attraversamento postordine (prima il sottoalbero di sinistra e il sottoalbero di destra, poi la radice)
La sezione esecutiva del programma contiene un menu di scelte per l’utente e viene implementata con la seguente classe. Programma Java (ProgAlbero.java) import java.io.*;
CODIFICA
class ProgAlbero { InputStreamReader input = new InputStreamReader(System.in); BufferedReader tastiera = new BufferedReader(input); Albero a; public ProgAlbero() { int scelta; // crea l'albero vuoto a = new Albero();
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
151
do { System.out.println(); System.out.println("***** MENU *****"); System.out.println("1) Aggiunta di un dato"); System.out.println("2) Eliminazione di un dato"); System.out.println("3) Ricerca di un dato"); System.out.println("4) Stampa ordinata"); System.out.println("5) Stampa in preordine"); System.out.println("6) Stampa in postordine"); System.out.println("\n0) Fine\n"); System.out.print("Scelta: "); try { scelta = Integer.valueOf(tastiera.readLine()).intValue(); } catch(Exception e) { scelta = 10; } switch(scelta) { case 0: break; case 1: aggiunta(); break; case 2: eliminazione(); break; case 3: ricerca(); break; case 4: a.stampaInordine(); break; case 5: a.stampaPreordine(); break; case 6: a.stampaPostordine(); break; default: System.out.println("Scelta non corretta."); break; }
}
} while (scelta != 0);
public void aggiunta() { Nodo n; int codice;
152
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
String descrizione; try { System.out.print("Codice: "); codice = Integer.valueOf(tastiera.readLine()).intValue(); System.out.print("Descrizione: "); descrizione = tastiera.readLine(); n = new Nodo(codice, descrizione); a.inserisci(n);
}
} catch(Exception e) {}
public void eliminazione() { int codice;
}
try { System.out.print("Codice: "); codice = Integer.valueOf(tastiera.readLine()).intValue(); a.elimina(codice); } catch(Exception e) {}
public void ricerca() { Nodo n; int codice; try { System.out.print("Codice: "); codice = Integer.valueOf(tastiera.readLine()).intValue(); n = a.contiene(codice); } catch(Exception e) { n = null; }
}
if (n != null) { System.out.println("Nodo trovato:"); n.stampa(); } else { System.out.println("Codice inesistente."); }
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
153
}
// avvia il programma chiamando il costruttore public static void main(String args[]) { new ProgAlbero(); }
NOTA BENE Nei precedenti Proviamo insieme tutte le istruzioni del programma erano contenute nel metodo main. In questo esempio, invece, le istruzioni sono state spostate nel costruttore della classe ProgAlbero. Per attivare il programma a partire dal metodo main si crea soltanto un’istanza della classe usando l’operatore new.
Il Java Collections Framework per gestire gli insiemi di dati
7
I flussi di input/output Gli archivi di dati sono rappresentati da un insieme di informazioni registrate su un supporto di memorizzazione secondaria, quale può essere un disco o un nastro. Le informazioni presenti nella memoria secondaria sono indicate con il termine generico di file.
Perché utilizzare i file è conveniente?
open, read, write, close
Si hanno due principali vantaggi nel memorizzare i dati all’interno di file. Il primo è la persistenza dei dati, in quanto non vengono persi quando si chiude l’applicazione oppure si spegne il computer. Si possono quindi utilizzare i file per memorizzare le informazioni che si vogliono mantenere e recuperare per varie esecuzioni del programma. Il secondo vantaggio è rappresentato dalla grande quantità di dati che può essere memorizzata in un file: le memorie di massa hanno dimensioni che superano quelle della memoria principale e sono utili per gestire grandi quantità di informazioni. Le operazioni fondamentali riguardanti il trattamento di un file sono: • apertura del file: si stabilisce un collegamento tra la memoria centrale e l’unità di memoria di massa che contiene il file per svolgere su di esso delle operazioni; • lettura dal file: le operazioni che trasferiscono dati dal file alla memoria centrale; • scrittura sul file: le operazioni che trasferiscono dati dalla memoria centrale al file; • chiusura del file: si chiude il collegamento tra memoria centrale e file. La lettura si indica anche con input e la scrittura con output. Le operazioni che trasferiscono informazioni dalla memoria centrale al file e viceversa si chiamano, in generale, operazioni di I/O (Input/Output) sul file. NOTA BENE Le classi e i metodi che gestiscono l’I/O sono contenuti nel package java.io. Java gestisce tutte le operazioni di I/O, e quindi anche i file, con il concetto di stream, cioè di flusso di dati. Gli stream costituiscono in pratica sequenze ordinate di dati e si dividono in:
154
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
• stream di input, in cui i dati vengono presi da una sorgente e trasferiti al programma che li richiede; L’input SORGENTE STREAM
PROGRAMMA
• stream di output, in cui i dati vengono generati dal programma e diretti verso una destinazione. L’output DESTINAZIONE STREAM
PROGRAMMA
La sorgente degli stream di input può essere un file su disco da cui si leggono dati, oppure un dispositivo di input come la tastiera da cui si ricevono i caratteri digitati dall’utente. La destinazione degli stream di output può essere un file su cui si scrive oppure un dispositivo di output come il video a cui vengono inviati i dati per essere visualizzati. Gli stream di input e output sono utilizzati anche per la ricezione e l’invio di informazioni in rete.
Che cosa sono gli stream? Come vengono classificati?
Sorgenti e destinazioni degli stream
OUTPUT
OUTPUT INPUT INPUT/OUTPUT
INPUT/OUTPUT
Gli stream vengono creati in Java istanziando le classi opportune contenute nel package java.io. È possibile dividere queste classi in due categorie principali: • classi basate sui byte; • classi basate sui caratteri. In Java questa differenza è ulteriormente marcata dal fatto che i byte sono formati da 8 bit mentre i caratteri sono gestiti con 16 bit. Le classi basate sui byte hanno come sopraclassi InputStream (per gli stream di input) e OutputStream (per gli stream di output). Le classi basate sui byte
Object InputStream
FileInputStream
OutputStream
ObjectInputStream
© Istituto Italiano Edizioni Atlas
FileOutputStream
ObjectOutputStream
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
155
Le classi basate sui caratteri hanno come sopraclassi Reader (per gli stream di input) e Writer (per gli stream di output). Le classi basate sui caratteri
Object Reader
BufferedReader
Writer
InputStreamReader
PrintWriter
OutputStreamWriter
FileReader
FileWriter
Una delle caratteristiche peculiari dei flussi di I/O in Java è la possibilità di concatenare tra loro più stream. Questo risulta utile perché ogni stream consente di osservare i dati in un certo modo, accedendovi attraverso dei metodi tipici del singolo stream. ESEMPIO Un esempio di concatenazione di stream è già stato visto con la lettura di dati da tastiera. In questo caso si leggono i caratteri, quindi si devono utilizzare le classi basate sui caratteri; inoltre, essendo un’operazione di input, si utilizzano gli stream di input. Le classi Java vanno scelte tra le sottoclassi della classe Reader. Le seguenti istruzioni mostrano come vengono impostati i due stream: InputStreamReader input = new InputStreamReader(System.in); BufferedReader tastiera = new BufferedReader(input); La prima istruzione crea uno stream chiamato input dall’oggetto System.in che rappresenta lo standard input. La seconda istruzione crea un secondo stream chiamato tastiera che si collega al primo e permette di accedere ai dati utilizzando il metodo readLine. Questo metodo è presente nella classe BufferedReader, ma non nella classe InputStreamReader.
Che cos’è la concatenazione di stream?
InputStreamReader
BufferedReader
oggetto input
oggetto tastiera
TASTIERA PROGRAMMA
I tipi di file in Java
I file trattati da Java possono essere classificati in due categorie: • file strutturati; • file di testo. I file strutturati sono composti da una struttura definita nel programma: per interpretare il contenuto di un file strutturato se ne deve conoscere la struttura. ESEMPIO Un file composto da sequenze di due numeri interi, un numero reale e una stringa, può essere letto solo conoscendo questo ordine, altrimenti si ottengono dei risultati imprevisti.
156
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Al contrario un file di testo è composto da sequenze di linee di caratteri, in cui ogni linea termina con un carattere speciale di fine riga. Il contenuto di questi file può essere letto anche usando un editor di testi. I file strutturati utilizzano le classi basate sui byte per le operazioni di I/O, mentre i file di testo utilizzano le classi basate sui caratteri.
8
Quali sono le differenze tra file strutturati e file di testo?
Lettura dei dati da tastiera con la classe Console
I file strutturati
Il modo con cui Java tratta i file strutturati, spesso indicato con il termine di serializzazione, può prevedere diverse operazioni: apertura, chiusura, scrittura, lettura.
L’apertura e la chiusura L’apertura di un file strutturato per le operazioni di output, cioè per la scrittura, viene eseguita con le dichiarazioni dei seguenti oggetti: FileOutputStream f = new FileOutputStream("elenco.dat"); ObjectOutputStream fOUT = new ObjectOutputStream(f); La prima riga crea uno stream f per scrivere sul file elenco.dat. Le operazioni di scrittura non vengono fatte direttamente su questo stream, ma sul secondo stream creato dalla classe ObjectOutputStream. È in questa classe che sono contenuti i metodi per la scrittura. ObjectOutputStream
L’apertura del file per la scrittura
FileOutputStream FILE
oggetto fOUT
PROGRAMMA
oggetto f
elenco.dat
Usando i precedenti comandi, se il file elenco.dat esiste viene sovrascritto e viene cancellato tutto il suo contenuto. Se invece si vuole aprire un file esistente per accodare dei valori si deve sostituire la creazione del FileOutputStream nel seguente modo: FileOutputStream f = new FileOutputStream("elenco.dat", true); Il valore del secondo parametro indica la condizione di accodamento: se è true il file viene aperto per aggiungere i dati in coda a quelli preesistenti, altrimenti se non è presente o è false il file viene aperto in scrittura e ciò comporta la cancellazione di un eventuale archivio preesistente.
append
L’apertura di un file strutturato per le operazioni di input, cioè per la lettura, viene eseguita con le dichiarazioni dei seguenti oggetti: FileInputStream f = new FileInputStream("elenco.dat"); ObjectInputStream fIN = new ObjectInputStream(f); La prima riga crea uno stream f per leggere dal file elenco.dat. Le operazioni di lettura non vengono fatte direttamente su questo stream, ma sul secondo stream creato dalla classe ObjectInputStream. È in questa classe che sono contenuti i metodi per la lettura dei dati memorizzati. FileInputStream
ObjectInputStream
oggetto f
oggetto fIN
L’apertura del file per la lettura
FILE elenco.dat
© Istituto Italiano Edizioni Atlas
PROGRAMMA
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
157
Come si esegue l’apertura di un file strutturato? E la chiusura?
La chiusura di uno stream, sia di input che di output, viene fatta richiamando il metodo close nel seguente modo: f.close(); Le operazioni che gestiscono l’I/O possono generare diverse eccezioni, per esempio quando il metodo close riscontra una situazione anomala, oppure quando l’apertura di uno stream di input specifica un nome di file non esistente. Per questi motivi si devono racchiudere tutte le istruzioni che gestiscono i file in un blocco try…catch che cattura le eccezioni. Per controllare esattamente dove si verifica l’eccezione, si possono specificare tanti blocchi di controllo, uno per ogni istruzione, secondo la struttura seguente: FileInputStream f = null; try { // istruzione di I/O } catch(Exception e) { System.out.println("Eccezione: " + e.getMessage()); } finally { if (f != null) { try { f.close(); } catch(IOException ex) { } } }
La scrittura Dopo l’apertura dello stream di output si possono utilizzare diversi metodi per la scrittura. Ogni metodo memorizza sul file un particolare tipo di dato e assume la forma writeDato. Al posto di Dato si sostituisce il tipo di dato che si vuole memorizzare. ESEMPIO fOUT.writeInt(25400); fOUT.writeDouble(12.36);
Perché esistono diversi metodi per la scrittura?
Prima di chiudere il file è importante eseguire il metodo flush, che serve per scrivere su disco tutti i dati che sono attualmente contenuti nel buffer dello stream. Il metodo di scrittura più importante è writeObject. Con questo metodo è possibile salvare su di un file anche gli oggetti: è Java che si preoccupa di salvare la struttura dell’oggetto, memorizzando tutti i suoi attributi non statici. Un oggetto salvato su disco diventa persistente, cioè sopravvive alla singola esecuzione del programma e può essere richiamato in una successiva esecuzione. Una classe le cui istanze si vogliono rendere persistenti deve implementare l’interfaccia Serializable.
PROVIAMO INSIEME
1 IL PROGRAMMA DI SCRITTURA
Memorizzare nel file elenco.dat le informazioni relative a 3 persone Le informazioni che si vogliono memorizzare sul file sono contenute negli attributi nome ed eta dalla classe Persona, descritta nel diagramma di classe a fianco.
158
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
Persona nome eta
© Istituto Italiano Edizioni Atlas
Implementazione della classe (Persona.java) import java.io.*; class Persona implements Serializable { private String nome; private int eta; // costruttore public Persona(String nome, int eta) { this.nome = nome; this.eta = eta; }
}
CODIFICA
la dichiarazione della classe Persona mette in evidenza l’uso dell’interfaccia Serializable, necessaria per poter trasferire le sue istanze sugli stream di input e output
// rappresentazione testuale dell'oggetto public String toString() { String s = "Nome: " + nome + " Eta': " + eta; return s; }
Programma Java (ScriviDati.java) import java.io.*; class ScriviDati { public static void main(String args[]) { Persona p1, p2, p3; p1 = new Persona("Mario", 31); p2 = new Persona("Anna", 25); p3 = new Persona("Luigi", 57);
CODIFICA
creazione di tre istanze
try { FileOutputStream f = new FileOutputStream("elenco.dat"); ObjectOutputStream fOUT = new ObjectOutputStream(f); fOUT.writeObject(p1); fOUT.writeObject(p2); fOUT.writeObject(p3); fOUT.flush(); f.close();
}
}
scrittura nel file con il metodo writeObject
metodo flush, eseguito subito
} dopo le tre operazioni di scrittura, per rendere effettivo il trasferimento catch(Exception e) dei dati verso la destinazione { System.out.println("Eccezione: " + e.getMessage()); }
continua a pag. 160
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
159
A che cosa serve il metodo readObject?
La lettura Per leggere le informazioni contenute in un file strutturato si usano i metodi della classe ObjectInputStream. Questi metodi assumono la forma readDato, dove al posto di Dato si sostituisce il tipo di dato che si vuole leggere. Per evitare di ottenere inconsistenza, i dati devono essere letti nello stesso ordine in cui sono stati salvati. Tra i metodi di lettura c’è il metodo readObject, che consente di recuperare un oggetto precedentemente salvato. Questo metodo restituisce un oggetto di classe Object che attraverso il casting può essere riportato alla sua classe originaria. La lettura di un oggetto comporta la creazione di una nuova istanza della classe, in cui a ogni attributo viene assegnato il valore letto dal file. Se non si conosce quanti sono i dati contenuti nel file, si può usare un ciclo infinito per continuare a leggere finchè viene generata l’eccezione EOFException. Questa eccezione segnala che si è raggiunta la fine del file e non ci sono più dati da leggere; si può quindi interrompere il ciclo.
PROVIAMO INSIEME
1 IL PROGRAMMA DI LETTURA
segue da pag. 158
Leggere dal file elenco.dat e stampare le informazioni delle persone memorizzate
Questo programma di lettura da file utilizza la classe Persona definita nel Proviamo insieme precedente. Dopo aver aperto il file in lettura, viene attivato un ciclo infinito con la seguente struttura di ripetizione: while (true) { } Il ciclo si interrompe con l’esecuzione del comando break, dopo che è stata rilevata l’eccezione EOFException. Programma Java (LeggiDati.java) import java.io.*;
CODIFICA
class LeggiDati { public static void main(String args[]) { Persona p; try { FileInputStream f = new FileInputStream("elenco.dat"); ObjectInputStream fIN = new ObjectInputStream(f); // ciclo infinito per leggere i dati while (true) { try { p = (Persona) fIN.readObject(); System.out.println(p); }
160
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
casting dalla classe Object alla classe Persona i dati letti sono assegnati all’oggetto p
© Istituto Italiano Edizioni Atlas
catch(EOFException e) { // interrompe il ciclo break; }
} f.close();
}
9
}
} catch(Exception e) { System.out.println("Eccezione: " + e.getMessage()); }
Gestione dei file ad accesso casuale
I file di testo
Le principali operazioni eseguibili sui file di testo sono molto simili a quanto già visto per i file strutturati.
L’apertura e la chiusura L’apertura di un file di testo per le operazioni di output, cioè per la scrittura, viene eseguita con le dichiarazioni dei seguenti oggetti: FileWriter f = new FileWriter("agenda.txt"); PrintWriter fOUT = new PrintWriter(f); La prima riga crea uno stream f per scrivere sul file agenda.txt. Le operazioni di scrittura non vengono fatte direttamente su questo stream, ma sul secondo stream creato dalla classe PrintWriter. È in questa classe che sono contenuti i metodi per la scrittura. PrintWriter
L’apertura del file per la scrittura
FileWriter FILE
PROGRAMMA
oggetto fOUT
oggetto f
agenda.txt
Usando i precedenti comandi, se il file agenda.txt esiste viene sovrascritto e viene cancellato tutto il suo contenuto. Se si vuole aprire un file esistente, per accodare dei valori si deve sostituire la creazione del FileWriter nel seguente modo: FileWriter f = new FileWriter("agenda.txt", true); Il valore del secondo parametro indica la condizione di append (accodamento): se è true il file viene aperto per aggiungere i dati in coda a quelli preesistenti, altrimenti se non è presente o è false il file viene aperto in scrittura e ciò comporta la cancellazione di un eventuale archivio preesistente.
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
161
L’apertura di un file di testo per le operazioni di input, cioè per la lettura, viene eseguita con le dichiarazioni dei seguenti oggetti: FileReader f = new FileInputStream("agenda.txt"); BufferedReader fIN = new BufferedReader(f);
Come si esegue l’apertura di un file di testo?
La prima riga crea uno stream f per leggere dal file agenda.txt. Le operazioni di lettura non vengono fatte direttamente su questo stream, ma sul secondo stream creato dalla classe BufferedReader. È in questa classe che sono contenuti i metodi per la lettura dei dati memorizzati.
L’apertura del file per la lettura
FileReader
BufferedReader
oggetto f
oggetto fIN
FILE agenda.txt
PROGRAMMA
La chiusura di uno stream, sia di input che di output, viene fatta richiamando il metodo close nel seguente modo: Come si esegue la chiusura?
f.close(); Come per i file strutturati, le operazioni che gestiscono l’I/O dei file di testo possono generare diverse eccezioni, che devono essere gestite racchiudendo le istruzioni in blocchi try…catch.
A che cosa servono i metodi print e printIn?
La scrittura La scrittura di un file di testo che utilizza lo stream PrintWriter viene eseguita con i metodi print e println. Questi metodi sono simili a quelli richiamati con System.out e usati per scrivere sullo standard output. Entrambi i metodi scrivono caratteri; la differenza è che il metodo println aggiunge alla fine un carattere speciale indicante il ritorno a capo (\n).
PROVIAMO INSIEME
1 L’AGENDA DEI CONTATTI
Creare un archivio per memorizzare un’agenda dei contatti Si vuole creare un archivio su file che permetta di memorizzare cognome, nome e numero di telefono. Questi dati vengono inseriti da tastiera attraverso un’iterazione che si arresta quando al posto del cognome viene digitato il carattere ‘*’. La memorizzazione di questi dati viene effettuata su un file di testo in modo da rendere visibile l’archivio anche con un programma per l’editing dei testi. Il cognome, il nome e il numero di telefono vengono memorizzati su una riga di testo e ognuno viene separato con il carattere ‘;’. Gli attributi e i metodi della classe Contatto sono descritti nel seguente diagramma: Contatto cognome nome telefono leggi stampa
NOTA BENE A differenza dei file strutturati, le istanze della classe Contatto non verranno scritte direttamente nel file e quindi non implementano l’interfaccia Serializable.
162
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Le operazioni di apertura del file sono racchiuse da un blocco try...catch per gestire un’eventuale eccezione IOException. In questo caso il programma si interrompe con codice di errore 1, come mostra il seguente frammento di codice: try { f = new FileWriter("agenda.txt"); fOUT = new PrintWriter(f); } catch (IOException e) { System.out.println("Errore nell'apertura del file."); System.exit(1); } Implementazione della classe (Contatto.java) import java.io.*;
CODIFICA
class Contatto { public String cognome; public String nome; public String telefono; public Contatto() {} public Contatto leggi() { InputStreamReader input = new InputStreamReader(System.in); BufferedReader tastiera = new BufferedReader(input); try { System.out.print("Inserisci il cognome (* per finire): "); cognome = tastiera.readLine(); // controlla la fine dell'inserimento if (cognome.equals("*")) { return null; } System.out.print("Inserisci il nome: "); nome = tastiera.readLine(); System.out.print("Inserisci il telefono: "); telefono = tastiera.readLine();
} catch(IOException e) {} return this; } public void stampa() {
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
163
}
}
System.out.println(cognome + "\t" + nome + "\tTel. " + telefono);
Programma Java (ScriviAgenda.java) import java.io.*;
CODIFICA
class ScriviAgenda { // costruttore vuoto public ScriviAgenda() {} public void scrivi() { Contatto c = null; FileWriter f = null; PrintWriter fOUT = null; try { f = new FileWriter("agenda.txt"); fOUT = new PrintWriter(f); } catch (IOException e) { System.out.println("Errore nell'apertura del file."); System.exit(1); } c = new Contatto(); while (c.leggi() != null) { // scrive sul file fOUT.println(c.cognome + ";" + c.nome + ";" + c.telefono); fOUT.flush(); }
}
}
try { f.close(); } catch (IOException e) { System.out.println("Errore nella chiusura del file."); System.exit(1); }
public static void main(String args[]) { ScriviAgenda a = new ScriviAgenda(); a.scrivi(); } continua a pag. 166
164
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
La lettura Per leggere le informazioni contenute in un file di testo si usano due metodi della classe BufferedReader : read e readLine. Il metodo read legge un singolo carattere, ma come valore di ritorno restituisce un intero. Se si vuole ottenere il carattere letto si deve effettuare la conversione al tipo di dato char nel seguente modo: char c = (char) fIN.read();
Quali sono le differenze tra i metodi read e readLine?
Il metodo read restituisce il valore -1 quando viene raggiunta la fine del file. Il metodo readLine legge una riga di testo e come valore di ritorno restituisce una stringa. Se è stata raggiunta la fine del file, il metodo restituisce un valore null. Per effettuare la lettura sequenziale di ogni riga di un file di testo si esegue un ciclo come il seguente: String s; try { s = fIN.readLine(); while (s != null) { // operazioni sulla stringa s
}
variabile temporanea s nella quale viene memorizzata la riga letta il ciclo viene ripetuto mentre la variabile s si mantiene diversa dal valore null
s = fIN.readLine();
qui vanno inserite le operazioni da applicare alle singole righe
} catch (IOException e) { System.out.println("Errore nella lettura del file."); System.exit(1); }
PER APPROFONDIRE
LA CLASSE STRINGTOKENIZER Una classe molto utile per la gestione delle stringhe è StringTokenizer, contenuta nel package java.util. Questa classe consente di dividere una stringa in pezzi (token) in base a caratteri speciali che vengono usati come delimitatori di questi token. Se il delimitatore è lo spazio (‘ ‘), allora i token corrispondono alle parole che formano la stringa. ESEMPIO Il seguente esempio mostra come una stringa può essere interpretata usando i token. In questo caso il delimitatore è il carattere punto e virgola (;). delimitatore R
O
S
S
I
TOKEN
© Istituto Italiano Edizioni Atlas
;
M
delimitatore A
R
TOKEN
I
O
;
0
1
2
/
3
4
5
6
7
8
TOKEN
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
165
Un oggetto di classe StringTokenizer viene costruito con la seguente dichiarazione: StringTokenizer st = new StringTokenizer(stringa, delimitatore); Il costruttore di questa classe riceve come parametri due stringhe: la prima stringa è quella che viene manipolata, la seconda contiene l’elenco di caratteri che vengono usati come delimitatori. I metodi principali della classe StringTokenizer sono: • hasMoreTokens(): restituisce il valore true se ci sono token disponibili per essere estratti dalla stringa; • nextToken(): restituisce il token successivo rappresentato da una stringa. L’iterazione usata per scorrere tutti i token generati dall’oggetto st di classe StringTokenizer è la seguente: while (st.hasMoreTokens()) { token = st.nextToken();
}
// operazioni sul token
PROVIAMO INSIEME
1 LA STAMPA DEI CONTATTI
segue da pag. 162
Stampare il contenuto dell’agenda dei contatti Questo programma di lettura da file utilizza la classe Contatto definita nel Proviamo insieme precedente. Per stampare il contenuto dell’agenda dei contatti si procede con un’iterazione che comprende la lettura sequenziale di ogni riga, la scomposizione della riga in campi (cognome, nome e telefono) e la sua stampa. La stringa letta viene passata all’oggetto st di classe StringTokenizer che divide la stringa usando come delimitatore il carattere punto e virgola. Gli attributi del contatto vengono impostati leggendo i singoli token nel seguente modo: c.cognome c.nome c.telefono
= st.nextToken(); = st.nextToken(); = st.nextToken(); NOTA BENE
L’oggetto c di classe Contatto viene sovrascritto a ogni nuova riga letta dal file. Se il programma avesse richiesto di mantenere i contatti in memoria, invece di un unico oggetto si sarebbe dovuta creare una struttura dinamica basata sulla classe Vector. Programma Java (LeggiAgenda.java) import java.io.*; import java.util.*;
CODIFICA
class LeggiAgenda { // costruttore vuoto public LeggiAgenda() {}
166
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
public void leggeToken() { FileReader f = null; BufferedReader fIN = null; Contatto c; String s; StringTokenizer st; try { f = new FileReader("agenda.txt"); fIN = new BufferedReader(f); } catch (IOException e) { System.out.println("Errore nell'apertura del file."); System.exit(1); } c = new Contatto(); try { s = fIN.readLine(); // legge e stampa una riga while (s != null) { st = new StringTokenizer(s, ";"); c.cognome = st.nextToken(); c.nome = st.nextToken(); c.telefono = st.nextToken(); c.stampa(); s = fIN.readLine();
} } catch (IOException e) { System.out.println("Errore nella lettura del file."); System.exit(1); } try {
}
f.close(); } catch (IOException e) { System.out.println("Errore nella chiusura del file."); System.exit(1); }
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
167
public static void main(String args[]) { LeggiAgenda a = new LeggiAgenda(); a.leggeToken(); }
}
2 LA COPIA DI BACKUP
Eseguire la copia di backup di un file di testo Occorre utilizzare contemporaneamente uno stream di input e uno di output. La copia avviene tra un file sorgente, aperto in lettura, e un file di destinazione aperto in scrittura. La rappresentazione degli stream coinvolti in questo processo è la seguente: FileReader
BufferedReader
PrintWriter
FileWriter
oggetto f1
oggetto fIN
oggetto fOUT
oggetto f2
FILE
FILE
readme.txt
PROGRAMMA
readme.txt.bak
Programma Java (Copia.java) import java.io.*;
CODIFICA
class Copia { public static void main(String args[]) { String filename = "readme.txt"; String s; FileReader f1 = null; BufferedReader fIN = null; FileWriter f2 = null; PrintWriter fOUT = null; try { // sorgente f1 = new FileReader(filename); fIN = new BufferedReader(f1); // destinazione f2 = new FileWriter(filename + ".bak"); fOUT = new PrintWriter(f2); } catch (IOException e) { System.out.println("Errore nell'apertura del file."); System.exit(1); } try { s = fIN.readLine(); while (s != null)
168
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
il nome assegnato al file di destinazione viene generato aggiungendo l’estensione .bak al nome del file sorgente
apertura
iterazione sul file sorgente leggendo una riga per volta scrittura
© Istituto Italiano Edizioni Atlas
{
}
la riga è immediatamente scritta nel file di destinazione
fOUT.println(s); fOUT.flush(); s = fIN.readLine();
} catch (IOException e) { System.out.println("Errore nella lettura del file."); System.exit(1); }
scrittura
try { f1.close(); f2.close(); } catch (IOException e) { System.out.println("Errore nella chiusura del file."); System.exit(1); }
}
chiusura
}
Operazioni sulle directory e sui file
© Istituto Italiano Edizioni Atlas
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
169
Mappa concettuale LE STRUTTURE DI DATI E I FILE
STRUTTURE DI DATI DINAMICHE array dinamico (Vector)
gestore automatico della memoria (operatore new) Garbage Collector
pila coda lista concatenata FLUSSI DI INPUT/OUTPUT albero stream
albero binario
basate sui byte classi del package java.io basate sui caratteri
operazioni: • apertura • scrittura • lettura • chiusura
file di testo
file strutturati
serializzazione
170
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
StringTokenizer
© Istituto Italiano Edizioni Atlas
Verifica le tue conoscenze PER CIASCUNA DELLE SEGUENTI AFFERMAZIONI, INDICA SE È VERA (V) O FALSA (F) 1
V F
2
V F
3
V F
4
V F
5
V F
6
V F
7
V F
8
V F
9
V F
10
V F
11
V F
12
V F
13
V F
14
V F
15
V F
16
V F
17
V F
18
V F
19
V F
La classe Vector rappresenta un array di oggetti dinamico La classe Vector è inclusa nel package java.io Le dimensioni della classe Vector sono fissate con il costruttore Il primo elemento del vettore ha indice 0 La capacità della classe Vector si modifica dinamicamente In Java la deallocazione deve essere eseguita dal programmatore Il gestore della memoria può stabilire che un oggetto non è più utilizzato contando il numero di riferimenti a quell’oggetto Prima che il Garbage Collector provveda all’eliminazione di un oggetto, viene eseguito un metodo particolare detto finalizzatore Il Garbage Collector resta attivo durante tutta l’esecuzione di un’applicazione Java In una lista concatenata ogni elemento conosce qual è il suo successore In una lista concatenata il riferimento al nodo testa è superfluo Una lista concatenata viene gestita utilizzando i riferimenti agli oggetti Se la lista concatenata contiene un solo elemento, il riferimento del nodo testa è uguale al riferimento del nodo coda In una lista concatenata le operazioni di inserimento ed eliminazione sono veloci Gli stream sono delle sequenze ordinate di dati Gli stream si dividono in stream di input e stream di output Gli stream possono essere concatenati tra loro Gli stream sono utilizzati solo per i file di testo Le sottoclassi della classe Reader gestiscono gli stream di input
PER CIASCUNA DELLE SEGUENTI AFFERMAZIONI, SELEZIONA LA RISPOSTA CORRETTA 1
Il costruttore della classe Vector non viene usato correttamente nella dichiarazione a. Vector v = new Vector(); b. Vector v = new Vector(5); c. Vector v = new Vector(5,2); d. Vector v = new Vector(true);
2
L’oggetto restituito dal metodo elementAt appartiene alla classe a. Integer. b. Object. c. String. d. Vector.
3
L’istruzione usata per realizzare l’operazione di pop in una pila è a. obj = elementi.elementAt(size); b. obj = elementi.elementAt(size-1); c. obj = elementi.elementAt(1); d. obj = elementi.elementAt(0);
4
L’istruzione usata per realizzare l’operazione di togli in una coda è a. obj = elementi.elementAt(size); b. obj = elementi.elementAt(size-1); c. obj = elementi.elementAt(1); d. obj = elementi.elementAt(0); © Istituto Italiano Edizioni Atlas
5
L’iterazione usata per scorrere tutti i token dall’oggetto st di classe StringTokenizer è a. while (st.hasMore) { token = st.next; } b. while (st.hasMoreTokens()) { token = st.nextToken(); } c. while (hasMoreTokens()) { token = nextToken(); } d. while (st.nextToken()) { token = st.hasMoreTokens(); }
CAPITOLO
3 • LE STRUTTURE DI DATI E I FILE
171
6
Il package in cui sono contenute le classi e i metodi che gestiscono le operazioni di Input/Output è a. java.awt. b. java.io. c. java.util. d. java.input.
7
L’istruzione usata per aprire un file strutturato per l’accodamento è a. FileWriter f = new FileWriter("xyz"); b. FileOutputStream f = new FileOutputStream("xyz"); c. FileWriter f = new FileWriter("xyz", true); d. FileOutputStream f = new FileOutputStream("xyz", true);
SVOLGI I SEGUENTI ESERCIZI 1
Completa la tabella, che mette a confronto la pila e la coda, utilizzando una o più tra le parole seguenti. FIFO • push • vuota • pop • togli • LIFO • size • top • aggiungi Pila
Coda
Modalità di gestione Operazioni di modifica Operazioni di interrogazione 2
Completa le frasi utilizzando una tra le parole seguenti. attraversamento • inizio • testa • fine • riferimento • coda • visita • ultimo • nodo a. Il riferimento al primo elemento di una lista è detto …………………….. b. Il riferimento all’ultimo elemento di una lista è detto …………………….. c. Con l’operazione di …………………… si naviga tra gli oggetti della lista. d. Ogni nodo della lista contiene un ……………………. al nodo successivo.
3
Completa le frasi associando ogni termine alla sua corretta definizione. a. La radice 1. è il nodo terminale di un albero. b. Le foglie 2. è il nodo da cui partono le connessioni che generano l’albero. 3. sono i nodi esterni che non hanno nodi figli. 4. sono i nodi interni dell’albero.
4
Associa ciascuna classe della colonna di sinistra alla corretta sottoclasse della colonna di destra. a. InputStream 1. FileOutputStream, ObjectOutputStream b. OutputStream 2. PrintWriter, OutputStreamWriter, FileWriter c. Reader 3. FileInputStream, ObjectInputStream d. Writer 4. BufferedReader, InputStreamReader, FileReader
5
Associa ciascun metodo alla classe corrispondente. a. writeInt b. close c. readObject 1. ObjectOutputStream d. print 2. ObjectInputStream e. readLine 3. PrintWriter f. flush 4. BufferedReader g. println h. writeObject
172
PARTE PRIMA
• IL LINGUAGGIO DI PROGRAMMAZIONE
© Istituto Italiano Edizioni Atlas
Sviluppa le tue competenze COMPRENDERE LA DIFFERENZA TRA GESTIONE STATICA E GESTIONE DINAMICA DELLA MEMORIA 1
Il seguente frammento di codice crea un vettore contenente dei nomi e lo stampa a video. Correggi gli errori presenti, aiutandoti anche con il compilatore. Vector v = new Vector(10, 5, 1); String s; v.addElement("Maria"); v.addElement("Elena"); for (int i=0; i
366
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Facendo doppio clic sul file activity_main.xml, nel riquadro centrale di Android Studio si apre un’area di modifica che, in modo grafico, aiuta lo sviluppatore nel disegno dell’interfaccia grafica dell’applicazione (layout). La modalità di costruzione dell’interfaccia grafica in Android è simile a quanto è stato descritto nell’Inserto A per la costruzione delle interfacce grafiche con NetBeans. Selezionando il pannello Design si apre l’area in cui si può costruire in modo visuale l’interfaccia utente. La finestra palette contiene tutte le componenti standard dell’interfaccia utente (come caselle di testo, pulsanti, etichette, ecc.) che possono essere trascinate sul pannello centrale per comporre la schermata visualizzata dall’utente finale. La finestra attributes mostra un insieme di caratteristiche degli oggetti grafici che possono essere modificate, come la posizione, la dimensione e il tipo di font. La schermata, automaticamente creata con il progetto, contiene un’etichetta di testo (textview) che verrà usata per inserire l’orario corrente da visualizzare nell’applicazione. Fare clic sull’etichetta e modificare le seguenti proprietà nella finestra Attributes: • nella proprietà id inserire il valore txt_orario, per identificare la componente grafica; • nella proprietà text cancellare il contenuto, in quanto sarà aggiornato successivamente con l’ora corrente; • nella proprietà textsize impostare la dimensione del font con il valore 20sp.
la dimensione è espressa in sp (scale-independent pixels), che indica una misura scalabile secondo la preferenza del font dell’utente
La descrizione dell’interfaccia grafica viene memorizzata in un file XML, il cui contenuto è visibile selezionando il pannello Text ed è riportato alla pagina seguente.
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
367
L’activity implementa le funzionalità dell’app e il layout definisce l’insieme di oggetti di interfaccia utente, realizzato da uno o più file XML. layout (res/layout/activity_main.xml)
il valore completo della proprietà
id è @+id/txt_orario
Facendo doppio clic sul file MainActivity.java, nel riquadro centrale di Android Studio si apre il codice sorgente Java relativo alla maschera principale dell’applicazione. Il metodo onCreate viene eseguito quando l’utente avvia l’applicazione, quindi deve contenere le istruzioni di inizializzazione dell’interfaccia grafica. L’applicazione deve leggere l’ora attuale del dispositivo e la deve inserire nell’etichetta txt_orario, definita nel file di layout. Il codice completo della classe MainActivity è riportato di seguito. activity (MainActivity.java) package it.istitutotecnico.orario; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView;
CodiFiCa comandi di import per tutte le classi utilizzate. Nel caso non siano riportate tutte le classi, Android Studio segnala l’errore colorando di rosso il nome della classe non riconosciuta
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
metodo onCreate eseguito quando l’utente avvia l’applicazione l’ora corrente viene letta utilizzando la classe date e viene inserita in una stringa usando la formattazione definita con la classe dateFormat
Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); String strOrario = dateFormat.format(date); TextView txtOrario = (TextView) findViewById(R.id.txt_orario); txtOrario.setText(strOrario); } }
368
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
l’etichetta è stata identificata nel file del layout con il nome txt_orario e può essere utilizzata nel codice Java cercando il riferimento con il metodo findViewById
© Istituto Italiano Edizioni Atlas
Facendo doppio clic sul file build.gradle del modulo, nel riquadro centrale di Android Studio si apre un file con le impostazioni di configurazione dell’app e le modalità di compilazione. Si può, per esempio, impostare la versione dell’app espressa con due campi: un numero (Version code), usato internamente e aggiornato dallo sviluppatore a ogni nuova pubblicazione, e un nome (Version name) visibile all’utente finale. Viene indicata la versione minima richiesta per eseguire il programma (minSdkVersion) e quella usata per la compilazione (compileSdkVersion). Android Studio inserisce automaticamente in questo file altre impostazioni, tra cui il riferimento alle librerie importate per la corretta compilazione dell’app (dependencies). Il contenuto completo del file è riportato di seguito. apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "it.istitutotecnico.orario" minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } Per completare la fase di sviluppo, si deve salvare tutto il lavoro facendo clic sul menu File e poi su save all, oppure utilizzando la combinazione di tasti Ctrl + s. 2. test e debug Per testare l’applicazione, eseguire l’emulatore facendo clic sul menu run e poi sulla voce run, oppure usando la combinazione di tasti maiusc + F10. Se sono presenti più emulatori, si può impostare quello preferito dal menu Run facendo clic su Edit Configurations. All’interno del campo target, selezionare smartHigh come AVD preferito e infine fare clic su apply per confermare la scelta.
Test e Debug
Quando viene avviata l’esecuzione sull’emulatore, Android Studio opera nel seguente modo: • genera il pacchetto compilato ProgettoOrario.apk; • installa il pacchetto nel dispositivo virtuale; • avvia l’applicazione. Sull’emulatore, la nuova applicazione viene aggiunta alla lista delle applicazioni e si identifica con l’icona e il nome che sono stati impostati nel campo icon e label del file AndroidManifest.xml. NoTA BeNe Durante la fase di test, è opportuno effettuare il collaudo dell’applicazione su diversi emulatori in modo da garantire il corretto funzionamento sul maggior numero possibile di dispositivi.
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
369
eseCuZioNe
Android dispone di un sistema per la raccolta e la visualizzazione di tutti i messaggi di errore, chiamato logcat. Logcat può essere aperto facendo clic sull’omonimo pannello Logcat situato nella parte bassa della finestra di Android Studio. Oltre ai messaggi relativi agli errori di run-time, lo sviluppatore può inserire nel codice Java i punti di controllo, prevedendo la scrittura dei propri messaggi di log nella finestra Logcat. I metodi da usare per stampare questi messaggi sono contenuti nella classe log. Per esempio, per stampare un messaggio di log che mostra l’orario calcolato, si deve usare il comando: Log.i("MainActivity", "Orario = " + strOrario); I due parametri del metodo log.i vengono visualizzati rispettivamente nella colonna tag e nella colonna text della finestra di Logcat.
La classe Log, a seconda del tipo di messaggio che si vuole stampare, suggerisce l’utilizzo di uno tra i seguenti cinque metodi: • log.v per i messaggi verbose, cioè di stile descrittivo; • log.d per i messaggi specifici di debug; • log.i per i messaggi informativi (information); • log.w per i messaggi di avvertimento (warning), quando ci sono malfunzionamenti; • log.e per i messaggi di errore (error). 3. pubblicazione Dopo l’esecuzione dei test su diversi emulatori e dopo la correzione degli eventuali malfunzionamenti riscontrati, si predispone il pacchetto apK per distribuire l’applicazione sui dispositivi Android. La compilazione dell’applicazione genera automaticamente un pacchetto che prende il nome di unsigned application package. Se la cartella del progetto è posizionata in C:\esempi\ProgettoOrario, il pacchetto non firmato app-debug.apk è memorizzato nella seguente sottocartella: C:\esempi\ProgettoOrario\app\build\outputs\apk\debug La distribuzione dell’applicazione sui marketplace online richiede che il pacchetto venga firmato con un certificato digitale. Questa modalità di pubblicazione sarà illustrata nel Capitolo 9 (vedi pag. 441).
Aggiornare ed estendere l’Android SDK L’ambiente di sviluppo Eclipse
370
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
5
Le etichette, le caselle di testo e i pulsanti di comando
L’interfaccia grafica di un’app si progetta in modo visuale, utilizzando la finestra Design di Android Studio e le componenti grafiche contenute nella Palette. Il layout viene memorizzato in uno o più file XML e ogni componente, con i suoi attributi, è descritta all’interno di un tag specifico. L’etichetta viene creata utilizzando la classe textview (android.widget.TextView) ed è solitamente utilizzata per inserire messaggi di testo, o descrizioni di caselle di testo, nelle videate dell’applicazione. Per aggiungere un’etichetta basta trascinare l’oggetto TextView, presente nel gruppo Common della finestra Palette di Android Studio, sulla finestra Design. Nello stesso gruppo della Palette, oltre all’oggetto base TextView, sono presenti altri oggetti grafici di uso comune.
8.3 Il gruppo Common
Il testo da visualizzare può essere modificato direttamente nella finestra Properties, impostando l’attributo text. Come tutte le altre componenti grafiche, l’etichetta viene registrata in un file XML all’interno della cartella res/layout, con il seguente tag:
La proprietà id stabilisce un nome univoco (txtDesc) per l’etichetta che deve essere indicato con la codifica @+id/txtDesc. Questo nome potrà essere utilizzato successivamente all’interno del codice Java come riferimento all’oggetto grafico.
8.4 Il gruppo Text
La casella di testo edittext (android.widget.EditText) è uno degli oggetti grafici più utilizzati per permettere all’utente di inserire i dati. Per aggiungere una casella di testo si deve trascinare uno degli oggetti presenti nel gruppo Text della finestra Palette. Il corrispondente codice XML è il seguente:
Le proprietà layout_width e layout_height stabiliscono le dimensioni in larghezza e in altezza dell’oggetto grafico. Il valore wrap_content indica che le dimensioni devono adattarsi al contenuto della casella di testo, mentre il valore match_parent stabilisce di espandere le dimensioni fino a raggiungere quelle del contenitore in cui la casella di testo è inserita. Nello stesso gruppo della Palette, oltre all’oggetto base EditText, sono presenti altre caselle di testo che gestiscono e facilitano l’inserimento di valori alfanumerici come password, indirizzi email, numeri di telefono e dati anagrafici.
Come si crea un’etichetta? E una casella di testo?
I pulsanti di comando (o bottoni) vengono creati utilizzando la classe Button (android. widget.Button) e sono utilizzati per attivare l’esecuzione di particolari azioni. Per aggiungere un pulsante in una schermata dell’applicazione occorre trascinare l’oggetto Button presente nel gruppo Buttons della finestra Palette.
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
371
Il corrispondente codice XML è il seguente: la proprietà onClick indica il gestore dell’evento per il pulsante. Il valore è il nome del metodo che viene eseguito in risposta all’evento click sul pulsante
Nel codice Java si deve inserire un metodo pubblico, contenente le azioni da eseguire in risposta all’evento, con la seguente struttura: public void calcolaTotale(View view) { // azioni da eseguire }
Come si aggiunge un pulsante?
Il file strings.xml La proprietà Text delle etichette e dei pulsanti di comando viene utilizzata per specificare il testo mostrato nell’interfaccia grafica. Un corretto stile di programmazione in Android prevede che nella proprietà Text non venga indicato direttamente il testo, ma il riferimento alla risorsa che contiene il testo da visualizzare. esempio La proprietà Text della componente Button, dichiarata precedentemente con la notazione: android:text ="Calcola" dovrebbe essere sostituita con la seguente: riferimento a una risorsa di tipo testo (@string) che si chiama str_calcola
android:text ="@string/str_calcola" Il file strings.xml, contenuto nella cartella res/values, raggruppa tutte le risorse di tipo testo che possono essere utilizzate dall’applicazione. esempio Il valore della stringa str_calcola viene dichiarato nel file strings.xml utilizzando il seguente tag: Calcola Un esempio di file strings.xml che, oltre alla stringa precedente, contiene le stringhe app_name e str_descrizione è il seguente:
Calcolatrice Calcola Descrizione
NoTA BeNe
A che cosa serve il file strings.xml?
372
PARTE SECONDA
Questa modalità di rappresentazione delle risorse consente di mantenere separato il layout della pagina, salvato nella cartella res/layout, dal contenuto memorizzato nella cartella res/values.
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
proviamo iNsieme
1 i meGapiXel di uNa FotoCamera Calcolare il numero di Megapixel di una fotocamera, date le dimensioni di un’immagine prodotta Si vuole creare un’applicazione che permetta all’utente di inserire le dimensioni di un’immagine, specificando i valori di altezza e larghezza espressi in pixel. Facendo clic su un pulsante di comando, l’applicazione calcola e visualizza il numero di Megapixel della fotocamera che ha scattato l’immagine. Si ricorda che il megapixel (Mp) è un’unità di misura corrispondente a un milione di pixel ed è utilizzata per definire la risoluzione di un’immagine prodotta da una fotocamera. Interfaccia grafica casella di testo (editAltezza) casella di testo (editLarghezza)
pulsante di comando (btnCalcola) etichetta (txtRisultato) per il risultato del calcolo
La seguente tabella riassume tutte le classi grafiche che vengono aggiunte al file di layout res/layout/activity_main.xml e le due principali proprietà, Id e Text. Nella colonna Nome oggetto viene indicato il nome utilizzato nel codice Java. Classe
id
text
Nome oggetto
TextView
@+id/txtAltezza
@string/str_altezza
TextView
@+id/txtLarghezza
@string/str_larghezza
EditText
@+id/editAltezza
editAltezza
EditText
@+id/editLarghezza
editLarghezza
Button
@+id/btnCalcola
@string/str_calcola
TextView
@+id/txtMegapixel
@string/str_megapixel
TextView
@+id/txtRisultato
txtRisultato
In aggiunta alle precedenti, impostare nell’etichetta txtRisultato le seguenti proprietà: • gravity: center_horizontal, per allineare il testo al centro; • background: #00CCCC, per evidenziare lo sfondo con il colore azzurro. Nelle caselle di testo editAltezza e editLarghezza indicare come proprietà inputtype il valore number, per consentire all’utente di inserire solo cifre numeriche. Per il pulsante btnCalcola specificare, nella proprietà onClick, il metodo calcolaRisultato come gestore dell’evento. risorse (res/values/strings.xml)
MegaPixel Altezza Larghezza Calcola Megapixel
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
373
layout (res/layout/activity_main.xml)
consente all’utente di inserire solo cifre numeriche
consente all’utente di inserire solo cifre numeriche
metodo che gestisce l’evento
Nel codice Java, i riferimenti agli elementi grafici vengono dichiarati come attributi privati della classe MainActivity: private EditText editAltezza, editLarghezza; private TextView txtRisultato; All’interno del metodo onCreate, viene eseguito il metodo setContentview per caricare l’interfaccia grafica descritta nel file di layout activity_main.xml. Il riferimento al layout è indicato con il nome del file preceduto dalla notazione r.layout: setContentView(R.layout.activity_main); Successivamente vengono recuperati i collegamenti con le componenti grafiche dichiarate nel layout: editAltezza editLarghezza txtRisultato
= (EditText) findViewById(R.id.editAltezza); = (EditText) findViewById(R.id.editLarghezza); = (TextView) findViewById(R.id.txtRisultato);
Il metodo findViewById cerca l’oggetto grafico il cui nome, indicato nel parametro, è preceduto dalla notazione r.id. Nel metodo calcolaRisultato, i valori inseriti dall’utente vengono letti utilizzando i metodi gettext().tostring() sull’oggetto grafico e vengono convertiti in valori numerici: altezza = Integer.parseInt(editAltezza.getText().toString()); larghezza = Integer.parseInt(editLarghezza.getText().toString()); Il risultato viene visualizzato nell’etichetta txtRisultato utilizzando il metodo settext: txtRisultato.setText("" + mp + " Mp"); Il codice completo della classe Java che implementa l’applicazione è mostrato alla pagina seguente. © Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
375
activity (MainActivity.java) package it.istitutotecnico.megapixel; import import import import import import import
CodiFiCa
android.support.v7.app.AppCompatActivity; android.os.Bundle; android.util.Log; android.view.View; android.widget.EditText; android.widget.TextView; android.widget.Toast; gli elementi grafici sono dichiarati come attributi privati della classe MainActivity
public class MainActivity extends AppCompatActivity { private EditText editAltezza, editLarghezza; private TextView txtRisultato; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
metodo setContentview per caricare l’interfaccia grafica
riferimento al layout collegamenti con le componenti grafiche dichiarate nel layout
// Crea il collegamento con le componenti grafiche editAltezza = (EditText) findViewById(R.id.editAltezza); editLarghezza = (EditText) findViewById(R.id.editLarghezza); txtRisultato = (TextView) findViewById(R.id.txtRisultato); } public void calcolaRisultato(View view) { int altezza, larghezza, mp;
valori inseriti dall’utente e convertiti in valori numerici
altezza = Integer.parseInt(editAltezza.getText().toString()); larghezza = Integer.parseInt(editLarghezza.getText().toString()); Log.i("MainActivity", "Altezza= " + altezza + " Larghezza= " + larghezza); mp = (altezza * larghezza) / 1000000;
metodo settext: visualizza il risultato nell’etichetta txtRisultato
txtRisultato.setText("" + mp + " Mp"); } } continua nell’esercizio seguente
2 uN messaGGio di avvertimeNto per l’uteNte
Modificare l’applicazione precedente per il calcolo dei Megapixel, aggiungendo un controllo che avvisi l’utente quando mancano alcuni dati Se l’utente fa clic sul pulsante Calcola prima di aver inserito i valori dell’altezza e della larghezza dell’immagine, viene visualizzato un messaggio di avvertimento sul dispositivo mobile.
376
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
In Android, la classe toast (android.widget.Toast) implementa l’oggetto grafico che visualizza un messaggio di testo, resta visibile per un certo periodo di tempo e poi automaticamente scompare. La creazione dell’oggetto viene eseguita con il metodo toast.maketext, il cui primo parametro è il contesto, il secondo è il messaggio da visualizzare e il terzo è la durata. I valori standard per la durata sono indicati dai due attributi statici: • Toast.LENGTH_LONG; • Toast.LENGTH_SHORT.
toast = Toast.makeText(getApplicationContext(), "Altezza sbagliata", Toast.LENGTH_LONG);
contesto
messaggio da visualizzare
durata
Per visualizzare il messaggio si deve usare il metodo show: toast.show(); Il codice del metodo calcolaRisultato deve essere modificato come segue. Gestione degli eventi public void calcolaRisultato(View view) { int altezza, larghezza, mp; Toast toast;
CodiFiCa
try { altezza = Integer.parseInt(editAltezza.getText().toString()); } catch (NumberFormatException exc) { Log.e("MainActivity", "Errore conversione altezza"); toast = Toast.makeText(getApplicationContext(), "Altezza sbagliata", Toast.LENGTH_LONG); toast.show(); return; } try { larghezza = Integer.parseInt(editLarghezza.getText().toString()); } catch (NumberFormatException exc) { Log.e("MainActivity", "Errore conversione larghezza"); toast = Toast.makeText(getApplicationContext(), "Larghezza sbagliata", Toast.LENGTH_LONG); toast.show(); return; } Log.i("MainActivity", "Altezza= " + altezza + " Larghezza= " + larghezza); mp = (altezza * larghezza) / 1000000; txtRisultato.setText("" + mp + " Mp"); }
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
377
prova di esecuzione Se il valore nella casella editAltezza non può essere correttamente trasformato in un numero, appare un messaggio che comunica il tipo di anomalia. In caso contrario si procede normalmente. eseCuZioNe
per approFoNdire
la loCaliZZaZioNe del soFtWare La localizzazione (in inglese localisation) è il processo che consente di adattare l’applicazione software all’utilizzo in altre nazioni e, nella maggior parte delle situazioni, consiste nel fornire le traduzioni del testo nella lingua richiesta. In casi più particolari, la localizzazione potrebbe richiedere ulteriori adattamenti per adeguare l’applicazione alla cultura del paese in cui si vuole distribuire. Per gestire la localizzazione, Android consente di definire più risorse all’interno della stessa applicazione. In fase di esecuzione sarà scelta la risorsa che meglio si adatta al dispositivo e all’utente. Il file res/values/strings.xml rappresenta la risorsa di default per i messaggi di testo. Contiene i messaggi espressi nella lingua che ci si aspetta essere quella maggiormente utilizzata dagli utenti dell’applicazione. Le risorse alternative, per i messaggi di testo in altre lingue, devono essere memorizzate all’interno di cartelle specifiche il cui nome identifica il tipo di localizzazione. esempio res/values-en/strings.xml contiene le stringhe tradotte in lingua inglese. res/values-fr/strings.xml contiene le stringhe tradotte in lingua francese. Se la risorsa di default (res/value/strings.xml) contiene i seguenti messaggi:
Nome Cognome
le risorse alternative in lingua inglese (res/value-en/strings.xml) sono:
First name Last name
378
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
6
La classe Activity
All’interno del Capitolo 4 (vedi pag. 185) è stato spiegato che le finestre delle applicazioni Java corrispondono a oggetti di classe JFrame, detti anche contenitori. In Android, il contenitore corrispondente al JFrame è rappresentato dalla classe activity. Ogni finestra di un’applicazione Android deve essere dichiarata come una sottoclasse di Activity, nel seguente modo: public class FinestraPrincipale extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }
Come si dichiara una finestra in un’app?
} NoTA BeNe Per mantenere la compatibilità con le precedenti versioni di Android, nei Proviamo insieme di questo capitolo è stata utilizzata la classe appCompactactivity, una sottoclasse della classe Activity. Il metodo onCreate, ereditato dalla sopraclasse Activity, deve essere ridefinito (Override) con l’aggiunta di tutte le istruzioni necessarie per la visualizzazione e la gestione della finestra grafica. La prima istruzione del metodo onCreate richiama il costruttore della sopraclasse. Successivamente viene aggiunta l’istruzione per caricare l’interfaccia grafica, definita in un file XML. esempio Se l’interfaccia grafica è salvata nel file prima_videata.xml, l’istruzione per il suo caricamento è la seguente: setContentView(R.layout.prima_videata); Per poter utilizzare un’Activity, oltre a dichiarare la sua classe, si deve inserire il nome della classe nel file AndroidManifest.xml dell’applicazione, utilizzando il seguente tag:
La realizzazione di un’applicazione composta da due videate comporta la creazione di due sottoclassi di Activity e l’inserimento nel Manifest di due riferimenti tramite il tag . Activity1
© Istituto Italiano Edizioni Atlas
un’applicazione con due videate
Activity2
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
379
Per passare dalla videata Activity1 alla videata Activity2, si devono eseguire le seguenti istruzioni:
Come si realizza un’app con due Activity?
Intent intent = new Intent(Activity1.this, Activity2.class); startActivity(intent); Il metodo startactivity viene richiamato con il parametro intent, che stabilisce l’oggetto da cui scaturisce l’azione (Activity1.this) e la classe dell’Activity che deve essere aperta (Activity2.class). La classe intent è usata in Android come strumento di comunicazione per indicare l’azione da eseguire e gli eventuali dati da comunicare, chiamati extra. Il metodo putextra è usato per aggiungere i dati all’Intent come coppie di nomi (chiavi) e valori.
proviamo iNsieme
1 il CoNsumo di CarBuraNte Creare un’app per calcolare il consumo medio di carburante di un veicolo L’applicazione è composta da due Activity: la prima contiene due caselle di testo per la raccolta dei dati e un pulsante per l’avvio del calcolo, la seconda visualizza il risultato del calcolo.
Km: Litri:
Calcola
Il consumo viene calcolato dividendo i km percorsi per i litri di carburante consumati ed è espresso in km/l. Il valore calcolato viene passato alla seconda Activity all’interno di un Intent. Le componenti usate per la progettazione dell’interfaccia grafica sono indicate nella seguente tabella: Classe
id
text
TextView
@+id/txtKM
@string/str_km
TextView
@+id/txtLitri
@string/str_litri
EditText
@+id/editKM
EditText
@+id/editLitri
Button
@+id/btnConsumo
TextView
@+id/txtConsumo
Dopo aver creato il progetto con l’Activity principale, per creare la seconda Activity si deve fare clic sul menu File, scegliere New, poi activity e infine fare clic su empty activity.
Nome oggetto
editKm editLitri @string/str_consumo txtConsumo
nome della classe
nome del layout
clic su Finish
380
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Vengono generati automaticamente i file ConsumoActivity.java e activity_consumo.xml. Inoltre il file AndroidManifest.xml viene aggiornato con le informazioni sulla nuova Activity. Il codice sorgente di tutti i file che compongono l’app è riportato di seguito. manifest (AndroidManifest.xml)
risorse (res/values/strings.xml)
Calcolatrice Calcola Descrizione
layout (res/layout/activity_main.xml)
metodo da eseguire in risposta all’evento
layout (res/layout/activity_consumo.xml)
activity (MainActivity.java) package it.istitutotecnico.consumo;
CodiFiCa
import android.content.Intent; import android.net.Uri;
382
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
import import import import
android.support.v7.app.AppCompatActivity; android.os.Bundle; android.view.View; android.widget.EditText;
costante PARAM_CONSUMO: assegna un nome univoco al parametro
public class MainActivity extends AppCompatActivity { public final static String PARAM_CONSUMO = "param_consumo"; private EditText editKM, editLitri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // crea il collegamento con le componenti grafiche editKM = (EditText) findViewById(R.id.editKM); editLitri = (EditText) findViewById(R.id.editLitri); }
gestore dell’evento clic sul pulsante di calcolo
public void calcolaConsumo(View view) { int km, litri; double consumo;
valori inseriti dall’utente e convertiti in valori numerici
km = Integer.parseInt(editKM.getText().toString()); litri = Integer.parseInt(editLitri.getText().toString()); // arrotonda il consumo alla prima cifra decimale consumo = (1.0 * km) / litri; consumo = Math.round(10.0 * consumo) / 10.0;
esegue il calcolo
// apre la seconda Activity Intent intent = new Intent(this, ConsumoActivity.class); intent.putExtra(PARAM_CONSUMO, consumo); startActivity(intent);
visualizza il risultato nella seconda Activity
CodiFiCa
}
metodo putextra: aggiunge il parametro consumo all’oggetto intent
} activity (ConsumoActivity.java) package it.istitutotecnico.consumo; import import import import
CodiFiCa
android.os.Bundle; android.support.v7.app.AppCompatActivity; android.content.Intent; android.widget.TextView;
public class ConsumoActivity extends AppCompatActivity { private TextView txtConsumo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_consumo);
la lettura del parametro numerico viene eseguita con il metodo getdoubleextra dall’Activity, indicando come nome del parametro la costante pubblica PARAM_CONSUMO dichiarata nella classe MainActivity
// legge i parametri ricevuti // viene recuperato l'Intent che l'ha invocata Intent intent = getIntent(); double consumo = intent.getDoubleExtra(MainActivity.PARAM_CONSUMO, 0); // imposta il valore nella TextView txtConsumo = (TextView) findViewById(R.id.txtConsumo); txtConsumo.setText("" + consumo); } }
© Istituto Italiano Edizioni Atlas
metodo findViewByld: cerca il riferimento nel file del layout. Metodo settext: visualizza il risultato nell’etichetta
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
383
eseCuZioNe
Consumi
Il ciclo di vita delle activity
per approFoNdire
avviare uNa teleFoNata Il meccanismo di comunicazione tramite gli Intent (vedi pag. 380) è utilizzato ampiamente per scambiare le informazioni tra videate diverse della stessa applicazione o tra applicazioni diverse. Molte applicazioni predefinite in Android, per esempio il gestore delle chiamate telefoniche, sono predisposte per essere invocate tramite l’utilizzo di Intent. Per comunicare con l’applicazione Telefono si deve creare un oggetto di classe Intent, passando al costruttore l’azione da eseguire (intent.aCtioN_dial) e il numero di telefono da visualizzare, indicato all’interno di una stringa di testo con il prefisso tel:. Intent telefonata = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:333 456789")); Dopo aver costruito l’oggetto telefonata, si usa il metodo startactivity per richiamare l’applicazione Telefono: startActivity(telefonata);
Per verificare il comportamento delle precedenti istruzioni si deve realizzare un’applicazione e la si deve eseguire su un dispositivo reale, perché l’emulatore non dispone dell’applicazione predefinita Telefono. Quando il metodo startActivity viene eseguito, l’applicazione Telefono viene aperta e il numero di telefono viene visualizzato al suo interno, ma la telefonata non inizia automaticamente: l’utente può modificare il numero e dare inizio alla chiamata con l’opportuno pulsante.
384
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Mappa concettuale ANDROID E L’AMBIENTE DI SVILUPPO
dispositivi mobili
INFORMATICA MOBILE
gesti touch
interfaccia di Android
SISTEMA OPERATIVO ANDROID
versioni di Android
file XML file Java
app
SDK (Software Development Kit)
AMBIENTE DI SVILUPPO ANDROID STUDIO
Manifest Risorse Layout MainActivity
sviluppo dell’app
emulatore di dispositivo AVD (Android Virtual Device)
test e debug
file APK (Android Package)
pubblicazione
oggetti dell’interfaccia grafica: • TextView • EditText • Button
localizzazione del software
classe Activity
chiamata telefonica
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
385
Verifica le tue conoscenze PER CIASCUNA DELLE SEGUENTI AFFERMAZIONI, INDICA SE È VERA (V) O FALSA (F) 1 V
F
2 V
F
3 V
F
4 V
F
5 V
F
6 V
F
7 V
F
8 V
F
9 V
F
10 V
F
11 V
F
12 V
F
13 V
F
14 V
F
15 V
F
16 V
F
17 V
F
18 V
F
19 V
F
20 V
F
I dispositivi mobili hanno una capacità di elaborazione paragonabile ai computer Solitamente i dispositivi mobili sono collegati alla rete Internet I dispositivi mobili sono di grandi dimensioni Spesso i dispositivi mobili sono dotati di uno schermo sensibile al tatto Android è un sistema operativo solo per telefoni cellulari Android è un sistema operativo sviluppato da Google Android è un insieme di servizi Internet utilizzabili con uno smartphone Il software Android è open source Android Studio è un pacchetto fornito da Google Android Studio contiene sono un editor di testi Android Studio è un ambiente di sviluppo integrato All’interno di Android Studio sono inclusi gli strumenti per simulare i dispositivi mobili Il test può essere eseguito su un dispositivo mobile Logcat è un sistema per la raccolta e visualizzazione dei messaggi di errore I messaggi di avvertimento possono essere stampati con il metodo Log.a Le applicazioni devono essere collaudate su un solo emulatore La classe Toast visualizza un’immagine a pieno schermo Il prefisso R.layout è usato per riferirsi ai file dell’interfaccia grafica Il gestore degli eventi per i pulsanti di comando è indicato dalla proprietà onClick Il valore wrap_content è usato per impostare le dimensioni degli oggetti grafici
PER CIASCUNA DELLE SEGUENTI AFFERMAZIONI, SELEZIONA LA RISPOSTA CORRETTA 1
Tra gli strumenti integrati nei moderni smartphone non si trova a. l’antenna GPS. b. la fotocamera. c. l’interfaccia WiFi. d. il mouse.
2
Il dispositivo virtuale usato nell’ambiente di sviluppo Android è a. l’emulatore AVD. b. l’emulatore APP. c. l’emulatore SDK. d. il plug-in ADT.
3
386
La fase di pubblicazione di un’applicazione Android consiste a. nel creare un progetto e nello scrivere il codice sorgente. b. nell’eseguire l’applicazione su uno o più dispositivi virtuali. c. nel generare il pacchetto da distribuire agli utenti finali. d. nel ridurre la possibilità di compiere errori.
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
4
Durante la creazione di un progetto Android non si deve fornire a. il nome dell’applicazione. b. il nome del progetto. c. il nome delle componenti grafiche. d. il nome del package. e. la versione dell’SDK.
5
Il nome che identifica un’applicazione Android non firmata è a. Signed APK. b. Unsigned APK. c. Application package. d. Installation package. e. Unsigned application.
6
La notazione che rappresenta l’id di una casella di testo chiamata importo è a. @id/importo b. @string/importo c. @+id/importo d. @+string/importo
© Istituto Italiano Edizioni Atlas
7
8
Tutte le risorse di tipo testo che possono essere utilizzate dall’applicazione vengono inserite nel file a res/layout/strings.xml b. res/images/strings.xml c. res/values/manifest.xml d. res/values/strings.xml
c. traduzione. d. versioning. 9
L’adattamento di un’applicazione all’utilizzo in diverse nazioni è indicato con il termine a. geolocalizzazione. b. localizzazione.
Il metodo che viene eseguito per passare da un’Activity all’altra è a. startIntent. b. putExtra. c. getIntExtra. d. startActivity.
SVOLGI I SEGUENTI ESERCIZI 1
Associa a ogni gesto il corrispondente effetto. a. toccare 1. spostare le icone b. trascinare 2. eseguire uno scorrimento verticale c. far scorrere 3. aumentare o ridurre lo zoom d. pizzicare 4. attivare i pulsanti
2
Completa le frasi utilizzando una tra le parole seguenti. avvio • back • ricerca • stato • navigazione • home • preferiti • Android • widget a. I ....................... sono le applicazioni direttamente utilizzabili dalla schermata Home. b. Il pulsante ....................... permette di ritornare sulla schermata precedente. c. Le notifiche sono visualizzate nella barra di ....................... d. La schermata ....................... si compone di più pannelli virtuali.
3
Completa le frasi utilizzando una tra le parole seguenti. Code • Name • Palette • Design • AndroidManifest.xml • activity_main.xml • res/layout • res/src • res/value • Attributes a. Il file ....................... descrive le caratteristiche principali dell’applicazione. b. La cartella ....................... contiene la descrizione dell’interfaccia grafica. c. Il Version ....................... si riferisce a un codice di versione usato internamente. d. L’area in cui costruire l’interfaccia grafica in modo visuale si chiama ....................... e. La finestra ....................... mostra un insieme di caratteristiche degli oggetti grafici.
4
Associa a ogni classe la corrispondente componente grafica. a. TextView 1. casella di testo b. EditText 2. finestra c. Button 3. etichetta d. Activity 4. pulsante di comando
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
387
Sviluppa le tue competenze PROGETTARE APPLICAZIONI PER DISPOSITIVI MOBILI BASATI SUL SISTEMA OPERATIVO ANDROID 1
Raccogli e confronta le caratteristiche di tre smartphone, elencando gli strumenti multimediali integrati, le interfacce di comunicazione e la presenza di strumenti di geolocalizzazione.
2
Seguendo lo schema del problema precedente, metti a confronto tre modelli di tablet.
3
Collegati al sito di Google per prelevare e installare il pacchetto Android Studio.
COLLAUDARE I PROGETTI CON UN EMULATORE DI DISPOSITIVI 4
Utilizzando Android SDK Manager, installa la versione più recente di Android.
5
Crea un emulatore con il display da 5‘‘ e una versione di Android superiore a 6.
6
Crea un emulatore con il display a bassa risoluzione e una versione di Android inferiore a 7.
7
Crea un emulatore per simulare un tablet con un display da 10’’.
8
Crea un’applicazione che visualizzi il nome dell’utente al centro dello schermo.
9
Esegui il test dell’applicazione precedente su tre emulatori diversi.
10
Installa l’applicazione precedente su un dispositivo reale.
11
Aggiorna l’applicazione creata precedentemente visualizzando, oltre al nome, anche il cognome in un’altra etichetta. Aggiorna la versione (Version Code e Version Name) nel file build.gradle e pubblica il nuovo pacchetto.
UTILIZZARE L’AMBIENTE DI SVILUPPO DELLE APPLICAZIONI PER REALIZZARE PROGETTI DI INFORMATICA MOBILE 12
13
Crea un’applicazione che visualizzi l’ora corrente all’interno di tre etichette, indicanti separatamente le ore, i minuti e i secondi. Crea un’applicazione per l’inserimento dei dati anagrafici (nome e cognome) e due pulsanti di comando. Un pulsante aggiunge il dato anagrafico a un array, mentre l’altro pulsante cancella il contenuto delle caselle di testo.
14
Crea un’applicazione per calcolare la conversione di un importo da euro a dollari. Se l’importo non è inserito correttamente, l’applicazione segnala un errore.
15
Crea un’applicazione per autenticare gli utenti, con le caselle per il nome utente e la password. Se l’utente è autorizzato viene mostrato un messaggio di conferma, altrimenti di accesso negato.
16
Estendi l’applicazione precedente, inserendo le traduzioni per la lingua inglese e francese.
17
Crea un’applicazione composta da tre pulsanti a cui è associato il numero di telefono di tre amici. Il tocco su un pulsante (evento clic) deve attivare la chiamata al numero relativo.
18
Crea un’applicazione composta da una schermata principale e da due videate secondarie. Inserisci due pulsanti nella schermata principale per aprire le videate secondarie.
388
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
STUDIO DI CASI REALI 1
CONTEGGIO DELLE ORE Un tecnico manutentore ha necessità di conteggiare le ore di lavoro durante i suoi interventi. Le informazioni che il tecnico annota sono l’orario di inizio e di fine dell’intervento e la descrizione. Crea un’app che raccolga le informazioni sull’intervento e conteggi il totale delle ore, arrotondato alla mezz’ora, di tutti gli interventi fatti. I dati del singolo intervento vengono utilizzati per aggiornare il totale e vengono successivamente cancellati per lasciare posto all’inserimento dell’intervento successivo. Il totale deve sempre essere visibile nell’app e può essere azzerato con un opportuno pulsante. Per l’inserimento degli orari predisponi due caselle di testo numeriche, una per le ore e una per i minuti. Per il calcolo della durata ti può risultare utile convertire gli orari di inizio e di fine con una rappresentazione a minuti e successivamente eseguire la differenza. Per esempio, se l’intervento inizia alle 14:50 e finisce a 16:15, il valore in minuti per l’inizio è (14 x 60) + 50 = 890 e per la fine è (16 x 60) + 15 = 975. La durata è quindi la differenza tra i due numeri (975 – 890) = 85. Convertendo questo valore in ore, con l’arrotondamento alla mezz’ora, si ottiene come risultato 1,5 ore, che andrà aggiunto al totale.
2
LISTINO PREZZI PER TELEVISORI Crea un’app per la raccolta dei prezzi dei televisori venduti in un negozio. Il listino deve registrare la marca, il modello, le dimensioni in pollici e il prezzo del televisore. Prevedi anche due possibilità di ricerca dei televisori presenti a listino: • tutti i televisori con una certa dimensione; • tutti i televisori all’interno di una fascia di prezzo, indicata con due valori minimo e massimo. Prima di iniziare la stesura del programma, descrivi le strutture di dati che ti serviranno per raccogliere i dati dei televisori in una classe e per memorizzare l’elenco dei televisori in un vettore dinamico. Questo caso non prevede il salvataggio del listino in un database o su file. Puoi posizionare le componenti grafiche per l’inserimento e per la ricerca dei televisori in una stessa schermata; invece puoi visualizzare in una seconda Activity il risultato della ricerca, contenente un elenco di televisori. Per il passaggio della stringa con il risultato tra un’Activity e l’altra, puoi utilizzare i metodi putExtra per inserire la stringa nell’Intent e getStringExtra per leggere la stringa dalla seconda Activity.
3
RACCOLTA DELLE COMANDE Il menu di un bar contiene 30 articoli identificati da un codice numerico, una descrizione e un prezzo. Il cameriere, mentre raccoglie le comande, annota il numero del tavolo e i codici degli articoli con la quantità ordinata. Crea un’app per la raccolta delle comande e per la visualizzazione del totale dello scontrino per il pagamento. Definisci il menu all’interno del codice con un array di articoli e inizializzalo durante la creazione dell’app. Il cameriere deve poter eseguire le seguenti operazioni: • creare una nuova comanda indicando il tavolo; • aggiungere l’ordine di un articolo alla comanda precedentemente aperta; • chiudere la comanda e calcolare il totale dello scontrino. Gli ordini non possono essere aggiunti a una comanda chiusa.
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
389
ANDROID DEVELOPMENT ENVIRONMENT MOBILE COMPUTING Mobile computing is the use of portable computing devices (such as laptop, smartphone and tablet) in conjunction with mobile communication technologies to enable users to access the Internet and data anywhere and anytime. A mobile operating system is an operating system that controls a mobile device such as smartphones or tablet computers. This operating system manages the device hardware and provides various system applications, such as notifications, mail, browser, message services, newsstand for books and magazines, camera, photos, social networks and other standard system services. The user interface is based on touch controls. The most important are: • iOS, the Apple’s mobile operating system for iPhone, iPod Touch and iPad; • Android, developed by Google. ANDROID AND ANDROID STUDIO Android is a Linux-based operating system developed by Google. It is a mobile platform that makes apps, games, songs, books and movies available on touchscreen devices like smartphones and tablets. Google released the Android code as open source
GLOSSARY
software. Android has a large community of developers writing applications (apps), written in a version of Java language, that extend the functionality of devices. Applications for Android are developed using the Android Studio. This integrated development environment provides a set of libraries and developer tools necessary to build, test and debug apps. Developers can create apps that look great and take advantage of the hardware capabilities available on each device. Android automatically adapts the user interface to look its best on different device types. The development environment also creates virtual devices that emulate any hardware configuration. TOUCH GESTURES Users interact with an app via touch gestures. The touch-based interaction can increase usefulness and appeal of an app. There are several common gestures: • tap: touching surface with fingertip; • double tap: rapidly touching surface; • drag: moving fingertip over surface; • pinch and spread: touching surface with two finger and moving them closer or apart; • swipe: scrolling lists or making selections.
QUIZ
Activity A single screen of an Android application.
1
Localisation The process of translating an application into different languages. Mobile computing Processing activity and interaction with a computer that can be transported during its usage. Pinch A gesture of a user touching the screen with two fingers and moving outwards and inwards, used for scaling or zooming content. Swipe A gesture of a user touching the screen with a finger and moving horizontally, used to navigate between panels. Tap A gesture of a user touching the screen with a finger, used for selecting an element or perform an action. This is a replacement of left mouse click on mobile devices.
390
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
2
3
Which of the following data must be provided when creating an Android project? a. Application name b. Project name c. Package name d. JDK version e. SDK version f. Project location g. Company domain Match each file in the left column to its folder in the right column. a. AndroidManifest.xml 1. app/res/layout b. activity_main.xml 2. app/java c. strings.xml 3. app/manifests d. MainActivity.java 4. app/res/values Which of these is the Intent action for a phone call? a. ACTION_PHONE b. ACTION_INTENT c. ACTION_DIAL d. ACTION_SEND
© Istituto Italiano Edizioni Atlas
SCHEDA DI AUTOVALUTAZIONE
1 = con molta difficoltà 2 = con difficoltà 3 = con incertezza
COMPETENZE DIGITALI
4 = con sicurezza 5 = con padronanza
1
2
3
4
5
Conosco le linee evolutive dell’informatica mobile. Descrivo le caratteristiche del sistema operativo Android. Riconosco i gesti dell’utente su dispositivi con touchscreen. So predisporre l’ambiente di sviluppo per realizzare progetti di informatica mobile. Utilizzo le funzionalità dell’ambiente di sviluppo Android Studio. Conosco i passi per realizzare le applicazioni per Android. Distinguo i diversi file XML e Java che formano l’app. Realizzo applicazioni con l’interfaccia grafica. Utilizzo etichette, caselle di testo e pulsanti di comando. Inserisco nell’app i controlli sulle attività dell’utente. So organizzare l’app con le activity. Collaudo l’app con emulatori di dispositivi.
© Istituto Italiano Edizioni Atlas
CAPITOLO
8 • ANDROID E L’AMBIENTE DI SVILUPPO
391
CAPITOLO
9
Le app per l’informatica mobile COMPETENZE • Progettare app efficaci nella presentazione e nell’interazione con l’utente • Realizzare app per i dispositivi di informatica mobile • Pubblicare le app sullo store per Android
CONOSCENZE • Liste dinamiche • Menu • File di dati • Immagini e fotocamera • Distribuzione delle applicazioni • Dispositivi wearable
ABILITÀ • Organizzare i dati in liste • Costruire una lista per l’accesso ai contatti • Realizzare applicazioni per gestire le immagini e la fotocamera • Realizzare applicazioni per smartwatch • Effettuare la registrazione sullo store di Android • Predisporre i file per la pubblicazione delle applicazioni • Distribuire le applicazioni tramite lo store
© Istituto Italiano Edizioni Atlas
PER INIZIARE 1 Quale tra i seguenti file contiene il codice sorgente relativo alla maschera principale dell’applicazione Android? a. AndroidManifest.xml b. MainActivity.java
c. activity_main.xml d. strings.xml
2 Quale tra i seguenti termini indica il disegno dell’interfaccia grafica di un’applicazione? a. layout
b. activity
c. palette d. widget
3 Scrivi nelle caselle vuote le parole mancanti del seguente frammento di codice Java. @Override protected void
(Bundle savedInstanceState) { .onCreate(savedInstanceState); (R.layout.activity_main);
. . . . . . . . . . . . }
© Istituto Italiano Edizioni Atlas
393
1
Le liste dinamiche Le liste dinamiche scorrevoli sono una modalità grafica con cui i dati vengono visualizzati sui dispositivi mobili. Le informazioni sono disposte all’interno di righe e compongono un elenco scorrevole: l’utente può interagire muovendo il dito sullo schermo e toccando le singole righe. Le liste sono chiamate dinamiche perché, solitamente, l’app fornisce i comandi per l’aggiunta di un nuovo elemento e l’eliminazione di quelli presenti. 9.1 Una lista dinamica scorrevole
esempio
Che cos’è una lista dinamica scorrevole?
Un esempio di lista dinamica è l’elenco dei contatti presenti nella rubrica telefonica dello smartphone: ogni riga contiene il nome ed eventualmente il numero di telefono del contatto; l’utente può scorrere l’elenco e toccare con il dito per attivare una chiamata telefonica. Allo stesso modo, l’app che gestisce la posta elettronica presenta l’elenco dei messaggi tramite una lista dinamica. In questo caso la singola riga può contenere più informazioni: l’oggetto della mail, la data, le prime parole del messaggio e la foto del mittente.
La ListView Le liste dinamiche vengono inserite all’interno di un’app utilizzando la classe ListView (android.widget.ListView) nel gruppo Legacy del riquadro Palette di Android Studio, sulla finestra Design. 9.2 La classe ListView
394
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Il corrispondente codice XML, contenuto nella cartella res/layout, è il seguente:
Come si inserisce una lista dinamica in un’app?
All’interno del codice Java, il riferimento alla lista dinamica utilizza il nome univoco specificato nella proprietà id, indicato con la codifica @+id/listViewContatti. Anche se il nome della lista dinamica può essere scelto liberamente, l’utilizzo di un nome significativo, con il prefisso listView, consente di autodocumentare e facilitare il riconoscimento della lista all’interno del codice.
Gli Adapter Il collegamento tra la ListView e la sorgente dei dati visualizzati al suo interno è gestito da oggetti chiamati Adapter. In particolare, gli Adapter si occupano di definire il layout di ogni riga della lista e gestiscono l’inserimento dei valori e il loro aggiornamento. La classe ArrayAdapter implementa un Adapter standard di Android che collega una ListView, dove ogni riga visualizza un’etichetta (TextView), con una sorgente dati basata sulle strutture di dati dinamiche (Java Collections Framework). La classe ArrayList è la principale struttura di dati dinamica utilizzata con un ArrayAdapter. Un ArrayList, composto da un elenco di stringhe, viene istanziato con la seguente dichiarazione: ArrayList elenco = new ArrayList(); I seguenti metodi permettono di aggiungere una nuova stringa, cancellare una stringa in una certa posizione, ordinare alfabeticamente l’elenco ed eliminare tutte le stringhe: elenco.add("Nuova stringa"); elenco.remove(5); Collections.sort(elenco); elenco.clear(); A seguito di una modifica all’ArrayList, per aggiornare il contenuto del componente grafico ListView si deve richiamare il metodo notifyDataSetChanged dell’ArrayAdapter. Ricapitolando, i passaggi per costruire e modificare una lista dinamica sono i seguenti: 1. costruire un ArrayAdapter indicando la sorgente di dati; 2. collegare l’ArrayAdapter con la lista dinamica; 3. eseguire le operazioni di modifica sull’elenco; 4. chiedere all’ArrayAdapter di aggiornare il contenuto della lista dinamica.
Come si crea e si modifica una lista dinamica?
L’evento clic La ListView può rispondere ai clic (tocco del dito) dell’utente sulle singole righe definendo un ascoltatore (OnItemClickListener) con il metodo setOnItemClickListener. L’ascoltatore deve implementare il metodo onItemClick con cui vengono specificate le azioni da eseguire in seguito alla generazione dell’evento clic. La struttura generica del gestore dell’evento clic per un oggetto listViewContatti è: listViewContatti.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Log.i("onItemClick", "Click sulla riga " + position); // Codice del gestore di eventi } });
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
395
Come si gestisce il clic sulla lista?
Il gestore di eventi, usando il parametro position, conosce il numero di riga su cui è stato fatto clic e può usare questa informazione per implementare la sua logica di gestione, leggendo e manipolando la sorgente di dati.
PROVIAMO INSIEME
1 LA LISTA DELLA SPESA Creare un’app per gestire una lista della spesa e le operazioni di aggiunta ed eliminazione degli articoli da acquistare L’app si presenta con una casella di testo per l’inserimento dell’articolo da acquistare e una lista dinamica che visualizza tutti gli articoli inseriti. L’eliminazione di un articolo avviene tramite un clic sulla lista. Per evitare che si cancellino inavvertitamente gli articoli, è prevista una maschera di conferma. La seguente tabella riassume tutte le classi grafiche che vengono aggiunte al file di layout res/layout/ activity_main.xml. Nella colonna Id è indicato l’identificativo, mentre nella colonna Nome oggetto viene indicato il nome che sarà utilizzato successivamente nel codice Java. Nessuno degli oggetti utilizza la proprietà Text. Classe
Id
EditText
@+id/editArticolo
ImageButton
@+id/btnAggiungi
ListView
@+id/listViewSpesa
Text
Nome oggetto editArticolo listViewSpesa
In aggiunta alle precedenti, impostare nella casella di testo editArticolo la proprietà Hint: @string/articoloHint, un’etichetta visibile finché l’utente inizia a digitare nella casella. Inoltre impostare nel pulsante btnAggiungi la proprietà Src: @android:drawable/ic_input_add, per indicare l’icona da visualizzare nel pulsante. L’interfaccia utente dell’app si costruisce in Android Studio facendo doppio clic sul file res/layout/activity_main.xml e modificando il seguente layout, che viene proposto come default:
Si deve eliminare la componente TextView e trasformare il ConstraintLayout in LinearLayout per disporre gli elementi grafici in verticale, dichiarando il valore vertical nella proprietà orientation. Poi, selezionando il pannello Design, dalla finestra Palette si potranno trascinare in sequenza i seguenti elementi: un RelativeLayout, al cui interno saranno posizionati un EditText e un ImageButton; poi, sotto il RelativeLayout, andrà inserita una ListView. Infine, nella finestra Attributes, si dovranno impostare le proprietà inserendo gli Id e verificando in particolare il valore del layout_width e layout_height per le dimensioni degli oggetti.
396
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
I file XML modificati, contenuti nella cartella res, sono riportati di seguito. Risorse (res/values/strings.xml)
Lista della Spesa Settings Nuovo articolo
Layout (res/layout/activity_main.xml)
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
397
Nel codice Java sono dichiarati gli attributi privati relativi agli elementi grafici (listViewSpesa, editArticolo) e gli attributi per gestire la lista dinamica. Il comando per la creazione dell’oggetto adapter è il seguente: adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, listaArticoli); Il primo parametro è un riferimento all’Activity, il secondo parametro è il layout con cui verranno disegnate le singole righe della lista e il terzo è la sorgente di dati. L’assegnazione dell’adapter alla ListView è realizzata con il seguente metodo setAdapter: listViewSpesa.setAdapter(adapter); Il metodo aggiungiArticolo, indicato nella proprietà onClick dell’ImageButton, viene richiamato quando l’utente fa clic sul pulsante di aggiunta. I nuovi articoli vengono inseriti nella prima posizione della lista, indicata con l’indice zero, usando il seguente comando: listaArticoli.add(0, nuovoArticolo); Il metodo eliminaArticolo aggiorna la sorgente dati, rimuovendo l’articolo dalla posizione specificata dal parametro. La richiesta di conferma all’eliminazione è gestita dal metodo eliminaArticoloConConferma. La classe AlertDialog.Builder si occupa di costruire la finestra di dialogo in cui il messaggio viene impostato con il metodo setMessage e i pulsanti di conferma (e annullamento) con i metodi setPositiveButton (e setNegativeButton). Se l’utente fa clic sul pulsante di conferma vengono eseguite le operazioni dichiarate nel metodo onClick. Con il clic sul pulsante di annullamento non vengono eseguite operazioni, perché non è definito alcun ascoltatore (null) come secondo parametro del metodo setNegativeButton. Il codice completo della classe Java che implementa l’applicazione è mostrato di seguito. Activity (MainActivity.java) package it.istitutotecnico.listadellaspesa; import import import import import import import import import
CODIFICA
android.content.DialogInterface; android.support.v7.app.AlertDialog; android.support.v7.app.AppCompatActivity; android.os.Bundle; android.view.View; android.widget.AdapterView; android.widget.ArrayAdapter; android.widget.EditText; android.widget.ListView;
import java.util.ArrayList;
398
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
public class MainActivity extends AppCompatActivity { private ListView listViewSpesa; private EditText editArticolo;
attributi privati relativi agli elementi grafici
attributi privati per gestire la lista dinamica. listaArticoli : struttura dati dell’elenco. adapter : collegamento tra la sorgente dati e l’elemento grafico listViewSpesa
private ArrayList listaArticoli; private ArrayAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
// crea il collegamento con le componenti grafiche listViewSpesa = (ListView) findViewById(R.id.listViewSpesa); editArticolo = (EditText) findViewById(R.id.editArticolo); // crea l'ArrayList per la lista degli articoli listaArticoli = new ArrayList(); creazione dell’oggetto // collega la lista di articoli alla componente grafica adapter // tramite l'ArrayAdapter adapter = new ArrayAdapter(this, assegnazione dell’adapter android.R.layout.simple_list_item_1, alla ListView listaArticoli); listViewSpesa.setAdapter(adapter); // imposta un gestore di eventi sulla lista listViewSpesa.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { eliminaArticoloConConferma(position); } }); } /** metodo richiamato quando l’utente fa clic sul pulsante * Aggiunge l'articolo alla lista. di aggiunta */ public void aggiungiArticolo(View view) { String nuovoArticolo = editArticolo.getText().toString(); if (nuovoArticolo.length() > 0) { listaArticoli.add(0, nuovoArticolo); } // Avvisa l'adapter che i dati sono cambiati adapter.notifyDataSetChanged(); // Svuota la casella editArticolo.setText(""); } /** * Toglie l'articolo dalla lista. */
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
399
public void eliminaArticolo(int position) { listaArticoli.remove(position); adapter.notifyDataSetChanged(); } /** * Apre una finestra dialog per chiedere conferma dell'eliminazione. */ public void eliminaArticoloConConferma(final int position) { richiesta di conferma dell’eliminazione AlertDialog.Builder dialog = new AlertDialog.Builder(this); ascoltatore non definito (null ): con
dialog.setMessage("Cancellare l'articolo ?"); un clic sul pulsante di annullamento non vengono eseguite operazioni dialog.setNegativeButton("No", null); dialog.setPositiveButton("Si", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { eliminaArticolo(position); } }); dialog.show(); }
Lista della spesa
} continua a pag. 411
2
A che cosa serve il Contacts Provider?
L’accesso ai contatti
Tutti i dispositivi mobili sono dotati di una rubrica dove memorizzare i nomi delle persone di cui si vuole ricordare il numero di telefono, l’indirizzo di posta elettronica e le altre informazioni anagrafiche. Google Contatti è un esempio di app che si occupa di organizzare i contatti e, in aggiunta, offre i servizi per eseguire il backup e mantenere l’elenco sincronizzato su tutti i dispositivi. Le informazioni sui contatti sono conservate in un database centralizzato all’interno dei dispositivi Android. L’accesso ai dati è gestito da un’interfaccia chiamata Content Provider (letteralmente “fornitore di contenuti”), che fornisce alle app una modalità standard per accedere alla sorgente dei dati. In particolare, il database dei contatti può essere letto e modificato utilizzando l’interfaccia Contacts Provider. Il Contacts Provider rende disponibili i contatti alle applicazioni tramite un insieme di tabelle, in modo simile ai database relazionali. Le righe della tabella corrispondono ai singoli contatti, mentre le colonne rappresentano i dati (come il nome e il numero di telefono del contatto). Più nel dettaglio, per uno stesso contatto si possono memorizzare più numeri di telefono (casa, cellulare, lavoro) che formano a loro volta una tabella. La lettura dal database dei contatti è fatta con il metodo query a cui vengono passati cinque parametri: 1. la tabella da cui leggere, per esempio Phone.CONTENT_URI per i numeri di telefono; 2. le colonne da estrarre, indicate con un array di stringhe; 3. eventuali condizioni per filtrare le righe; 4. eventuali dati da aggiungere come parametri alle condizioni; 5. un ordinamento delle righe. Il seguente frammento di codice mostra come recuperare tutti i numeri di telefono di un contatto in base al suo identificativo:
400
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
String[] campi = { Phone.NUMBER }; String condizioneWhere = Phone.CONTACT_ID + " = ?"; String[] parametriWhere = { "1236" }; il valore null indica String ordinamento = null;
nessun ordinamento
Cursor cursore = getContentResolver().query( Phone.CONTENT_URI, campi, condizioneWhere, parametriWhere, ordinamento);
Come si cercano i numeri di telefono di un contatto?
NoTA BeNe L’utilizzo del punto interrogativo nella stringa condizioneWhere ha lo scopo di gestire il passaggio di parametri alla query e di evitare possibili attacchi tramite SQL injection, nel caso in cui il parametro fosse letto dall’esterno dell’applicazione. Il risultato dell’esecuzione della query è un oggetto di classe Cursor. Se non sono state trovate righe, il metodo getCount restituisce il valore zero; altrimenti per muoversi tra le righe del risultato si usa il metodo moveToNext inserito in un ciclo. Il package android.provider.ContactsContract contiene le classi per la gestione dei contatti. Le classi principali sono: • Contacts (android.provider.ContactsContract.Contacts); • Phone (android.provider.ContactsContract.CommonDataKinds.Phone); • Email (android.provider.ContactsContract.CommonDataKinds.Email); • StructuredPostal (android.provider.ContactsContract.CommonDataKinds.StructuredPostal).
Quali sono le classi per la gestione dei contatti?
La seguente tabella descrive, per ogni classe, il nome della tabella da utilizzare per l’accesso ai dati dei contatti e il nome del campo principale. Classe
Tabella dati
Campo principale
Descrizione campo
Contacts
Contacts.CONTENT_URI
Contacts.DISPLAY_NAME_PRIMARY
Nome del contatto
Phone
Phone.CONTENT_URI
Phone.NUMBER
N. di telefono
Email
Email.CONTENT_URI
Email.ADDRESS
Email
StructuredPostal
StructuredPostal.CONTENT_URI
StructuredPostal.FORMATTED_ADDRESS Indirizzo
PROVIAMO INSIEME
1 I NUMERI DI CELLULARE Costruire un’app per visualizzare i numeri di cellulare di tutti i contatti L’app carica in una lista scorrevole tutti i contatti e, quando l’utente ne tocca uno, i numeri telefonici associati alla tipologia cellulare vengono mostrati nella parte superiore. Il permesso per accedere alle informazioni sui contatti deve essere richiesto all’utente, che può decidere di concederlo o negarlo. Nel manifest deve essere inserito il tag uses-permission con cui si dichiara di voler utilizzare il permesso READ_CONTACTS per leggere l’elenco dei contatti presenti sul dispositivo. Successivamente, nel codice dell’activity, verrà gestito il popup da mostrare all’utente per la scelta del consenso. Manifest (AndroidManifest.xml)
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
401
L’interfaccia grafica è composta da due componenti TextView e ListView inserite in un contenitore di tipo LinearLayout, su cui è stata impostata la proprietà orientation con il valore vertical. L’etichetta TextView è usata per visualizzare i numeri di telefono di un contatto. Le proprietà impostate per gestire la visualizzazione su più righe e per evidenziarne il contenuto sono le seguenti: • lines: stabilisce il numero di righe da visualizzare; • padding: indica lo spazio da lasciare tra i caratteri e il bordo della componente; • textStyle: imposta uno stile grassetto; • textColor: indica il colore del font. I file XML modificati, contenuti nella cartella res, sono riportati di seguito. Risorse (res/values/strings.xml)
Contatti
Risorse (res/menu/activity_main.xml)
il colorPrimary è il colore usato per la barra del titolo dell'applicazione e viene configurato nel file res/values/colors.xml
Nel codice Java, la richiesta del permesso di lettura sui contatti viene attivata con il metodo requestPermission che deve essere eseguito prima di accedere ai contatti con il seguente comando: ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS},0); Alla prima esecuzione dell’app, viene aperto un popup per chiedere all’utente l’autorizzazione ad accedere ai dati. Se l’autorizzazione è stata concessa, nei successivi lanci non verrà più mostrato il popup e l’elenco dei contatti sarà visibile. Se l’autorizzazione viene negata, l’app non visualizzerà nessun contatto. Il controllo sulla scelta dell’utente viene fatto sovrascrivendo il metodo onRequestPermissionsResult. La lista dei contatti è inserita nella componente ListView utilizzando un adapter (vedi pag. 395) di tipo SimpleCursorAdapter con i seguenti comandi: adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, campi, idCampiLista, 0); listViewContatti.setAdapter(adapter); Il caricamento dei contatti è gestito implementando l’interfaccia LoaderManager.LoaderCallbacks e ridefinendo i tre metodi onCreateLoader, onLoadFinished e onLoaderReset. In particolare, nel metodo onCreateLoader viene usata la classe CursorLoader per eseguire la query, indicando i campi che si vogliono leggere e le eventuali condizioni where. Quando il caricamento è terminato, nel metodo onLoadFinished il cursore viene assegnato all’adapter che si occupa di visualizzare l’elenco nella ListView. L’app carica l’identificativo e il nome di tutti i contatti con le seguenti istruzioni: String[] campi = { Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME_PRIMARY }; il valore null indica che la condizione where è String condizioneWhere = null; vuota, quindi il cursore caricherà tutti i contatti String[] parametriWhere = null; String ordinamento = Contacts.DISPLAY_NAME_PRIMARY + " ASC";
CursorLoader cursore = new CursorLoader(this, Contacts.CONTENT_URI, campi, condizioneWhere, parametriWhere, ordinamento);
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
403
Il campo Contacts._ID contiene l’identificativo univoco del contatto e verrà utilizzato nelle query successive per accedere ai dati di una specifica persona. NoTA BeNe Con il frammento di codice precedente vengono caricati tutti i contatti. Per leggere solo i contatti il cui nome inizia con la lettera A si può utilizzare la seguente condizione: String condizioneWhere = Contacts.DISPLAY_NAME_PRIMARY + " LIKE 'A%'";
Un contatto può avere diversi numeri di telefono e ogni numero è associato a una tipologia. Nel database dei contatti, la tipologia è contenuta nel campo Phone.TYPE e può assumere i seguenti valori: • Phone.TYPE_HOME per il telefono di casa; • Phone.TYPE_MOBILE per il telefono cellulare; • Phone.TYPE_WORK per il telefono di lavoro. L’app vuole visualizzare, per il contatto selezionato, solo i numeri di telefono cellulare. Per implementare questo filtro si utilizza la seguente condizione where, in cui vengono controllati il tipo di telefono e l’identificativo del contatto: String condizioneWhere =
Phone.TYPE + " = " + Phone.TYPE_MOBILE + " AND " + Phone.CONTACT_ID + " = ?";
Il tipo deve essere Phone.TYPE_MOBILE e l’identificativo deve essere uguale a un parametro che indica il contatto associato alla riga toccata dall’utente. Il codice completo della classe Java che implementa l’applicazione è mostrato di seguito. Activity (MainActivity.java) package it.istitutotecnico.contatti; import import import import import import import import import import import import import import import import import
CODIFICA
android.Manifest; android.app.LoaderManager; android.content.CursorLoader; android.content.Loader; android.content.pm.PackageManager; android.database.Cursor; android.provider.ContactsContract.Contacts; android.provider.ContactsContract.CommonDataKinds.Phone; android.support.v4.app.ActivityCompat; android.support.v7.app.AppCompatActivity; android.os.Bundle; android.view.View; android.widget.AdapterView; android.widget.ListView; android.widget.AdapterView.OnItemClickListener; android.widget.SimpleCursorAdapter; android.widget.TextView;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks { private ListView listViewContatti; private TextView txtDettagli;
404
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
private SimpleCursorAdapter adapter; @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // crea il collegamento con le componenti grafiche listViewContatti = (ListView) findViewById(R.id.listViewContatti); txtDettagli = (TextView) findViewById(R.id.txtDettagli); // richiede il permesso di lettura dei contatti ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS},0); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { // se c'è l'autorizzazione mostra i contatti if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mostraContatti();
il valore PERMISSION_GRANTED indica che l’autorizzazione è stata concessa
} } private void mostraContatti() { String[] campi = { Contacts.DISPLAY_NAME_PRIMARY }; int[] idCampiLista = { android.R.id.text1 }; // collega i contatti alla lista tramite il SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, campi, idCampiLista, 0); listViewContatti.setAdapter(adapter); // imposta un gestore di eventi sulla lista listViewContatti.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick (AdapterView parent, View view, int position, long id) { Cursor cursore = adapter.getCursor(); sposta il cursore nella posizione della cursore.moveToPosition(position); riga che l’utente ha toccato
long idContatto = cursore.getLong(0); mostraDettagli(idContatto);
recupera l’ID del contatto presente nel cursore
} }); // avvia il caricamento dei contatti getLoaderManager().initLoader(0, null, this); } private void mostraDettagli(long idContatto) { String[] campi = { Phone.NUMBER };
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
405
String condizioneWhere =
String[] parametriWhere =
Phone.TYPE + " = " + Phone.TYPE_MOBILE + " AND " + Phone.CONTACT_ID + " = ?"; { ""+idContatto };
String ordinamento = null; // recupera il numero di telefono Cursor cursoreTel = getContentResolver().query( Phone.CONTENT_URI, campi, condizioneWhere, parametriWhere, ordinamento); txtDettagli.setText(""); if ((cursoreTel != null) && (cursoreTel.getCount() > 0)) { // scorre il risultato while (cursoreTel.moveToNext()) { int colonna = cursoreTel.getColumnIndex(Phone.NUMBER); String tel = cursoreTel.getString(colonna); txtDettagli.append("N. telefono: " + tel + " \n"); } cursoreTel.close(); } else { txtDettagli.append("Nessun n. di telefono associato"); }
legge il valore della colonna Phone.NUMBER
chiude il cursore
@Override public Loader onCreateLoader (int i, Bundle args) { String[] campi = { Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME_PRIMARY }; String condizioneWhere = null; String[] parametriWhere = null; String ordinamento = Contacts.DISPLAY_NAME_PRIMARY + " ASC";
ordinamento crescente per nome
// recupera tutti i contatti del dispositivo CursorLoader cursore = new CursorLoader(this, Contacts.CONTENT_URI, campi, condizioneWhere, parametriWhere, ordinamento); return cursore; } @Override public void onLoadFinished (Loader loader, Cursor cursore) { adapter.swapCursor(cursore); al termine del caricamento, inserisce il cursore nell’adapter } @Override public void onLoaderReset (Loader loader) { adapter.swapCursor(null); } }
406
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
cancella il riferimento al cursore nell’adapter
© Istituto Italiano Edizioni Atlas
ESECUZIONE
3
Il menu e i file
L’Action Bar L’interfaccia standard delle app in Android non prevede una barra dei menu classica, come per le applicazioni desktop, ma una cosiddetta Action Bar. L’Action Bar si presenta solitamente con i seguenti elementi: • un’icona e un titolo nella parte sinistra; • una serie di pulsanti nella parte destra. 9.3 L’Action Bar
Come si presenta la barra dei menu in Android?
I pulsanti dell’Action Bar rappresentano le voci dell’unico menu associato alla finestra grafica. In particolare il pulsante all’estrema destra, indicato con tre puntini disposti in verticale, è chiamato icona di menu e raggruppa le voci di menu testuali, mentre gli altri pulsanti sono voci di menu identificate da un’icona e chiamate Action. La rappresentazione delle voci tramite icone è da preferirsi per le azioni che l’utente richiede frequentemente, a cui può avere immediato accesso tramite l’Action Bar. Al contrario, le voci di menu poco utilizzate possono essere raggruppate e nascoste all’interno dell’icona di menu. La Action Bar è stata introdotta con la versione 3.0 di Android, corrispondente alla versione dell’SDK indicata come API level 11. © Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
407
Per rendere visibile la Action Bar, nel caso non fosse già attiva, si deve utilizzare il metodo show sull’oggetto di classe ActionBar nel seguente modo: ActionBar actionBar = getSupportActionBar(); actionBar.show(); Le voci di menu vengono descritte all’interno di un file XML, posizionato nella cartella res/menu. In particolare una voce di menu testuale, contenente la scritta Aggiungi, è descritta con il seguente tag:
Come viene descritta una voce del menu?
La proprietà id specifica un identificativo per la voce di menu: sarà utilizzata nel codice Java per stabilire se l’utente abbia fatto clic sulla relativa voce. La proprietà title contiene la descrizione visibile all’utente. Una voce di menu che visualizza l’icona di ricerca è descritta nel file XML con il seguente tag:
La proprietà showAsAction, impostata a ifRoom, stabilisce che l’icona deve essere visualizzata se c’è spazio disponibile sulla Action Bar. In caso contrario, per esempio con dispositivi di ridotte dimensioni, la voce di menu Cerca viene automaticamente aggiunta al gruppo delle voci testuali. La proprietà icon indica l’immagine da visualizzare e la codifica @android:drawable/ic_menu_search fa riferimento a un file grafico standard di Android. La seguente tabella riporta l’elenco di icone predefinite che possono essere utilizzate per la costruzione delle voci di menu.
408
PARTE SECONDA
ic_menu_add
ic_menu_directions
ic_menu_agenda
ic_menu_edit
ic_menu_call
ic_menu_gallery
ic_menu_camera
ic_menu_help
ic_menu_close_clear_cancel
ic_menu_info_details
ic_menu_compass
ic_menu_manage
ic_menu_crop
ic_menu_mapmode
ic_menu_day
ic_menu_month
ic_menu_delete
ic_menu_more
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
ic_menu_my_calendar
ic_menu_send
ic_menu_mylocation
ic_menu_share
ic_menu_myplaces
ic_menu_slideshow
ic_menu_preferences
ic_menu_sort_alphabetically
ic_menu_recent_history
ic_menu_sort_by_size
ic_menu_report_image
ic_menu_today
ic_menu_revert
ic_menu_upload
ic_menu_rotate
ic_menu_view
ic_menu_save
ic_menu_week
ic_menu_search
ic_menu_zoom
L’archiviazione dei file Le app possono leggere e scrivere i file sulle unità di archiviazione integrate nei dispositivi mobili. Esistono due tipologie di archivio utilizzabili come memoria secondaria: • un archivio interno a uso esclusivo dell’app, non accessibile da altre app; • un archivio esterno in cui i file sono visibili, e a volte modificabili, dalle altre app. Queste due tipologie di archivio sono presenti in tutti i dispositivi e in alcuni casi l’archivio esterno può essere estraibile perché si basa su schede di memoria, come per esempio le SD card. Se si collega un dispositivo mobile con un computer, gli archivi esterni del dispositivo vengono riconosciuti come archivi rimovibili e il contenuto può essere letto e modificato dagli utenti.
internal storage, external storage
Qual è la differenza tra archivio interno ed esterno?
Le app che vogliono scrivere i file nell’archivio esterno devono richiedere esplicitamente l’autorizzazione nel file AndroidManifest.xml con la seguente dichiarazione:
Durante la fase di installazione, se l’utente desidera installare l’app, dovrà confermare l’autorizzazione alla scrittura sull’archivio esterno. La seguente tabella indica i metodi utilizzati da un’app per accedere alle proprie cartelle sull’archivio interno ed esterno. Metodo
Archivio
getFilesDir
Cartella principale dell’archivio interno
getExternalFilesDir
Cartella privata dell’archivio esterno
getExternalStoragePublicDirectory
Cartella pubblica nell’archivio esterno
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
409
esempio Un file di testo nomi.txt, presente nella cartella principale dell’archivio interno, viene indicato con un oggetto di classe File nel seguente modo: File pathCartella = getFilesDir(); File pathFile = new File(pathCartella, "nomi.txt"); Si noti che la stessa classe File è utilizzata per recuperare il path della cartella e per costruire il path del file. Per memorizzare il file nomi.txt nell’archivio esterno si deve costruire il path della cartella con la seguente istruzione: File pathCartella = getExternalFilesDir(null); Il parametro, nel precedente metodo, indica il tipo di cartella: con null si fa riferimento alla cartella principale. Se il nome del package in cui è inserita l’app è it.istitutotecnico. app, allora il pathCartella farà riferimento alla seguente cartella privata sul dispositivo: \Android\data\it.istitutotecnico.app\files L’accesso alle cartelle pubbliche, per esempio Pictures, richiede l’utilizzo del metodo statico getExternalStoragePublicDirectory nel seguente modo: String tipo = Environment.DIRECTORY_PICTURES; File pathCartella = Environment.getExternalStoragePublicDirectory(tipo); Il parametro Environment.DIRECTORY_PICTURES indica il tipo di cartella pubblica a cui si vuole fare riferimento. La seguente tabella riporta le cartelle pubbliche predefinite dei dispositivi Android. DIRECTORY_ALARMS
File audio utilizzabili come suoni per la sveglia
DIRECTORY_DCIM
Fotografie e video fatti con il dispositivo
DIRECTORY_DOWNLOADS
File scaricati dall’utente tramite browser o altre app
DIRECTORY_MOVIES
File video
DIRECTORY_MUSIC
File musicali
DIRECTORY_NOTIFICATIONS File audio utilizzabili come suoni di notifica DIRECTORY_PICTURES
File di immagini
DIRECTORY_PODCASTS
File audio che rappresentano podcast
DIRECTORY_RINGTONES
File audio utilizzabili come suonerie
I file di testo Un file di testo, indicato con l’oggetto pathFile di classe File, può essere letto da un’app utilizzando gli oggetti descritti nel Capitolo 3 (vedi pag. 162) e riportati nella seguente dichiarazione: FileReader f = new FileReader(pathFile); BufferedReader fIN = new BufferedReader(f); In che modo l’app può leggere e scrivere un file di testo?
410
PARTE SECONDA
Allo stesso modo, un’app può scrivere un file di testo (pathFile) utilizzando la classe PrintWriter per costruire il seguente oggetto fOUT e ricorrendo ai metodi indicati nel Capitolo 3. PrintWriter fOUT = new PrintWriter(pathFile);
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
PROVIAMO INSIEME
1 IL MENU DI SCELTE PER LA LISTA DELLA SPESA
segue da pag. 396
Estendere l’app che gestisce la lista della spesa con un menu e con le funzioni per salvare la lista su file, in modo da poterla ricaricare successivamente La funzione per salvare la lista della spesa è attivata da una voce di menu visualizzata sulla Action Bar. Una successiva voce di menu consente di svuotare l’intera lista e un’altra voce di menu permette di attivare o disattivare la richiesta di conferma durante l’eliminazione di un articolo. A ogni apertura dell’app viene verificata la presenza di un file precedentemente salvato e, in caso positivo, vengono visualizzati gli ultimi articoli salvati. Dopo aver creato un nuovo progetto in Android Studio, si deve modificare il file AndroidManifest.xml inserendo la richiesta di autorizzazione WRITE_EXTERNAL_STORAGE per la scrittura dei file sull’archivio esterno. Il menu, dichiarato nel file res/menu/activity_main.xml, contiene le voci di menu indicate nella seguente tabella: Id
Title
Icon
@+id/menu_salva
@string/str_salva
ic_menu_save
@+id/menu_svuota
@string/str_svuota
ic_menu_delete
@+id/menu_conferma
@string/str_conferma
I valori delle proprietà Title fanno riferimento alle stringhe che sono impostate nel file res/values/strings.xml. La voce menu_conferma rappresenta una voce di menu di tipo checkbox, in quanto la proprietà checkable è impostata a true e può assumere un valore booleano indicato dalla proprietà checked, come riportato nella seguente dichiarazione:
L’interfaccia grafica contenuta nel file res/layout/activity_main.xml è la stessa del Proviamo insieme a pag. 396, mentre gli altri file XML sono mostrati di seguito. Manifest (AndroidManifest.xml)
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
411
Risorse (res/values/strings.xml)
Lista della Spesa Nuovo articolo Salva Svuota Conferma eliminazione
Risorse (res/menu/activity_main.xml)
Nel codice Java, l’oggetto archivio è utilizzato per fare riferimento a un file di testo. Ogni volta che viene creato un nuovo file, è consigliabile informare il servizio di indicizzazione di Android richiamando il seguente comando: MediaScannerConnection.scanFile(this, new String[] { archivio.getPath() }, null, null); La creazione del menu è gestita dal metodo onCreateOptionsMenu, che viene ridefinito (override) per caricare le voci di menu dichiarate nel file XML. Gli eventi generati dai clic sulle voci di menu sono gestiti nel metodo onOptionsItemSelected. La voce di menu scelta dall’utente viene confrontata con la proprietà Id per stabilire quali operazioni devono essere eseguite. Con la voce di menu di tipo checkbox, il valore viene letto con il metodo isChecked e assegnato alla variabile conferma dopo averlo invertito; infine viene aggiornata la voce di menu con il metodo setChecked. Il codice completo della classe Java che implementa l’applicazione è mostrato di seguito. Activity (MainActivity.java) package it.istitutotecnico.listadellaspesa; import import import import
412
PARTE SECONDA
CODIFICA
android.content.DialogInterface; android.media.MediaScannerConnection; android.support.v7.app.AlertDialog; android.support.v7.app.ActionBar;
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
import import import import import import import import import import import
android.support.v7.app.AppCompatActivity; android.os.Bundle; android.util.Log; android.view.Menu; android.view.MenuItem; android.view.View; android.widget.AdapterView; android.widget.ArrayAdapter; android.widget.EditText; android.widget.ListView; android.widget.Toast;
import import import import import import
java.io.BufferedReader; java.io.File; java.io.FileReader; java.io.IOException; java.io.PrintWriter; java.util.ArrayList;
public class MainActivity extends AppCompatActivity { private ListView listViewSpesa; private EditText editArticolo; private ArrayList listaArticoli; private ArrayAdapter adapter; private boolean conferma = true; private static String NOME_FILE = "articoli.txt"; private File archivio;
oggetto archivio : file di testo
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Visualizza l'action bar ActionBar actionBar = getSupportActionBar(); actionBar.show(); // Imposta il file File dir = getExternalFilesDir(null); archivio = new File(dir, NOME_FILE); Log.d("SpesaActivity", "Path dell'archivio="+archivio); // Crea il collegamento con le componenti grafiche listViewSpesa = (ListView) findViewById(R.id.listViewSpesa); editArticolo = (EditText) findViewById(R.id.editArticolo); // Crea l'ArrayList per la lista degli articoli listaArticoli = new ArrayList(); leggiFile();
la lettura del file è incapsulata nel metodo leggiFile, che è richiamato durante l’apertura dell’app
// Collega la lista di articoli alla componente grafica // tramite l'ArrayAdapter
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
413
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, listaArticoli); listViewSpesa.setAdapter(adapter); // Imposta un gestore di eventi sulla lista listViewSpesa.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { if (conferma) { eliminaArticoloConConferma(position); } else { eliminaArticolo(position); } } }); } @Override creazione del menu public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int voceScelta = item.getItemId(); switch (voceScelta) { case R.id.menu_salva: scriviFile(); return true; case R.id.menu_svuota: svuota(); return true; case R.id.menu_conferma: conferma = ! item.isChecked(); item.setChecked(conferma); return true; default: return super.onOptionsItemSelected(item); }
gestione degli eventi generati dai clic sulle voci di menu
il valore viene letto con il metodo isChecked e assegnato alla variabile conferma dopo averlo invertito aggiorna la voce di menu
} /** * Salva la lista della spesa in un file di testo. */ public void scriviFile() { PrintWriter fOUT;
scrittura del file
Toast msg_ok = Toast.makeText(getApplicationContext(), "Lista della spesa salvata.", Toast.LENGTH_LONG); Toast msg_error = Toast.makeText(getApplicationContext(), "Errore: lista non salvata.", Toast.LENGTH_LONG);
414
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
visualizza un messaggio (Toast) all’utente per indicare se l’operazione è terminata positivamente oppure se non è stato possibile salvare il file
© Istituto Italiano Edizioni Atlas
try { fOUT = new PrintWriter(archivio); for(String articolo : listaArticoli) { fOUT.println(articolo); } fOUT.close(); msg_ok.show(); informa il servizio di
// Indicizza il nuovo file creato indicizzazione di Android MediaScannerConnection.scanFile(this, new String[] { archivio.getPath() }, null, null); } catch (IOException e) { msg_error.show(); Log.d("scriviFile()", "Errore durante il salvataggio."); } } /** * Legge una precedente lista della spesa salvata. */ public void leggiFile() { FileReader f; BufferedReader fIN; String s;
lettura del file
try { f = new FileReader(archivio); fIN = new BufferedReader(f); s = fIN.readLine(); while (s != null) { listaArticoli.add(s); s = fIN.readLine(); } } catch (IOException e) { // Il file non esiste o errore in lettura Log.d("leggiFile()", "Errore durante la lettura."); } } /** * Aggiunge l'articolo alla lista. */ aggiunta di un articolo public void aggiungiArticolo(View view) { String nuovoArticolo = editArticolo.getText().toString(); if (nuovoArticolo.length() > 0) { listaArticoli.add(0, nuovoArticolo); } // Avvisa l'adapter che i dati sono cambiati adapter.notifyDataSetChanged();
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
415
// Svuota la casella editArticolo.setText(""); } /** * Toglie l'articolo dalla lista. */ public void eliminaArticolo(int position) { listaArticoli.remove(position); adapter.notifyDataSetChanged(); }
eliminazione di un articolo
/** * Pulisce la lista della spesa togliendo tutti gli articoli. */ svuota la lista public void svuota() { listaArticoli.clear(); adapter.notifyDataSetChanged(); } /** * Apre una finestra dialog per chiedere conferma dell'eliminazione. */ public void eliminaArticoloConConferma(final int position) { AlertDialog.Builder dialog = new AlertDialog.Builder(this); richiesta di conferma
dialog.setMessage("Cancellare l'articolo ?"); dell’eliminazione dialog.setNegativeButton("No", null); dialog.setPositiveButton("Si", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { eliminaArticolo(position); } }); dialog.show(); } }
PER APPROFONDIRE
LA CONDIVISIONE DI CONTENUTI TRA LE APPLICAZIONI La condivisione di contenuti tra le applicazioni è una funzione disponibile nella maggior parte delle app. In Android l’icona standard che identifica la condivisione è ic_menu_share e, per inserirla come voce di menu, si deve aggiungere il seguente elemento al file XML:
416
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
La condivisione viene gestita tramite la creazione di un Intent di tipo ACTION_SEND, a cui si deve indicare il tipo di dati da condividere (oltre ai dati stessi). Il tipo di dati viene impostato con il metodo setType. I dati vengono aggiungi all’Intent con il metodo putExtra come coppie di nomi e valori. Il primo parametro del metodo indica il nome del dato, tramite una costante contenuta nella classe Intent, mentre il secondo parametro specifica il valore. esempio Il codice completo per condividere l’elenco degli articoli contenuti in listaArticoli è descritto nel seguente frammento di codice: @Override public boolean onOptionsItemSelected(MenuItem item) { int voceScelta = item.getItemId(); switch (voceScelta) { case R.id.menu_condividi: Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Lista della spesa"); shareIntent.putExtra(Intent.EXTRA_TEXT, listaArticoli.toString()); startActivity(shareIntent); return true; default: return super.onOptionsItemSelected(item); } }
La costante EXTRA_SUBJECT indica il testo da condividere come oggetto del messaggio, mentre la costante EXTRA_TEXT indica il contenuto del messaggio. Quando il metodo startActivity viene eseguito, Android cerca un’applicazione nel dispositivo che possa gestire l’azione ACTION_SEND e il tipo text/plain. Se ci sono più applicazioni installate che possono ricevere il messaggio testuale, Android mostra una finestra in cui l’utente può scegliere l’app che intende utilizzare. Dopo aver eseguito la scelta, l’app viene aperta con i dati che sono stati condivisi.
© Istituto Italiano Edizioni Atlas
capitolo
9 • le app per l’informatica mobile
417
4
Le immagini e la fotocamera
La classe ImageView Le immagini vengono inserite all’interno di un’app utilizzando la classe ImageView (android.widget.ImageView) presente nel gruppo Widget della finestra Palette di Android Studio, nel pannello Design. 9.4 La classe ImageView
Il corrispondente codice XML, contenuto nella cartella res/layout, è il seguente:
Come si inserisce un’immagine in un’app?
All’interno del codice Java, il riferimento al contenitore dell’immagine viene costruito facendo riferimento alla proprietà id, indicata con la codifica @+id/imgView. L’oggetto imgView, istanza della classe ImageView, viene creato dal metodo findViewById nel seguente modo: imgView = (ImageView) findViewById(R.id.imgView);
La classe Bitmap La componente ImageView può visualizzare le immagini nei formati JPG e PNG. Il collegamento tra l’ImageView e l’immagine da visualizzare al suo interno è gestita dalla classe Bitmap. Il metodo statico Bitmap.createBitmap crea un’immagine vuota con le dimensioni indicate dai primi due parametri. esempio Un’immagine larga 500 pixel e alta 400 viene creata con il seguente comando: Bitmap bitmap = Bitmap.createBitmap(500, 400, Bitmap.Config.ARGB_8888); Il valore Bitmap.Config.ARGB_8888 stabilisce che ogni pixel venga memorizzato con 4 byte: uno per ogni componente di colore RGB e un ulteriore byte per la trasparenza, indicata con la lettera A (Alpha). Le immagini già memorizzate su file possono essere caricate in memoria con i seguenti metodi statici: • BitmapFactory.decodeFile decodifica l’immagine di cui viene fornito il nome del file; • BitmapFactory.decodeResource legge le immagini contenute nelle risorse dell’applicazione, cioè nelle cartelle /res/drawable; • BitmapFactory.decodeStream decodifica uno stream di input.
418
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Nei seguenti Proviamo insieme saranno utilizzate le tre modalità per caricare l’immagine in un oggetto di classe Bitmap. Dopo che l’immagine è stata caricata in memoria (bitmap), può essere visualizzata nel contenitore ImageView (imgView) con il metodo setImageBitmap: imgView.setImageBitmap(bitmap); La classe Bitmap, oltre a gestire la creazione e il caricamento delle immagini, contiene il metodo compress per scrivere l’immagine su uno stream di output, per esempio un file.
Quali sono le funzioni della classe Bitmap?
FileOutputStream out = null; try { out = new FileOutputStream(imgFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.close(); // Indicizza l'immagine MediaScannerConnection.scanFile(this, new String[] { imgFile.getPath() }, null, null); } catch (Exception e) { // Errore } Il primo parametro del metodo compress indica il formato dell’immagine, che può essere Bitmap.CompressFormat.JPEG oppure Bitmap.CompressFormat.PNG. Il secondo parametro indica la compressione che si vuole applicare, con un valore tra 0 (bassa qualità) e 100 (alta qualità). L’ultimo parametro è il nome dello stream su cui verrà inviata l’immagine. Dopo aver salvato l’immagine su un file, è necessario eseguire l’indicizzazione con il comando MediaScannerConnection.scanFile per rendere disponibile il nuovo elemento multimediale a tutte le altre applicazioni.
Le classi Canvas e Paint La classe Canvas viene usata per modificare un’immagine, perché contiene i metodi per disegnare le linee e le figure geometriche. In aggiunta, quasi tutti i metodi che agiscono sulle immagini utilizzano la classe Paint per stabilire il colore, lo spessore e lo stile delle linee, come pure il font e l’allineamento del testo.
Quali classi si usano per modificare un’immagine?
L’immagine da modificare viene passata al Canvas come parametro del costruttore nel seguente modo: Canvas canvas = new Canvas(bitmap); L’oggetto canvas può utilizzare un insieme di metodi, indicati dal prefisso draw, per modificare l’immagine. esempio Il seguente frammento di codice riporta i principali comandi per tracciare linee e figure geometriche: // Riempie lo sfondo del canvas con il colore rosso canvas.drawColor(Color.RED); // Punto in posizione (400, 100) canvas.drawPoint(400, 100, stile); // Rettangolo con i vertici opposti in posizione (600,600) e (750,700) canvas.drawRect(600, 600, 750, 700, stile);
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
419
// Linea dal punto (80,50) al punto (200,200) canvas.drawLine(80, 50, 200, 200, stile); // Cerchio in posizione (200,200) con raggio 50 canvas.drawCircle(200, 200, 50, stile); // Arco da 0 a 270 gradi inscritto nel rettangolo (10,10) (150,90) canvas.drawArc(10, 10, 150, 90, 0, 270, false, stile); // Ellisse inscritta nel rettangolo (50,400) (500,600) canvas.drawOval(50, 400, 500, 600, stile); // Testo in posizione (20,15) canvas.drawText("Ciao", 20, 15, stile); // Immagine in posizione (50,50) canvas.drawBitmap(immagine, 50, 50, null); L’oggetto stile, utilizzato in quasi tutti i metodi dell’esempio precedente, descrive la modalità con cui le figure geometriche devono essere disegnate. esempio • Stile di un rettangolo, di cui si vogliono tracciare solo i contorni (Style.STROKE), con un colore blu e uno spessore delle linee di 5 pixel: stile = new Paint(); stile.setColor(Color.BLUE); stile.setStrokeWidth(5); stile.setStyle(Style.STROKE); • Stile di un cerchio colorato interamente (Style.FILL) di verde e con un effetto ombreggiato a distanza di 5 pixel: stile = new Paint(); stile.setColor(Color.GREEN); stile.setStyle(Style.FILL); stile.setShadowLayer(5, 5, 5, Color.BLACK); • Stile di un testo di colore nero, con il font serif (Typeface.SERIF) di dimensione 60 pixel e in grassetto (Typeface.BOLD), allineato al centro rispetto alla posizione indicata nel metodo drawText: stile = new Paint(); stile.setColor(Color.BLACK); stile.setTypeface(Typeface.create(Typeface.SERIF, Typeface.BOLD)); stile.setTextSize(60); stile.setTextAlign(Align.CENTER);
PROVIAMO INSIEME
1 UN’IMMAGINE PERSONALIZZATA Creare un’immagine all’interno di un’app utilizzando i metodi della classe Canvas Questo problema utilizza gli oggetti per visualizzare e modificare le immagini: ognuno è stato dichiarato con un attributo privato all’interno della classe principale dell’applicazione.
420
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
private private private private
ImageView imgView; Bitmap bitmap; Canvas canvas; Paint stile1, stile2, stile3;
I passi per la costruzione di un’immagine personalizzata (evidenziati nel codice Java a pag. 423) sono i seguenti: 1. creare l’oggetto bitmap; 2. creare l’oggetto canvas associato alla bitmap; 3. impostare gli stili come istanze della classe Paint; 4. disegnare sul canvas con i metodi draw; 5. riportare la bitmap sulla componente grafica imgView. L’interfaccia grafica di questa applicazione è composta da un pulsante (btnCrea) e da un’immagine (imgView) per visualizzare il risultato. Queste due componenti grafiche sono disposte all’interno di un layout in cui la parte superiore è riservata ai pulsanti di comando, mentre la parte centrale è riservata all’immagine. Questa stessa impostazione verrà ripresa anche nei Proviamo insieme successivi. pulsante di comando (btnCrea)
immagine (imgView)
L’icona smile, identificata dalla risorsa con la notazione R.drawable, è un’immagine PNG (smile.png) memorizzata nella cartella /res/drawable del progetto. Il caricamento dell’icona, il cui riferimento completo è R.drawable.smile, è eseguito dal metodo decodeResource nel seguente modo: Bitmap ico = BitmapFactory.decodeResource(getResources(), R.drawable.smile); NoTA BeNe Per posizionare l’icona nel centro dell’immagine, è stato necessario calcolare la posizione (posX, posY) dello spigolo in alto a sinistra nel seguente modo: int posX = w/2 - ico.getWidth()/2; int posY = h/2 - ico.getHeight()/2; Le variabili w e h indicano rispettivamente la larghezza e l’altezza dell’immagine, mentre le dimensioni dell’icona sono calcolate con i metodi ico.getWidth e ico.getHeight. Il codice sorgente di tutti i file che compongono il progetto è riportato di seguito. Manifest (AndroidManifest.xml)
Risorse (res/values/strings.xml)
Disegno Crea
Layout (res/layout/activity_main.xml)
422
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Activity (MainActivity.java) package it.istitutotecnico.disegno; import import import import import import import import import import import import import
CODIFICA
android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Canvas; android.graphics.Color; android.graphics.Paint; android.graphics.Paint.Align; android.graphics.Paint.Style; android.graphics.Typeface; android.support.v7.app.AppCompatActivity; android.os.Bundle; android.util.Log; android.view.View; android.widget.ImageView;
public class MainActivity extends AppCompatActivity { private private private private
attributi privati relativi agli elementi grafici: • oggetto bitmap; • oggetto canvas associato alla bitmap; • stili come istanze della classe Paint
ImageView imgView; Bitmap bitmap; Canvas canvas; Paint stile1, stile2, stile3;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgView = (ImageView) findViewById(R.id.imgView); } public void crea(View v) { int w = imgView.getWidth(); int h = imgView.getHeight(); Log.i("DEBUG", "Dimensioni w="+w+", h="+h); (1)
//1- Crea la bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
(2)
//2- Crea il canvas canvas = new Canvas(bitmap); //3- Imposta gli stili stile1 = new Paint(); stile1.setColor(Color.BLUE); stile1.setStrokeWidth(5); stile1.setStyle(Style.STROKE);
(3)
stile2 = new Paint(); stile2.setColor(Color.GREEN); stile2.setStyle(Style.FILL); stile2.setShadowLayer(5, 5, 5, Color.RED); stile3 = new Paint(); stile3.setColor(Color.BLACK); stile3.setTextSize(60); stile3.setTypeface(Typeface.create(Typeface.SERIF, Typeface.BOLD)); stile3.setTextAlign(Align.CENTER);
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
423
//4- Modifica il canvas/bitmap canvas.drawColor(Color.LTGRAY); disegna sul canvas con i metodi draw
canvas.drawRect(20, 20, w-20, 200, stile2); canvas.drawCircle(w/2, h/2, 200, stile1); canvas.drawText("CIAO", w/2, h-150, stile3); canvas.drawLine(100, h-100, w-100, h-100, stile2);
(4)
Bitmap ico = BitmapFactory.decodeResource(getResources(), R.drawable.smile); int posX = w/2 - ico.getWidth()/2; int posY = h/2 - ico.getHeight()/2; canvas.drawBitmap(ico, posX, posY, null); //5- Riporta la bitmap sulla componente grafica imgView.setImageBitmap(bitmap);
(5)
} } ESECUZIONE
2 DISEGNARE CON IL DITO Creare un’applicazione che, gestendo il trascinamento del dito sul dispositivo, permetta di creare disegni digitali L’interfaccia grafica, descritta nel file di layout activity_main.xml, si presenta con tre componenti disposte orizzontalmente all’interno di un LinearLayout: • un pulsante per creare un nuovo disegno (Button); • una casella combinata per scegliere il colore del tratto (Spinner); • una barra per scegliere lo spessore della linea (SeekBar). pulsante di comando (Button)
barra di scelta per trascinamento (SeekBar)
casella combinata (Spinner)
disegno
424
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
La seguente tabella riassume tutte le classi grafiche che vengono aggiunte al file di layout res/layout/ activity_main.xml e le due principali proprietà, Id e Text. Nella colonna Nome oggetto viene indicato il nome dell’attributo utilizzato nel codice Java, mentre la colonna onClick indica il nome del metodo richiamato dall’attivazione del relativo pulsante. Classe
Id
Text
Nome oggetto
Button
@+id/btnNuovo
@string/str_nuovo
Spinner
@+id/colore
colore
SeekBar
@+id/spessore
spessore
ImageView
@+id/imgView
imgView
onClick nuovo
Manifest (AndroidManifest.xml)
Risorse (res/values/strings.xml)
DisegnoTouch Nuovo
Layout (res/layout/activity_main.xml)
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
425
Nel codice Java sono dichiarate tre costanti per indicare lo spessore massimo (MAX_RAGGIO), il nome (STR_COLORI) e il valore intero dei colori (INT_COLORI). Le costanti sono state posizionate all’inizio della classe per facilitare le eventuali operazioni di modifica future. Per esempio, se si volesse aggiungere un quarto colore la modifica sarebbe localizzata e non richiederebbe l’analisi di tutto il programma. La barra per la scelta dello spessore è implementata con la classe SeekBar. Il metodo setMax stabilisce il valore massimo che la barra può raggiungere, mentre il metodo setProgress imposta il valore iniziale. Il valore minimo è zero. In fase di inizializzazione, la barra viene configurata nel seguente modo: spessore.setMax(MAX_RAGGIO); spessore.setProgress(MAX_RAGGIO/2); La classe Spinner descrive una casella combinata: i suoi elementi vengono aggiunti tramite un ArrayAdapter, in un modo simile a come sono stati costruiti i menu nel Proviamo insieme del paragrafo precedente. La gestione dell’evento di trascinamento del dito sul dispositivo è delegata al metodo onTouch, assegnato all’immagine (imgView) e dichiarato nel seguente modo: imgView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { . . . } }
426
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Ogni volta che l’utente tocca lo schermo (azione MotionEvent.ACTION_DOWN), muove il dito (azione MotionEvent.ACTION_MOVE) o lo alza (azione MotionEvent.ACTION_UP), viene richiamato il metodo onTouch e il parametro event raccoglie le informazioni sull’evento. La posizione del dito sullo schermo è stabilita dalla coppia di valori ottenuta con i metodi getX e getY. Il metodo getAction restituisce il tipo di azione eseguita dall’utente. Per gli scopi di questo problema, al verificarsi dell’azione MotionEvent.ACTION_MOVE viene impostato il colore dello stile con il valore (posColore) letto dallo Spinner e viene disegnato un cerchio, con le dimensioni (raggio) lette dalla SeekBar, nel punto in cui l’utente ha posizionato il dito (touchX, touchY). stile.setColor(INT_COLORI[posColore]); canvas.drawCircle(touchX, touchY, raggio, stile); Il codice completo della classe Java che implementa l’applicazione è mostrato di seguito. Activity (MainActivity.java) package it.istitutotecnico.disegnotouch; import import import import import import import import import import import import
CODIFICA
android.graphics.Bitmap; android.graphics.Canvas; android.graphics.Color; android.graphics.Paint; android.support.v7.app.AppCompatActivity; android.os.Bundle; android.view.MotionEvent; android.view.View; android.widget.ArrayAdapter; android.widget.ImageView; android.widget.SeekBar; android.widget.Spinner;
public class MainActivity extends AppCompatActivity { private static final int MAX_RAGGIO = 100; private static final String STR_COLORI[] = { "Rosso", "Blue", "Verde" }; private static final int INT_COLORI[] = { Color.RED, Color.BLUE, Color.GREEN }; private private private private
ImageView imgView; Bitmap bitmap; Canvas canvas; Paint stile;
private SeekBar spessore; private Spinner colore; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Imposta la barra per la scelta dello spessore spessore = (SeekBar) findViewById(R.id.spessore); spessore.setMax(MAX_RAGGIO); spessore.setProgress(MAX_RAGGIO/2);
configurazione della barra di scelta dello spessore
// Imposta il menu per la scelta del colore colore = (Spinner) findViewById(R.id.colore);
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
427
ArrayAdapter aa = new ArrayAdapter(this, android.R.layout.simple_spinner_item, STR_COLORI); aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); colore.setAdapter(aa); bitmap = null; canvas = null; stile = new Paint(); stile.setStyle(Paint.Style.FILL); imgView = (ImageView) findViewById(R.id.imgView); // Imposta il gestore dell'evento Touch imgView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { float touchX = event.getX(); float touchY = event.getY(); int posColore = colore.getSelectedItemPosition(); int raggio = spessore.getProgress(); if (canvas == null) { return true; }
gestione dell’evento di trascinamento del dito sul dispositivo
metodo getSelectedItemPosition: legge l’indice dell’elemento selezionato metodo getProgress: restituisce il valore attuale della barra, con un intero tra zero e MAX_RAGGIO
switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: stile.setColor(INT_COLORI[posColore]); canvas.drawCircle(touchX, touchY, raggio, stile); imgView.setImageBitmap(bitmap); break; case MotionEvent.ACTION_UP: break; }
disegna un cerchio nel punto in cui l’utente ha posizionato il dito
return true; } }); } public void nuovo(View v) { int w = imgView.getWidth(); int h = imgView.getHeight(); bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); imgView.setImageBitmap(bitmap); } }
428
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
ESECUZIONE
3 UN BORDO PER LE IMMAGINI
Modificare le immagini memorizzate sul dispositivo aggiungendo un bordo L’applicazione prevede tre funzioni, gestite da altrettanti pulsanti: • apri, per leggere un’immagine tra quelle memorizzate nel dispositivo; • modifica, per disegnare un bordo intorno all’immagine; • salva, per memorizzare l’immagine modificata con un nuovo nome. pulsanti di comando
immagine
La seguente tabella riassume tutte le classi grafiche che vengono aggiunte al file di layout res/layout/ activity_main.xml. Classe
Id
Text
Nome oggetto
onClick
Button
@+id/btnApri
@string/str_apri
apri
Button
@+id/btnModifica
@string/str_modifica
modifica
Button
@+id/btnSalva
@string/str_salva
salva
ImageView
@+id/imgView
imgView
Per salvare il file nella memoria del dispositivo è necessario richiedere l’autorizzazione tramite la seguente dichiarazione nel file Manifest:
A partire da Android 6.0, per gestire i permessi delle app, l'utente deve aprire le Impostazioni del dispositivo, scegliere la voce App e notifiche e successivamente fare clic sul nome della app. Infine, all'interno del pannello Autorizzazioni, si possono attivare o disattivare i singoli permessi. © Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
429
Manifest (AndroidManifest.xml)
Risorse (res/values/strings.xml)
Crea Bordo Apri Modifica Salva
Layout (res/layout/activity_main.xml)
Nel codice Java, all’interno del metodo apri, viene richiesta l’apertura dell’applicazione standard che si occupa di visualizzare la galleria di immagini. Dopo la scelta dell’immagine, viene eseguito il metodo onActivityResult e il parametro data contiene un riferimento all’immagine. Se il parametro data non è nullo, l’immagine può essere letta tramite uno stream di input (in) costruito nel seguente modo: in = getContentResolver().openInputStream(immagine); Il metodo decodeStream legge lo stream e importa l’immagine nell’applicazione (bitmap). NoTA BeNe L’apertura di immagini fotografiche, soprattutto ad alta risoluzione, richiede una grande quantità di memoria che, sui dispositivi meno potenti, può essere insufficiente. Per limitare l’utilizzo della memoria, l’opzione inSampleSize stabilisce il fattore di ridimensionamento: 1 per ottenere l’immagine intera, 2 per ridurre le dimensioni a metà e numeri maggiori per diminuire ulteriormente l’occupazione di memoria. BitmapFactory.Options opzioni = new BitmapFactory.Options(); opzioni.inMutable = true; opzioni.inSampleSize = 4; bitmap = BitmapFactory.decodeStream(in, null, opzioni); Nel metodo salva, l’immagine viene registrata con un nuovo nome nella cartella pubblica predefinita Environment.DIRECTORY_PICTURES. Per evitare che possano essere sovrascritte altre immagini con lo stesso nome viene creato un nome univoco, inserendo la data e l’ora corrente nel nome del file: SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date oggi = new Date(); String nome = "img_" + sdf.format(oggi) + ".jpg";
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
431
L’applicazione comunica il risultato delle operazioni all’utente utilizzando la classe Toast. Vengono inoltre scritti i messaggi di log nella finestra di Logcat con il metodo Log.i, per permettere allo sviluppatore di controllare le dimensioni dell’immagine e il path in cui è stato salvato il file. Log.i("DEBUG", "width = " + w); Log.i("DEBUG", "height = " + h); Log.i("DEBUG", "Path dell'immagine = " + imgFile); Il codice completo della classe Java che implementa l’applicazione è mostrato di seguito. Activity (MainActivity.java) package it.istitutotecnico.bordo; import import import import import import import import import import import import import import import import
android.content.Intent; android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Canvas; android.graphics.Color; android.graphics.Paint; android.graphics.Paint.Style; android.media.MediaScannerConnection; android.net.Uri; android.os.Environment; android.support.v7.app.AppCompatActivity; android.os.Bundle; android.util.Log; android.view.View; android.widget.ImageView; android.widget.Toast;
import import import import import
java.io.File; java.io.FileOutputStream; java.io.InputStream; java.text.SimpleDateFormat; java.util.Date;
CODIFICA
public class MainActivity extends AppCompatActivity { private static final int RICHIESTA_GALLERIA = 0; private static final int SPESSORE_BORDO = 50; private Bitmap bitmap; private ImageView imgView; private Toast toast; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bitmap
= null;
imgView = (ImageView) findViewById(R.id.imgView); imgView.setBackgroundColor(Color.LTGRAY); }
432
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
metodo setBackgroundColor: imposta il colore grigio chiaro come sfondo dell’area dell’immagine
© Istituto Italiano Edizioni Atlas
public void apri(View v) { String action = Intent.ACTION_PICK; Uri uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; Intent galleria = new Intent(action, uri); startActivityForResult(galleria, RICHIESTA_GALLERIA); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if ((resultCode == RESULT_OK) && (requestCode == RICHIESTA_GALLERIA) && (data != null)) { Uri immagine = data.getData(); costruisce uno stream di input InputStream in; da cui leggere l’immagine try { in = getContentResolver().openInputStream(immagine); } catch (Exception e) { in = null; }
if (in != null) { // Legge l'immagine dallo stream BitmapFactory.Options opzioni = new BitmapFactory.Options(); opzioni.inMutable = true; opzioni.inSampleSize = 4; bitmap = BitmapFactory.decodeStream(in, null, opzioni);
opzione inMutable = true : l’immagine può essere successivamente modificata
if (bitmap != null) { legge lo stream e importa l’immagine nell’applicazione imgView.setImageBitmap(bitmap); } else { toast = Toast.makeText(this, "Errore durante la decodifica", Toast.LENGTH_SHORT); toast.show(); } } } else { toast = Toast.makeText(this, "Nessuna immagine selezionata", Toast.LENGTH_LONG); toast.show(); } } public void modifica(View v) { if (bitmap == null) { toast = Toast.makeText(this, "Nessuna immagine da modificare", Toast.LENGTH_SHORT); toast.show(); return; } Canvas canvas = new Canvas(bitmap); Paint stile = new Paint(); stile.setColor(Color.BLUE);
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
433
stile.setStyle(Style.STROKE); stile.setStrokeWidth(SPESSORE_BORDO); int w = canvas.getWidth(); int h = canvas.getHeight(); canvas.drawRect(0, 0, w, h, stile); imgView.setImageBitmap(bitmap);
aggiunge il bordo e aggiorna l’immagine
Log.i("DEBUG", "width = " + w); Log.i("DEBUG", "height = " + h); } public void salva(View v) { if (bitmap == null) { toast = Toast.makeText(this, "Nessuna immagine da salvare", Toast.LENGTH_SHORT); toast.show(); return; } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date oggi = new Date(); String nome = "img_" + sdf.format(oggi) + ".jpg"; registra l’immagine con un nuovo nome nella cartella // Imposta il file pubblica predefinita String tipo = Environment.DIRECTORY_PICTURES; File dir = Environment.getExternalStoragePublicDirectory(tipo); File imgFile = new File(dir, nome); Log.i("DEBUG", "Path dell'immagine = " + imgFile);
FileOutputStream out = null; try { out = new FileOutputStream(imgFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.close(); // Aggiorna il MediaStore MediaScannerConnection.scanFile(this, new String[] { imgFile.getPath() }, null, null); toast = Toast.makeText(this, "File salvato", Toast.LENGTH_SHORT); toast.show(); } catch (Exception e) { toast = Toast.makeText(this, "Errore: file non salvato", Toast.LENGTH_LONG); toast.show(); } } } NoTA BeNe Per utilizzare il pulsante Salva, è necessario concedere alla app le autorizzazioni di scrittura sul dispositivo. Si devono aprire le Impostazioni del dispositivo, scegliere la voce App e notifiche e poi l’applicazione Crea Bordo. Nel pannello Autorizzazioni si deve attivare l’autorizzazione di Archiviazione.
434
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
ESECUZIONE
Bordo dell’immagine
4 A CHE ORA HO SCATTATO LA FOTOGRAFIA? Catturare un’immagine con la fotocamera e aggiungere l’ora in cui è stata scattata L’interfaccia grafica è simile a quella del Proviamo insieme precedente. pulsanti di comando
immagine
La seguente tabella riassume tutte le classi grafiche che vengono aggiunte al file di layout res/layout/ activity_main.xml. Classe
Id
Text
Nome oggetto
onClick
Button
@+id/btnScatta
@string/str_scatta
scatta
Button
@+id/btnSalva
@string/str_salva
salva
ImageView
@+id/imgView
imgView
Manifest (AndroidManifest.xml)
Risorse (res/values/strings.xml)
Fotocamera Scatta foto Salva
Layout (res/layout/activity_main.xml)
436
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Il metodo scatta utilizza l’azione MediaStore.ACTION_IMAGE_CAPTURE, passandola alla classe Intent, per attivare la fotocamera del dispositivo. Dopo che l’immagine è stata scattata e accettata dall’utente viene eseguito il metodo onActivityResult. La fotografia ricevuta dalla fotocamera viene estratta dall’oggetto data e viene assegnata a un oggetto di classe Bitmap. Questa immagine non è modificabile e, per poterla elaborare, si deve creare una copia come mostra il seguente frammento di codice: Bundle extras = data.getExtras(); Bitmap fotografia = (Bitmap) extras.get("data"); bitmap = fotografia.copy(Bitmap.Config.ARGB_8888,true); Prima di visualizzare l’immagine, viene eseguito il metodo aggiungiOrario per inserire l’ora corrente nella parte inferiore dell’immagine. Il metodo salva esegue le stesse operazioni già utilizzate nel problema precedente per scrivere l’immagine in un file. Il codice completo della classe Java che implementa l’applicazione è mostrato di seguito. Activity (MainActivity.java) package it.istitutotecnico.fotocamera; import import import import import import import import import import import import import import import import import
android.content.Intent; android.graphics.Bitmap; android.graphics.Canvas; android.graphics.Color; android.graphics.Paint; android.graphics.Paint.Align; android.graphics.Paint.Style; android.graphics.Typeface; android.media.MediaScannerConnection; android.os.Environment; android.provider.MediaStore; android.support.v7.app.AppCompatActivity; android.os.Bundle; android.util.Log; android.view.View; android.widget.ImageView; android.widget.Toast;
import import import import
java.io.File; java.io.FileOutputStream; java.text.SimpleDateFormat; java.util.Date;
CODIFICA
public class MainActivity extends AppCompatActivity {
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
437
private static final int RICHIESTA_FOTO = 0; private Bitmap bitmap; private ImageView imgView; private Toast toast; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgView = (ImageView) findViewById(R.id.imgView); imgView.setBackgroundColor(Color.LTGRAY); } public void scatta(View v) { String action = MediaStore.ACTION_IMAGE_CAPTURE;
azione che attiva la fotocamera
Intent fotocamera = new Intent(action); if (fotocamera.resolveActivity(getPackageManager()) != null) { startActivityForResult(fotocamera, RICHIESTA_FOTO); } } protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if ((resultCode == RESULT_OK) && (requestCode == RICHIESTA_FOTO)) { Bundle extras = data.getExtras(); Bitmap fotografia = (Bitmap) extras.get("data"); // Crea una copia modificabile dell'immagine bitmap = fotografia.copy(Bitmap.Config.ARGB_8888,true); if (bitmap != null) { aggiungiOrario(); imgView.setImageBitmap(bitmap); } else { toast = Toast.makeText(this, "Errore durante la decodifica", Toast.LENGTH_SHORT); toast.show(); } } else { toast = Toast.makeText(this, "Foto non disponibile", Toast.LENGTH_SHORT); toast.show(); } } public void aggiungiOrario() { Canvas canvas = new Canvas(bitmap); Paint stile = new Paint(); stile.setColor(Color.WHITE); stile.setAlpha(150); stile.setStyle(Style.FILL);
438
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
metodo setAlpha: imposta la trasparenza per il rettangolo contenente l’orario
© Istituto Italiano Edizioni Atlas
Paint stileFont = new Paint(); stileFont.setColor(Color.BLACK); stileFont.setTextSize(10); stileFont.setTypeface(Typeface.SANS_SERIF); stileFont.setTextAlign(Align.CENTER); int w = canvas.getWidth(); int h = canvas.getHeight(); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); Date oggi = new Date(); String msg = "Scattata alle ore " + sdf.format(oggi); inserisce l’ora corrente nella parte inferiore dell’immagine
canvas.drawRect(20, h-30, w-20, h-10, stile); canvas.drawText(msg, w/2, h-15, stileFont); }
public void salva(View v) { if (bitmap == null) { toast = Toast.makeText(this, "Nessuna foto da salvare", Toast.LENGTH_SHORT); toast.show(); return; } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date oggi = new Date(); String nome = "img_" + sdf.format(oggi) + ".jpg"; String tipo = Environment.DIRECTORY_PICTURES; File dir = Environment.getExternalStoragePublicDirectory(tipo); File imgFile = new File(dir, nome); FileOutputStream out = null; try { out = new FileOutputStream(imgFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.close(); // Aggiorna il MediaStore MediaScannerConnection.scanFile(this, new String[] { imgFile.getPath() }, null, null); toast = Toast.makeText(this, "File salvato", Toast.LENGTH_SHORT); toast.show(); } catch (Exception e) { toast = Toast.makeText(this, "Errore: file non salvato", Toast.LENGTH_LONG); toast.show(); } } } NoTA BeNe Per utilizzare il pulsante Salva, è necessario concedere alla app le autorizzazioni di scrittura sul dispositivo. Si devono aprire le Impostazioni del dispositivo, scegliere la voce App e notifiche e poi l’applicazione Fotocamera. Nel pannello Autorizzazioni si deve attivare l’autorizzazione di Archiviazione.
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
439
ESECUZIONE
5
La distribuzione delle applicazioni
La disponibilità di un grande numero di applicazioni on line, di cui molte gratuite, è uno tra i motivi di successo dell’informatica mobile negli anni recenti. Le applicazioni per i dispositivi mobili sono distribuite dalle software house, o direttamente dai programmatori, nei cosiddetti store (negozi virtuali) di applicazioni. Esistono diversi store per Android gestiti da importanti società nel mondo dell’informatica, per esempio Amazon (Amazon Appstore) e Samsung (Samsung Apps).
Dove vengono distribuite le applicazioni?
Google Play è lo store ufficiale di Google e permette di scaricare applicazioni, libri e musica sia gratuitamente che a pagamento. L’accesso a Google Play dai dispositivi mobili avviene tramite Play Store, un’applicazione preinstallata su tutti i dispositivi Android. Google Play è disponibile anche sul Web all’indirizzo http://play.google.com. In questo caso l’elenco di applicazioni è visualizzabile con un browser Web e, collegandosi con un account Google, si ha anche accesso alle applicazioni installate sui propri dispositivi mobili.
Pubblicazione
Il passo finale nella realizzazione di un’applicazione è la sua pubblicazione in uno store in modo da poterla distribuire nel mercato globale. Prima della pubblicazione, il programmatore deve eseguire i collaudi su diversi emulatori in modo da garantire un alto livello di qualità del software prodotto. Nel seguito vengono illustrati i passi necessari per pubblicare un’applicazione su Google Play.
La registrazione Per poter caricare applicazioni su Google Play è richiesta la registrazione come sviluppatore, che comporta il pagamento di una quota di iscrizione. Non ci sono ulteriori commissioni per la distribuzione delle applicazioni gratuite, mentre per le applicazioni a pagamento Google richiede, come rimborso del servizio offerto, una provvigione sul prezzo di vendita. Come si esegue la registrazione dello sviluppatore?
440
PARTE SECONDA
La registrazione come sviluppatore può essere eseguita comunicando i propri dati personali a Google tramite il sito riservato agli sviluppatori (Google Play Console) raggiungibile all’indirizzo:
• IL WEB E L’INFORMATICA MOBILE
https://play.google.com/apps/publish © Istituto Italiano Edizioni Atlas
La firma del file APK Pubblicare un’applicazione su Google Play significa caricare il file APK (Android Package), firmato con un certificato digitale, la cui chiave privata è conosciuta solo dal programmatore. In questo modo Google può garantire che la pubblicazione, e soprattutto gli aggiornamenti successivi, facciano riferimento allo stesso programmatore.
Perché è necessario firmare l’app?
In Android Studio esiste una procedura guidata per firmare un’applicazione: dal menu Build, fare clic su Generate Signed Bundle or APK e successivamente selezionare l’opzione APK, quindi fare clic sul pulsante Next. Dopo aver indicato il nome del progetto da esportare, occorre specificare il nome dell’archivio (keystore) contenente la chiave da usare per la firma e la password. archivio (keystore) contenente la chiave
informazioni per la creazione della chiave
9.5 La creazione della chiave
Per creare una nuova chiave, dopo aver fatto clic su Create new, indicare il percorso del file nel Key store path e una password. Nella maschera vengono richieste altre informazioni per la creazione della chiave: il nome della chiave (alias), la password, gli anni di validità e i dati identificativi del creatore. Dopo aver fatto clic su OK per confermare la creazione della chiave, si deve premere Next, indicare la cartella di destinazione del file APK e fare clic su Finish. L’applicazione, costituita dal file .apk appena creato, è pronta per essere caricata nello store.
L’anteprima Oltre al caricamento del file APK firmato, Google Play richiede l’inserimento di una descrizione e di uno o più screenshot (videate) che permettano agli utenti di visualizzare un’anteprima del prodotto software. È opportuno impostare un’icona che identifichi l’applicazione e diverse immagini che possono essere utilizzate per invogliare gli utenti a scaricare, ed eventualmente acquistare, l’applicazione. È inoltre consigliata la traduzione della descrizione in altre lingue, o come minimo in lingua inglese, in modo da poter offrire l’applicazione a un pubblico di utenti più vasto.
Quali elementi possono essere inseriti nell’anteprima?
Le statistiche Dopo aver pubblicato un’applicazione, la Google Play Console consente allo sviluppatore di monitorare le statistiche dettagliate sull’andamento delle installazioni, per esempio il numero di installazioni e disinstallazioni suddivise per giorno, per area geografica e per tipo di dispositivo. La Google Play Console riporta anche gli errori generati dall’applicazione e che sono stati automaticamente inviati a Google dai dispositivi mobili. Queste informazioni risultano molto utili allo sviluppatore per eseguire il debug e correggere errori e anomalie, in modo da migliorare il software e rilasciare una nuova versione aggiornata. Le componenti grafiche di Android Il layout degli oggetti La geolocalizzazione
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
441
6
Le applicazioni per smartwatch Lo smartwatch è un orologio intelligente dotato di un sistema operativo che, oltre alle normali funzioni di un orologio, consente l’esecuzione di vere e proprie applicazioni.
Che cos’è uno smartwatch? Che cosa significa wearable?
Lo smartwatch è classificato come un dispositivo wearable, cioè indossabile, ha uno schermo di tipo touch e dispone di interfacce di comunicazione Bluetooth o Wifi per la comunicazione con altri dispositivi mobili. I dispositivi wearable possono contenere sensori ambientali come il barometro, l’altimetro e la bussola, sensori di movimento come l’accelerometro e strumenti per la misura del battito cardiaco, oltre a un’eventuale antenna GPS per il supporto alla navigazione. Wear OS è la versione del sistema operativo Android per gli smartwatch. Wear OS gestisce gli orologi con schermo sia rotondo che quadrato e, tramite le app chiamate Watch Faces, permette di installare sul dispositivo i quadranti personalizzati. Le app per gli smartwatch sono sviluppate usando Android Studio, con una modalità simile a quanto già visto per gli smartphone. Nel caso in cui l’applicazione richieda uno scambio di dati tra il dispositivo wearable e il dispositivo mobile si dovranno creare due app, una per ogni dispositivo.
PROVIAMO INSIEME
1 LA GARA DI CORSA Costruire un’app per smartwatch per il calcolo della velocità media di una gara di corsa e per l’invio di questi dati allo smartphone collegato L’app per lo smartwatch permette l’inserimento della distanza (misurata in metri) e del tempo (misurato in minuti). L’utente, con un tocco sullo schermo dell’orologio, attiva il calcolo: la velocità media viene visualizzata sull’orologio e contemporaneamente i dati vengono inviati allo smartphone. L’app per il telefono deve essere in esecuzione e si occupa di ricevere e visualizzare i dati nella schermata. Occorre creare un nuovo progetto facendo clic su Start a new Android Studio project nella schermata di benvenuto di Android Studio. Nella pagina che appare scrivere Velocita come nome dell’app e ProgettoVelocita come cartella di progetto, oltre al nome del dominio istitutotecnico.it. Fare clic su Next e, nella successiva finestra, selezionare i dispositivi Phone and Tablet e Wear OS, scegliendo la API 26 o superiore.
Se l’API non fosse presente nella lista, si deve tornare alla schermata di benvenuto ed eseguire l’installazione aprendo SDK Manager dal pulsante Configure. Nella finestra di configurazione del modulo Mobile scegliere Empty Activity e fare clic su Next due volte mantenendo le impostazioni predefinite per i nomi dell’attività e del layout. Nella finestra di configurazione del modulo Wear scegliere Blank Wear Activity e fare clic su Next.
442
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Nel nome dell’attività scrivere MainWearActivity, mentre nel nome del layout indicare activity_main_wear. Facendo clic su Finish, Android Studio genera tutti i file del progetto creando i moduli mobile e wear. Entrambi i moduli hanno una struttura simile: il modulo mobile contiene i file dell’app per lo smartphone, mentre il modulo wear contiene i file dell’app per lo smartwatch.
Come per le app viste nei Proviamo insieme precedenti, i file principali del modulo wear sono: • AndroidManifest.xml per la descrizione delle macrocomponenti; • activity_main_wear.xml per la descrizione dell’interfaccia grafica; • MainWearActivity.java per il codice sorgente. Aprendo il file AndroidManifest.xml del modulo wear si può verificare che l’app richiede l’utilizzo di uno smartwatch per poter funzionare:
È possibile costruire graficamente l’interfaccia utente aprendo il file activity_main_wear.xml, ricordando che, a differenza delle app per smartphone, lo spazio disponibile è ridotto. Scegliere dalla barra degli strumenti il dispositivo Wear Round per visualizzare l’anteprima del layout sullo smartwatch. Rispetto al layout proposto come default, eliminare la componente TextView e trasformare il FrameLayout in LinearLayiout, dichiarando il valore vertical nell’attributo orientation. Aggiungere due componenti Plain Text per l’input della distanza e del tempo, un Button per il calcolo e una TextView per visualizzare la velocità calcolata. Impostare nel pannello Attributes le proprietà delle componenti grafiche, inserendo gli ID e indicando il valore number per la proprietà inputType delle caselle di testo. Per il pulsante Velocità inserire il nome del metodo calcola nella proprietà onClick. © Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
443
I file XML modificati, contenuti nel modulo wear, sono riportati di seguito. Manifest (AndroidManifest.xml)
Risorse (res/values/strings.xml)
Velocità
Risorse (res/menu/activity_main_wear.xml)
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
445
Nel codice Java occorre dichiarare un attributo privato per ogni elemento grafico (editKm, editTempo, txtVelocita e btnCalcola) e creare il collegamento con le relative componenti usando il metodo findViewById. Il metodo calcola viene richiamato quando l’utente tocca il pulsante Velocità: viene eseguito il calcolo della velocità media e viene costruita la stringa msgToPhone da passare allo smartphone. Il metodo inviaMessaggio contiene le istruzioni per inviare la stringa allo smartphone. La comunicazione dei dati utilizza le classi Node e Wearable per trovare i dispositivi connessi e per inviare i messaggi. Il metodo getConnectedNodes trova i dispositivi mobili connessi allo smartwatch, mentre il metodo sendMessage invia il messaggio convertendolo in una sequenza di byte. Oltre al messaggio viene inviata anche l’etichetta PATH, che consentirà allo smartphone di verificare la correttezza della provenienza del messaggio. Il codice completo della classe Java che implementa l’app per lo smartwatch è mostrato di seguito. Activity (MainWearActivity.java) package it.istitutotecnico.velocita;
CODIFICA
import import import import import import import
android.os.Bundle; android.support.wearable.activity.WearableActivity; android.view.View; android.widget.Button; android.widget.EditText; android.widget.TextView; android.widget.Toast;
import import import import
com.google.android.gms.tasks.Task; com.google.android.gms.tasks.Tasks; com.google.android.gms.wearable.Node; com.google.android.gms.wearable.Wearable;
import java.util.List; import java.util.concurrent.ExecutionException; public class MainWearActivity extends WearableActivity { private static String PATH = "MsgVelocita";
la classe WearableActivity è usata per costruire le finestre grafiche degli smartwatch
private EditText editKm, editTempo; private TextView txtVelocita; private Button btnCalcola; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_wear); editKm = findViewById(R.id.editKm); editTempo = findViewById(R.id.editTempo); txtVelocita = findViewById(R.id.txtVelocita); btnCalcola = findViewById(R.id.btnCalcola); } public void calcola(View view) { double metri, minuti; double velocita; metri = Double.parseDouble(editKm.getText().toString()); minuti = Double.parseDouble(editTempo.getText().toString());
446
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
velocita = (metri / 1000) / (minuti / 60); velocita = Math.round(10.0 * velocita) / 10.0; txtVelocita.setText("" + velocita + " Km/h"); final String msgToPhone = "Distanza: " + metri + " m\n" + "Tempo: " + minuti + " min\n" + "Velocità: " + velocita + " km/h"; la stringa msgToPhone contiene il messaggio da inviare allo smartphone
new Thread(new Runnable() { public void run() { inviaMessaggio(msgToPhone); } }).start();
il metodo inviaMessaggio viene eseguito all’interno di un thread separato per non bloccare l’esecuzione dell’app
} private void inviaMessaggio(String msg) { try { // trova i dispositivi connessi Task nodeListTask = Wearable.getNodeClient(getApplicationContext()) .getConnectedNodes(); List dispositivi = (List) Tasks.await(nodeListTask); for (Object obj : dispositivi) { Node dispositivo = (Node) obj; // invia il messaggio al dispositivo Task sendMessageTask = Wearable.getMessageClient(MainWearActivity.this) .sendMessage(dispositivo.getId(), PATH, msg.getBytes()); Tasks.await(sendMessageTask); } } catch (ExecutionException exception) {} catch (InterruptedException exception) {} } } Nel modulo mobile il file manifest non deve essere modificato. Si deve invece aggiornare il layout activity_main.xml, convertendo il contenitore di default in un LinearLayout. Per eseguire la conversione fare clic con il tasto destro sul nome della componente nel pannello Component Tree e, dopo aver scelto Convert View, indicare il nuovo layout. La componente TextView già presente può essere aggiornata inserendo nell’ID il valore txtMessaggi, cancellando il contenuto dell’attributo text e aumentando la dimensione dei caratteri impostando il valore 18sp nella proprietà textSize. I file XML modificati, contenuti nel modulo mobile, sono riportati di seguito. Manifest (AndroidManifest.xml)
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
447
Risorse (res/values/strings.xml)
Wear - Ricezione dati
Risorse (res/menu/activity_main.xml)
la proprietà scrollbars rende scorrevole la componente TextView
Nel codice Java si deve dichiarare che la classe MainActivity implementa l’interfaccia MessageClient.OnMessageReceivedListener per gestire la ricezione dei messaggi da parte dei dispositivi wearable. L’implementazione è contenuta nel metodo onMessageReceived, che viene eseguito ogni volta che arriva un messaggio. Il codice presente nel metodo controlla se il messaggio arriva dallo smartwatch, confrontando il valore del PATH, e successivamente inserisce la stringa letta nella casella di testo. Il codice completo della classe Java che implementa l’app per lo smartphone è mostrato alla pagina seguente.
448
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Activity (MainActivity.java) package it.istitutotecnico.velocita; import import import import
CODIFICA
android.support.v7.app.AppCompatActivity; android.os.Bundle; android.text.method.ScrollingMovementMethod; android.widget.TextView;
import com.google.android.gms.wearable.MessageClient; import com.google.android.gms.wearable.MessageEvent; import com.google.android.gms.wearable.Wearable; public class MainActivity extends AppCompatActivity implements MessageClient.OnMessageReceivedListener { private static String PATH = "MsgVelocita"; TextView txtMessaggi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtMessaggi = findViewById(R.id.txtMessaggi); // attiva la scrollbar txtMessaggi.setMovementMethod(new ScrollingMovementMethod()); } il metodo onResume viene eseguito @Override quando l’app diventa visibile: public void onResume() { si attiva l’ascoltatore dei messaggi in arrivo dallo smartwatch super.onResume(); Wearable.getMessageClient(this).addListener(this); } il metodo onPause viene eseguito @Override quando l’app non è più visibile: protected void onPause() { si disattiva l’ascoltatore super.onPause(); Wearable.getMessageClient(this).removeListener(this); }
@Override public void onMessageReceived(MessageEvent messageEvent) { if (messageEvent.getPath().equals(PATH)) { String msgFromWatch = new String(messageEvent.getData()); txtMessaggi.append(msgFromWatch + "\n\n"); } } }
Ambiente per il collaudo dell’applicazione Per eseguire il test delle app si crea un nuovo emulatore aprendo la finestra dell’AVD Manager. Fare clic sul pulsante Create Virtual Device e scegliere Wear OS Round dall’elenco dei dispositivi.
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
449
Fare clic su Next e, nella schermata successiva, scegliere la versione di Android che è stata usata nel progetto oppure una versione successiva. Proseguire con Next e infine fare clic su Finish per creare l’emulatore. Nella barra degli strumenti di Android Studio è possibile scegliere, con un menu a tendina, il modulo da eseguire. Scegliere wear e fare clic sulla freccia verde per eseguire l’app. Nella finestra che appare, scegliere l’emulatore precedentemente creato e confermare con OK. Al termine del caricamento, l’app viene visualizzata nell’emulatore e può essere testata. Per eseguire il test di comunicazione con lo smartphone, collegare il telefono al computer usando una porta USB. Per indirizzare la comunicazione dell’emulatore verso il telefono si deve eseguire il seguente comando dal Prompt dei comandi: adb -d forward tcp:5601 tcp:5601 Sul telefono installare l’app Wear OS, scaricandola da Play Store. Per collegare l’emulatore e il telefono si deve eseguire, sul telefono, l’app Wear OS. Quando l’emulatore viene riconosciuto, appare la scritta Connesso nella barra del titolo. A questo punto, da Android Studio, scegliere il modulo mobile e fare clic sulla freccia verde per eseguire l’app. Nella finestra che appare, scegliere il telefono collegato al computer e confermare con OK. Avendo le due app in esecuzione sui due dispositivi, se si inseriscono i valori nell’emulatore e si preme il tasto Velocità, appare la velocità media e i dati vengono contemporaneamente visualizzati sullo smartphone. ESECUZIONE
450
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
Mappa concettuale LE APP PER I DISPOSITIVI MOBILE
APP
classe ListView
liste dinamiche
DISTRIBUZIONE
Action Bar
menu
file APK (Android Package)
classe File
file di dati firma
ACTION_SEND
condivisione di contenuti store
classe ImageView
immagine registrazione come sviluppatore
classe Canvas
disegno pubblicazione
file del modulo wear: • AndroidManifest • activity_main_wear • MainWearActivity
APP PER DISPOSITIVI WEARABLE
sistema operativo Wear OS
emulatore
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
451
Verifica le tue conoscenze PER CIASCUNA DELLE SEGUENTI AFFERMAZIONI, INDICA SE È VERA (V) O FALSA (F) 1
V
F
2
V
F
3
V
F
4
V
F
5
V
F
6
V
F
7
V
F
8
V
F
9
V
F
10
V
F
11
V
F
12
V
F
13
V
F
14
V
F
15
V
F
16
V
F
17
V
F
18
V
F
19
V
F
20
V
F
21
V
F
22
V
F
23
V
F
24
V
F
25
V
F
26
V
F
L’utente interagisce con le liste dinamiche scorrevoli muovendo il dito sullo schermo La classe ListView identifica una lista scorrevole Il parametro position indica il numero massimo di elementi della lista dinamica scorrevole Il numero di elementi di una lista dinamica scorrevole può solo aumentare Il metodo setAdapter è contenuto nella classe ListView Per scrivere i file nella memoria secondaria è necessaria l’autorizzazione WRITE_EXTERNAL_STORAGE Nella memoria secondaria il metodo getExternalFilesDir indica la cartella privata dell’archivio esterno Nella memoria secondaria il metodo getExternalStoragePublicDirectory indica la cartella pubblica interna Nella memoria secondaria le fotografie sono contenute nella cartella predefinita DIRECTORY_PODCAST Nella memoria secondaria la classe File si utilizza per recuperare il path delle cartelle Per leggere i contatti è necessaria l’autorizzazione READ_CONTACTS Il numero di telefono dei contatti è contenuto nel campo Number.PHONE La query con la condizione where impostata a null estrae tutti i contatti I dati dei contatti vengono caricati in un cursore per essere letti Il metodo drawColor della classe Canvas disegna un bordo colorato Il metodo drawCircle della classe Canvas riceve come parametro il diametro del cerchio Il metodo drawRect della classe Canvas può disegnare un quadrato Il metodo drawString della classe Canvas inserisce il testo in una lista dinamica Le applicazioni per dispositivi mobili sono distribuite in negozi virtuali online La pubblicazione delle app consiste nel renderle disponibili online La pubblicazione delle applicazioni sullo store di Google prevede che il pacchetto APK sia firmato Non si può usare Android Studio per firmare le applicazioni I dispositivi wearable sono orologi intelligenti I quadranti personalizzati degli smartwatch si chiamano watch faces Le app per smartwatch sono sviluppate con Android Studio Le app per smartwatch non possono essere testate su un emulatore
PER CIASCUNA DELLE SEGUENTI AFFERMAZIONI, SELEZIONA LA RISPOSTA CORRETTA 1
L’interfaccia che indica il fornitore di contenuti per accedere al database dei contatti si chiama a. Content Provider. b. Phone Provider. c. Database Provider. d. Contacts Provider.
3
La proprietà che stabilisce se un’icona può essere visualizzata sulla Action Bar è a. id. b. title. c. showAsAction. d. icon.
2
In un’Action Bar non si presenta l’elemento a. Icona. b. Titolo. c. Pulsante. d. File. e. Menu.
4
La cartella contenente il file XML che descrive le voci di menu è a. /res/menu. b. /res/layout. c. /res/drawable. d. /res/values.
452
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
5
6
Lo stile della classe Paint che colora solo il perimetro delle figure geometriche è a. Style.FILL b. Style.STROKE c. Style.BORDER d. Style.LINE L’evento onTouch non può generare l’azione a. MotionEvent.ACTION_DOWN b. MotionEvent.ACTION_MOVE c. MotionEvent.ACTION_TOUCH d. MotionEvent.ACTION_UP
7
8
La classe BitmapFactory, per caricare un’immagine, non può usare il metodo a. decodeBitmap. b. decodeFile. c. decodeResource. d. decodeStream. Uno dei più diffusi sistemi operativi per gli smartwatch si chiama a. Wear OS. b. Android. c. Wearable System. d. Android Mobile.
SVOLGI I SEGUENTI ESERCIZI 1
Completa le frasi utilizzando una tra le parole seguenti. Adapter • ListView • ArrayAdapter • notifyDataSetChanged • setOnItemClickListener • position • onItemClick • setAdapter a. Gli ....................... collegano la lista dinamica e la sorgente di dati. b. La classe ....................... implementa un Adapter standard di Android. c. Il metodo ....................... aggiorna il contenuto di una lista dinamica. d. L’ascoltatore dell’evento clic sulla lista dinamica si imposta con il metodo .......................
2
Completa le frasi utilizzando una tra le parole seguenti. setPositiveButton • setNegativeButton • layout • setMessage • AlertDialog.Builder • null • onClick • orientation a. La classe ....................... si occupa di costruire una finestra di dialogo. b. Il pulsante di conferma in una finestra di dialogo si imposta con il metodo ....................... c. Il metodo ....................... stabilisce il messaggio visualizzato in una finestra di dialogo. d. Le operazioni eseguite all’evento clic sul pulsante di conferma sono contenute nel metodo .......................
3
4
Associa a ogni classe la corrispondente componente grafica. a. ListView 1. casella combinata b. ImageView 2. barra di selezione c. Spinner 3. lista scorrevole d. SeekBar 4. immagine Associa a ogni classe la corrispondente azione. a. ImageView 1. modifica l’immagine b. Bitmap 2. visualizza l’immagine c. Canvas 3. imposta lo stile d. Paint 4. crea l’immagine
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
453
Sviluppa le tue competenze PROGETTARE APP EFFICACI NELLA PRESENTAZIONE E NELL’INTERAZIONE CON L’UTENTE 1
2
3
4
Crea un’applicazione per gestire una lista di canzoni da ascoltare, con le relative operazioni per aggiungere ed eliminare un titolo. Crea un’applicazione per gestire una lista di verbi in lingua inglese: la lista deve sempre essere visualizzata in ordine alfabetico. Apri un file di testo con un elenco di nomi, contenuto nella cartella pubblica Download, e visualizzalo in una lista dinamica. Crea un’applicazione che raccolga in una lista dinamica un elenco di numeri di telefono e, tramite un pulsante di condivisione, permetta di condividerlo con un’altra applicazione.
5
Realizza un’applicazione per visualizzare l’elenco di tutti i contatti il cui nome inizia con una vocale.
6
Realizza un’applicazione per ottenere tutti gli indirizzi email associati a un contatto selezionato.
7
8 9
10
11
12
Disegna le linee di una scacchiera e inserisci le immagini delle pedine, dopo aver memorizzato i file nella cartella res/drawable. Aggiungi il bordo a un’immagine consentendo all’utente di selezionare il colore e le dimensioni. Modifica un’immagine scelta dalla galleria, aggiungendo quattro cerchi (raggio 20 pixel) ai quattro angoli. Successivamente unisci i quattro cerchi con una linea (spessore 10 pixel). Crea un’applicazione che permetta di creare dei disegni digitali in cui il trascinamento del dito produca una linea visibile solo nella parte superiore dell’immagine. Si può quindi intervenire solo sui punti le cui coordinate verticali vanno da 0 fino a h/2, dove h è l’altezza dell’immagine. Crea un’applicazione che, tramite un menu, consenta di visualizzare un’immagine, scegliendola dalla galleria oppure acquisendola tramite la fotocamera. Cattura un’immagine con la fotocamera e aggiungi la data in cui è stata scattata e il nome dell’autore, inserito tramite una casella di testo.
PUBBLICARE LE APP SULLO STORE PER ANDROID 13
Crea un certificato digitale valido 25 anni per firmare un’applicazione.
14
Genera il pacchetto APK firmato per una delle applicazioni sviluppate precedentemente.
15
Predisponi la descrizione e gli screenshot per una delle applicazioni sviluppate precedentemente.
REALIZZARE APP PER I DISPOSITIVI DI INFORMATICA MOBILE 16 17
454
Crea un’applicazione per smartwatch per convertire la velocità da km/h a m/s. Realizza un’applicazione per smartwatch con lo scopo di registrare i punti di una partita a tennis. I punti sono incrementati tramite due pulsanti sull’orologio, associati ai due giocatori. Ogni punto viene comunicato allo smartphone che visualizza il punteggio aggiornato.
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
© Istituto Italiano Edizioni Atlas
STUDIO DI CASI REALI 1
LISTA DEI PROMEMORIA Un’agenda elettronica permette la raccolta e la gestione di un elenco di promemoria. Crea un’app per l’aggiunta di promemoria e per il loro salvataggio in un file di testo. I promemoria possono essere cancellati e possono essere condivisi con un’altra applicazione di messaggistica. Rendi visibile il numero totale dei promemoria sopra l’elenco, all’interno di un’etichetta. Inizialmente il numero dei promemoria sarà uguale alla quantità letta dal file. Successivamente, con l’aggiunta e la cancellazione dei promemoria, il numero deve aggiornarsi di conseguenza.
2
CALCOLO DELLA DISTANZA, DEL TEMPO E DEL PASSO Il passo è una grandezza che misura la velocità, indicando in quanti minuti viene percorsa la distanza di un chilometro. Se si percorre la distanza di 5 chilometri in 37 minuti, significa che si sta tenendo un passo di 7 minuti e 24 secondi al chilometro (7’24”/km). Conoscendo la distanza e il tempo, la formula per il calcolo del passo, espresso in minuti/km, è: • Passo = Tempo / Distanza se la distanza è espressa in chilometri e il tempo in minuti; • Passo = Tempo / (Distanza / 1000) se la distanza è espressa in metri e il tempo in minuti. Allo stesso modo, conoscendo il passo e la distanza e facendo attenzione alle unità di misura utilizzate, si può dedurre il tempo con la formula: Tempo = Passo * Distanza Infine conoscendo il passo e il tempo si può dedurre la distanza con la formula: Distanza = Tempo / Passo Crea un’app che, conoscendo due delle tre grandezze, calcoli la terza grandezza. L’applicazione deve consentire la scelta tra le unità di misura chilometri e metri.
3
ELABORAZIONE DELLE FOTOGRAFIE I ritratti delle persone scattati con un telefono possono essere camuffati aggiungendo i baffi, un cappello, un paio di occhiali o di orecchini. Predisponi un elenco di immagini, inserendole nella cartella di progetto /res/drawable, e crea un’app per l’elaborazione delle fotografie. L’applicazione deve consentire di: • scegliere una fotografia dalla galleria; • scegliere l’immagine da inserire, usando una casella combinata che ne riporti la descrizione; • posizionare l’immagine sopra la fotografia con il tocco sul touchscreen.
4
REGISTRAZIONE DELLA TEMPERATURA AMBIENTALE Lo smartwatch può essere utilizzato per misurare la temperatura ambientale. Realizza un’app di tipo wearable per la raccolta delle temperature rilevate dallo smartwatch e trasmetti i dati allo smartphone. Memorizza i dati delle temperature in un file, con la data e l’ora della rilevazione. Le temperature sono inserite tramite una casella di testo sullo smartwatch.
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER I DISPOSITIVI MOBILE
455
MOBILE DEVICE APPS THE MANIFEST FILE Each Android application has an XML file called AndroidManifest.xml. The manifest defines the components of the application and several parameters. It contains a description for each Activity that composes the user interface. A manifest tag can contain only one application tag that specifies the name and the icon of the application. For every Activity in the application, an activity tag is needed, otherwise the application will not be able to open it and an exception will be raised. The main attribute of an activity tag is the name that refers to the name of the relevant Java class. THE APP STORE When the application is ready, the developer can upload an app, build the product pages, configure prices and distribution, and publish on Google Play. Applications are available for download through the Google Play online store. Users can browse, download and install thousands of apps; some of them are free and others have to be bought. In addition to browsing and searching for new apps in
GLOSSARY
the Google Play, users can add their own comments and ratings. A user can also add his own reviews to help others choose new apps and multimedia. The Web store lets the Android users have apps instantly delivered and installed on their Android devices. WEARABLE DEVICES A wearable device is a technology that is worn on the human body, incorporated into a person's clothing or personal accessories, and capable of storing and processing data. The devices are small enough to wear and include sensor technologies that can collect and deliver information about health, fitness, people, news, geolocation, and so on. Examples of wearable devices include: smartwatches, fitness tracking devices and smart glasses. A wearable device can be synced with another device, like a smartphone or a computer. Examples of applications for wearable devices are: • immediate access to important data for anyone whose occupation requires mobility; • the ability to take voice notes immediately; • tracking a user's vital signs.
QUIZ
APK The file format used by Android applications.
1
Which of these are methods that return the image dimensions? a. getImage b. setDimension c. getWidth d. getHeight
2
Which method returns the index of selected element in a spinner? a. getSelectedItemPosition b. getProgress c. getAction d. onItemClick
Emulator A virtual device that can simulate several physical devices. Geolocation Obtaining the current geographic position of a mobile device. Google Play Console A Google Web tool for developers, used to manage the application publishing process. Keystore A container of private keys and public certificates. Layout file An XML file that describes the structure of the user interface for an activity. Manifest file An XML file that contains information about the application.
456
PARTE SECONDA
• IL WEB E L’INFORMATICA MOBILE
3
What is the proper sequence of app publishing operations on the store (from 1 to 4)? a. Digitally sign the APK file with a certificate. ... b. Upload the APK file. ... c. Add app’s information. ... d. Create APK file. ...
© Istituto Italiano Edizioni Atlas
SCHEDA DI AUTOVALUTAZIONE COMPETENZE DIGITALI
1 = con molta difficoltà 2 = con difficoltà 3 = con incertezza 4 = con sicurezza 5 = con padronanza
1
2
3
4
5
So organizzare i dati in liste dinamiche. Costruisco una lista per l’accesso ai contatti. Utilizzo l’Action Bar per inserire un menu di scelte per l’utente. So scrivere e leggere i dati di un file. So condividere i contenuti tra le applicazioni. Realizzo applicazioni per gestire le immagini. Realizzo applicazioni per gestire la fotocamera. Conosco il significato di dispositivi wearable. Realizzo applicazioni per smartwatch. Effettuo la registrazione sullo store di Android. Predispongo i file per la pubblicazione delle app. Distribuisco le app tramite lo store.
© Istituto Italiano Edizioni Atlas
CAPITOLO
9 • LE APP PER L’INFORMATICA MOBILE
457
quick reference Linguaggio Java Parole riservate abstract
default
if
private
throw
boolean
do
implements
protected
throws
break
double
import
public
transient
byte
else
instanceof
return
try
case
extends
int
short
void
catch
final
interface
static
volatile
char
finally
long
super
while
class
float
native
switch
const
for
new
synchronized
continue
goto
package
this
Tipi numerici Tipi interi Tipo
Dimensione
Valori
Byte
8 bit
da -128 a 127
Short
16 bit
da -32.768 a 32.767
Int
32 bit
da -2.147.483.648 a 2.147.483.647
Long
64 bit
da - 263 a 263-1
Tipi a virgola mobile Tipo
Dimensione
Precisione
Float
32 bit
singola
Double
64 bit
doppia
Strutture di controllo Iterazione while (condizione) { // Istruzioni } do { // Istruzioni } while (condizione); for (inizializzazione; terminazione; incremento) { // Istruzioni }
458
quick reference
© Istituto Italiano Edizioni Atlas
Selezione if (condizione) { // Istruzioni } if (condizione) { // Istruzioni } else { // Istruzioni } if (condizione) { // Istruzioni } else if (condizione) { // Istruzioni } else if (condizione) { // Istruzioni } else { // Istruzioni } switch (espressione intera) { case espressione intera: // Istruzioni break; ... default: // Istruzioni break; }
Istruzioni di salto Istruzione
Descrizione
break
Termina i seguenti costrutti: switch, for, while e do-while
continue
Termina l’iterazione e valuta la condizione booleana che controlla il ciclo
return valore
Termina il metodo ed eventualmente restituisce un valore al chiamante
© Istituto Italiano Edizioni Atlas
quick reference
459
Struttura per la gestione delle eccezioni try { // Istruzioni da controllare } catch (tipoeccezione nome) { // Istruzioni } catch (tipoeccezione nome) { // Istruzioni } finally { // Istruzioni }
Eccezioni Nome
Package
Descrizione
ArithmeticException
java.lang
Eccezione matematica, la più comune è la divisione per zero
ClassCastException
java.lang
Indica che si è tentato di eseguire un casting di un oggetto verso una classe di cui non è istanza
ClassNotFoundException
java.lang
L’applicazione sta caricando una classe ma non trova il file .class
EOFException
java.io
È stata raggiunta la fine del file
Exception
java.lang
Eccezione generica
FileNotFoundException
java.io
Il file specificato non è presente
IndexOutOfBoundsException
java.lang
Sono stati superati i limiti di un array
InterruptedException
java.lang
Generata quando un processo viene interrotto da un altro
IOException
java.io
Eccezione relativa alle operazioni di input/output
MalformedURLException
java.net
Un URL non è stato definito correttamente
NullPointerException
java.lang
Si cerca di usare un riferimento null dove sarebbe richiesto l’uso di un oggetto
NumberFormatException
java.lang
Generata quando la conversione da un valore stringa ad un formato numerico non ha successo
SQLException
java.sql
Eccezione relativa alle operazioni in SQL
460
quick reference
© Istituto Italiano Edizioni Atlas
Proprietà degli oggetti dell’interfaccia grafica Variable Name
Definisce il nome dell'oggetto utilizzato all’interno del codice Java
text
Imposta il testo visualizzato sull'oggetto (etichetta o pulsante)
background
Imposta il colore di sfondo dell’oggetto
editable
Determina se la casella di testo è modificabile
font
Specifica le caratteristiche del font utilizzato per i caratteri
foreground
Imposta il colore di primo piano utilizzato per il testo dell’oggetto
tooltip
Indica il testo da visualizzare quando l’utente si sposta con il mouse sopra l’oggetto
border
Imposta lo stile del bordo dell’oggetto
enabled
Determina se il controllo è attivato, cioè se è in grado di rispondere agli eventi generati dall’utente. Per esempio, se un pulsante non è attivo resta visibile, ma assume un aspetto più sfumato e l’utente non può fare clic
Horizontal Size
Determina la larghezza dell’oggetto in pixel
Vertical Size
Determina l’altezza dell’oggetto in pixel
Costanti statiche per i colori Color.bLACk
Color.mAGEnTA
Color.bLuE
Color.OrAnGE
Color.CyAn
Color.PInk
Color.DArkGrAy
Color.rED
Color.GrAy
Color.WhITE
Color.GrEEn
Color.yELLOW
Color.LIGhTGrAy
Metodi dell'interfaccia WindowListener Evento
Metodo eseguito
Quando la finestra viene ridotta a icona
WindowIconified
Quando la finestra viene ingrandita
WindowDeiconified
Quando la finestra riceve lo stato attivo
WindowActivated
Quando la finestra perde lo stato attivo
WindowDeactivated
Quando la finestra viene aperta
WindowOpened
Quando la finestra è stata chiusa
WindowClosed
Quando la finestra si sta chiudendo
WindowClosing
© Istituto Italiano Edizioni Atlas
quick reference
461
Android Classi del package android manifest
r.drawable
r.plurals
r.anim
r.fraction
r.raw
r.animator
r.id
r.string
r.array
r.integer
r.style
r.attr
r.interpolator
r.styleable
r.bool
r.layout
r.xml
r.color
r.menu
r.dimen
r.mipmap
Classi del package android.widget AbsListView
GridLayout
ShareActionProvider
AbsoluteLayout
GridView
SimpleAdapter
AbsSeekbar
headerViewListAdapter
SimpleCursorAdapter
AbsSpinner
horizontalScrollView
SimpleExpandableListAdapter
AdapterView
Imagebutton
SlidingDrawer
AlphabetIndexer
ImageSwitcher
Space
AnalogClock
ImageView
Spinner
ArrayAdapter
LinearLayout
StackView
AutoCompleteTextView
ListPopupWindow
Switch
baseAdapter
ListView
Tabhost
baseExpandableListAdapter
mediaController
TableLayout
button
multiAutoCompleteTextView
Tablerow
CalendarView
numberPicker
TabWidget
Checkbox
OverScroller
TextClock
CheckedTextView
Popupmenu
TextSwitcher
Chronometer
PopupWindow
TextView
Compoundbutton
Progressbar
TimePicker
CursorAdapter
QuickContactbadge
Toast
CursorTreeAdapter
radiobutton
Togglebutton
DatePicker
radioGroup
TwoLineListItem
DialerFilter
ratingbar
VideoView
DigitalClock
relativeLayout
ViewAnimator
EdgeEffect
remoteViews
ViewFlipper
EditText
resourceCursorAdapter
ViewSwitcher
ExpandableListView
Scroller
Zoombutton
Filter
ScrollView
ZoomControls
FrameLayout
SearchView
Gallery
Seekbar
462
quick reference
© Istituto Italiano Edizioni Atlas
Icone predefinite delle voci di menu ic_menu_add
ic_menu_mylocation
ic_menu_agenda
ic_menu_myplaces
ic_menu_call
ic_menu_preferences
ic_menu_camera
ic_menu_recent_history
ic_menu_close_clear_cancel
ic_menu_report_image
ic_menu_compass
ic_menu_revert
ic_menu_crop
ic_menu_rotate
ic_menu_day
ic_menu_save
ic_menu_delete
ic_menu_search
ic_menu_directions
ic_menu_send
ic_menu_edit
ic_menu_share
ic_menu_gallery
ic_menu_slideshow
ic_menu_help
ic_menu_sort_alphabetically
ic_menu_info_details
ic_menu_sort_by_size
ic_menu_manage
ic_menu_today
ic_menu_mapmode
ic_menu_upload
ic_menu_month
ic_menu_view
ic_menu_more
ic_menu_week
ic_menu_my_calendar
ic_menu_zoom
© Istituto Italiano Edizioni Atlas
quick reference
463
Acronimi ADT
Android Developer Tools
JDK
Java Development Kit
API
Application Programming Interface
JRE
Java Runtime Environment
APK
Android Package
JSP
Java Server Page
ART
Android run Time
JVM
Java Virtual Machine
ASCII
American Standard Code for Information Interchange
LAN
Local Area network
LF
Line Feed
ASP
Active Server Page
LIFO
Last-In First-Out
AVD
Android Virtual Device
MP
megaPixel
AWT
Abstract Window Toolkit
ODBC
Open Database Connectivity
C/S
Client/Server
OO
Object-Oriented
CPU
Central Processing unit
OOP
Object-Oriented Programming
CR
Carriage return
PHP
PhP: hypertext Preprocessor
DB
Database
RGB
red, Green, blue
DBMS
Database management System
RPM
revolutions per minute
DSN
Data Source name
SDK
Software Development kit
EAR
Enterprise Archive
SP
Scale-independent Pixels
EOF
End Of File
SQL
Structured Query Language
FIFO
First-In First-Out
UI
user Interface
GPS
Global Positioning System
UML
Unified Modeling Language
HTML
hyperText markup Language
URL
uniform resource Locator
HTTP
hyperText Transfer Protocol
USB
universal Serial bus
I/O
Input/Output
UTF
unicode Transformation Format
IDE
Integrated Development Environment
W3C
World Wide Web Consortium
IE
Internet Explorer
WAN
Wide Area network
IIS
Internet Information Services
WAR
Web application Archive
iOS
iPhone Operating System
WiFi
Wireless Fidelity
JAR
Java ARchive
WWW World Wide Web
JDBC
Java DataBase Connectivity
XML
464
quick reference
eXtensible markup Language
© Istituto Italiano Edizioni Atlas
inDice AnALiTico A abs, 108 accedere agli attributi, 76 Access, 282 accesso ai dati, 343 accodamento, 157, 161 Action bar, 407 ACTIOn_ImAGE_CAPTurE, 437 ACTIOn_SEnD, 417 ActionEvent, 215 ActionListener, 214 actionPerformed, 191, 214, 215 Activity, 379, 380 activity_main.xml, 366 Adapter, 395 add, 186, 192, 196, 197, 199, 224, 226, 236 addActionListener, 212 addElement, 125, 233 addItem, 196 addSeparator, 227 addWindowListener, 212 affected rows, 290 AJAX, 332 albero, 145, 236 albero binario, 146 albero binario di ricerca, 146 AlertDialog.builder, 398 allocazione dell’oggetto, 72 allocazione di un array, 29 Alt, 227 ambiente, 187, 315 ambiente di sviluppo integrato, 46 analisi dei dati, 59 AnD, 24 Android, 359 Android Studio, 360, 362, 365 androidmanifest.xml, 366 apertura, 154, 157, 161 API, 8, 107, 282 API level 11, 407 APk, 360, 370, 441 app, 360 App e notifiche, 429 AppCompactActivity, 379 app-debug.apk, 370 append, 157, 161, 195, 215 application package, 370 application/json, 335 applicazioni, 8 applicazioni Java, 283 applicazioni recenti, 361 Apply, 369 aprire, 236 architettura 2-tier, 323 architettura 3-tier, 324 architettura Client/Server, 308, 313 archivio esterno, 409 archivio interno, 409 arco, 253 area di testo, 181, 195 © Istituto Italiano Edizioni Atlas
aree di disegno, 249 args, 9, 30 args.length, 30 ArithmeticException, 33 array, 28, 331 array di oggetti, 89 array dinamico, 124 array multidimensionali, 31 ArrayAdapter, 395 ArrayIndexOutOfboundsException, 29 ArrayList, 395 ArT, 360 ascoltatori, 211 ASP.nET, 311 assegnamento, 75 attraversamento, 140 Attributes, 367 attributi, 59, 64 attributo statico, 79 AudioSystem, 263 autocompletamento, 53 Autorizzazioni, 429 AVD, 363 AVD manager, 363, 449 avvertimenti, 49, 50 avvio, 361 AWT, 183
B back, 361 background, 373 bak, 168 barra dei menu, 407 barra dei preferiti, 361 barra di ricerca, 361 barra di stato, 361 bitmap, 418, 419, 423 bitmapFactory, 418 blackbox, 83 blocchi, 23 blocco, 9 blocco di istruzioni, 66 boolean, 14 borderLayout, 198 break, 24, 27 breakpoint, 50, 54 browser, 309 btn, 191 bufferedImage, 253 bufferedreader, 20, 21 bug, 46 build, 55, 441 build Project, 53 button, 107, 371, 424 buttonGroup, 224 byte, 13 bytecode, 7
C campionatura, 263 canImport, 245 Canvas, 419, 423, 424
caratteristiche per gli attributi, 65 caricamento di un’immagine, 253 cartella java, 366 cartella principale, 410 cartelle pubbliche, 410 case, 24 casella combinata, 182, 196, 218 casella di controllo, 197 casella di testo, 181, 371, 194 case-sensitive, 9 casting, 15, 25 catch, 284, 285 char, 14 charAt, 110 check box, 197 Check for updates, 362 checkable, 411 checkbox, 412 checked, 411 chiudere, 236 chiusura, 154, 158, 162 ciclo, 25 circonferenza, 252 class, 9, 48, 62 classe, 60, 106 classe base, 94 classe derivata, 94 classes, 316 classi, 8 ClassnotFoundException, 326 client, 308 Client/Server, 313 Clip, 263 close, 285, 286 Close Project, 55 cloud, 360 coda, 124, 136 collapse, 236 Color, 193, 252 colori, 252 colori predefiniti, 252 colorPrimary, 403 comandi SQL, 343 combo box, 196, 218 commento, 9, 18 compareTo, 142 compatibilità, 379 compilare, 10 compilato .class, 48 compilazione, 53, 337 compilazione di una servlet, 317 component, 184, 184 Component Tree, 447 componenti, 188, 189 componenti atomiche, 185 componenti software, 83 compress, 419 CompressFormat, 419 comunicazione, 309 concatenare, 156 condivisione delle risorse, 308 Configure, 362 indice analitico
465
Connection, 283 Console, 49 Contacts, 401 Contacts Provider, 400 Contacts._ID, 404 container, 184, 185, 186 contenitore, 188 contenitori intermedi, 185 contenitori principali, 185 content pane, 185 Content Provider, 400 contenuto dinamico, 311 contenuto statico, 311 continue, 27 control, 188 controlli, 188 ConvertFrame, 217 ConvertView, 447 coordinate, 250 copia dei riferimenti, 75 copy, 232 cos, 108 costante, 12 costruttore, 61, 72, 125, 254 costruttore vuoto, 72 creare un oggetto, 72 Create Virtual Device, 449 createbitmap, 418 createStatement, 284 createTransferable, 244 Ctrl + F11, 49 Ctrl + F2, 50 Ctrl + F5, 54 Ctrl + maiuscolo + b, 50 Ctrl + maiuscolo + n, 51 Ctrl + maiuscolo + S, 53 Ctrl + n, 55 Ctrl + S, 49 Cursor, 401 cursore, 290 CursorLoader, 403 cut, 232
D data, 431 database, 282, 400 database remoto, 323 DatabasemetaData, 295 DataFlavor, 248 dateFormat, 368 DbmS, 282 Debug, 50, 54, 364, 369 Debug Project, 54 debugging, 50 decodeFile, 418 decoderesource, 418 decodeStream, 418 decremento, 16 default, 24 DefaultListmodel, 232 DefaultmutableTreenode, 236 delegazione, 211
466
indice analitico
deployment descriptor, 316 descrizione, 441 Design, 189 destinazione, 155, 244 destroy, 312 device, 358 diagonali, 251 diagramma degli oggetti, 61 diagramma delle classi, 60, 94 diagrammi, 258 dichiarazione degli attributi, 86 dichiarazione dei metodi, 65, 86 dichiarazione della classe, 62, 86 dichiarazione di un array, 28 dichiarazione di un attributo, 64 dichiarazione di un oggetto, 62, 72 dichiarazioni, 336 dispositivi, 358 dispositivi mobili, 358 dispositivo di puntamento, 181 disposizione, 181 dist, 55 divisione intera, 23 documentazione, 107 doGet, 312, 335 doPost, 312, 335 Double, 13, 71 drag, 244 drag and drop, 243 draw, 424 drawArc, 253 drawImage, 254 drawLine, 251, 260 drawOval, 252 drawrect, 250, 251 drawString, 250, 253 driver, 282 Drivermanager, 283 drop, 244
E eccezione, 20, 32, 158, 162, 284 Eclipse, 46 editare, 9 editor, 52 EditText, 371 elementAt, 125 elenco, 331 elenco di parametri, 67 eliminazione fisica, 148 eliminazione logica, 148 ellisse, 252 Email, 401 Empty Activity, 380 emulatore, 363 EOFException, 160 equals, 110 ereditarietà, 94 ereditarietà multipla, 95 ereditarietà singola, 95, 97 error, 49 errore, 15, 49
errori di programmazione, 50 errori sintattici, 50, 53 esecuzione di una servlet, 318 eseguire, 10 espressioni, 336 estensione .class, 10, 86 estensione .java, 86 estensione .jsp, 337 estraibile, 409 etichetta, 181, 192, 371 event, 427 eventi del mouse, 259 evento, 210 Exception, 20, 33 executeQuery, 284, 290, 343 executeupdate, 284, 287, 288, 345, 347 exit, 91 exp, 108 expand, 236 exportDone, 244 Expressions, 50 extends, 97 external storage, 409 EXTRA_SUBJECT, 417 EXTrA_TEXT, 417
F F11, 50, 53 F5, 50 F6, 54 F8, 50 FIFO, 136 File, 47, 48, 49, 51, 53, 55, 154, 410 file di testo, 157 file strutturati, 156 FileChooser, 232 Files, 54 fillArc, 253 fillOval, 253 fillRect, 251 final, 12, 65, 79, 101 finalize, 132 finalizzatore, 132 finally, 32, 284, 285 findViewById, 368 findViewByld, 383 finestra, 181 finestre di dialogo, 220 finestre operative, 189 firma, 441 Float, 13 FlowLayout, 197 flush, 158, 159 foglie, 145 Font, 253 for, 26 form, 320, 339
G Garbage Collector, 131 generazione di un evento, 210 © Istituto Italiano Edizioni Atlas
gerarchia delle classi, 94, 100 gerarchia delle componenti, 184 gerarchie, 236 gesti, 359 gestione degli eventi, 189 gestione della memoria, 8, 131 gestione delle eccezioni, 284 gestore, 210, 211 gestore automatico della memoria, 131 gestore del layout, 184 gestore di eventi, 210 get, 81, 310, 312 getAction, 427 getActionCommand, 215 getAudioInputStream, 263 getClip, 263 getConnectednodes, 446 getConnection, 283 getContentPane, 186 getCount, 401 getDoubleExtra, 383 getExternalFilesDir, 409 getExternalStoragePublicDirectory, 409 getFilesDir, 409 getGraphics, 254 getLastSelected, 237 getmessage, 284 getParameter, 321 getProgress, 428 getSelectedFile, 232 getSelectedIndices, 233 getSelectedItemPosition, 428 getSequencer, 264 getSize, 250 getSource, 228 getSourceActions, 244 getText, 195, 216, 228 getuserObject, 237, 238 getValuesAdjusting, 234 getX, 259, 427 getXXX, 290 gety, 259, 427 Google Contatti, 400 Google Play, 360, 440 Google Play Console, 440 GPS, 359 grafo di gerarchia, 94, 100 Graphics, 249 gravity, 373 GridLayout, 199 griglia, 199 GuI, 180 GuI builder, 190
H handler, 210 hardware, 308 hasmoreTokens, 166 head, 310 heap, 131 © Istituto Italiano Edizioni Atlas
height, 250 hint, 396 home, 361, 404 hTTP, 310 httpServlet, 312 httpServletrequest, 313 httpServletresponse, 313
I ic_menu_share, 416 icon, 408 icona, 441 icona di menu, 407 id, 367, 371, 395, 408 IDE, 7, 46, 51 identificatori, 10 Image, 253 ImageIO.read, 253 ImageIO.write, 254 ImageView, 418 immagini, 253, 418, 441 implementare, 124 implements, 212, 259 import, 107 importData, 245 Impostazioni del dispositivo, 429 in ordine, 151 incapsulamento, 61 include, 336 incremento, 16 indentazione, 9 IndexOutOfboundException, 33 indice, 29 indirizzo IP 127.0.0.1, 310 informatica mobile, 358 information hiding, 80, 82 init, 312, 319 inizializzazione dell’array, 29 inmutable, 433 InputStream, 155 InputStreamreader, 21 InputType, 373, 443 inSampleSize, 431 insertElementAt, 233 installazione, 362 instanceof, 242 Int, 13 Integer, 20 Intent, 380, 417 Intent.ACTIOn_DIAL, 384 interfacce a caratteri, 180, 183 interfacce di comunicazione, 359 interfacce grafiche, 180 interfaccia di una classe, 81 interfaccia utente, 180 intermediate container, 185 internal storage, 409 Internet, 308, 358 interpretato, 7 interrogazione, 124, 133, 137, 141, 290 invocazione di un metodo, 76 IOException, 33
isChecked, 412, 414 istanza, 60 istanza di classe, 72, 74 istruzioni, 66 iterazione, 25, 166
J JAR, 55, 282 Java, 6, 106, 360 Java Application, 187 Java Class, 55 Java Virtual Machine, 7 java.applet, 106 java.awt, 8, 106, 183 java.awt.event, 212 java.io, 8, 21, 106 java.lang, 8, 106, 107 java.lang.math, 108 java.net, 8, 106 java.sql, 283, 324, 343 java.util, 8, 106, 124 javac, 53 JavaScript, 311 javax.servlet, 312, 315 javax.servlet.http, 312 javax.sound, 263 javax.swing, 183 JButton, 190, 193 JCheckBox, 197 JColorChooser, 258 JComboBox, 196 JDBC, 282 JDK, 7, 46 JFileChooser, 228 JFrame, 188 JLabel, 190, 192, 224 JList, 232 JMenu, 226 JMenuBar, 226 JMenuItem, 226 JOptionPane, 220 JPanel, 249 JPEG, 419 JRadioButton, 224 JScrollPane, 227 JSON, 331 JSON.parse, 332 JSP, 311, 335 JTextArea, 195, 228 JTextField, 190, 194 JTree, 236 JVM, 7
K keystore, 441
L LAn, 308 landscape, 359 lato client, 311 lato server, 311
indice analitico
467
layout, 181, 184, 197 Layout manager, 184, 197 layout_height, 371 layout_width, 371 lbl, 191 length, 29, 110 lettura, 154 lettura di numeri, 20 lettura di una stringa, 20 librerie, 8, 97, 100, 106 LIFO, 133 linee, 251 lines, 402 linguaggi di scripting, 311 linguaggio umL, 61 linguaggio XmL, 316 linked list, 140 lista concatenata, 124, 140 liste, 232 liste dinamiche scorrevoli, 394 listener, 211 ListSelectionListener, 233 ListView, 394 livelli di visibilità, 64, 80 livelli di visibilità di un metodo, 68 localhost, 310 localizzazione, 378 log, 108 Log, 370 Log.d, 370 Log.e, 370 Log.i, 370 Log.v, 370 Log.w, 370 Logcat, 370 Long, 13 loop, 25
mIDI, 264 midiSystem, 264 miniaturizzazione, 358 mobile, 404, 442 mobile computing, 358 modalità paesaggio, 359 modalità ritratto, 359 modello del sistema, 58 modifica, 124, 133, 137, 140, 146, modulo mobile, 443, 447 modulo wear, 443 mouse, 181 mouseEvent, 259 mouseListener, 259 mousemotionListener, 259 moveTonext, 401
M
O
main, 8, 9, 48, 58, 86 main Class, 55 mainActivity.java, 366 manifest, 366 manifests, 366 marketplace, 360 mascheramento dell’informazione, 80 match_parent, 371 math, 25, 63, 108 math.PI, 63 math.random, 80 math.round, 77 matrice, 31 mediaStore, 437 megapixel, 373 menu, 182, 226 messageClient, 448 metadati, 295 metodi, 59, 65 metodi di classe, 80 metodi ricorsivi, 147 metodi statici, 80 metodo costruttore, 74
Object, 100, 160 ObjectInputStream, 160 ObjectOutputStream, 157 oggetti, 59, 183 onActivityresult, 431 onClick, 372, 373 onCreate, 368, 379 onCreateOptionsmenu, 412 onItemClick, 395 onmessagereceived, 448 OnmessagereceivedListener, 448 onOptionsItemSelected, 412 onreadystatechange, 332 onrequestPermissionsresult, 403 onTouch, 426 OOP, 58 open, 263, 264 open source, 359 operatore !, 24 operatore %, 23 operatore &&, 24 operatore /, 23 operatore ||, 24
468
indice analitico
N name, 363 navigator, 189 netbeans, 51, 183, 187, 282 new, 20, 29, 47, 48, 62, 72, 125, 131 new File, 55 new Project, 51 next, 290 nextToken, 166 node, 446 nodi interni, 145 nome del metodo, 66 nome dell’oggetto, 79 nome della classe, 79 nOT, 24 notifyDataSetChanged, 395 null, 29, 73, 74, 140, 165, 220, 400, 403 nullPointerException, 33, 74 numeri casuali, 135 numero e, 108
operatore ==, 75 operatore di assegnamento, 16 operatore di concatenazione, 17, 109 operatore punto, 76, 77 operatori, 16 operatori booleani, 24 operatori di confronto, 23 operazioni aritmetiche, 16 operazioni di I/O, 154 operazioni di input, 19 operazioni di output, 18 Or, 24 ordine anticipato, 147 ordine posticipato, 147 ordine simmetrico, 147 organizzazione dell’algoritmo, 58 orientation, 396 origine, 211 OutputStream, 155 overloading, 101, 102, 105 overriding, 95, 101, 104
P pacchetto APk, 370 pack, 217 package, 48, 106, 360 padding, 402 page, 336 pagine JSP, 311, 336 pagine Web, 309 Paint, 419, 423 paintComponent, 249, 251 Palette, 189, 190, 367 pane, 185 pannelli, 185 parametri, 288, 339 parametri nell’indirizzo urL, 342 parentesi graffa, 23, 53, 66 parentesi tonde, 16 parole chiave, 11 passaggio di parametri, 320 paste, 232 PATh, 7 PathComponent, 237 pathFile, 410 per estensione, 95 per ridefinizione, 95 per valore, 67 Permission_Granted, 405 persistente, 158 persistenza, 154 Phone, 401 Phone.TyPE, 404 PhP, 311 PI, 108 piattaforma, 6 pigreco, 108 pila, 124, 133 pixel, 180 Play Store, 440 plug-in, 46 PnG, 419 © Istituto Italiano Edizioni Atlas
polimorfismo, 101, 103 pop, 133 porta 80, 310 porta 8080, 315 portabilità, 6 porting, 6 portrait, 359 position, 396 Post, 310, 312 postfissi, 17 postordine, 151 pow, 108 prefissi, 17 preordine, 151 PreparedStatement, 288 prepareStatement, 288, 293 primitivi, 12 print, 19, 162 println, 9, 19, 102, 162 PrintWriter, 313 private, 65, 68 progettare un’interfaccia grafica, 182 progetto, 51 programmazione, 58 programmazione guidata dagli eventi, 210 programmazione orientata agli oggetti, 58 programmazione strutturata, 58 programmazione visuale, 187 programmi client, 309 programmi server, 308 Project, 47, 187, 365 Project Explorer, 49 Project name, 48 projects, 52, 55, 189 promozione, 14 Properties, 55, 189, 190 proprietà, 189 protected, 65, 68, 105 protocollo, 308 pubblicazione, 364, 440 public, 9, 65, 68, 79 pulsante, 181 pulsante di opzione, 182 pulsanti, 193 pulsanti di comando, 371 pulsanti di navigazione, 361 punto di interruzione, 50, 54 punto e virgola, 9 push, 133 putExtra, 380, 417
Q quantità, 154 query, 290, 400 queue, 136
R r.drawable, 421 radice, 145, 146 random, 25, 80 © Istituto Italiano Edizioni Atlas
read, 165, 232 rEAD_COnTACTS, 401 readDato, 160 reader, 156 readLine, 20, 165 readObject, 160 regioni, 198 registrazione, 440 reload, 236 remove, 233, 236 removeElement, 233 removeElementAt, 125 repaint, 249, 255 res/layout, 366, 371 res/menu, 408 res/values, 372 res/values/colors.xml, 403 resolution, 363 resto, 16, 23 resultSet, 290 resultSet.getmetaData, 295 resultSetmetaData, 295 resume, 50 rete geografica, 308 rete locale, 308 rettangolo, 251 return, 67 rGb, 252 riferimenti agli oggetti, 140 riferimenti nulli, 74 riferimento, 12, 72 ripetizione, 25 ripetizione con contatore, 26 risoluzione, 180 risorsa di default, 378 riusabilità del software, 8 riutilizzo della stessa variabile, 140 riutilizzo programmabile del software, 96 root, 146 rubrica, 400 run, 49, 50, 55, 369 run Project, 54 ruotare lo schermo, 359
S salvataggio, 254 Samples, 51 Save, 49 Save All, 53 scale-independent pixels, 367 scambio di messaggi, 76 schermata di benvenuto, 362 schermata home, 360 schermi grafici, 180 schermo sensibile al tatto, 358 scope, 12 scorciatoia, 227 screenshot, 441 script, 311 scriptlet, 336, 337 scrittura, 154
scrollPathToVisible, 242 SDk, 360 Seekbar, 424, 426 selezione, 23 selezione multipla, 24 sendmessage, 446 Sequence, 264 Sequencer, 263 sequenza, 22 sequenze di escape, 14 Serializable, 158, 159 serializzazione, 157 server, 308 server Web, 309 service, 312 servlet, 312 servlet engine, 317, 319 servlet-api.jar, 317 ServletConfig, 319 set, 81 setAdapter, 398 setAlpha, 438 setbackground, 193 setbackgroundColor, 432 setChecked, 412 setColor, 251 setContentView, 375, 376 setDragEnabled, 244 setEditable, 195 setEnabled, 193 setFont, 253 setForeground, 193 setIcon, 224 setImagebitmap, 419 setJMenuBar, 226 setLayout, 197 setLoopCount, 268 setmax, 426 setnegativebutton, 398 setOnItemClickListener, 395 setPositivebutton, 398 setProgress, 426 setSelectedFile, 259 setSelectionmode, 233 setText, 193, 195, 375, 376, 383 setTitle, 232 setTransferhandler, 245 setType, 417 setVisible, 187 setXXX, 288 sezione privata, 80 sezione pubblica, 80 Short, 13 shortcut, 227 show, 377, 408 showAsAction, 408 showConfirmDialog, 220 showInputDialog, 220 showmessageDialog, 220 showOpenDialog, 228, 232 showOptionDialog, 220 showSaveDialog, 228 indice analitico
469
Signed bundle, 441 SimpleCursorAdapter, 403 sin, 108 sintassi, 11 situazione ricorsiva, 147 size, 125 smarthigh, 364 smartLow, 364 smartphone, 358 smartwatch, 442 software, 308 sopraclasse, 94, 98 sorgente, 155, 244 sorgente .java, 48 sottoalbero destro, 146 sottoalbero sinistro, 146 sottoclasse, 94 Source, 189 sp, 367 Spinner, 424, 426 SQL, 343 SQL Injection, 288 SQLException, 284 sqrt, 108 stack, 131, 133 start, 263, 264, 364 startActivity, 380, 384, 417 Statement, 284, 288 static, 9, 65, 79 statistiche, 441 Step Into, 50 Step Over, 50 stop, 264 store, 440 stream, 154 stream di input, 155 stream di output, 155 String, 71, 109 Stringbuffer, 334 stringFlavor, 248 stringhe, 14, 109 strings.xml, 372 StringTokenizer, 165 StructuredPostal, 401 strumenti di geolocalizzazione, 359 strumenti integrati, 359 strumenti multimediali, 359 struttura di un oggetto, 60 strutture di dati dinamiche, 124 Style.FILL, 420 Style.STrOkE, 420 substring, 110 super, 98, 102 superclasse, 94 sviluppo, 364 Swing, 183 switch, 24 System, 91 System.err, 18 System.exit, 91, 271 System.in, 19 System.out, 9, 18
470
indice analitico
T tabelle, 400 tablet, 358 Tag, 370 tag di azione, 336 tag di comando, 336 tag di commento, 336 tag JSP, 336 tan, 108 Target, 363, 369 Terminate, 50 test, 189, 364, 369 Text, 190, 367, 370, 371 textColor, 402 textSize, 367 textStyle, 402 TextView, 371, 402 this, 76, 77, 78, 217, 220 Thread.sleep, 272 throws, 313, 319 tipi booleani, 14 tipi carattere, 14 tipi interi, 13 tipi numerici, 13 tipi riferimento, 67 tipo di dato, 12 title, 408 Toast, 377, 414 Toast.makeText, 377 toccare, 359 toccare due volte, 359 toccare e tenere premuto, 359 token, 165 tolowerCase, 110 Tomcat, 315, 337 top-level container, 185 touch, 358, 359 touchscreen, 358 toupperCase, 110 traduzione, 441 Transferhandler, 244 TransferSupport, 248 trascina e rilascia, 244 trascinare, 359 TreePath, 242 TreeSelectionListener, 237 try, 20, 32, 284, 285 txt, 191 Type, 363 Typeface.bOLD, 420 Typeface.SErIF, 420
U uCanAccess, 282 uguaglianza dei riferimenti, 75 uguaglianza tra oggetti, 75 uguaglianza tra variabili, 75 umL, 61 unicode, 14 unità di archiviazione, 409 urL, 283, 322
uses-permission, 401 uTF-8, 335 utilizzo della classe, 62
V valore di ritorno, 66 valore null, 74 valueChanged, 233, 237 vantaggi, 59, 82 variabile di ambiente, 7 variabile di classe, 79 variabile locale, 66 variabili, 11 variabili di istanza, 64 Variable name, 190 Variables, 54 Vector, 124, 125 versioni di Android, 360 versioning, 46 virgola mobile, 13, 21 Virtual Device, 363 visibilità, 12 visualizzazione, 254 Vk, 227 void, 9, 66, 70
W WAn, 308 warning, 49 Watch, 50 Watch Faces, 442 Wear, 442 Wear Activity, 442 Wear OS, 442, 450 Wear OS round, 449 Wear round, 443 wearable, 442446 WearableActivity, 446 web.xml, 316 webapps, 316 WEb-InF, 316 while, 25 widget, 360 width, 250 Window, 189 WindowListener, 212 Work, 404 Workbench, 47 Workplace, 46, 48 wrap_content, 371 WrITE_EXTErnAL_STOrAGE, 411 writeDato, 158 writeObject, 158, 159 Writer, 156 WWW, 309
X XmL, 316, 395 XmLhttprequest, 332
Z zona rettangolare, 250 © Istituto Italiano Edizioni Atlas
PRO.TECH Informatica per Istituti Tecnici Tecnologici è un corso per la Scuola Secondaria di Secondo Grado che guida lo studente verso l’acquisizione di un profilo professionale che gli consenta, in contesti applicativi, di utilizzare con sicurezza e competenza le procedure e le tecniche informatiche e di contribuire in modo attivo all’innovazione e all’adeguamento tecnologico dei processi produttivi. PER LO STUDENTE A STAMPA
PRO.TECH A Algoritmi e programmazione Linguaggi C e C++ Pagine Web
PRO.TECH B Linguaggio Java Programmazione ad oggetti Web e applicazioni Android
IN DIGITALE
PRO.TECH C Database Linguaggio SQL Dati in rete
eBook+
DVD
978-88-268-2187-0 978-88-268-2188-7 978-88-268-2189-4
SOLO PER L’INSEGNANTE A STAMPA
www.edatlas.it
Risorse per l’insegnante 978-88-268-2192-4
Risorse per l’insegnante pdf + word
PRO.TECH B
Linguaggio Java Programmazione ad oggetti Web e applicazioni Android con DVD
La proposta editoriale PRO.TECH INFORMATICA PER ISTITUTI TECNICI TECNOLOGICI è disponibile in modalità mista di tipo b) e in modalità digitale di tipo c). Tutti i volumi sono disponibili in formato accessibile a favore di studenti non vedenti, ipovedenti o con Disturbi Specifici di Apprendimento. Le versioni in modalità digitale di tipo c) sono poste in vendita su piattaforma dedicata (consultare il catalogo cartaceo e/o digitale sul sito www.edatlas.it)