PRO.TECH Informatica per Istituti Tecnici Tecnologici [B]
 9788826821887

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) etti 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 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 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 ott 18564 fl con { si ting secondi. F La cas un int dal tipo 11 V ta con il int per int a = 3;
Cognome O FALSA rA (V)
Nome
Password omaticam sezione Java SE mento al sito http:// uaggio a
Email
float al tipo int in ore, minuti e versione void main(String ata pro Per esempio 5 ore,
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)