Sviluppo di applicazioni ADOBE AIR 1.5 con ADOBE FLASH CS4 PROFESSIONAL ® ® ® ™ © 2008 Adobe Systems Incorporated. Tutti i diritti riservati. Copyright Sviluppo di applicazioni Adobe® AIR™ 1.5 con Adobe® Flash® CS4 Se la presente guida viene distribuita con software che include un accordo di licenza per l'utente finale, la guida e il software in essa descritto sono concessi in licenza e possono essere usati e copiati solo in conformità con i termini di tale licenza. Ad eccezione di quanto eventualmente concesso da tale licenza, nessuna parte di questa guida può essere riprodotta, memorizzata in un sistema per il recupero dati o trasmessa in qualsiasi forma o con qualsiasi mezzo, elettronico, meccanico, di registrazione o altro, senza il previo consenso scritto da parte di Adobe Systems Incorporated. Il contenuto di questa guida è protetto dalle leggi sui diritti d'autore, anche se non distribuito con software corredato di accordo di licenza per l'utente finale. Il contenuto di questa guida viene fornito unicamente a scopo informativo, è soggetto a modifiche senza preavviso e non comporta alcun impegno per Adobe Systems Incorporated. Adobe Systems Incorporated declina ogni responsabilità per eventuali errori o imprecisioni presenti in questa guida. Se si inseriscono in un progetto grafica e immagini esistenti, si tenga presente che tali materiali potrebbero essere protetti dalla legge sul copyright. L'inserimento non autorizzato di tali materiali nel proprio lavoro potrebbe rappresentare una violazione dei diritti del titolare del copyright. Assicurarsi sempre di ottenere le eventuali autorizzazioni necessarie dal titolare dei diritti d'autore. Tutti i riferimenti a nomi di società o persone negli esempi forniti hanno scopo puramente dimostrativo e non intendono fare riferimento ad alcuna organizzazione o persona realmente esistente. Adobe, the Adobe logo, Acrobat, ActionScript, Adobe AIR, ColdFusion, Dreamweaver, Flash, Flex, Flex Builder, and Reader are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Apple, Macintosh, and Mac OS are trademarks of Apple Inc., registered in the United States and other countries. Java is a trademarks or registered trademark of Sun Microsystems, Inc. in the United States and other countries. Linux is the registered trademark of Linus Torvalds in the U.S. and other countries. All other trademarks are the property of their respective owners. This work is licensed under the Creative Commons Attribution Non-Commercial 3.0 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/us/ This product includes software developed by the Apache Software Foundation (http://www.apache.org/) MPEG Layer-3 audio compression technology licensed by Fraunhofer IIS and Thomson Multimedia (http://www.mp3licensing.com). Speech compression and decompression technology licensed from Nellymoser, Inc. (www.nellymoser.com) Video compression and decompression is powered by On2 TrueMotion video technology. © 1992-2005 On2 Technologies, Inc. All Rights Reserved. http://www.on2.com. This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/) This product contains either BSAFE and/or TIPEM software by RSA Security, Inc. Sorenson Spark™ video compression and decompression technology licensed from Sorenson Media, Inc. This product includes software developed by the IronSmith Project (http://www.ironsmith.org/). Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA. Notice to U.S. Government End Users. The Software and Documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference. iii Sommario Capitolo 1: Installazione di Adobe AIR Installazione di Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Rimozione di Adobe AIR ............................................................................................... 2 Installazione ed esecuzione delle applicazioni AIR di esempio ........................................................... 2 Capitolo 2: Impostazione di Flash CS3 per Adobe AIR Requisiti di sistema per l'aggiornamento Adobe AIR per Flash CS3 Installazione dell'aggiornamento Adobe AIR per Flash CS3 Rimozione dell'aggiornamento Adobe AIR per Flash CS3 Funzioni supplementari di AIR per Flash CS3 ...................................................... 4 .............................................................. 4 ............................................................... 5 ........................................................................... 6 Capitolo 3: Presentazione di Adobe AIR Novità in AIR 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Novità in AIR 1.5 ....................................................................................................... 9 Capitolo 4: Reperimento delle risorse AIR Capitolo 5: Creazione della prima applicazione AIR mediante Flash CS3 o CS4 Creazione dell'applicazione Hello World in Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Prova dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Conversione di un file FLA in un'applicazione Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Capitolo 6: Aggiornamento Adobe AIR per Flash CS3 Professional Creazione di un file Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Configurazione delle impostazioni di pubblicazione di Adobe AIR Anteprima di un'applicazione Adobe AIR Debug delle applicazioni Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Creazione dei file dell'applicazione e del programma di installazione AIR Creazione di un file descrittore applicazione personalizzato Aggiunta di una firma all'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Capitolo 7: Sicurezza in AIR Nozioni fondamentali sulla sicurezza in AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Installazione e aggiornamenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Funzioni di sicurezza sandbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Sicurezza in HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Creazione di script tra contenuti in diversi domini Scrittura su disco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Operazioni sicure con contenuto non attendibile Procedure di sicurezza ottimali per gli sviluppatori Firma del codice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Capitolo 8: Impostazione delle proprietà dell'applicazione AIR Struttura del file descrittore dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Definizione delle proprietà nel file descrittore dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL iv Sommario Capitolo 9: Funzionalità specifiche di Adobe AIR Classi specifiche di AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Classi di runtime con funzionalità specifiche per AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Classi con struttura per il monitoraggio del servizio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Capitolo 10: Operazioni con le finestre native Informazioni in linea aggiuntive sulle finestre native . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Nozioni di base sulle finestre AIR Creazione di finestre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Gestione delle finestre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Intercettazione degli eventi della finestra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Visualizzazione di finestre a schermo intero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Capitolo 11: Schermate Ulteriori informazioni online sulle schermate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Nozioni di base sulle schermate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Enumerazione delle schermate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Capitolo 12: Uso dei menu nativi Ulteriori informazioni disponibili online sui menu nativi Nozioni di base sui menu di AIR Creazione dei menu nativi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Informazioni sui menu di scelta rapida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Informazioni sui menu di scelta rapida in HTML Definizione dichiarativa dei menu nativi Visualizzazione dei menu a comparsa Gestione degli eventi dei menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Esempio: menu della finestra e dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Capitolo 13: Icone della barra delle applicazioni Informazioni in linea aggiuntive sulle icone della barra delle applicazioni Informazioni sulle icone della barra delle applicazioni Icone del dock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Icone della barra delle applicazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Icone e pulsanti della barra delle applicazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Capitolo 14: Operazioni con il file system Informazioni online supplementari sull'API File di AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Elementi di base dei file AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Operazioni con oggetti File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Recupero di informazioni sul file system Operazioni con le directory Operazioni con i file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Lettura e scrittura di file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Capitolo 15: Trascinamento della selezione Informazioni supplementari online sul trascinamento Elementi di base del trascinamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL v Sommario Supporto del movimento di trascinamento verso esterno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Supporto del movimento di trascinamento verso interno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Trascinamento HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Capitolo 16: Copia e incolla Ulteriori informazioni online sulle operazioni di copia e incolla Copia e incolla HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Comandi di menu e sequenze di tasti per le operazioni di copia e incolla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Capitolo 17: Utilizzo di array di byte Lettura e scrittura di un ByteArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Esempio di ByteArray: lettura di un file zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Capitolo 18: Utilizzo dei database SQL locali Ulteriori informazioni online riguardanti i database SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Introduzione ai database SQL locali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Creazione e modifica di un database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Manipolazione dei dati dei database SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Utilizzo delle operazioni di database sincrone e asincrone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Uso della crittografia con i database SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Strategie per l'utilizzo dei database SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Capitolo 19: Memorizzazione di dati crittografati Capitolo 20: Informazioni sull'ambiente HTML Panoramica sull'ambiente HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Estensioni di AIR e Webkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Capitolo 21: Programmazione in HTML e JavaScript Informazioni sulla classe HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Errori JavaScript relativi alla sicurezza da evitare Accesso alle classi API di AIR da JavaScript Informazioni sugli URL in AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Uso degli oggetti di ActionScript in JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Accesso agli oggetti JavaScript e al modello DOM HTML da ActionScript Incorporamento del contenuto SWF nel contenuto HTML Uso delle librerie di ActionScript in una pagina HTML Conversione degli oggetti Date e RegExp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Elaborazione di un foglio di stile HTML in ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Scambio di script per il contenuto presente in sandbox di sicurezza diverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Capitolo 22: Gestione di eventi relativi a HTML Eventi HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Gestione di eventi DOM con ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Risposta a eccezioni JavaScript non identificate Gestione di eventi runtime con JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL vi Sommario Capitolo 23: Creazione di script per il contenitore HTML Proprietà di visualizzazione degli oggetti HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Scorrimento del contenuto HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Accesso all'elenco cronologico HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 Impostazione dell'agente utente utilizzato durante il caricamento del contenuto HTML Impostazione della codifica dei caratteri da usare per il contenuto HTML Definizione di interfacce simili a browser per il contenuto HTML Creazione di sottoclassi della classe HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 Capitolo 24: Aggiunta di contenuto PDF Rilevamento della funzionalità PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Caricamento di contenuto PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Uso di script nel contenuto PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Limiti noti per il contenuto PDF in AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Capitolo 25: Uso della funzionalità DRM (Digital Rights Management) Informazioni supplementari online sul DRM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 Flusso di lavoro FLV crittografato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Membri ed eventi della classe NetStream correlati a DRM Uso della classe DRMStatusEvent Uso della classe DRMAuthenticateEvent Uso della classe DRMErrorEvent Uso della classe DRMManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 Uso della classe DRMContentData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Capitolo 26: Opzioni di avvio e di uscita dalle applicazioni Chiamata dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 Acquisizione degli argomenti della riga di comando Avvio all'accesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Chiamata del browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Terminazione dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 Capitolo 27: Lettura delle impostazioni dell'applicazione Lettura del file descrittore dell'applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Ottenimento dell'identificatore dell'applicazione e dell'editore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Capitolo 28: Uso delle informazioni di runtime e del sistema operativo Gestione delle associazioni di file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Informazioni su versione runtime e livello patch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Rilevamento delle funzionalità AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Verifica delle presenza dell'utente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Capitolo 29: Monitoraggio della connettività di rete Rilevamento delle modifiche relative alla connettività di rete Nozioni di base sul monitoraggio dei servizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Rilevamento della connettività HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Rilevamento della connettività socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL vii Sommario Capitolo 30: Richieste URL e connettività di rete Uso della classe URLRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Modifiche alla classe URLStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 Apertura di un URL nel browser Web predefinito del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 Capitolo 31: Comunicazione tra le applicazioni Capitolo 32: Distribuzione, installazione ed esecuzione di applicazioni AIR Installazione ed esecuzione di un'applicazione AIR dal desktop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Installazione ed esecuzione di applicazioni AIR da una pagina Web Distribuzione aziendale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Firma digitale di un file AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Capitolo 33: Aggiornamento delle applicazioni AIR Informazioni sull'aggiornamento delle applicazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 Presentazione di un'interfaccia utente di aggiornamento dell'applicazione personalizzata Scaricamento di un file AIR nel computer dell'utente Controllo per verificare se un'applicazione viene eseguita per la prima volta Uso del framework di aggiornamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 Capitolo 34: Localizzazione di applicazioni AIR Introduzione alla localizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 Localizzazione del nome e della descrizione dell'applicazione nel programma di installazione dell'applicazione . . . . . . . . 348 Selezione delle impostazioni locali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Localizzazione di contenuto Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Localizzazione di contenuto HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 Localizzazione di date, ore e valute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 Capitolo 35: Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Utilizzo di ADL (AIR Debug Launcher) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Creazione di un pacchetto di un file di installazione AIR mediante ADT (AIR Developer Tool) Firma di un file AIR per la modifica del certificato dell'applicazione Creazione di un certificato autofirmato mediante ADT Utilizzo di Apache Ant con gli strumenti SDK Indice . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 1 Capitolo 1: Installazione di Adobe AIR Adobe® AIR™ consente di eseguire applicazioni AIR sul desktop. È possibile installare il runtime nei modi seguenti: • Installando il runtime separatamente (senza l'ulteriore installazione di un'applicazione AIR) • Installando un'applicazione AIR per la prima volta (viene richiesto di installare anche il runtime) • Impostando un ambiente di sviluppo AIR come AIR SDK, Adobe® Flex™ Builder™ 3 oppure Adobe Flex™ 3 SDK (che include gli strumenti di sviluppo AIR della riga di comando) Il runtime deve essere installato una sola volta per computer. I requisiti di sistema per l'installazione di AIR e l'esecuzione di applicazioni AIR sono descritti dettagliatamente sul sito Adobe AIR: requisiti di sistema (http://www.adobe.com/it/products/air/systemreqs/). Installazione di Adobe AIR Utilizzate le seguenti istruzioni per scaricare e installare le versioni di AIR per Windows®, Mac OS X e Linux. Per aggiornare il runtime, un utente deve disporre di privilegi di amministrazione per il computer. Installare il runtime su un computer Windows 1 Scaricate il file di installazione del runtime. 2 Fate doppio clic sul file di installazione del runtime. 3 Nella finestra di installazione, eseguite i comandi per completare l'installazione. Installare il runtime su un computer Mac 1 Scaricate il file di installazione del runtime. 2 Fate doppio clic sul file di installazione del runtime. 3 Nella finestra di installazione, eseguite i comandi per completare l'installazione. 4 Se il programma di installazione visualizza una finestra di autenticazione, immettete il vostro nome utente e la password di Mac OS. Installare il runtime su un computer Linux 1 Scaricate il file di installazione del runtime. 2 Impostate le autorizzazioni del file per consentire l'esecuzione dell'applicazione di installazione: Da una riga di comando, potete impostare le autorizzazioni del file con il comando chmod +x installer.bin. Alcune versioni di Linux consentono di impostare le autorizzazioni dei file nella finestra di dialogo delle proprietà aperta tramite un menu di scelta rapida. 3 Eseguite il programma di installazione dalla riga di comando o facendo doppio clic sul file di installazione del runtime. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 2 Installazione di Adobe AIR 4 Nella finestra di installazione, eseguite i comandi per completare l'installazione. AIR viene installato come pacchetto rpm o dpkg, con i nomi di pacchetto: adobeairv.n e adobecerts. L'installazione richiede l'esecuzione di un server X. AIR registra il tipo mime: application/vnd.adobe.air-applicationinstaller-package+zip. Rimozione di Adobe AIR Dopo l'installazione del runtime, potete rimuoverlo mediante le seguenti procedure. Rimuovere il runtime in un computer Windows 1 Nel menu Start di Windows, selezionate Impostazioni > Pannello di controllo. 2 Selezionate il pannello di controllo Installazione applicazioni. 3 Selezionate "Adobe AIR" per rimuovere il runtime. 4 Fate clic sul pulsante Cambia/Rimuovi. Rimuovere il runtime in un computer Mac • Fate doppio clic su “Adobe AIR Uninstaller”, che si trova nella cartella /Applications/Utilities. Rimuovere il runtime in un computer Linux Effettuate una delle seguenti operazioni. • Selezionate il comando relativo al programma di disinstallazione di Adobe AIR dal menu Applicazioni. • Eseguite il file binario del programma di installazione di AIR con l'opzione -uninstall • Rimuovete i pacchetti AIR (adobeairv.n e adobecerts) utilizzando lo strumento di gestione pacchetti. Installazione ed esecuzione delle applicazioni AIR di esempio Sono disponibili alcune applicazioni di esempio che illustrano le funzionalità di AIR. Potete accedere a tali applicazioni e installarle mediante le seguenti istruzioni: 1 Scaricate ed eseguite le applicazioni di esempio AIR. Sono disponibli sia le applicazioni compilate che il codice sorgente. 2 Per scaricare ed eseguire un'applicazione di esempio, fate clic sul pulsante Installa adesso dell'applicazione. Viene richiesto di installare ed eseguire l'applicazione. 3 Se scegliete di scaricare le applicazioni di esempio e di eseguirle in seguito, selezionate gli appositi collegamenti. Potete eseguire applicazioni AIR in qualsiasi momento: • In Windows, facendo doppio clic sull'icona dell'applicazione sul desktop o selezionandola nel menu Start di Windows. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 3 Installazione di Adobe AIR • In Mac OS, facendo doppio clic sull'icona dell'applicazione, che per impostazione predefinita è installata nella cartella Applicazioni della vostra directory utente (ad esempio, in Macintosh HD/Utenti/JoeUser/Applicazioni/). • In Linux, facendo doppio clic sull'icona dell'applicazione sul desktop o selezionandola nel menu Applicazioni. Le applicazioni AIR vengono installate nella relativa cartella nella directory /opt. Nota: verificate se sono disponibili aggiornamenti a queste istruzioni nelle note sulla versione di AIR, che si trovano al seguente indirizzo: http://www.adobe.com/go/learn_air_relnotes_it. 4 Capitolo 2: Impostazione di Flash CS3 per Adobe AIR L'aggiornamento Adobe® AIR™ per Adobe® Flash® CS3 Professional espande l'ambiente di sviluppo di Flash con elementi che consentono di realizzare applicazioni AIR con Flash e di eseguirne la prova e il debug. Adobe® Flash® CS4 Professional è dotato del supporto incorporato per la creazione di applicazioni AIR. Per ulteriori informazioni, consultate Pubblicazione per Adobe AIR nella guida Uso di Flash. L'aggiornamento di Adobe AIR per Flash CS3 supporta AIR 1.0 e 1.1 e Flash Player 9.x. Flash CS4 è necessario per sviluppare applicazioni con AIR 1.5 e Flash Player 10. Requisiti di sistema per l'aggiornamento Adobe AIR per Flash CS3 Per poter utilizzare Flash CS3 per sviluppare ed eseguire le applicazioni AIR, è necessario che sul computer sia installato il seguente software: • Flash CS3 Professional Se non possedete una copia di Flash CS3 Professional, potete acquistarla direttamente sul sito Web Adobe all'indirizzo: http://www.adobe.com/it/products/flash/ • Adobe AIR Per ulteriori informazioni sull'installazione di Adobe AIR, consultate “Installazione di Adobe AIR” a pagina 1. • Aggiornamento Adobe AIR per Flash CS3 Se avete già installato una versione dell'aggiornamento di Adobe AIR per Flash CS3, disinstallatela seguendo la procedura descritta alla sezione Disinstallazione dell'aggiornamento Adobe AIR per Flash CS3. Se non avete ancora installato l'aggiornamento Adobe AIR per Flash CS3, passate alla sezione “Installazione dell'aggiornamento Adobe AIR per Flash CS3” a pagina 4. Installazione dell'aggiornamento Adobe AIR per Flash CS3 Prima di installare l'aggiornamento Adobe AIR per Flash CS3, uscite da Flash e chiudete gli eventuali browser aperti. • Scaricate l'aggiornamento Adobe AIR per Flash CS3. • Al termine del download, fate doppio clic sul file patch dell'aggiornamento per installarlo. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 5 Impostazione di Flash CS3 per Adobe AIR Rimozione dell'aggiornamento Adobe AIR per Flash CS3 Se avete già installato l'aggiornamento Adobe AIR per Flash CS3, utilizzate la seguente procedura per rimuoverlo prima di installare la nuova versione. 1 Eliminate la seguente cartella: (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\AIK (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/AIK 2 Spostatevi sul seguente percorso: (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\<lingua>\First Run\Commands\ (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/First Run/Commands ed eliminate i seguenti file/cartelle: • Cartella AIR • AIR - Application and Installer Settings.jsfl • AIR - Create AIR File.jsfl 3 Eliminate il seguente file: (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\<lingua>\Configuration\External Libraries\FLAir.dll (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/Configuration/External Libraries/FLAir.bundle. 4 Eliminate il seguente file: (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\<lingua>\Configuration\Players\AdobeAIR1_0.xml (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/Configuration/Players/ AdobeAIR1_0.xml 5 Spostatevi sul seguente percorso: (Windows) Disco rigido:\Documents and Settings\<nome utente>\Impostazioni locali\Dati applicazioni\Adobe\Flash CS3\<lingua>\Configuration\Commands\ (Mac) Disco rigido:/Utenti/<nome utente>/Libreria/Supporto applicazioni/Adobe/Flash CS3/<lingua>/Configuration/Commands/ ed eliminate i seguenti file/cartelle: • Cartella AIR • AIR - Application and Installer Settings.jsfl • AIR - Create AIR File.jsfl Nota: se il percorso specificato non è visibile in Windows, attivate "Visualizza cartelle e file nascosti" in Opzioni cartella. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 6 Impostazione di Flash CS3 per Adobe AIR Funzioni supplementari di AIR per Flash CS3 Dopo l'installazione dell'aggiornamento Adobe AIR, noterete le seguenti modifiche in Flash: • Nella finestra di dialogo Impostazioni pubblicazione (File -> Impostazioni pubblicazione), sulla scheda Flash, sarà presente nel menu Versione una nuova voce per Adobe AIR 1.0 • La schermata di benvenuto sarà stata aggiornata e conterrà la voce File Flash (Adobe AIR) che consente appunto la creazione di un file Flash per Adobe AIR (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\it\FirstRun\StartPage (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\it\FirstRun\StartPage\resources Nota: in ambiente Macintosh, se l'opzione File Flash (Adobe AIR) non appare sulla schermata di benvenuto, eliminate la seguente cartella e riavviate Flash: Disco rigido:/Utenti/<nome utente>/Librerie/Supporto applicazioni/Adobe/Flash CS3/<lingua>/Configuration/StartPage • Un nuovo file playerglobal.swc che comprende tutte le API di ActionScript 3.0 e quelle di Adobe AIR nella cartella ActionScript 3.0/Classes (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\it\Configuration\ActionScript 3.0 Classes (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/Configuration/ActionScript 3.0/Classes/ • Nuovi file jsfl (AIR - Application and Installer Settings.jsfl e AIR - Publish AIR File.jsfl) (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\it\FirstRun\Commands (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/First Run/Commands/ • Adobe AIR Software Development Kit (AIK) (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\AIK • Libreria esterna (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\it\Configuration\External Libraries (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/Configuration/External Libraries/ • File di configurazione di destinazione (Windows) Disco rigido:\Programmi\Adobe\Adobe Flash CS3\it\Configuration\Players\ (Mac) Disco rigido:/Applicazioni/Adobe Flash CS3/Configuration/Players 7 Capitolo 3: Presentazione di Adobe AIR Adobe® AIR™ è un runtime compatibile con diversi sistemi operativi che consente di creare e distribuire applicazioni Rich Internet (RIA) complete sul desktop sfruttando le capacità di sviluppo per il Web che avete già acquisito (Adobe® Flash® CS3 Professional, Adobe® Flash® CS4 Professional, Adobe® Flex™, Adobe® ActionScript® 3.0, HTML, JavaScript®, Ajax). Potete trovare ulteriori informazioni sull'uso di Adobe AIR e sulle prime operazioni con il programma nel sito Adobe AIR Developer Connection (http://www.adobe.com/devnet/air/). AIR vi consente di lavorare in ambienti familiari, sfruttare gli strumenti e i metodi con cui avete maggiore dimestichezza e, grazie al supporto di Flash, Flex, HTML, JavaScript e Ajax, di realizzare progetti che soddisfano pienamente le vostre esigenze. Ad esempio, potete sviluppare le applicazioni mediante utilizzando una o più delle tecnologie seguenti: • Flash / Flex / ActionScript • HTML / JavaScript / CSS / Ajax • Il formato PDF può essere incluso con qualsiasi applicazione Di conseguenza, le applicazioni AIR possono essere: • Basate su Flash o Flex: applicazioni il cui contenuto principale è Flash/Flex (SWF) • Basate su Flash o Flex con HTML o PDF: applicazioni il cui contenuto principale è Flash/Flex (SWF) con contenuto HTML (HTML, JS, CSS) o PDF incluso • Basate su HTML: applicazioni il cui contenuto principale è HTML, JS, CSS • Basate su HTML con Flash/Flex o PDF: applicazioni il cui contenuto principale è HTML con contenuto Flash/Flex (SWF) o PDF incluso Gli utenti interagiscono con applicazioni AIR nello stesso modo in cui interagiscono con applicazioni desktop native. Il runtime viene installato una volta nel computer dell'utente e quindi le applicazioni AIR vengono installate ed eseguite come qualunque altra applicazione desktop. La piattaforma e il framework per l'implementazione delle applicazioni forniti dal runtime hanno caratteristiche omogenee nei diversi sistemi operativi e pertanto eliminano la necessità di testare le applicazioni in più browser, garantendo funzionalità e interazioni uniformi in tutti gli ambienti desktop. Invece di sviluppare per un sistema operativo specifico, potete utilizzare il runtime come unico riferimento, ottenendo i seguenti vantaggi: • Le applicazioni sviluppate per AIR funzionano in più sistemi operativi senza ulteriori interventi da parte vostra. Il runtime garantisce caratteristiche visive e interazioni omogenee e prevedibili nell'intera gamma dei sistemi operativi supportati da AIR. • Le applicazioni possono essere realizzate più rapidamente grazie alla possibilità di sfruttare le tecnologie Web e i modelli di design esistenti e di estendere la funzionalità delle applicazioni Web al desktop senza dover apprendere le tecnologie tradizionali di sviluppo per desktop o la complessità del codice nativo. • Lo sviluppo delle applicazioni è più semplice rispetto all'uso di linguaggi di livello più basso come C e C++. Non dovete gestire le complesse API di basso livello specifiche di ciascun sistema operativo. Quando sviluppate applicazioni per AIR, potete avvalervi di un'ampia serie di framework e API. • API specifiche di AIR fornite dal runtime e dal framework AIR SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 8 Presentazione di Adobe AIR • API di ActionScript utilizzate nei file SWF e nel framework Flex (nonché altre librerie e framework basati su ActionScript) • HTML, CSS e JavaScript • La maggior parte dei framework Ajax AIR modifica notevolmente le modalità di creazione, implementazione e interazione delle applicazioni. Avete a disposizione un maggiore controllo, più spazio per la creatività e potete estendere le vostre applicazioni basate su Flash, Flex, HTML e Ajax all'ambiente desktop senza dover conoscere le tradizionali tecnologie di sviluppo desktop. Novità in AIR 1.1 In Adobe AIR 1.1 sono state introdotte le nuove funzionalità seguenti: • Le finestre di dialogo dell'installazione e altre finestre di dialogo della fase di esecuzione sono state tradotte nelle lingue seguenti: • portoghese brasiliano • cinese (tradizionale e semplificato) • francese • tedesco • italiano • giapponese • coreano • russo • francese • spagnolo • Supporto per la compilazione di applicazioni internazionalizzate, tra cui input da tastiera per le lingue a doppio byte. Consultate “Localizzazione di applicazioni AIR” a pagina 348. • Supporto per la localizzazione degli attributi name e description nel file descrittore dell'applicazione. • Supporto per la localizzazione di messaggi di errore, ad esempio SQLError.detailID e SQLError.detailArguments, nel database SQLite. • Aggiunta della proprietà Capabilities.languages per ottenere un array di lingue preferite per l'interfaccia utente impostate dal sistema operativo. • Le etichette dei pulsanti HTML e i menu predefiniti, ad esempio menu di scelta rapida e la barra dei menu Mac, sono stati localizzati in tutte le lingue supportate. • Supporto per la migrazione dei certificati da un'applicazione autofirmata a un'altra concatenata con un'autorità di certificazione (CA). • Supporto di Microsoft Windows XP Tablet PC Edition e delle edizioni a 64 bit di Windows Vista® Home Premium, Business, Ultimate o Enterprise. • Aggiunta dell'API File.spaceAvailable per ottenere la quantità di spazio disponibile su un disco. • Aggiunta della proprietà NativeWindow.supportsTransparency per determinare se una finestra può essere disegnata come trasparente dal sistema operativo corrente. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 9 Presentazione di Adobe AIR Per ulteriori informazioni sulla versione 1.1 di AIR, consultate le note sulla versione di Adobe AIR 1.1 (http://www.adobe.com/go/learn_air_relnotes_it). Novità in AIR 1.5 In Adobe AIR 1.5 sono state introdotte le nuove funzionalità seguenti: • Supporto delle funzioni di Flash Player 10 seguenti. • Filtri ed effetti personalizzati • API di disegno migliorata • Generazione dinamica dell'audio • Tipo di dati vettoriali • API per il download e il caricamento migliorati • Protocollo RTMFP (Real Time Media Flow Protocol) • Effetti 3D • Supporto avanzato del testo • Gestione del colore • Motore di testo • Streaming dinamico • Codec audio Speex Per ulteriori informazioni e dettagli su queste funzioni, consultate http://www.adobe.com/it/products/flashplayer/features/. • Ulteriori lingue supportate nel programma di installazione e in altre finestre di dialogo della fase di esecuzione di AIR 1.5: ceco, olandese, svedese, turco, polacco. • Crittografia dei database. In AIR 1.5 i file di database possono essere crittografati. Tutto il contenuto dei database, inclusi i metadati, può essere crittografato affinché i dati non possano essere letti all'esterno dell'applicazione AIR in cui sono stati crittografati. Questa funzione consente agli sviluppatori di crittografare, decrittografare e ricrittografare file di database. Consultate “Memorizzazione di dati crittografati” a pagina 218. • La versione di WebKit utilizzata da Adobe AIR è stata aggiornata e include ora il supporto dell'interprete JavaScript SquirrelFish. • Potete utilizzare nuove API per la convalida di firme XML per facilitare la verifica dell'integrità e dell'identità del firmatario di dati o informazioni. Consultate Convalida delle firme XML. Per ulteriori informazioni sulla versione 1.5 di AIR, consultate le note sulla versione di Adobe AIR 1.5 (http://www.adobe.com/go/learn_air_relnotes_it). 10 Capitolo 4: Reperimento delle risorse AIR Per ulteriori informazioni sullo sviluppo delle applicazioni Adobe® AIR™, consultate le seguenti risorse. Fonte Posizione Programmazione in ActionScript 3.0 http://www.adobe.com/go/learn_fl_cs4_programmingAS3_it Guida di riferimento del linguaggio e dei componenti ActionScript 3.0 (include AIR) http://www.adobe.com/go/learn_flashcs4_langref_it Guide rapide di Adobe AIR per Flash http://www.adobe.com/go/learn_air_flash_qs_it Uso di Flash http://www.adobe.com/go/learn_fl_cs4_using_it Uso dei componenti ActionScript 3.0 http://www.adobe.com/go/learn_fl_cs4_as3components_it È possibile reperire articoli, file di esempio e presentazioni create sia dagli esperti di Adobe che da quelli della comunità nel Centro per sviluppatori Adobe AIR: http://www.adobe.com/it/devnet/. Su tale sito è inoltre possibile scaricare il software Adobe AIR e programmi correlati. È presente una sezione interamente dedicata agli sviluppatori Flash all'indirizzo http://www.adobe.com/devnet/air/flash/. Visitate il sito web del supporto Adobe all'indirizzo http://www.adobe.com/it/support/, che contiene informazioni per la risoluzione dei problemi sui vari prodotti e un elenco di opzioni per il supporto tecnico sia gratuito che a pagamento. Seguite il collegamento Formazione e Certificazione per accedere alla sezione dedicata ai libri della Adobe Press, che comprendono una serie di risorse di formazione, programmi di certificazione per il software Adobe e molto altro. 11 Capitolo 5: Creazione della prima applicazione AIR mediante Flash CS3 o CS4 Per una rapida dimostrazione pratica del funzionamento di Adobe® AIR™, seguire le istruzioni fornite nell'ambito di questo argomento per creare e assemblare la semplice applicazione AIR "Hello World" utilizzando Adobe® Flash® CS3 Professional. Se non lo avete già fatto, scaricate e installate l'aggiornamento Adobe AIR per Flash CS3. Per ulteriori informazioni sull'installazione di Adobe AIR per Flash CS3, consultate “Impostazione di Flash CS3 per Adobe AIR” a pagina 4. Se utilizzate Adobe® Flash® CS4 Professional, il supporto per Adobe AIR è incorporato e non dovete quindi installare nulla prima di iniziare. Creazione dell'applicazione Hello World in Flash La procedura per la creazione di applicazioni Adobe AIR in Flash è analoga a quella per la creazione di altri file FLA. L'unica differenza è rappresentata dal fatto che iniziate creando un file Flash (Adobe AIR) a partire dalla schermata di benvenuto e terminate creando le impostazioni dell'applicazione e del programma di installazione e successivamente installando l'applicazione AIR stessa. La procedura seguente illustra come creare un'applicazione Hello World semplice con Flash CS3 o Flash CS4. Creazione dell'applicazione "Hello World" 1 Avviate Flash. 2 Nella schermata di benvenuto, fate clic su File Flash (Adobe AIR) per creare un file FLA vuoto con le impostazioni di pubblicazione di Adobe AIR. 3 Fate clic su OK per rispondere alla finestra di riepilogo, Authoring per Adobe AIR con Flash CS3. Per la prima visualizzazione della finestra di dialogo sono necessari alcuni secondi. Questa finestra di dialogo non viene visualizzata in Flash CS4. 4 Selezionate lo strumento Testo nel pannello Strumenti e create un campo di testo statico (quello predefinito) al centro dello stage. Createlo di dimensioni sufficienti a contenere 15-20 caratteri. 5 Digitate il testo "Hello World" nel campo. 6 Salvate il file dandogli un nome, ad esempio helloAIR. Prova dell'applicazione 1 Premete Ctrl + Invio o selezionate Controllo -> Prova filmato per provare l'applicazione in Adobe AIR. 2 Per utilizzare la funzione Debug filmato, aggiungete innanzitutto all'applicazione il codice ActionScript. Potete provarla rapidamente aggiungendo una dichiarazione trace come la seguente: trace("Running AIR application using Debug Movie"); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 12 Creazione della prima applicazione AIR mediante Flash CS3 o CS4 3 Premete Ctrl + Maiusc + Invio o selezionate Controllo -> Debug filmato per eseguire l'applicazione con Debug filmato. 4 Selezionate Comandi > AIR - Impostazioni applicazione e programma di installazione per aprire la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione. In Flash CS4, potete aprire questa finestra di dialogo selezionando l'opzione File > Impostazioni AIR. 5 Firmate il pacchetto Adobe AIR con un certificato digitale autofirmato, nel modo seguente: a Fate clic sul pulsante Imposta per visualizzare il prompt Firma digitale e aprire la finestra di dialogo Firma digitale. b Fate clic sul pulsante Crea per aprire la finestra di dialogo Crea certificato digitale autofirmato. c Compilate i campi Nome editore, Unità organizzativa, Nome organizzazione, E-mail, Paese, Password e Conferma password. d Specificate il tipo di certificato. L'opzione Tipo del certificato si riferisce al livello di protezione: 1024-RSA utilizza una chiave a 1024 bit (minore protezione) e 2048-RSA utilizza una chiave a 2048 bit (maggiore protezione). e Salvate le informazioni in un file di certificato compilando la voce Salva con nome oppure facendo clic sul pulsante Sfoglia per specificare la cartella desiderata, ad esempio C:/Temp/mycert.pfx. Al termine, fate clic su OK. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 13 Creazione della prima applicazione AIR mediante Flash CS3 o CS4 f Flash visualizza di nuovo la finestra di dialogo Firma digitale. Il percorso e il nome file del certificato autofirmato appena creato appaiono nella casella di testo Certificato. Se non vengono visualizzati, immetteteli oppure fate clic sul pulsante Sfoglia per individuarli e selezionarli. g Immettete nel campo di testo Password della finestra di dialogo Firma digitale la stessa password che avete assegnato al punto c, quindi fate clic su OK. Per ulteriori informazioni su come applicare firme alle applicazioni Adobe AIR che create, consultate “Aggiunta di una firma all'applicazione” a pagina 22. 6 Per creare il file dell'applicazione e il programma di installazione, fare clic sul pulsante Pubblica file AIR. Prima di creare il file AIR è necessario eseguire Prova filmato o Debug filmato per creare il file SWF e i file application.xml. 7 Per installare l'applicazione, fate doppio clic sul file AIR (application.air) nella stessa cartella in cui avete salvato l'applicazione stessa. 8 Fate clic sul pulsante Installa nella finestra di dialogo Installazione applicazione. 9 Ricontrollate le impostazioni in Preferenze installazione e Percorso e accertatevi che la casella di controllo Avvia l'applicazione dopo l'installazione contenga un segno di spunta, quindi fate clic su Continua. 10 Fate clic su Fine quando appare il messaggio Installazione completata. L'applicazione Hello World avrà l'aspetto seguente: Conversione di un file FLA in un'applicazione Adobe AIR Potete inoltre convertire un file FLA esistente in un'applicazione AIR. Per ulteriori informazioni, consultate “Configurazione delle impostazioni di pubblicazione di Adobe AIR” a pagina 15. Se utilizzate Flash CS4, consultate Pubblicazione per Adobe Air nella guida Uso di Flash. 14 Capitolo 6: Aggiornamento Adobe AIR per Flash CS3 Professional L'aggiornamento Adobe® AIR™ per Adobe® Flash® CS3 Professional espande l'ambiente di authoring in modo da consentire la creazione, il debugging e il packaging di applicazioni AIR con Flash. La procedura di creazione di un'applicazione Adobe AIR prevede la creazione di un file FLA di Adobe AIR, la configurazione delle impostazioni di pubblicazione appropriate, lo sviluppo dell'applicazione e la creazione dei file dell'applicazione e del programma di installazione che consentono l'utilizzo dell'applicazione stessa. Se utilizzate Adobe® Flash® CS4 Professional, consultate Pubblicazione per Adobe Air nella guida Uso di Flash per ottenere maggiori informazioni sulla creazione di applicazioni AIR. Per ulteriori informazioni sulle API di Adobe AIR ActionScript®3.0 che possono essere utilizzate nelle vostre applicazioni, consultate la Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. Per un elenco delle API ActionScript di Adobe AIR, consultate “Funzionalità specifiche di Adobe AIR” a pagina 56. Nota: per utilizzare le classi del pacchetto air.net, per prima cosa trascinate il componente ServiceMonitorShim dal pannello Componenti al pannello Libreria e successivamente aggiungete la seguente istruzione import al codice ActionScript 3.0. import air.net.*; Creazione di un file Adobe AIR Potete creare documenti File Flash (Adobe AIR) utilizzando la schermata di benvenuto di Flash oppure creare un file Flash (ActionScript 3.0) e convertirlo in un file Adobe AIR tramite la finestra di dialogo Impostazioni pubblicazione. Non potete invece creare un file Adobe AIR tramite la finestra di dialogo Nuovo documento (File > Nuovo). Per ulteriori informazioni sulla conversione di un file FLA in un file di Adobe AIR, consultate “Configurazione delle impostazioni di pubblicazione di Adobe AIR” a pagina 15. 1 Avviate Flash o, se è già in esecuzione, chiudete gli eventuali documenti aperti per tornare alla schermata di benvenuto. Nota: se avete disabilitato la schermata di benvenuto di Flash, potete visualizzarla di nuovo selezionando Modifica > Preferenze e scegliendo Schermata di benvenuto dal menu a comparsa All'avvio nella categoria Generali. 2 Nella schermata di benvenuto, fate clic su File Flash (Adobe AIR). Viene visualizzato un messaggio di avviso con le istruzioni per l'accesso alle impostazioni dell'applicazione Adobe AIR e alla Guida in linea. Potete evitare che il messaggio di avviso venga visualizzato in futuro selezionando Non mostrare più. Tenete tuttavia presente che non sarà poi possibile visualizzarlo di nuovo. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 15 Aggiornamento Adobe AIR per Flash CS3 Professional Configurazione delle impostazioni di pubblicazione di Adobe AIR Utilizzate le impostazioni di pubblicazione di Flash per esaminare o modificare le impostazioni dei file AIR e per convertire i documenti File Flash (ActionScript 3.0) in documenti File Flash (Adobe AIR). Visualizzare le impostazioni di pubblicazione di Adobe AIR 1 Dalla schermata di benvenuto di Flash, aprite un documento File Flash (Adobe AIR). 2 Selezionate File > Impostazioni pubblicazione e fate clic sulla scheda Flash per visualizzare le impostazioni di pubblicazione di Adobe AIR. All'apertura di un documento Adobe AIR, Adobe AIR 1.0 viene selezionato automaticamente nel menu Versione. La versione di ActionScript viene impostata automaticamente su ActionScript 3.0. L'impostazione Sicurezza riproduzione locale è disattivata in quanto non è pertinente per i file SWF di AIR. Se avete aperto un file Flash FLA, potete convertirlo in un file Flash AIR modificandone le impostazioni di pubblicazione. Convertire un file Flash FLA in un file Flash AIR mediante la finestra di dialogo Impostazioni pubblicazione 1 Effettuate una delle seguenti operazioni. • Aprite un file FLA esistente. • Utilizzate la schermata di benvenuto oppure selezionate File > Nuovo per creare un file FLA. 2 Selezionate File > Impostazioni pubblicazione. 3 Nella scheda Flash, selezionate Adobe AIR 1.0 dal menu a comparsa Versione. La voce relativa alla versione di ActionScript è disabilitata in quanto ActionScript 3.0 è l'unica opzione possibile per i file AIR. Le altre opzioni predefinite sono uguali sia per i file FLA che per i file Adobe AIR. 4 Fate clic sul pulsante Pubblica e poi su OK per chiudere la finestra di dialogo Impostazioni pubblicazione. Quando scegliete lo strumento Selezione, la finestra di ispezione Proprietà indica che il lettore di destinazione corrente è Adobe AIR 1. Nota: quando scegliete il profilo Adobe AIR 1.0, Flash aggiunge automaticamente la posizione del file AIR playerglobal.swc alla variabile d'ambiente Classpath. Il file AIR playerglobal.swc consente di utilizzare le API AIR di ActionScript. Tuttavia, se passate da Adobe AIR 1 ad Adobe® Flash® Player 9, Flash non torna automaticamente al profilo predefinito né modifica l'impostazione Classpath in modo da fare uso del file playerglobal.swc per Flash Player 9. Se modificate le impostazioni di pubblicazione da Adobe AIR 1 a Flash Player 9, dovete anche impostare il profilo di pubblicazione su Predefinito. Per ulteriori informazioni sulla finestra di dialogo Impostazioni pubblicazione, consultate il manuale Uso di Flash all'indirizzo www.adobe.com/go/learn_fl_using_it. Convertire un file Flash FLA in un'applicazione Flash AIR mediante il menu Comandi 1 Aprite il file Flash FLA. 2 Se state aprendo un nuovo File Flash (ActionScript 3.0), salvatelo. Il mancato salvataggio provoca la visualizzazione di un avviso quando eseguite il passaggio successivo. 3 Selezionate Comandi > AIR - Impostazioni applicazione e programma di installazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 16 Aggiornamento Adobe AIR per Flash CS3 Professional Viene visualizzato un messaggio di avviso che chiede se desiderate convertire il file nelle impostazioni di pubblicazione di Adobe AIR. 4 Fate clic su OK per convertire il file FLA nelle impostazioni di pubblicazione Adobe AIR. Viene visualizzata la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione. Per ulteriori informazioni sulla finestra di dialogo AIR - Impostazioni applicazione e programma di installazione, consultate “Creazione dei file dell'applicazione e del programma di installazione AIR” a pagina 17. Sul file FLA AIR convertito potete usare i comandi Prova filmato, Debug filmato e Crea file AIR. Anteprima di un'applicazione Adobe AIR Potete visualizzare l'anteprima di un file SWF Flash AIR per verificare come apparirà nella finestra dell'applicazione AIR. La funzione di anteprima è utile per visualizzare l'aspetto delle caratteristiche visibili dell'applicazione senza doverla assemblare e installare. 1 Assicuratevi di aver configurato le impostazioni di pubblicazione corrette per un'applicazione Adobe AIR. Per ulteriori informazioni, consultate “Configurazione delle impostazioni di pubblicazione di Adobe AIR” a pagina 15. 2 Selezionate Controllo > Prova filmato o premete Ctrl+Invio. Se non avete configurato le impostazioni dell'applicazione tramite la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione, Flash genera un file descrittore dell'applicazione predefinito (swfnameapp.xml) nella stessa cartella in cui è memorizzato il file SWF. Se invece avete configurato le impostazioni dell'applicazione tramite la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione, il file descrittore riflette tali impostazioni. Debug delle applicazioni Adobe AIR Potete eseguire il debug del file SWF Adobe AIR esattamente come si fa per i file SWF di Flash Player 9 ActionScript 3.0, ad eccezione del debug remoto. 1 Accertatevi di aver configurato le impostazioni di pubblicazione Adobe AIR. 2 Aggiungete il codice ActionScript nel pannello Azioni (Finestra > Azioni). A scopo di prova, potete aggiungere semplicemente un'istruzione trace() come quella riportata di seguito al pannello Azioni, nel primo fotogramma della linea temporale: trace("My application is running"); 3 Selezionate Debug > Debug filmato o premete Ctrl + Maiusc + Invio. Flash avvia il debugger ActionScript ed esporta il file SWF con i dati di debug. Se non avete configurato le impostazioni dell'applicazione tramite la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione, Flash genera un file descrittore dell'applicazione predefinito (swfnameapp.xml) nella stessa cartella in cui è memorizzato il file SWF. Se invece avete configurato le impostazioni dell'applicazione tramite la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione, il file descrittore riflette tali impostazioni. Quando selezionate Debug > Debug filmato o premete Ctrl+Maiusc+Invio per eseguire il debug dell'applicazione, Flash visualizza un avviso nel caso in cui essa non contenga codice ActionScript. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 17 Aggiornamento Adobe AIR per Flash CS3 Professional Creazione dei file dell'applicazione e del programma di installazione AIR Quando l'applicazione è completa, create i file AIR e i file di installazione per distribuirla. Adobe AIR aggiunge due nuove voci al menu Comandi di Flash: IR - Impostazioni applicazione e programma di installazione e AIR - Crea file AIR. Dopo aver definito le impostazioni dell'applicazione AIR e del programma di installazione, potete utilizzare l'opzione AIR - Crea file AIR per ricreare il file AIR (.air) con le impostazioni esistenti. Creare il file del programma di installazione e il file dell'applicazione Adobe AIR 1 In Flash, aprite la pagina o la serie di pagine che compongono l'applicazione Adobe AIR. 2 Salvate il file FLA Adobe AIR prima di aprire la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione. 3 Selezionate Comandi > AIR - Impostazioni applicazione e programma di installazione. 4 Impostate la finestra di dialogo AIR - Impostazioni applicazione e programma di installazione, quindi fate clic su Pubblica file AIR. Quando fate clic sul pulsante Pubblica file AIR, viene creato un pacchetto contenente i seguenti file: il file FLA, il file SWF, il file descrittore dell'applicazione, i file delle icone dell'applicazione e i file elencati nella casella di testo File inclusi. Se non avete ancora creato un certificato digitale, quando fate clic sul pulsante Pubblica file AIR, in Flash viene visualizzata la finestra di dialogo Firma digitale. La finestra di dialogo AIR - Impostazioni applicazione e programma di installazione è suddivisa in due sezioni: Impostazioni applicazione e Impostazioni programma di installazione. Per ulteriori informazioni su queste impostazioni, consultate le sezioni seguenti. Impostazioni applicazione La sezione Impostazioni applicazione della finestra di dialogo AIR - Impostazioni applicazione e programma di installazione comprende le seguenti opzioni: Nome file Nome del file principale dell'applicazione. Per impostazione predefinita, viene indicato il nome del file SWF. Nome Il nome utilizzato dal programma di installazione per generare il nome del file dell'applicazione e la cartella dell'applicazione. Il nome può contenere solo caratteri validi per i nomi di file o di cartella. Il valore predefinito corrisponde al nome del file SWF. Versione Opzionale. Specifica un numero di versione per l'applicazione. Per impostazione predefinita, questo campo è vuoto. ID Identifica l'applicazione con un ID univoco. Se desiderate, l'ID può essere modificato. Non inserite spazi o caratteri speciali nell'ID. Gli unici caratteri validi sono 0-9, a-z, A-Z, . (punto) e - (trattino), con una lunghezza da 1 a 212 caratteri. Il valore predefinito è com.adobe.example.application_name. Descrizione Opzionale. Permette di immettere una descrizione dell'applicazione, da visualizzare durante l'installazione dell'applicazione da parte dell'utente. Per impostazione predefinita, questo campo è vuoto. Copyright Opzionale. Permette di immettere un avviso di copyright, da visualizzare durante l'installazione dell'applicazione da parte dell'utente. Stile finestre Specifica lo stile di visualizzazione (chrome) da utilizzare per l'interfaccia utente quando l'utente esegue l'applicazione sul proprio computer. È possibile specificare Chrome di sistema (stile visivo del sistema operativo), Chrome personalizzato (opaco) o Chrome personalizzato (trasparente). Per visualizzare l'applicazione senza il chrome di sistema, selezionate Nessuno. Con il chrome di sistema, vengono applicati all'applicazione i controlli di interfaccia SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 18 Aggiornamento Adobe AIR per Flash CS3 Professional standard del sistema operativo. Con il chrome personalizzato (opaco), i controlli standard di sistema vengono rimossi ed è possibile creare un aspetto personalizzato per l'interfaccia dell'applicazione. (Il chrome personalizzato deve essere creato direttamente nel file FLA.) Il chrome personalizzato (trasparente) è simile a quello opaco, ma aggiunge la trasparenza ai bordi della pagina, permettendo così di utilizzare finestre dell'applicazione che non sono di forma quadrata o rettangolare. Icona Opzionale. Consente di specificare un'icona per l'applicazione. L'icona viene visualizzata dopo l'installazione dell'applicazione e la sua esecuzione in Adobe AIR. Potete specificare quattro dimensioni differenti per l'icona (128, 48, 32 e 16 pixel) corrispondenti alle diverse viste in cui sarà visualizzata. Ad esempio, l'icona può apparire nel browser di file nelle viste miniatura, dettaglio e affiancata, oppure come icona sul desktop e nel titolo della finestra dell'applicazione AIR, così come in altre posizioni. Se non si specifica alcun file in particolare, l'immagine dell'icona assume per impostazione predefinita l'aspetto dell'icona di esempio delle applicazioni AIR. Per specificare un'icona, fate clic sul pulsante Seleziona immagini icone nella finestra di dialogo AIR - Impostazioni applicazione e programma di installazione. Nella finestra di dialogo Immagini icone che viene visualizzata, fate clic sulla cartella corrispondente a ciascuna dimensione e selezionate il file di icona da utilizzare. I file devono essere in formato PNG (Portable Network Graphics). L'illustrazione seguente mostra la finestra di dialogo Immagini icone con le icone predefinite dell'applicazione Adobe AIR. Impostazione di dimensioni diverse per le immagini delle icone dell'applicazione Se specificate un'immagine, essa deve avere dimensioni esatte (128 x 128, 48 x 48, 32 x 32 oppure 16 x 16). Se per una dimensione dell'icona non specificate alcuna immagine, una delle immagini specificate viene ridimensionata in Adobe AIR per creare l'immagine mancante dell'icona. Impostazioni avanzate Il pulsante Impostazioni della finestra di dialogo AIR - Impostazioni applicazione e programma di installazione consente di specificare impostazioni avanzate relative al file descrittore dell'applicazione. Quando fate clic sul pulsante Impostazioni viene visualizzata la finestra di dialogo Impostazioni avanzate. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 19 Aggiornamento Adobe AIR per Flash CS3 Professional La finestra di dialogo Impostazioni avanzate permette di specificare i tipi di file associati che l'applicazione dovrà elaborare. Ad esempio, se desiderate utilizzare l'applicazione come programma principale per la gestione dei file HTML, questa impostazione deve essere specificata nella casella di testo Tipi di file associati. Potete inoltre definire le impostazioni relative ai seguenti aspetti dell'applicazione: • Le dimensioni e la posizione della finestra iniziale • La cartella in cui deve essere installata l'applicazione • La cartella del menu Programmi in cui inserire l'applicazione La finestra di dialogo contiene le seguenti opzioni: Tipi di file associati Permette di specificare i tipi di file associati che l'applicazione AIR gestirà. Fate clic sul pulsante Più (+) per aggiungere un nuovo tipo di file alla casella di testo dell'applicazione. Quando selezionate questo pulsante, viene visualizzata la finestra di dialogo Impostazioni tipo di file. Il pulsante Meno (-) consente invece di rimuovere una voce selezionata dalla casella di testo. Il pulsante con l'immagine della matita visualizza la finestra di dialogo Impostazioni tipo di file e permette di modificare le impostazioni di una voce selezionata nella casella di testo. Inizialmente, i pulsanti Meno (-) e Matita sono disabilitati. Diventano disponibili quando selezionate una voce nella casella di testo, consentendo così di rimuovere o modificare la voce selezionata. Il valore predefinito della casella di testo è Nessuno. Per ulteriori informazioni sulle impostazioni del tipo di file per i tipi di file associati, consultate “Impostazioni tipo di file” a pagina 20. Impostazioni iniziali finestra Consente di specificare le dimensioni e la posizione della finestra dell'applicazione iniziale. • Larghezza: specifica la larghezza iniziale della finestra in pixel. Per impostazione predefinita, il campo è vuoto. • Altezza: specifica l'altezza iniziale della finestra in pixel. Per impostazione predefinita, il campo è vuoto. • X: la posizione orizzontale iniziale della finestra in pixel. Per impostazione predefinita, il campo è vuoto. • Y: la posizione verticale iniziale della finestra in pixel. Per impostazione predefinita, il campo è vuoto. • Larghezza massima e Altezza massima: le dimensioni massime della finestra, in pixel. Per impostazione predefinita, entrambi i campi sono vuoti. • Larghezza minima e Altezza minima: le dimensioni minime della finestra, in pixel. Per impostazione predefinita, entrambi i campi sono vuoti. • Ingrandibile: permette di specificare se l'utente può ingrandire la finestra. Per impostazione predefinita, questa opzione è selezionata. • Riducibile a icona: permette di specificare se l'utente può ridurre a icona la finestra. Per impostazione predefinita, questa opzione è selezionata. • Ridimensionabile: permette di specificare se l'utente può ridimensionare la finestra. Se questa opzione non è selezionata, le opzioni Larghezza massima, Altezza massima, Larghezza minima e Altezza minima sono disabilitate. Per impostazione predefinita, questa opzione è selezionata. • Visibile: permette di specificare se la finestra dell'applicazione è visibile inizialmente. Per impostazione predefinita, questa opzione è selezionata. Altre impostazioni Permette di specificare le seguenti informazioni aggiuntive relative all'installazione: • Cartella di installazione: la cartella in cui viene installata l'applicazione. • Cartella menu Programmi: il nome della cartella dell'applicazione nel menu Programmi. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 20 Aggiornamento Adobe AIR per Flash CS3 Professional • Interfaccia utente ad aggiornamento automatico: specifica quale azione viene eseguita quando un utente apre un file AIR di un'applicazione che risulta già installata. Per impostazione predefinita, AIR visualizza una finestra di dialogo che permette all'utente di aggiornare la versione installata con la versione del file AIR. Per consentire all'applicazione di gestire autonomamente gli aggiornamenti, anziché permettere all'utente di decidere in merito, selezionate questa opzione. In questo modo il comportamento predefinito non viene applicato e l'applicazione ha il controllo totale degli aggiornamenti. Per ulteriori informazioni sui metodi programmatici di aggiornamento delle applicazioni AIR, consultate “Aggiornamento delle applicazioni AIR” a pagina 332. Impostazioni tipo di file La finestra di dialogo Impostazioni tipo di file viene visualizzata quando fate clic sul pulsante Più (+) o sul pulsante Matita nella finestra di dialogo Impostazioni avanzate per aggiungere o modificare i tipi di file associati all'applicazione. Gli unici due campi obbligatori di questa finestra sono Nome ed Estensione. Se fate clic su OK e uno dei due campi è vuoto, viene visualizzata una finestra di dialogo di errore. Per un tipo di file associato potete specificare le seguenti impostazioni: Nome Il nome del tipo di file (ad esempio, Hypertext Markup Language, File di testo o Esempio). Estensione L'estensione del nome del file (ad esempio html, txt o xmpl); potete utilizzare fino a 39 caratteri alfanumerici standard, [A-Z, a-z, 0-9], senza il punto iniziale. Descrizione Opzionale. Descrizione del tipo di file (ad esempio File video Adobe). Tipo di contenuto Opzionale. Specifica il tipo MIME per il file. Impostazioni icona tipo di file Opzionale. Consente di specificare un'icona associata al tipo di file. Potete specificare quattro dimensioni differenti per l'icona (128x128, 48x48, 32x32 e 16x16 pixel) corrispondenti alle diverse viste in cui sarà visualizzata. Ad esempio, l'icona può apparire nel browser di file nelle viste miniatura, dettaglio e affiancata, Se specificate un'immagine, questa deve essere delle dimensioni che avete impostato. Se non specificate un file per una particolare dimensione, AIR utilizza l'immagine con la dimensione più vicina e la ridimensiona per il tipo non specificato. Per specificare un'icona, fate clic sulla cartella corrispondente alle dimensioni dell'icona e selezionate un file di icona da utilizzare o immettetene il percorso e il nome nella casella di testo accanto al messaggio di richiesta. Il file di icona deve essere in formato PNG. I nuovi tipi di file creati vengono indicati nella casella di riepilogo Tipi di file associati della finestra di dialogo Impostazioni avanzate. Impostazioni del file descrittore dell'applicazione Le impostazioni dell'applicazione specificate vengono salvate nel file nome_applicazione-app.xml. È possibile, tuttavia, indicare a Flash che desiderate utilizzare un file descrittore personalizzato per l'applicazione. Usa file descrittore dell'applicazione personalizzato Consente di selezionare un file descrittore applicazione personalizzato. Se selezionate l'opzione Usa file descrittore applicazione personalizzato, la sezione Impostazioni applicazione della finestra di dialogo viene disabilitata. Per specificare la posizione del file descrittore personalizzato, immettetela nel campo di testo sotto l'opzione Usa file descrittore applicazione personalizzato oppure fate clic sull'icona della cartella e specificate la posizione. Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Creazione di un file descrittore applicazione personalizzato” a pagina 21. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 21 Aggiornamento Adobe AIR per Flash CS3 Professional Impostazioni programma di installazione La seconda sezione della finestra di dialogo AIR - Impostazioni applicazione e programma di installazione contiene le impostazioni relative all'installazione dell'applicazione. Firma digitale Tutte le applicazioni Adobe AIR devono essere firmate per poter essere installate su un altro sistema. Per ulteriori informazioni sull'assegnazione di una firma digitale alle applicazioni Flash Adobe AIR, consultate “Aggiunta di una firma all'applicazione” a pagina 22. Destinazione Specifica il percorso di salvataggio del file AIR. La posizione predefinita è la directory nella quale è stato salvato il file FLA. Per selezionare una posizione diversa, fate clic sull'icona della cartella. Il nome di pacchetto predefinito è il nome dell'applicazione con l'aggiunta dell'estensione .air. File inclusi Specifica i file e le cartelle supplementari da includere nell'applicazione. Fate clic sul pulsante Più (+) per aggiungere dei file e sul pulsante della cartella per aggiungere delle cartelle. Per eliminare un file o una cartella dall'elenco, selezionatelo e fate clic sul pulsante Meno (-). Per impostazione predefinita, il file descrittore dell'applicazione e il file SWF principale vengono aggiunti automaticamente all'elenco del pacchetto. L'elenco del pacchetto mostra questi file anche se il file FLA Adobe AIR non è ancora stato pubblicato. I file e le cartelle sono elencati senza alcuna gerarchia particolare. I file contenuti nelle cartelle non sono compresi nell'elenco, mentre i percorsi completi dei file sono indicati ma, se necessario, troncati. I file di icone non sono inclusi nell'elenco. Quando Flash crea il pacchetto per i file, i file di icone vengono copiati in una cartella temporanea la cui posizione è relativa a quella del file SWF. Una volta terminata la creazione del pacchetto, Flash elimina la cartella. Errore durante la creazione del file dell'applicazione e del file del programma di installazione La creazione dei file dell'applicazione e del programma di installazione non riesce nei seguenti casi. • La stringa dell'ID dell'applicazione ha una lunghezza non corretta o contiene caratteri non validi. La stringa dell'ID può contenere da 1 a 212 caratteri e includere i seguenti caratteri: 0-9, a-z, A-Z, . (punto) e - (trattino). • I file inclusi nell'elenco non esistono. • Le dimensioni dei file di icone personalizzati non sono corrette. • La cartella di destinazione AIR non è accessibile in scrittura. • L'applicazione non è stata firmata oppure non è stato specificato che è un'applicazione Adobe AIRI da firmare successivamente. Creazione di un file descrittore applicazione personalizzato Il file descrittore dell'applicazione è in formato XML e può essere modificato con un editor di testo. Per creare un file descrittore applicazione personalizzato, modificate i valori specificando quelli desiderati. I valori predefiniti sono i seguenti. • id = com.adobe.example.swfname • fileName = swfname • name = swfname SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 22 Aggiornamento Adobe AIR per Flash CS3 Professional • version = 1.0 • description = vuoto • copyright = vuoto • initialWindow • title = nome • content = swfname.swf • systemChrome = standard, type = normal • transparent = false • visible = true • icon • image128x128 = icons/AIRApp_128.png • image48x48 = icons/AIRApp_48.png • image32x32 = icons/AIRApp_32.png • image16x16 = icons/AIRApp_16.png • customUpdateUI = false • allowBrowserInvocation = false Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. Aggiunta di una firma all'applicazione Tutte le applicazioni Adobe AIR devono essere firmate per essere installate in un sistema diverso. Tuttavia, Flash consente di creare file di installazione Adobe AIR senza firma in modo che l'applicazione possa essere firmata in un secondo momento. I file non firmati sono detti pacchetti AIRI. Questa possibilità è utile nei casi in cui il certificato si trova su un computer diverso oppure la firma delle applicazioni viene gestita separatamente rispetto all'attività di sviluppo. Firmare un'applicazione Adobe AIR con un certificato digitale acquistato da un'autorità di certificazione 1 Fate clic sul pulsante Imposta accanto a Firma digitale nella finestra di dialogo AIR - Impostazioni applicazione e programma di installazione. Viene visualizzata la finestra di dialogo Firma digitale. In questa finestra sono disponibili due pulsanti che consentono di firmare l'applicazione Adobe AIR con un certificato digitale oppure di preparare un pacchetto AIRI. Se firmate l'applicazione AIR, potete utilizzare un certificato digitale emesso da un'autorità di certificazione oppure creare un certificato autofirmato. Un certificato autofirmato è facile da creare ma non garantisce lo stesso livello di affidabilità assicurato da un certificato emesso da un'autorità di certificazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 23 Aggiornamento Adobe AIR per Flash CS3 Professional Finestra di dialogo Firma digitale per la firma di un'applicazione AIR 2 Selezionate un file di certificato dal menu a comparsa oppure fate clic sul pulsante Sfoglia per individuarlo. 3 Selezionate il certificato. 4 Immettete una password. 5 Fate clic su OK. Per ulteriori informazioni sulla firma di un'applicazione AIR, consultate “Firma digitale di un file AIR” a pagina 325. Creare un certificato digitale autofirmato 1 Fate clic sul pulsante Crea. Viene visualizzata la finestra di dialogo Crea certificato digitale autofirmato. 2 Impostate le opzioni Nome editore, Unità organizzativa, Nome organizzazione, Paese, Password e Conferma password. 3 Specificate il tipo di certificato. L'opzione Tipo si riferisce al livello di sicurezza del certificato: 1024-RSA utilizza una chiave a 1024 bit (meno sicura), mentre 2048-RSA utilizza una chiave a 2048 bit (più sicura). 4 Salvate le informazioni in un file di certificato specificandolo nel campo Salva con nome o facendo clic sul pulsante Sfoglia per selezionarlo da una cartella. 5 Fate clic su OK. 6 Nella finestra di dialogo Firma digitale, immettete la password assegnata al punto 2 di questa procedura, quindi fate clic su OK. Dopo che avete impostato un certificato digitale, il pulsante Imposta diventa Cambia. Per fare in modo che Flash memorizzi la password utilizzata per la sessione corrente, fate clic su Ricorda la password per questa sessione. Se l'opzione Indicazione data/ora è deselezionata quando fate clic su OK, una finestra di dialogo segnala che l'applicazione non potrà essere installata dopo la scadenza del certificato digitale. Se fate clic s Sì in risposta a questo avviso, l'indicazione data/ora viene disattivata. Se fate clic su No, l'opzione Indicazione data/ora viene selezionata automaticamente e l'aggiunta della data e dell'ora viene così attivata. Per ulteriori informazioni sulla creazione dei certificati digitali autofirmati, consultate “Firma digitale di un file AIR” a pagina 325. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 24 Aggiornamento Adobe AIR per Flash CS3 Professional Potete anche creare un'applicazione AIR Intermediate (AIRI) priva di firma digitale. In questo caso, tuttavia, gli utenti non potranno installare l'applicazione sul desktop finché non viene aggiunta la firma digitale. Preparare un pacchetto AIRI da firmare successivamente ❖ Nella finestra di dialogo Firma digitale, selezionate Prepara un file AIR Intermediate (AIRI) da firmare in seguito, quindi fate clic su OK. Lo stato della firma digitale cambia per indicare che avete scelto di preparare un pacchetto AIRI che verrà firmato in seguito, e il pulsante Imposta diventa Cambia. 25 Capitolo 7: Sicurezza in AIR In questo argomento vengono discussi i problemi relativi alla sicurezza che è opportuno considerare quando sviluppate un'applicazione AIR. Nozioni fondamentali sulla sicurezza in AIR Le applicazioni AIR vengono eseguite con gli stessi privilegi utente delle applicazioni native. In generale, questi privilegi consentono un accesso esteso alle funzioni del sistema operativo, ad esempio leggere e scrivere file, avviare applicazioni, disegnare sullo schermo e comunicare con la rete. Le stesse restrizioni del sistema operativo applicabili alle applicazioni native, ad esempio i privilegi specifici per un utente, vengono applicate alle applicazioni AIR. Sebbene il modello di sicurezza di Adobe® AIR™ costituisca un'evoluzione del modello di sicurezza di Adobe® Flash® Player, il contratto di sicurezza è diverso da quello applicato al contenuto in un browser. Questo contratto offre agli sviluppatori uno strumento sicuro e dotato di funzionalità più ampie, che consentono una maggiore libertà di azione per ottenere risultati che sarebbero inadeguati per un'applicazione basata su browser. Le applicazioni AIR vengono create mediante codice byte compilato (contenuto del file SWF) o uno script interpretato (JavaScript, HTML), in modo che la gestione della memoria venga fornita dal runtime. In tal modo viene ridotta al minimo la possibilità che le applicazioni AIR siano esposte a vulnerabilità correlate alla gestione della memoria, ad esempio overflow del buffer e danneggiamento della memoria. Queste sono solo alcune delle più comuni vulnerabilità che interessano le applicazioni desktop scritte in codice nativo. Installazione e aggiornamenti Le applicazioni AIR sono distribuite tramite i file del programma di installazione di AIR, che hanno l'estensione air. Quando Adobe AIR viene installato e viene aperto un file del programma di installazione di AIR, il processo di installazione viene gestito dal runtime. Nota: gli sviluppatori possono specificare una versione e il nome di un'applicazione, oltre a un'origine di pubblicazione, tuttavia il flusso di lavoro iniziale per l'installazione dell'applicazione non può essere modificato. Questa restrizione presenta dei vantaggi per gli utenti, in quanto tutte le applicazioni AIR condividono una procedura di installazione sicura, ottimizzata e coerente, gestita dal runtime. Se necessario, l'applicazione può essere personalizzata alla prima esecuzione. Percorso di installazione del runtime Le applicazioni AIR richiedono innanzitutto l'installazione del runtime sul computer dell'utente, così come i file SWF richiedono che venga installato per primo il plug-in Flash Player per browser. Il runtime viene installato nel seguente percorso sul computer dell'utente: • Mac OS: /Library/Frameworks/ • Windows: C:\Programmi\File • Linux: /opt/Adobe AIR/ comuni\Adobe AIR SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 26 Sicurezza in AIR In Mac OS, per installare una versione aggiornata di un'applicazione, l'utente deve disporre dei privilegi di sistema appropriati per l'installazione nella directory dell'applicazione. In Windows e Linux, sono richiesti privilegi di amministratore. Il runtime può essere installato in due modi: tramite la funzione di installazione invisibile (direttamente da un browser Web) oppure manualmente. Per ulteriori informazioni, consultate “Distribuzione, installazione ed esecuzione di applicazioni AIR” a pagina 316. Installazione invisibile (runtime e applicazione) La funzione di installazione invisibile consente agli sviluppatori di ottimizzare la procedura di installazione per gli utenti che non hanno ancora installato Adobe AIR. Con il metodo di installazione invisibile, lo sviluppatore crea un file SWF che presenta l'applicazione per l'installazione. Quando un utente fa clic nel file SWF per installare l'applicazione, viene effettuato automaticamente il tentativo di rilevare il runtime. Se il runtime non viene rilevato, viene installato e attivato immediatamente con il processo per l'installazione dell'applicazione dello sviluppatore. Installazione manuale In alternativa, l'utente può scaricare e installare manualmente il runtime prima di aprire un file AIR. Lo sviluppatore può quindi distribuire un file AIR in vari modi (ad esempio, tramite e-mail o utilizzando un collegamento HTML a un sito Web). All'apertura del file AIR, il runtime inizia il processo di installazione dell'applicazione. Per ulteriori informazioni su questo processo, consultate “Distribuzione, installazione ed esecuzione di applicazioni AIR” a pagina 316 Flusso di installazione dell'applicazione Il modello di sicurezza di AIR consente agli utenti di scegliere se installare o meno un'applicazione AIR. La procedura di installazione di AIR presenta diversi miglioramenti rispetto alle tecnologie di installazione dell'applicazione native, che consentono agli utenti di decidere più facilmente se considerare attendibile l'installazione: • Il runtime offre una procedura di installazione coerente per tutti i sistemi operativi, anche quando un'applicazione AIR viene installata da un collegamento in un browser Web. La maggior parte delle procedure di installazione di applicazioni native dipendono dal browser o da altre applicazioni per fornire informazioni sulla sicurezza, ammesso che vengano fornite. • La procedura di installazione dell'applicazione AIR identifica l'origine dell'applicazione e presenta le informazioni sui privilegi disponibili per tale applicazione (se l'utente accetta di continuare l'installazione). • Il runtime gestisce il processo di installazione di un'applicazione AIR, la quale non può modificare il processo di installazione utilizzato dal runtime. In generale, gli utenti non dovrebbero installare una qualsiasi applicazione desktop proveniente da un'origine che non considerano attendibile o che non può essere verificata. Il problema della prova di attendibilità ai fini della sicurezza per le applicazioni native è altrettanto importante per le applicazioni AIR, come per qualsiasi altra applicazione installabile. Destinazione dell'applicazione La directory di installazione può essere impostata utilizzando una delle due opzioni riportate di seguito: 1 L'utente personalizza la destinazione durante l'installazione. L'applicazione viene installata nella directory specificata dall'utente. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 27 Sicurezza in AIR 2 Se l'utente non modifica la destinazione di installazione, l'applicazione viene installata nel percorso predefinito, determinato dal runtime: • Mac OS: ~/Applicazioni/ • Windows XP e versioni precedenti: C:\Programmi\ • Windows Vista: ~/Apps/ • Linux: /opt/ Se lo sviluppatore specifica un'impostazione installFolder nel file descrittore dell'applicazione, l'applicazione viene installata in un sottopercorso di questa directory. Il file system di AIR Il processo di installazione per le applicazioni AIR copia tutti i file che lo sviluppatore ha incluso nel file del programma di installazione di AIR nel computer locale dell'utente. L'applicazione installata è costituita dai seguenti elementi: • Windows: una directory contenente tutti i file inclusi nel file del programma di installazione di AIR. Durante l'installazione dell'applicazione AIR, il runtime crea anche un file exe. • Linux: directory contenente tutti i file inclusi nel file del programma di installazione di AIR. Durante l'installazione dell'applicazione AIR, il runtime crea anche un file bin. • Mac OS: un file app che contiene tutto il contenuto incluso nel file del programma di installazione di AIR. Il contenuto può essere verificato utilizzando l'opzione per la visualizzazione del contenuto del pacchetto nel Finder. Il runtime crea questo file app durante l'installazione dell'applicazione AIR. Un'applicazione AIR viene eseguita mediante: • Windows: esecuzione del file .exe presente nella cartella di installazione, oppure un collegamento corrispondente a questo file (ad esempio un collegamento nel menu Start Menu o sul desktop). • Linux: esecuzione del file .bin presente nella cartella di installazione, scelta dell'applicazione dal menu Applications (Applicazioni) o esecuzione da un alias o un collegamento sul desktop. • Mac OS: esecuzione del file .app o di un alias che punta a tale file. Il file system dell'applicazione comprende anche alcune sottodirectory correlate alla funzione dell'applicazione. Le informazioni scritte, ad esempio, nell'area di memorizzazione locale crittografata vengono salvate in una sottodirectory di una directory il cui nome corrisponde all'identificatore dell'applicazione. Directory di memorizzazione di AIR Le applicazioni AIR dispongono dei privilegi di scrittura in qualsiasi posizione sul disco rigido dell'utente; tuttavia, si consiglia agli sviluppatori di utilizzare il percorso app-storage:/ per la memorizzazione locale delle loro applicazioni. I file scritti in app-storage:/ da un'applicazione vengono inseriti in un percorso standard che dipende dal sistema operativo dell'utente: • In Mac OS: la directory di memorizzazione di un'applicazione è <appData>/<appId>/Local Store/ dove <appData> è la “cartella delle preferenze” dell'utente, in genere /Users/<NomeUtente>/Library/Preferences • In Windows: la directory di memorizzazione di un'applicazione è <appData>\<appId>\Local Store\ dove <appData> è la “cartella speciale CSIDL_APPDATA dell'utente, in genere C:\Documents and Settings\<NomeUtente>\Dati applicazioni • In Linux: <appData>/<appID>/Local Store/dove <appData> è /home/<NomeUtente>/.appdata SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 28 Sicurezza in AIR Potete accedere alla directory di memorizzazione dell'applicazione tramite la proprietà air.File.applicationStorageDirectory. Per accedere al suo contenuto, potete utilizzare il metodo resolvePath() della classe File. Per maggiori dettagli, consultate “Operazioni con il file system” a pagina 108. Aggiornamento di Adobe AIR Quando un utente installa un'applicazione AIR che richiede una versione aggiornata del runtime, il runtime stesso installa automaticamente l'aggiornamento richiesto. Per aggiornare il runtime, l'utente deve disporre dei privilegi amministrativi per il computer in uso. Aggiornamento di applicazioni AIR Lo sviluppo e la distribuzione degli aggiornamenti software costituiscono una delle principali problematiche di sicurezza relative alle applicazioni basate su codice nativo. L'API AIR fornisce un meccanismo per migliorare questo aspetto: il metodo Updater.update() che può essere richiamato all'avvio per effettuare il controllo della posizione remota di un file AIR. Se l'aggiornamento è appropriato, il file AIR viene scaricato e installato e l'applicazione riavviata. Gli sviluppatori possono usare questa classe non solo per fornire nuove funzionalità, ma anche per risolvere le potenziali vulnerabilità di sicurezza. Nota: gli sviluppatori possono specificare la versione di un'applicazione impostando la proprietà version del file del descrittore dell'applicazione. AIR non è in grado di interpretare in alcun modo la stringa relativa alla versione. Di conseguenza, la versione “3.0” non viene considerata più recente della versione “2.0”. È quindi compito dello sviluppatore gestire in modo significativo il controllo delle versioni. Per maggiori dettagli, consultate “Definizione delle proprietà nel file descrittore dell'applicazione” a pagina 47. Disinstallazione di un'applicazione AIR L'utente può disinstallare un'applicazione AIR nel modo seguente: • In Windows: utilizzando Installazione applicazioni nel Pannello di controllo per rimuovere l'applicazione. • In Mac OS: eliminando il file app dal percorso di installazione. La rimozione di un'applicazione AIR comporta la rimozione di tutti i file presenti nella directory dell'applicazione. Tuttavia, non vengono rimossi i file eventualmente scritti dall'applicazione all'esterno della propria directory. La rimozione di applicazioni AIR non comporta l'annullamento delle modifiche apportate dall'applicazione AIR ai file al di fuori della directory dell'applicazione. Disinstallazione di Adobe AIR AIR può essere disinstallato nel modo seguente: • In Windows: utilizzando Installazione applicazioni nel Pannello di controllo, selezionando Adobe AIR, quindi Rimuovi. • In Mac OS: eseguendo il programma di disinstallazione di Adobe AIR presente nella directory Applications. Impostazioni del registro di sistema di Windows per gli amministratori In Windows, gli amministratori possono configurare un computer in modo da impedire (o consentire) l'installazione di applicazioni AIR e gli aggiornamenti del runtime. Queste impostazioni sono contenute nella chiave seguente del Registro di sistema di Windows: HKLM\Software\Policies\Adobe\AIR. Tali impostazioni includono: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 29 Sicurezza in AIR Impostazione del Registro di sistema Descrizione AppInstallDisabled Specifica che l'installazione e la disinstallazione dell'applicazione AIR sono consentite. Impostate su 0 per “consentire” o su 1 per “non consentire”. UntrustedAppInstallDisabled Specifica che l'installazione di applicazioni AIR non attendibili (le applicazioni che non includono un certificato attendibile) è consentita (consultate “Firma digitale di un file AIR” a pagina 325). Impostate su 0 per “consentire” o su 1 per “non consentire”. UpdateDisabled Specifica che l'aggiornamento del runtime è consentito, sia come attività in background che mediante un'installazione esplicita. Impostate su 0 per “consentire” o su 1 per “non consentire”. Funzioni di sicurezza sandbox AIR include un'architettura di sicurezza completa che definisce di conseguenza le autorizzazioni per ogni file di un'applicazione AIR, sia interno che esterno. Le autorizzazioni sono concesse ai file in base alla loro origine e vengono assegnate in raggruppamenti di sicurezza logici definiti sandbox. Informazioni sulle funzioni di sicurezza sandbox dell'applicazione AIR Il modello di sicurezza delle sandbox di runtime è costituito dal modello di sicurezza di Flash Player con l'aggiunta della sandbox dell'applicazione. I file che non sono contenuti nella sandbox dell'applicazione presentano restrizioni di sicurezza analoghe a quelle specificate dal modello di sicurezza di Flash Player. Il runtime utilizza queste sandbox di sicurezza per definire la gamma di dati a cui il codice può accedere e le operazioni che può eseguire. Per mantenere la sicurezza locale, i file contenuti in ogni sandbox sono isolati da quelli di altre sandbox. Un file SWF caricato, ad esempio, in un'applicazione AIR da un URL Internet esterno viene inserito in una sandbox remota e, per impostazione predefinita, non dispone dell'autorizzazione di inserire script nei file che risiedono nella directory dell'applicazione, che sono assegnati alla sandbox dell'applicazione. Nella seguente tabella è descritto ogni tipo di sandbox: Sandbox Descrizione application (applicazione) Il file risiede nella directory dell'applicazione e dispone dell'intero set di privilegi di AIR. remote (remota) Il file ha origine da un URL Internet e viene gestito tramite regole sandbox basate su dominio analoghe a quelle che applicate ai file remoti in Flash Player. (Sono disponibili sandbox remote separate per ogni dominio di rete, ad esempio http://www.example.com e https://foo.example.org). local-trusted (locale attendibile) Il file è un file locale che è stato considerato attendibile dall'utente tramite Gestione impostazioni o il file di configurazione Flash Player Trust. Può leggere le origini dati locali e comunicare con Internet, ma non dispone dell'intero set di privilegi di AIR. local-with-networking (locale con rete) Il file è un file SWF locale pubblicato con una designazione di rete, ma che non è stato considerato esplicitamente attendibile dall'utente. Il file può comunicare con Internet ma non può leggere da origini dati locali. Questa sandbox è disponibile solo per il contenuto SWF. local-with-filesystem (locale con Il file è un file di script locale che non è stato pubblicato con una designazione di rete, né considerato file system) esplicitamente attendibile dall'utente. Sono inclusi i file JavaScript che non sono stati considerati attendibili. Il file può leggere le origini dati locali, ma non può comunicare con Internet. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 30 Sicurezza in AIR Questo argomento è incentrato soprattutto sulla sandbox dell'applicazione e sulle sue relazioni con altre sandbox nell'applicazione AIR. Agli sviluppatori che utilizzano contenuto assegnato ad altre sandbox si consiglia di consultare l'ulteriore documentazione sul modello di sicurezza di Flash Player. Vedere il capitolo “Sicurezza di Flash Player” in Programmazione in ActionScript 3.0 (http://www.adobe.com/go/flashcs4_prog_as3_security_it) e il white paper sulla sicurezza di Flash Player 9 (http://www.adobe.com/go/fp9_0_security_it) o il white paper sulla sicurezza di Flash Player 10 (http://www.adobe.com/go/fp10_0_security_it). La funzione di sicurezza sandbox dell'applicazione Durante l'installazione di un'applicazione, tutti i file inclusi in un file del programma di installazione di AIR vengono installati sul computer dell'utente in una directory dell'applicazione. Gli sviluppatori possono fare riferimento a questa directory nel codice utilizzando lo schema URL app:/ (consultate “Uso di schermi URL AIR negli URL” a pagina 310). Tutti i file presenti nella struttura di directory dell'applicazione vengono assegnati alla sandbox dell'applicazione al momento dell'esecuzione dell'applicazione. Al contenuto presente nella sandbox dell'applicazione sono concessi tutti i privilegi disponibili per un'applicazione AIR, compresa l'interazione con il file system locale. Molte applicazioni AIR utilizzano solo questi file installati localmente per la loro esecuzione. Tuttavia, le applicazioni AIR non sono limitate solo ai file contenuti nella directory dell'applicazione; infatti possono caricare qualsiasi tipo di file da qualsiasi origine, inclusi i file locali presenti nel computer dell'utente e i file dalle origini esterne disponibili, ad esempio quelli su una rete locale o su Internet. Il tipo di file non influisce delle restrizioni di sicurezza; i file HTML caricati dispongono degli stessi privilegi di sicurezza dei file SWF caricati dalla stessa origine. Il contenuto nella sandbox di sicurezza dell'applicazione dispone dell'accesso alle API AIR, il cui uso è invece impedito al contenuto di altre sandbox. La proprietà air.NativeApplication.nativeApplication.applicationDescriptor, ad esempio, che restituisce il contenuto del file del descrittore dell'applicazione per l'applicazione, è limitata al contenuto presente nella sandbox di sicurezza dell'applicazione. Un altro esempio di API con restrizioni è costituito dalla classe FileStream, che contiene i metodi per la lettura e la scrittura nel file system locale. Le API ActionScript disponibili solo per il contenuto presente nella sandbox di sicurezza dell'applicazione sono contrassegnate del logo AIR nella Guida di riferimento del linguaggio ActionScript 3.0 per Adobe AIR. L'uso di queste API in altre sandbox comporta la generazione di un'eccezione SecurityError da parte del runtime. Per il contenuto HTML (in un oggetto HTMLLoader), tutte le API JavaScript AIR (quelle disponibili tramite la proprietà window.runtime o l'oggetto air quando utilizzate il file AIRAliases.js) sono disponibili per il contenuto presente nella sandbox di sicurezza dell'applicazione. Il contenuto HTML in un'altra sandbox non dispone dell'accesso alla proprietà window.runtime, quindi non può accedere alle API AIR. Restrizioni relative a JavaScript e HTML Per il contenuto HTML presente nella sandbox di sicurezza dell'applicazione, sono presenti limitazioni all'uso di API che possono trasformare dinamicamente delle stringhe in codice eseguibile dopo il caricamento del codice. Questa limitazione ha lo scopo di impedire che l'applicazione introduca inavvertitamente, ed esegua, codice da origini non dell'applicazione (ad esempio domini di rete potenzialmente non sicuri). Un esempio è costituito dall'uso della funzione eval(). Per maggiori dettagli, consultate “Restrizioni relative al codice per il contenuto presente in diverse sandbox” a pagina 34. Restrizioni relative ai tag img presenti nel contenuto dei campi di testo di ActionScript Per impedire possibili attacchi mediante phishing, i tag img nel contenuto HTML degli oggetti TextField di ActionScript vengono ignorati nel contenuto SWF presente nella sandbox di sicurezza dell'applicazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 31 Sicurezza in AIR Restrizioni relative ad asfunction Al contenuto nella sandbox dell'applicazione non è consentito utilizzare il protocollo asfunction nel contenuto HTML presente nei campi di testo di ActionScript 2.0. Accesso non consentito alla cache persistente tra domini Al contenuto SWF nella sandbox dell'applicazione non è consentito utilizzare la cache tra domini, una funzione aggiunta a Flash Player 9 Aggiornamento 3. Questa funzione consente a Flash Player di memorizzare nella cache in modo persistente il contenuto dei componenti della piattaforma Adobe e di riutilizzarlo nel contenuto SWF caricato su richiesta (eliminando la necessità di ricaricare il contenuto più volte). Privilegi del contenuto presente in sandbox non dell'applicazione I file caricati da una rete o da Internet sono assegnati alla sandbox remote. I file caricati da un'origine esterna alla directory dell'applicazione sono assegnati alla sandbox local-with-filesystem, local-with-networking o local-trusted; la scelta della sandbox dipende dal modo in cui il file è stato creato e se l'utente ha esplicitamente indicato il file come attendibile tramite il pannello relativo alle impostazioni globali di Gestione impostazioni di Flash Player. Per maggiori dettagli, visitate http://www.macromedia.com/support/documentation/it/flashplayer/help/settings_manager.html. Restrizioni relative a JavaScript e HTML A differenza del contenuto presente nella sandbox di sicurezza dell'applicazione, al contenuto JavaScript in una sandbox di sicurezza non dell'applicazione è consentito chiamare la funzione eval() per eseguire il codice generato dinamicamente in qualsiasi momento. Tuttavia, sono presenti restrizioni relative a JavaScript in una sandbox di sicurezza non dell'applicazione, vale a dire: • Il codice JavaScript HTML in una sandbox non dell'applicazione non dispone dell'accesso all'oggetto window.runtime, pertanto questo codice non può eseguire le API AIR. • Per impostazione predefinita, al contenuto di una sandbox di sicurezza non dell'applicazione non è consentito utilizzare chiamate a XMLHttpRequest per caricare i dati da domini diversi da quello da cui ha origine la chiamata di richiesta. Tuttavia, il codice dell'applicazione può concedere tale autorizzazione al contenuto non dell'applicazione mediante l'impostazione dell'attributo allowCrossdomainXHR nel frame o iframe che lo contiene. Per ulteriori informazioni, consultate “Creazione di script tra contenuti in diversi domini” a pagina 37. • Sono presenti restrizioni relative alla chiamata al metodo JavaScript window.open(). Per maggiori dettagli, consultate “Restrizioni relative alla chiamata al metodo JavaScript window.open()” a pagina 37. Per maggiori dettagli, consultate “Restrizioni relative al codice per il contenuto presente in diverse sandbox” a pagina 34. Restrizioni relative al caricamento di elementi CSS, frame, iframe e img Al contenuto HTML nelle sandbox di sicurezza (di rete) remote è consentito caricare solo contenuto CSS, frame, iframe e img da domini remoti (da URL di rete). Al contenuto HTML nella sandbox di sicurezza local-with-filesystem, local-with-networking o local-trusted è consentito caricare solo contenuto CSS, frame, iframe e img da sandbox locali (non da URL dell'applicazione o di rete). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 32 Sicurezza in AIR Sicurezza in HTML Il runtime applica le regole a fornisce i meccanismi per superare le eventuali vulnerabilità di sicurezza in HTML e JavaScript. Vengono applicate le stesse regole, sia che la vostra applicazione sia scritta principalmente in JavaScript o se caricate il contenuto HTML e JavaScript in un'applicazione basata su SWF. Il contenuto nella sandbox dell'applicazione e quello nella sandbox di sicurezza non dell'applicazione (consultate “Funzioni di sicurezza sandbox” a pagina 29) hanno privilegi diversi. Quando carica del contenuto in un iframe o in un frame, il runtime fornisce un meccanismo di bridge sandbox protetto che consente al contenuto del frame o dell'iframe di comunicare in modo sicuro con il contenuto presente nella sandbox di sicurezza dell'applicazione. In questo argomento viene descritta l'architettura di sicurezza del contenuto HTML in AIR e come utilizzare gli iframe, i frame e il bridge sandbox per configurare la vostra applicazione. Per ulteriori informazioni, consultate “Errori JavaScript relativi alla sicurezza da evitare” a pagina 238. Panoramica della configurazione di un'applicazione basata su HTML I frame e gli iframe costituiscono una struttura pratica per organizzare il contenuto HTML in AIR. I frame consentono di mantenere la persistenza dei dati e utilizzare in modo sicuro il contenuto remoto. Poiché il contenuto HTML in AIR mantiene la propria normale organizzazione basata su pagine, l'ambiente HTML viene completamente aggiornato se il frame superiore del contenuto HTML “passa” a una pagina diversa. Potete usare frame e iframe per mantenere la persistenza dei dati in AIR, così come fareste per un'applicazione Web in esecuzione in un browser. Potete definire gli oggetti principali dell'applicazione nel frame superiore, che rimarranno persistenti finché non consentirete al frame di passare a una nuova pagina. Utilizzate frame o iframe secondari per caricare e visualizzare le parti non persistenti dell'applicazione. (Vi sono molti modi per mantenere la persistenza dei dati che potete usare insieme o al posto dei frame, ad esempio cookie, oggetti condivisi locali, memorizzazione locale dei file e memorizzazione locale del database). Poiché nel contenuto HTML in AIR viene mantenuta la normale riga sfocata tra il codice eseguibile e i dati, in AIR il contenuto viene inserito nel frame superiore dell'ambiente HTML, nella sandbox dell'applicazione. Dopo l'evento load della pagina, viene limitata qualsiasi operazione, ad esempio eval(), che possa convertire una stringa di testo in un oggetto eseguibile. Questa restrizione viene applicata anche quando un'applicazione non carica contenuto remoto. Per consentire al contenuto HTML di eseguire queste operazioni con restrizioni, dovete utilizzare frame o iframe per inserire contenuto in una sandbox non di applicazione. L'esecuzione di contenuto in un frame secondario inserito in una sandbox può risultare necessario quando usate alcune strutture di applicazioni JavaScript che si basano sulla funzione eval(). Per un elenco completo di restrizioni relative a JavaScript nella sandbox dell'applicazione, consultate “Restrizioni relative al codice per il contenuto presente in diverse sandbox” a pagina 34. Poiché il contenuto HTML in AIR mantiene la capacità di caricare contenuto remoto e possibilmente non sicuro, in AIR viene applicato un criterio basato sulla stessa origine, che impedisce al contenuto presente in un dominio di interagire con il contenuto in un altro dominio. Per consentire l'interazione tra il contenuto dell'applicazione e il contenuto in un altro dominio, potete configurare un bridge che funga da interfaccia tra un frame principale e un frame secondario. Impostazione di una relazione principale-secondaria tra sandbox In AIR vengono aggiunti gli attributi sandboxRoot e documentRoot agli elementi frame e iframe HTML. Questi attributi consentono di considerare il contenuto dell'applicazione come se provenisse da un altro dominio: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 33 Sicurezza in AIR Attributo Descrizione sandboxRoot URL da usare per determinare la sandbox e il dominio in cui inserire il contenuto del frame. Dovete usare lo schema URL file:, http: o https:. documentRoot URL da cui caricare il contenuto del frame. Dovete usare lo schema URL file:, app:, o app-storage:. Nell'esempio seguente, il contenuto installato nella sottodirectory della sandbox dell'applicazione viene mappato in modo che sia eseguito nella sandbox remota e nel dominio www.example.com: <iframe src="ui.html" sandboxRoot="http://www.example.com/local/" documentRoot="app:/sandbox/"> </iframe> Impostazione di un bridge tra frame principali e secondari in sandbox o domini diversi In AIR vengono aggiunte le proprietà childSandboxBridge e parentSandboxBridge all'oggetto window di qualsiasi frame secondario. Queste proprietà consentono di definire i bridge che fungono da interfaccia tra un frame principale e uno secondario. Ogni bridge è unidirezionale: childSandboxBridge: la proprietà childSandboxBridge consente al frame secondario di esporre un'interfaccia per il contenuto del frame principale. Per esporre un'interfaccia, impostate la proprietà childSandbox su una funzione o un oggetto nel frame secondario. Potete quindi accedere all'oggetto o alla funzione dal contenuto nel frame principale. Nell'esempio seguente viene illustrato il modo in cui uno script in esecuzione in un frame secondario possa esporre un oggetto contenente una funzione e una proprietà al relativo frame principale: var interface = {}; interface.calculatePrice = function(){ return .45 + 1.20; } interface.storeID = "abc" window.childSandboxBridge = interface; Se questo primo contenuto secondario si trova in un iframe a cui è assegnato un id"child", potete accedere all'interfaccia dal contenuto principale mediante la lettura della proprietà childSandboxBridge del frame: var childInterface = document.getElementById("child").childSandboxBridge; air.trace(childInterface.calculatePrice()); //traces "1.65" air.trace(childInterface.storeID)); //traces "abc" parentSandboxBridge : la proprietà parentSandboxBridge consente al frame principale di esporre un'interfaccia per il contenuto del frame secondario. Per esporre un'interfaccia, impostate la proprietà parentSandbox del frame secondario su una funzione o un oggetto nel frame principale. Potete quindi accedere all'oggetto o alla funzione dal contenuto nel frame secondario. Nell'esempio seguente viene illustrato il modo in cui uno script in esecuzione nel frame principale può esporre un oggetto contenente una funzione save a un frame secondario: var interface = {}; interface.save = function(text){ var saveFile = air.File("app-storage:/save.txt"); //write text to file } document.getElementById("child").parentSandboxBridge = interface; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 34 Sicurezza in AIR Usando questa interfaccia, il contenuto nel frame secondario potrebbe salvare del testo in un file di nome save.txt. Tuttavia, non disporrebbe di alcun altro tipo di accesso al file system. In generale, il contenuto dell'applicazione dovrebbe esporre l'interfaccia più limitata possibile alle altre sandbox. Il contenuto secondario potrebbe inviare una chiamata alla funzione save, come riportato di seguito: var textToSave = "A string."; window.parentSandboxBridge.save(textToSave); Se il contenuto secondario tenta di impostare una proprietà dell'oggetto parentSandboxBridge, il runtime genera un'eccezione SecurityError. Se il contenuto principale tenta di impostare una proprietà dell'oggetto childSandboxBridge, il runtime genera un'eccezione SecurityError. Restrizioni relative al codice per il contenuto presente in diverse sandbox Come illustrato nell'introduzione di questo argomento, “Sicurezza in HTML” a pagina 32, il runtime applica le regole a fornisce i meccanismi per superare le eventuali vulnerabilità di sicurezza in HTML e JavaScript. In questo argomento sono elencate tali restrizioni. Se il codice tenta di chiamare queste API con restrizioni, il runtime genera un errore con un messaggio in cui è indicato che si è verificata una violazione della sicurezza del runtime di Adobe AIR per il codice JavaScript nella sandbox di sicurezza dell'applicazione. Per ulteriori informazioni, consultate “Errori JavaScript relativi alla sicurezza da evitare” a pagina 238. Restrizioni all'uso della funzione JavaScript eval()e tecniche simili Per il contenuto HTML presente nella sandbox di sicurezza dell'applicazione, sono presenti limitazioni all'uso di API che possono trasformare dinamicamente delle stringhe in codice eseguibile dopo il caricamento del codice (dopo l'invio dell'evento onload dell'elemento body e al termine dell'esecuzione della funzione del gestore onload). Questa limitazione ha lo scopo di impedire che l'applicazione introduca inavvertitamente, ed esegua, codice da origini non dell'applicazione (ad esempio domini di rete potenzialmente non sicuri). Se, ad esempio, nella vostra applicazione usate dati in formato stringa da un'origine remota per scrivere nella proprietà innerHTML di un elemento DOM, la stringa potrebbe includere codice (JavaScript) eseguibile che può eseguire operazioni non sicure. Durante il caricamento del contenuto, tuttavia, non vi è alcun rischio di inserire stringhe remote nell'elemento DOM. Una restrizione riguarda l'uso della funzione JavaScript eval(). Una volta caricato il codice nella sandbox dell'applicazione e dopo l'elaborazione del gestore di eventi onload, potete usare la funzione eval() solo in modo limitato. Le seguenti regole si applicano all'uso della funzione eval()dopo il caricamento del codice dalla sandbox di sicurezza dell'applicazione: • Le espressioni che comportano valori letterali sono consentite. Ad esempio: eval("null"); eval("3 + .14"); eval("'foo'"); • I valori letterali oggetto sono consentiti, come nel seguente esempio: { prop1: val1, prop2: val2 } • I setter/getter dei valori letterali oggetto non sono consentiti, come nell'esempio seguente: { get prop1() { ... }, set prop1(v) { ... } } • I valori letterali di array sono consentiti, come nell'esempio seguente: [ val1, val2, val3 ] • Le espressioni che comportano letture di proprietà non sono consentite, come nell'esempio seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 35 Sicurezza in AIR a.b.c • La chiamata di funzione non è consentita. • Le definizioni di funzione non sono consentite. • L'impostazione di una qualsiasi proprietà non è consentita. • I valori letterali di funzione non sono consentiti. Tuttavia, durante il caricamento del codice, prima dell'evento onload e durante l'esecuzione della funzione del gestore di eventi onload, queste restrizioni non si applicano al contenuto presente nella sandbox di sicurezza dell'applicazione. Dopo il caricamento del codice, ad esempio, il codice riportato di seguito causa la generazione di un'eccezione da parte del runtime: eval("alert(44)"); eval("myFunction(44)"); eval("NativeApplication.applicationID"); Il codice generato dinamicamente, come quello risultante dalla chiamata alla funzione eval(), rappresenta un rischio per la sicurezza qualora fosse consentito all'interno della sandbox dell'applicazione. Un'applicazione, ad esempio, potrebbe inavvertitamente eseguire una stringa caricata da un dominio di rete e quella stringa potrebbe contenere codice dannoso. Questo codice potrebbe, ad esempio, eliminare o modificare dei file nel computer dell'utente. Potrebbe, in alternativa, trattarsi di codice che riporta il contenuto di un file locale a un dominio di rete non attendibile. Di seguito sono elencati i metodi per generare codice dinamico: • Chiamata alla funzione eval(). • Uso delle proprietà innerHTML o di funzioni DOM per inserire tag script che caricano uno script all'esterno della directory dell'applicazione. • Uso delle proprietà innerHTML o di funzioni DOM per inserire tag script che caricano uno script all'esterno della directory dell'applicazione. • Impostazione dell'attributo src per i tag script per caricare un file JavaScript che si trova all'esterno della directory dell'applicazione. • Uso dello schema URL javascript (come in href="javascript:alert('Test')"). • Uso della funzione setInterval() o setTimout()dove il primo parametro (che definisce il funzionamento asincrono della funzione) è una stringa (da valutare) anziché il nome di una funzione (come in setTimeout('x = 4', 1000)). • Chiamata a document.write() o document.writeln(). Il codice nella sandbox di sicurezza dell'applicazione può chiamare questi metodi solo durante il caricamento del contenuto. Queste restrizioni non impediscono l'uso di eval() con i valori letterali JSON, in modo il contenuto della vostra applicazione possa interagire con la libreria JavaScript JSON . Tuttavia, non potete utilizzare codice JSON overloaded (con gestori di eventi). Per altre strutture Ajax e librerie di codice JavaScript, verificate se il codice nella struttura o nella libreria funziona in base a queste restrizioni sul codice generato dinamicamente. In caso contrario, includete il contenuto che utilizza la struttura o la libreria in una sandbox di sicurezza non dell'applicazione. Per maggiori dettagli, consultate “Privilegi del contenuto presente in sandbox non dell'applicazione” a pagina 31 e “Creazione di script tra contenuto dell'applicazione e non dell'applicazione” a pagina 42. Adobe rende disponibile un elenco di strutture Ajax che notoriamente supportano la sandbox di sicurezza dell'applicazione all'indirizzo http://www.adobe.com/it/products/air/develop/ajax/features/. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 36 Sicurezza in AIR A differenza del contenuto presente nella sandbox di sicurezza dell'applicazione, al contenuto JavaScript in una sandbox di sicurezza non dell'applicazione è consentito chiamare la funzione eval() per eseguire il codice generato dinamicamente in qualsiasi momento. Restrizioni relative all'accesso alle API AIR (per sandbox non dell'applicazione) Il codice JavaScript HTML in una sandbox non dell'applicazione non dispone dell'accesso all'oggetto window.runtime, pertanto questo codice non può eseguire le API AIR. Se il contenuto in una sandbox di sicurezza non dell'applicazione chiama il seguente codice, l'applicazione genera un'eccezione TypeError: try { window.runtime.flash.system.NativeApplication.nativeApplication.exit(); } catch (e) { alert(e); } Il tipo di eccezione è TypeError (valore undefined), in quanto il contenuto nella sandbox non dell'applicazione non riconosce l'oggetto window.runtime, quindi viene visto come un valore undefined. Potete esporre la funzionalità runtime per il contenuto presente in una sandbox non dell'applicazione utilizzando un bridge script. Per maggiori dettagli, consultate “Creazione di script tra contenuto dell'applicazione e non dell'applicazione” a pagina 42. Restrizioni all'uso di chiamate a XMLHttpRequest Al contenuto HTML nella sandbox di sicurezza dell'applicazione non è consentito utilizzare metodi XMLHttpRequest sincroni per caricare dati dall'esterno della sandbox dell'applicazione durante il caricamento del contenuto HTML e durante l'evento onLoad. Per impostazione predefinita, al contenuto delle sandbox di sicurezza non dell'applicazione non è consentito utilizzare l'oggetto JavaScript XMLHttpRequest per caricare i dati da domini diversi da quello da cui ha origine la chiamata di richiesta. Un tag frame o iframe può includere un attributo allowcrosscomainxhr. L'impostazione di questo attributo su qualsiasi valore non null consente al contenuto presente nel frame o nell'iframe di utilizzare l'oggetto XMLHttpRequest JavaScript per caricare i dati da domini diversi da quello del codice da cui ha origine la chiamata di richiesta: <iframe id="UI" src="http://example.com/ui.html" sandboxRoot="http://example.com/" allowcrossDomainxhr="true" documentRoot="app:/"> </iframe> Per ulteriori informazioni, consultate “Creazione di script tra contenuti in diversi domini” a pagina 37. Restrizioni relative al caricamento di elementi CSS, frame, iframe e img (per il contenuto presente nelle sandbox non dell'applicazione) Al contenuto HTML nelle sandbox di sicurezza (di rete) remote è consentito caricare solo contenuto CSS, frame, iframe e img da sandbox remote (da URL di rete). Al contenuto HTML nella sandbox di sicurezza local-with-filesystem, local-with-networking o local-trusted è consentito caricare solo contenuto CSS, frame, iframe e img da sandbox locali (non da sandbox dell'applicazione o remote). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 37 Sicurezza in AIR Restrizioni relative alla chiamata al metodo JavaScript window.open() Se in una finestra creata tramite una chiamata al metodo JavaScript window.open() viene visualizzato il contenuto da una sandbox di sicurezza non dell'applicazione, il titolo della finestra inizia con il titolo della finestra principale (di avvio) seguito da un carattere due punti. Non potete usare il codice per spostare quella parte del titolo della finestra fuori dallo schermo. Il contenuto presente nelle sandbox di sicurezza non dell'applicazione può chiamare in modo corretto solo il metodo JavaScript window.open() in risposta a un evento attivato da un'interazione dell'utente mediante il mouse o la tastiera. In questo modo viene impedito al contenuto non dell'applicazione di creare finestre che potrebbero essere utilizzate in modo ingannevole, ad esempio per attacchi mediante phishing. Inoltre, il gestore eventi per l'evento del mouse o della tastiera non può impostare il metodo window.open() affinché venga eseguito dopo un determinato ritardo (ad esempio chiamando la funzione setTimeout()). Il contenuto presente nelle sandbox (di rete) remote può usare il metodo window.open() solo per aprire il contenuto di sandbox di rete remote. Non può invece usare il metodo window.open() per aprire contenuto da sandbox dell'applicazione o locali. Il contenuto nelle sandbox local-with-filesystem, local-with-networking o local-trusted (consultate “Funzioni di sicurezza sandbox” a pagina 29) può usare il metodo window.open() solo per aprire il contenuto in sandbox locali. Non può invece usare il metodo window.open() per aprire contenuto da sandbox dell'applicazione o remote. Errori durante la chiamata a codice con restrizioni Se chiamate codice di cui è limitato l'uso in una sandbox a causa di restrizioni della sicurezza, il runtime invia un errore JavaScript in cui è indicato che si è verificata una violazione della sicurezza del runtime di Adobe AIR per il codice JavaScript nella sandbox di sicurezza dell'applicazione. Per ulteriori informazioni, consultate “Errori JavaScript relativi alla sicurezza da evitare” a pagina 238. Protezione con sandbox quando il contenuto HTML viene caricato da una stringa Il metodo loadString() della classe HTMLLoader consente di creare contenuto HTML in fase di runtime. Se, tuttavia, come contenuto HTML usate dati che vengono caricati da un'origine Internet non sicura, questi potrebbero essere danneggiati. Per questo motivo, per impostazione predefinita, il contenuto HTML creato tramite il metodo loadString() non viene inserito nella sandbox dell'applicazione e non dispone quindi dell'accesso alle API di AIR. Potete, tuttavia, impostare la proprietà placeLoadStringContentInApplicationSandbox di un oggetto HTMLLoader su true per inserire il contenuto HTML creato tramite il metodo loadString() nella sandbox dell'applicazione. Per ulteriori informazioni, consultate “Caricamento di contenuto HTML da una stringa” a pagina 236. Creazione di script tra contenuti in diversi domini Alle applicazioni AIR vengono concessi privilegi speciali al momento dell'installazione. È fondamentale che gli stessi privilegi non vengano diffusi ad altro contenuto, ad esempio file remoti e file locali che non fanno parte dell'applicazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 38 Sicurezza in AIR Informazioni sul bridge sandbox AIR In genere, il contenuto da altri domini non può chiamare script in altri domini. Per proteggere le applicazioni AIR dalla diffusione accidentale del controllo o di informazioni con privilegi, vengono applicate le seguenti restrizioni al contenuto presente nella sandbox di sicurezza application (il contenuto installato con l'applicazione): • Il codice nella sandbox di sicurezza dell'applicazione non può consentire l'accesso ad altre sandbox mediante una chiamata al metodo Security.allowDomain(). Se chiamate questo metodo dalla sandbox di sicurezza dell'applicazione, viene generato un errore. • L'importazione di contenuto non dell'applicazione nella sandbox dell'applicazione mediante l'impostazione della proprietà LoaderContext.securityDomain o LoaderContext.applicationDomain non è consentita. Vi sono tuttavia alcuni casi in cui l'applicazione AIR principale richiede che il contenuto da un dominio remoto disponga dell'accesso controllato agli script nell'applicazione AIR principale o viceversa. A questo scopo, il runtime fornisce un meccanismo bridge sandbox che funge da gateway tra le due sandbox. Un bridge sandbox può fornire l'interazione esplicita tra le sandbox di sicurezza remota e dell'applicazione. Il bridge sandbox espone due oggetti a cui possono accedere gli script caricati e in fase di caricamento: • L'oggetto parentSandboxBridge consente al contenuto in fase di caricamento di esporre proprietà e funzioni agli script nel contenuto caricato. • L'oggetto childSandboxBridge consente al contenuto caricato di esporre proprietà e funzioni agli script nel contenuto in fase di caricamento. Gli oggetti esposti tramite il bridge sandbox vengono passati in base al valore, non al riferimento. Tutti i dati sono serializzati. Ciò significa che gli oggetti esposti da un lato del bridge non possono essere impostati dall'altro lato, e che gli oggetti esposti sono tutti senza tipo. Inoltre, potete esporre solo semplici oggetti e funzioni; non potete esporre oggetti complessi. Se il contenuto secondario tenta di impostare una proprietà dell'oggetto parentSandboxBridge, il runtime genera un'eccezione SecurityError. In modo analogo, se il contenuto principale tenta di impostare una proprietà dell'oggetto childSandboxBridge, il runtime genera un'eccezione SecurityError. Esempio di bridge sandbox (SWF) Supponete di voler fare in modo che un'applicazione AIR per un negozio di musica consenta ai file SWF remoti di diffondere il prezzo degli album, impedendo tuttavia che il file SWF remoto riveli se si tratta del prezzo di vendita. A questo scopo, la classe StoreAPI fornisce un metodo per acquisire il prezzo, nascondendo però il prezzo di vendita. Un'istanza di questa classe StoreAPI viene quindi assegnata alla proprietà parentSandboxBridge dell'oggetto LoaderInfo dell'oggetto Loader che carica il file SWF remoto. Di seguito è riportato il codice dell'applicazione AIR per il negozio di musica: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 39 Sicurezza in AIR <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" title="Music Store" creationComplete="initApp()"> <mx:Script> import flash.display.Loader; import flash.net.URLRequest; private var child:Loader; private var isSale:Boolean = false; private function initApp():void { var request:URLRequest = new URLRequest("http://[www.yourdomain.com]/PriceQuoter.swf") child = new Loader(); child.contentLoaderInfo.parentSandboxBridge = new StoreAPI(this); child.load(request); container.addChild(child); } public function getRegularAlbumPrice():String { return "$11.99"; } public function getSaleAlbumPrice():String { return "$9.99"; } public function getAlbumPrice():String { if(isSale) { return getSaleAlbumPrice(); } else { return getRegularAlbumPrice(); } } </mx:Script> <mx:UIComponent id="container" /> </mx:WindowedApplication> L'oggetto StoreAPI chiama l'applicazione principale per recuperare il normale prezzo dell'album, ma restituisce "Non disponibile" quando viene chiamato il metodo getSaleAlbumPrice(). Il seguente codice definisce la classe StoreAPI: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 40 Sicurezza in AIR public class StoreAPI { private static var musicStore:Object; public function StoreAPI(musicStore:Object) { this.musicStore = musicStore; } public function getRegularAlbumPrice():String { return musicStore.getRegularAlbumPrice(); } public function getSaleAlbumPrice():String { return "Not available"; } public function getAlbumPrice():String { return musicStore.getRegularAlbumPrice(); } } Il seguente codice rappresenta un esempio di file SWF denominato PriceQuoter SWF che indica il prezzo del negozio, ma non può indicare il prezzo di vendita: package { import flash.display.Sprite; import flash.system.Security; import flash.text.*; public class PriceQuoter extends Sprite { private var storeRequester:Object; public function PriceQuoter() { trace("Initializing child SWF"); trace("Child sandbox: " + Security.sandboxType); storeRequester = loaderInfo.parentSandboxBridge; var tf:TextField = new TextField(); tf.autoSize = TextFieldAutoSize.LEFT; addChild(tf); tf.appendText("Store price of album is: " + storeRequester.getAlbumPrice()); tf.appendText("\n"); tf.appendText("Sale price of album is: " + storeRequester.getSaleAlbumPrice()); } } } Esempio di bridge sandbox (HTML) Nel contenuto HTML, le proprietà parentSandboxBridge e childSandboxBridge vengono aggiunte all'oggetto JavaScript window di un documento secondario. Per un esempio di impostazione delle funzioni del bridge nel contenuto HTML, consultate “Impostazione dell'interfaccia per un bridge sandbox” a pagina 252. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 41 Sicurezza in AIR Limitazione dell'esposizione delle API Quando esponete i bridge sandbox, è importante esporre le API di alto livello che limitano il grado a cui potrebbero essere usate in modo improprio. Tenete presente che il contenuto che chiama la vostra implementazione del bridge potrebbe risultare compromesso (ad esempio, mediante introduzione, ovvero injection, di codice). Pertanto, l'esposizione, ad esempio, di un metodo readFile(path:String) (che legge il contenuto di un file arbitrario) tramite un bridge è soggetto a un uso abusivo. Sarebbe preferibile esporre un'API readApplicationSetting() che non segue un percorso e legge un file specifico. Un approccio più semantico limita il danno che potrebbe provocare un'applicazione qualora una parte di essa venisse compromessa. Consultare anche “Scambio di script per il contenuto presente in sandbox di sicurezza diverse” a pagina 251 “La funzione di sicurezza sandbox dell'applicazione” a pagina 30 “Privilegi del contenuto presente in sandbox non dell'applicazione” a pagina 31 Scrittura su disco L'interazione delle applicazioni eseguite in un browser Web è limitata solo al file system locale dell'utente. I browser Web implementano criteri di sicurezza che impediscono il danneggiamento del computer dell'utente a seguito del caricamento di contenuto Web. I file SWF eseguiti, ad esempio, tramite Flash Player in un browser non possono interagire direttamente con i file già presenti nel computer dell''utente. Gli oggetti condivisi e i cookie possono essere scritti sul computer di un utente allo scopo di mantenerne le preferenze e altri dati, tuttavia questo è il limite dell'interazione con il file system. Poiché le applicazioni AIR vengono installate in modo nativo, dispongono di un contratto di sicurezza diverso, che prevede la capacità di leggere e scrivere nel file system locale. Questo grado di libertà comporta un alto livello di responsabilità per gli sviluppatori. Le aree accidentalmente non sicure dell'applicazione compromettono non solo la funzionalità dell'applicazione, ma anche l'integrità del computer dell'utente. Per questo motivo si consiglia agli sviluppatori di leggere “Procedure di sicurezza ottimali per gli sviluppatori” a pagina 43. Gli sviluppatori AIR possono accedere e scrivere file nel file system locale usando varie convenzioni di schemi URL: Schema URL Descrizione app:/ Alias della directory dell'applicazione. Ai file accessibili da questo percorso viene assegnata la sandbox dell'applicazione; dispongono dei privilegi completi concessi dal runtime. app-storage:/ Alias della directory di memorizzazione locale, standardizzato dal runtime. Ai file accessibili da questo percorso viene assegnata una sandbox non dell'applicazione. file:/// Alias che rappresenta la radice del disco rigido dell'utente. A un file accessibile da questo percorso viene assegnata una sandbox dell'applicazione se si trova nella directory dell'applicazione; in caso contrario, gli viene assegnata una sandbox non dell'applicazione. Nota: le applicazioni AIR non possono modificare il contenuto utilizzando lo schema URL app:. Inoltre, la lettura della directory dell'applicazione è consentita solo a seguito delle impostazioni dell'amministratore. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 42 Sicurezza in AIR A meno che l'amministratore non abbia impostato delle restrizioni sul computer dell'utente, le applicazioni AIR dispongono dei privilegi di scrittura in qualsiasi percorso del disco rigido dell'utente. Si consiglia agli sviluppatori di utilizzare il percorso app-storage:/ per la memorizzazione locale delle loro applicazioni. I file scritti in appstorage:/ da un'applicazione vengono inseriti in un percorso standard: • In Mac OS: la directory di memorizzazione di un'applicazione è <appData>/<appId>/Local Store/ dove <appData> è la cartella delle preferenze dell'utente, in genere /Users/<utente>/Library/Preferences • In Windows: la directory di memorizzazione di un'applicazione è <appData>\<appId>\Local Store\ dove <appData> è la cartella speciale CSIDL_APPDATA dell'utente, in genere C:\Documents and Settings\<NomeUtente>\Dati applicazioni • In Linux: <appData>/<appID>/Local Store/dove <appData> è /home/<NomeUtente>/.appdata Se un'applicazione è progettata per interagire con i file esistenti nel file system dell'utente, leggete “Procedure di sicurezza ottimali per gli sviluppatori” a pagina 43. Operazioni sicure con contenuto non attendibile Il contenuto non assegnato alla sandbox dell'applicazione può fornire funzionalità aggiuntive per la creazione di script alla vostra applicazione, ma solo che soddisfa i criteri di sicurezza del runtime. In questo argomento viene descritto il contratto di sicurezza di AIR per il contenuto non dell'applicazione. Security.allowDomain() Le applicazioni AIR limitano l'accesso con script per il contenuto non dell'applicazione in modo più rigido rispetto al modo in cui il plug-in Flash Player per browser limita l'accesso con script per il contenuto non attendibile. Nel browser in Flash Player, ad esempio, quando un file SWF assegnato alla sandbox local-trustedchiama il metodo System.allowDomain(), l'accesso con script viene concesso a qualsiasi file SWF caricato dal dominio specificato. L'approccio analogo dal contenuto application non è consentito nelle applicazioni AIR, in quanto verrebbe concesso al file non dell'applicazione un livello di accesso eccessivo nel file system dell'utente. I file remoti non possono accedere direttamente alla sandbox dell'applicazione, indipendentemente dalle chiamate al metodo Security.allowDomain(). Creazione di script tra contenuto dell'applicazione e non dell'applicazione Le applicazioni AIR che creano script tra contenuto dell'applicazione e non dell'applicazione sono previsti schemi di sicurezza più complessi. Ai file non presenti nella sandbox dell'applicazione è consentito l'accesso solo alle proprietà e ai metodi dei file presenti nella sandbox dell'applicazione mediante l'uso di un bridge sandbox. Un bridge sandbox funge da gateway tra il contenuto dell'applicazione e il contenuto non dell'applicazione, consentendo un'interazione esplicita tra i due file. Quando vengono usati correttamente, i bridge sandbox forniscono un ulteriore livello di sicurezza, impedendo al contenuto non dell'applicazione di accedere ai riferimenti agli oggetti che fanno parte del contenuto dell'applicazione. Il vantaggio che deriva dall'uso dei bridge sandbox è illustrato più chiaramente da un esempio. Supponete di voler fare in modo che un'applicazione AIR per un negozio di musica fornisca un'API agli inserzionisti che desiderano creare file SWF personalizzati con cui l'applicazione possa quindi comunicare. Il negozio intende mettere a disposizione degli inserzionisti i metodi per la ricerca di artisti e CD nel negozio, isolando al contempo alcuni metodi e proprietà dal file SWF di terze parti, per motivi di sicurezza. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 43 Sicurezza in AIR Questa funzionalità può essere fornita con un bridge sandbox. Per impostazione predefinita, il contenuto caricato esternamente in un'applicazione AIR in fase di runtime non dispone dell'accesso ad alcun metodo o proprietà nell'applicazione principale. Con un'implementazione di bridge sandbox personalizzato, lo sviluppatore può fornire i servizi al contenuto remoto senza esporre tali metodi e proprietà. Considerate il bridge sandbox come un percorso tra il contenuto attendibile e quello non attendibile, che fornisce la comunicazione tra il contenuto caricante e quello caricato senza esporre i riferimenti agli oggetti. Per ulteriori informazioni sull'uso di bridge sandbox in modo sicuro, consultate “Creazione di script tra contenuti in diversi domini” a pagina 37. Protezione dalla generazione dinamica di contenuto SWF non sicuro Il metodo Loader.loadBytes() consente a un'applicazione di generare contenuto SWF da un array di byte. Tuttavia, gli attacchi mediante introduzione, o injection, di codice nei dati caricati da origini remote possono causare gravi danni durante il caricamento del contenuto, in particolare quando i dati vengono caricati nella sandbox dell'applicazione dove il contenuto SWF generato può accedere all'intero set di API AIR. Vi sono tuttavia casi in cui l'uso del metodo loadBytes() è consentito, senza generare codice SWF eseguibile. Potete usare il metodo loadBytes(), ad esempio, per generare i dati di un'immagine per controllare la tempistica di visualizzazione dell'immagine. Vi sono anche usi consentiti che si basano effettivamente sull'esecuzione di codice, ad esempio per la creazione dinamica di contenuto SWF per la riproduzione audio. In AIR, per impostazione predefinita, il metodo loadBytes()non consente di caricare il contenuto SWF; consente solo di caricare il contenuto dell'immagine. In AIR, la proprietà loaderContext del metodo loadBytes() dispone di una proprietà allowLoadBytesCodeExecution, che potete impostare su true per consentire esplicitamente all'applicazione di utilizzare loadBytes() per caricare contenuto SWF eseguibile. Il codice riportato di seguito mostra come utilizzare questa funzione: var loader:Loader = new Loader(); var loaderContext:LoaderContext = new LoaderContext(); loaderContext.allowLoadBytesCodeExecution = true; loader.loadBytes(bytes, loaderContext); Se chiamate loadBytes() per caricare contenuto SWF e la proprietà allowLoadBytesCodeExecution dell'oggetto LoaderContext è impostata su false (il valore predefinito), l'oggetto Loader genera un'eccezione SecurityError. Nota: in una futura versione di Adobe AIR questa API potrebbe essere modificata. In tal caso, potreste dover ricompilare il contenuto che utilizza la proprietà allowLoadBytesCodeExecution della classe LoaderContext. Procedure di sicurezza ottimali per gli sviluppatori Sebbene le applicazioni AIR vengano create usando le tecnologie Web, è importante che gli sviluppatori tengano presente che non stanno lavorando nella sandbox di sicurezza del browser. Ciò significa che è possibile creare applicazioni AIR potenzialmente dannose per il sistema locale, sia volontariamente che involontariamente. AIR tenta di ridurre il rischio, tuttavia vi sono modi attraverso i quali possono essere introdotte delle vulnerabilità. In questo argomento sono descritte alcuni importanti rischi di sicurezza potenziali. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 44 Sicurezza in AIR Rischio derivante dall'importazione di file nella sandbox di sicurezza dell'applicazione I file presenti nella directory dell'applicazione vengono assegnati alla sandbox dell'applicazione e dispongono dei privilegi completi del runtime. Le applicazioni che scrivono sul file system locale ricevono istruzioni di scrivere su app-storage:/. Questa directory è indipendente dai file dell'applicazione sul computer dell'utente, quindi i file non vengono assegnati alla sandbox dell'applicazione e costituiscono un rischio di sicurezza limitato. Si consiglia agli sviluppatori di tenere presente quanto segue: • Includete un file in un file AIR (nell'applicazione installata) solo se necessario. • Includete un file di script in un file AIR (nell'applicazione installata) solo il relativo comportamento è completamente chiaro e attendibile. • Evitate di scrivere o modificare il contenuto nella directory dell'applicazione. Il runtime impedisce alle applicazioni di scrivere o modificare file e directory tramite lo schema URL app:/ generando un'eccezione SecurityError. • Evitate di utilizzare dati da un'origine di rete, in quanto i parametri per i metodi dell'API AIR potrebbero comportare l'esecuzione di codice, ad esempio il metodo Loader.loadBytes() e la funzione JavaScript eval(). Rischio derivante dall'uso di un'origine esterna per determinare i percorsi Un'applicazione AIR potrebbe essere compromessa dall'uso di dati o contenuto esterno. Per questo motivo, prestate particolare attenzione quando usate dati dalla rete o dal file system. L'attendibilità, in ultima analisi, dipende dallo sviluppatore e della connessioni di rete che ha creato; tuttavia, i dati esterni comportano un rischio intrinseco e non dovrebbero essere usati per l'input in operazioni considerate sensibili. Si consiglia agli sviluppatori di evitare quanto segue: • Utilizzare dati da un'origine di rete per determinare il nome di un file • Utilizzare dati da un'origine di rete per creare un URL usato dall'applicazione per inviare informazioni riservate Rischi derivanti da uso, memorizzazione o trasmissione di credenziali non sicure La memorizzazione di credenziali utente nel file system locale dell'utente comporta intrinsecamente il rischio che tali credenziali vengano compromesse. Si consiglia agli sviluppatori di tenere presente quanto segue: • Se le credenziali devono essere archiviate localmente, crittografatele durante la scrittura nel file system locale. Il runtime fornisce un archivio crittografato univoca per ogni applicazione installata tramite la classe EncryptedLocalStore. Per informazioni dettagliate, consultate “Memorizzazione di dati crittografati” a pagina 218. • Evitate di trasmettere credenziali utente non crittografate a un'origine di rete, a meno che tale origine sia attendibile. • Non specificate mai una password predefinita quando create delle credenziali; fate in modo che gli utenti creino password personalizzate. Gli utenti che non modificano il valore predefinito espongono le proprie credenziali a possibili attacchi da parte di chi conosce già la password predefinita. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 45 Sicurezza in AIR Rischio derivante da un attacco con downgrade Durante l'installazione di un'applicazione, il runtime verifica che non sia già installata una versione di tale applicazione. Se un'applicazione è già installata, il runtime confronta la stringa della versione con la versione in corso di installazione. Se la stringa è diversa, l'utente può scegliere di aggiornare la propria installazione. Il runtime non è in grado di garantire che la nuova versione installata sia più recente di quella precedente; rileva solo che è diversa. Un utente malintenzionato potrebbe distribuire una versione meno recente per sfruttare eventuali punti deboli nella sicurezza. Per questo motivo, è opportuno che lo sviluppatore effettui controlli delle versioni quando viene eseguita l'applicazione. È buona norma fare in modo che l'applicazione ricerchi gli aggiornamenti necessari nella rete. In questo modo, anche se chi effettua l'attacco dovesse indurre l'utente a eseguire una versione precedente, questa rileverà automaticamente che è necessario un aggiornamento. L'uso di un chiaro schema di controllo delle versioni per la vostra applicazione, renderà anche più difficile indurre gli utenti a installare una versione precedente. Per maggiori dettagli sulla definizione delle versioni di un'applicazione, consultate “Definizione delle proprietà nel file descrittore dell'applicazione” a pagina 47. Firma del codice Il codice di tutti i file del programma di installazione di AIR deve essere firmato. La firma del codice è un processo crittografico per confermare l'accuratezza dell'origine del software specificata. Le applicazioni AIR possono essere firmate sia mediante il collegamento di un certificato da un'autorità di certificazione (CA) esterna, sia mediante la creazione di un certificato personalizzato. Un certificato commerciale di una CA nota è sicuramente consigliabile e garantisce agli utenti che l'applicazione è autentica, non una contraffazione. Potete comunque creare certificati autofirmati usando adt incluso nell'SDK oppure Flash, Flex Builder o un'altra applicazione che usa adt per generare certificati. I certificati autofirmati non costituiscono una garanzia che l'applicazione in fase di installazione sia autentica. Per ulteriori informazioni sulla firma digitale di applicazioni AIR, consultate “Firma digitale di un file AIR” a pagina 325 e “Creazione di un'applicazione AIR mediante gli strumenti della riga di comando” a pagina 360. 46 Capitolo 8: Impostazione delle proprietà dell'applicazione AIR Oltre a tutti i file e le altre risorse che la costituiscono, ogni applicazione AIR richiede un file descrittore. Il file descrittore dell'applicazione è un file XML che definisce le proprietà di base dell'applicazione. Se sviluppate applicazioni AIR con l'ausilio dell'Aggiornamento Adobe® AIR™ per Adobe® Flash® CS3 Professional o Adobe® Flash® CS4 Professional, il file descrittore dell'applicazione viene automaticamente generato quando create un progetto AIR. Potete accedere a un pannello per modificare le impostazioni del descrittore dell'applicazione dal menu Comandi > AIR > Impostazioni applicazione e programma di installazione. In alternativa, potete modificare il file descrittore dell'applicazione manualmente. Struttura del file descrittore dell'applicazione Il file descrittore dell'applicazione contiene le proprietà che hanno effetto sull'intera applicazione, come il nome, la versione, il copyright e così via. Potete utilizzare un nome file qualsiasi per il file descrittore dell'applicazione. Quando create un file AIR con le impostazioni predefinite in Flash CS3 o CS4, il file descrittore dell'applicazione viene rinominato in application.xml e inserito all'interno di una directory speciale nel pacchetto AIR. Di seguito è riportato un esempio di file descrittore dell'applicazione: <?xml version="1.0" encoding="utf-8" ?> <application xmlns="http://ns.adobe.com/air/application/1.5"> <id>com.example.HelloWorld</id> <version>2.0</version> <filename>Hello World</filename> <name>Example Co. AIR Hello World</name> <description> <text xml:lang="en">This is a example.</text> <text xml:lang="fr">C'est un exemple.</text> <text xml:lang="es">Esto es un ejemplo.</text> </description> <copyright>Copyright (c) 2006 Example Co.</copyright> <initialWindow> <title>Hello World</title> <content> HelloWorld-debug.swf </content> <systemChrome>none</systemChrome> <transparent>true</transparent> <visible>true</visible> <minimizable>true</minimizable> <maximizable>false</maximizable> <resizable>false</resizable> <width>640</width> <height>480</height> <minSize>320 240</minSize> <maxSize>1280 960</maxSize> </initialWindow> <installFolder>Example Co/Hello World</installFolder> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 47 Impostazione delle proprietà dell'applicazione AIR <programMenuFolder>Example Co</programMenuFolder> <icon> <image16x16>icons/smallIcon.png</image16x16> <image32x32>icons/mediumIcon.png</image32x32> <image48x48>icons/bigIcon.png</image48x48> <image128x128>icons/biggestIcon.png</image128x128> </icon> <customUpdateUI>true</customUpdateUI> <allowBrowserInvocation>false</allowBrowserInvocation> <fileTypes> <fileType> <name>adobe.VideoFile</name> <extension>avf</extension> <description>Adobe Video File</description> <contentType>application/vnd.adobe.video-file</contentType> <icon> <image16x16>icons/avfIcon_16.png</image16x16> <image32x32>icons/avfIcon_32.png</image32x32> <image48x48>icons/avfIcon_48.png</image48x48> <image128x128>icons/avfIcon_128.png</image128x128> </icon> </fileType> </fileTypes> </application> Definizione delle proprietà nel file descrittore dell'applicazione Utilizzate gli elementi e gli attributi XML nel file descrittore dell'applicazione per definire i tipi seguenti di proprietà per l'applicazione AIR: • versione di runtime di AIR necessaria; • identità dell'applicazione; • cartella di installazione e del menu dei programmi; • contenuto iniziale e proprietà della finestra; • file di icona dell'applicazione; • presenza o meno di un'interfaccia di aggiornamento personalizzata nell'applicazione; • possibilità di richiamare l'applicazione dal contenuto SWF in esecuzione nel browser dell'utente; • associazioni ai tipi di file. Specifica della versione di AIR richiesta L'attributo dell'elemento principale di un file descrittore dell'applicazione application specifica la versione del runtime AIR richiesta: <application xmlns="http://ns.adobe.com/air/application/1.5"> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 48 Impostazione delle proprietà dell'applicazione AIR xmlns Lo spazio dei nomi AIR, che dovete definire come spazio dei nomi XML predefinito. Lo spazio dei nomi cambia a ogni nuova versione principale di AIR che viene rilasciata (ma non con le patch secondarie). L'ultimo segmento dello spazio dei nomi, ad esempio “1.5”, indica la versione del runtime richiesta dall'applicazione. Assicuratevi di impostare lo spazio dei nomi su AIR 1.5 ("http://ns.adobe.com/air/application/1.5") se nell'applicazione vengono usate le nuove funzioni di AIR 1.5. Per le applicazioni basate su SWF la versione del runtime AIR specificata nel descrittore dell'applicazione determina la versione SWF massima che può essere caricata come contenuto iniziale dell'applicazione. Per la applicazioni per cui è specificato AIR 1.0 o AIR 1.1 potete utilizzare solo file SWF9 (Flash Player 9) come contenuto iniziale, anche se per l'esecuzione utilizzate il runtime AIR 1.5. Per le applicazioni per cui è specificato AIR 1.5 potete utilizzare file SWF9 o SWF10 (Flash Player 10) come contenuto iniziale. La versione SWF determina la versione disponibile delle API di AIR e Flash Player. Se come contenuto iniziale di un'applicazione AIR 1.5 viene utilizzato un file SWF9, l'applicazione avrà accesso solo alle API di AIR 1.1 e Flash Player 9. Le modifiche di comportamento apportate alle API esistenti in AIR 1.5 o Flash Player 10 non saranno inoltre applicate. Le modifiche importanti relative alla sicurezza apportate alle API rappresentano un'eccezione a questa condizione e possono essere applicate in modo retroattivo in patch presenti o future del runtime. Per le applicazioni basate su HTML solo la versione del runtime specificata nel descrittore dell'applicazione determina la versione delle API di AIR e Flash Player disponibili per l'applicazione. Il comportamento del codice HTML, CSS e JavaScript è sempre determinato dalla versione del WebKit utilizzato nel runtime AIR installato e non dal descrittore dell'applicazione. Quando un'applicazione AIR carica contenuto SWF, la versione delle API di AIR e Flash Player disponibile per il contenuto dipende dalla modalità di caricamento del contenuto. La tabella seguente illustra in che modo viene determinata la versione delle API in base al metodo di caricamento: Modalità di caricamento del contenuto Modalità di determinazione della versione delle API Contenuto iniziale, applicazione basata su SWF Versione SWF del file caricato Contenuto iniziale, applicazione basata su HTML Spazio dei nomi del descrittore dell'applicazione SWF caricato da contenuto SWF Versione del contenuto in corso di caricamento Libreria SWF caricata da contenuto HTML mediante tag <script> Spazio dei nomi del descrittore dell'applicazione SWF caricato da contenuto HTML mediante API di AIR o Flash Player (ad esempio flash.display.Loader) Spazio dei nomi del descrittore dell'applicazione SWF caricato da contenuto HTML mediante tag <object> o <embed> (o le API JavaScript equivalenti) Versione SWF del file caricato In caso di caricamento di un file SWF con una versione diversa dal contenuto in corso di caricamento, potreste incontrare due problemi: • caricamento di contenuto SWF10 da parte di SWF9 (o versioni precedenti): i riferimenti alle API di AIR 1.5 e Flash Player 10 nel contenuto caricato non verranno risolti; • caricamento di contenuto SWF9 (o versione precedente) da parte di SWF10: il comportamento delle API modificate in AIR 1.5 e Flash Player 10 potrebbe essere imprevisto per il contenuto caricato. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 49 Impostazione delle proprietà dell'applicazione AIR minimumPatchLevel Opzionale. Utilizzate l'attributo minimumPatchLevel per specificare il livello di patch minimo di Adobe AIR richiesto dall'applicazione. Le applicazioni AIR specificano di solito quale versione di AIR richiedono tramite la semplice definizione dello spazio dei nomi nel file descrittore dell'applicazione. Lo spazio dei nomi viene modificato per ogni nuova versione principale di AIR che viene rilasciata (ad esempio 1.0 o 1.5), mentre rimane invariato nel caso di versioni patch. Le versioni patch contengono solo una serie limitata di correzioni e nessuna modifica dell'API. Le applicazioni di solito non specificano quale versione di patch richiedono. Tuttavia, una correzione in una versione patch può a volte risolvere un problema presente in un'applicazione. In tale situazione, un'applicazione può specificare un valore per l'attributo minimumPatchLevel per far sì che una patch specifica venga applicata prima dell'installazione dell'applicazione. Se necessario, il programma di installazione dell'applicazione AIR richiederà all'utente di scaricare e installare la versione o la patch richiesta. L'esempio seguente mostra un elemento dell'applicazione che specifica un valore per l'attributo minimumPatchLevel: <application xmlns="http://ns.adobe.com/air/application/1.1" minimumPatchLevel="5331"> Definizione dell'identità dell'applicazione Gli elementi seguenti definiscono ID applicazione, versione, nome, nome file, descrizione e informazioni di copyright: <id>com.example.samples.TestApp</id> <version>2.0</version> <filename>TestApp</filename> <name> <text xml:lang="en">Hello AIR</text> <text xml:lang="fr">Bonjour AIR</text> <text xml:lang="es">Hola AIR</text> </name> <description>An MP3 player.</description> <copyright>Copyright (c) 2008 YourCompany, Inc.</copyright> id Una stringa di identificazione univoca per l'applicazione, nota come "ID applicazione". Il valore dell'attributo è limitato ai seguenti caratteri: • 0–9 • a–z • A–Z • . (punto) • - (trattino) Il valore deve contenere da 1 a 212 caratteri. Questo elemento è obbligatorio. La stringa id utilizza di solito una gerarchia separata da punto, in linea con un indirizzo di dominio DNS inverso, un pacchetto o nome classe Java™ oppure un identificativo di tipo universale Mac OS® X. Non viene applicata la forma di tipo DNS e AIR non crea alcuna associazione tra il nome e i domini DNS effettivi. version Specifica le informazioni della versione per l'applicazione. (Non ha alcuna relazione con la versione del runtime.) La stringa di versione è un indicatore definito dall'applicazione. AIR non interpreta in alcun modo tale stringa. Pertanto, la versione “3.0” non viene considerata più aggiornata della versione “2.0”. Esempi: "1.0", ".4", "0.5", "4.9", "1.3.4a". Questo elemento è obbligatorio. filename La stringa da utilizzare come nome file dell'applicazione (senza estensione) quando viene installata l'applicazione. Il file dell'applicazione avvia l'applicazione AIR nel runtime. Se non viene fornito un valore name, filename viene utilizzato anche come nome della cartella di installazione. Questo elemento è obbligatorio. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 50 Impostazione delle proprietà dell'applicazione AIR La proprietà filename può contenere qualsiasi carattere in formato Unicode (UTF-8) a eccezione di quelli seguenti, di cui non è consentito l'uso nei nomi file in vari file system: Carattere Codice esadecimale vari 0x00 – x1F * x2A " x22 : x3A > x3C < x3E ? x3F \ x5C | x7C Il valore filename non può terminare con un punto. name (Opzionale, ma consigliato) Il titolo visualizzato dal programma di installazione dell'applicazione AIR. Se specificate un unico nodo di testo (invece che più elementi text), il programma di installazine dell'applicazione AIR utilizza questo nome, a prescindere dal linguaggio del sistema: <name>Test Application</name> Lo schema del descrittore dell'applicazione AIR 1.0 consente di definire un unico nodo di testo semplice per il nome (non più elementi text). In AIR 1.1 (o versione successiva) potete invece specificare più lingue nell'elemento name. Ad esempio, l'elemento seguente specifica il nome in tre lingue (inglese, francese e spagnolo): <name> <text xml:lang="en">Hello AIR</text> <text xml:lang="fr">Bonjour AIR</text> <text xml:lang="es">Hola AIR</text> </name> L'attributo xml:lang di ogni elemento di testo specifica un codice lingua, definito dallo standard RFC4646 RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Il programma di installazione dell'applicazione AIR utilizza il nome che più corrisponde alla lingua dell'interfaccia utente del sistema operativo dell'utente. Ad esempio, considerate un'installazione in cui l'elemento name del file descrittore dell'applicazione comprende un valore per la versione locale en (inglese). Il programma di installazione dell'applicazione AIR utilizza il nome en se il sistema operativo identifica en (inglese) come lingua dell'interfaccia utente. Utilizza anche il nome en se la lingua dell'interfaccia utente del sistema è en-US (inglese americano). Tuttavia, se la lingua dell'interfaccia utente è en-US e il file descrittore dell'applicazione definisce i nomi en-US ed en-GB, quindi il programma di installazione dell'applicazione AIR utilizza il valore en-US. Se l'applicazione non definisce alcun nome che corrisponda alle lingue dell'interfaccia utente del sistema, programma di installazione dell'applicazione AIR utilizza il primo valore name definito nel file descrittore dell'applicazione. Se non è specificato alcun elemento name, il programma di installazione dell'applicazione AIR visualizza il valore filename come nome dell'applicazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 51 Impostazione delle proprietà dell'applicazione AIR L'elemento name specifica solo il titolo dell'applicazione utilizzato nel programma di installazione dell'applicazione AIR. Il programma di installazione dell'applicazione AIR supporta più lingue: cinese tradizionale, cinese semplificato, ceco, olandese, inglese, francese, tedesco, italiano, giapponese, coreano, polacco, portoghese brasiliano, russo, spagnolo, svedese e turco. Il programma di installazione dell'applicazione AIR seleziona la relativa lingua visualizzata (per il testo diverso dal titolo e dalla descrizione dell'applicazione) in base alla lingua dell'interfaccia utente del sistema. Questa selezione di lingua non dipende dalle impostazioni nel file descrittore dell'applicazione. L'elemento namenon definisce le versioni locali disponibili per l'esecuzione dell'applicazione installata. Per informazioni dettagliate sullo sviluppo di applicazioni multilingue, consultate “Localizzazione di applicazioni AIR” a pagina 348. description (Opzionale) La descrizione dell'applicazione visualizzata nel programma di installazione dell'applicazione AIR. Se si specifica un unico nodo di testo (non più elementi testo), il programma di installazione dell'applicazione AIR utilizza questa descrizione, a prescindere dalla lingua del sistema: <description>This is a sample AIR application.</description> Lo schema descrittore dell'applicazione AIR 1.0 consente di definire un unico nodo di testo semplice per il nome (non più elementi text). In AIR 1.1 (o versione successiva) potete invece specificare più lingue nell'elemento description. Ad esempio, l'esempio seguente specifica la descrizione in tre lingue (inglese, francese e spagnolo): <description> <text xml:lang="en">This is a example.</text> <text xml:lang="fr">C'est un exemple.</text> <text xml:lang="es">Esto es un ejemplo.</text> </description> L'attributo xml:lang di ogni elemento di testo specifica un codice lingua, definito dallo standard RFC4646 RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Il programma di installazione dell'applicazione AIR utilizza la descrizione che più corrisponde alla lingua dell'interfaccia utente del sistema operativo dell'utente. Ad esempio, considerate un'installazione in cui l'elemento description del file descrittore dell'applicazione comprende un valore per la versione locale en (inglese). Il programma di installazione dell'applicazione AIR utilizza il nome en se il sistema dell'utente identifica en (inglese) come lingua dell'interfaccia utente. Il nome en viene utilizzato anche se la lingua dell'interfaccia utente del sistema è en-US (inglese americano). Tuttavia, se la lingua dell'interfaccia utente del sistema è en-US e il file descrittore dell'applicazione definisce i nomi en-US ed en-GB, il programma di installazione dell'applicazione AIR utilizza il valore en-US. Se l'applicazione non definisce alcun nome che corrisponda alla lingua dell'interfaccia utente del sistema, il programma di installazione dell'applicazione AIR utilizza il primo valore description definito nel file descrittore dell'applicazione. Per ulteriori informazioni sullo sviluppo di applicazioni multilingue, consultate “Localizzazione di applicazioni AIR” a pagina 348. copyright (Opzionale) Le informazioni di copyright per l'applicazione AIR. In Mac OS, il testo di copyright appare nella finestra di dialogo Informazioni su per l'applicazione installata. In Mac OS, le informazioni di copyright sono utilizzate anche nel campo NSHumanReadableCopyright del file Info.plist per l'applicazione. Definizione della cartella di installazione e della cartella dei menu del programma Le cartelle dell'installazione e dei menu del programma sono definite con le seguenti impostazioni di proprietà: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 52 Impostazione delle proprietà dell'applicazione AIR <installFolder>Acme</installFolder> <programMenuFolder>Acme/Applications</programMenuFolder> installFolder (Opzionale) Identifica la sottodirectory della directory di installazione predefinita. In Windows, la sottodirectory di installazione predefinita è Programmi. In Mac OS, è la directory /Applicazioni. In Linux è /opt/. Se, ad esempio, la proprietà installFolder è impostata su "Acme" e un'applicazione è denominata "ExampleApp", l'applicazione viene installata in C:\Programmi\Acme\ExampleApp in Windows, in /Applicazioni/Acme/Example.app in MacOS e in /opt/Acme/ExampleApp in Linux. Utilizzate il carattere della barra (/) come separatore delle directory per specificare una sottodirectory nidificata, come nell'esempio seguente: <installFolder>Acme/Power Tools</installFolder> La proprietà installFolder può contenere qualsiasi carattere in formato Unicode (UTF-8) a eccezione di quelli non consentiti come nomi di cartella nei vari file system (fate riferimento alla proprietà filename descritta in precedenza per l'elenco delle eccezioni): La proprietà installFolder è opzionale. Se non viene specificata, l'applicazione viene installata in una sottodirectory della directory di installazione predefinita, in base alla proprietà name. programMenuFolder (Opzionale) Identifica il percorso in cui posizionare i collegamenti all'applicazione nel menu Tutti i programmi del sistema operativo Windows o nel menu Applications di Linux. (Questa impostazione è attualmente ignorata in altri sistemi operativi.) Le restrizioni per i caratteri non consentiti nel valore della proprietà sono identiche a quelle della proprietà installFolder. Non utilizzate il carattere barra (/) come ultimo carattere di questo valore. Definizione delle proprietà della finestra iniziale dell'applicazione Quando un'applicazione AIR viene caricata, il runtime utilizza i valori dell'elemento initialWindow per creare la finestra iniziale dell'applicazione. Il runtime quindi carica il file SWF o HTML specificato nell'elemento content nella finestra. Di seguito è riportato un esempio dell'elemento initialWindow: <initialWindow> <content>AIRTunes.swf</content> <title>AIR Tunes</title> <systemChrome>none</systemChrome> <transparent>true</transparent> <visible>true</visible> <minimizable>true</minimizable> <maximizable>true</maximizable> <resizable>true</resizable> <width>400</width> <height>600</height> <x>150</x> <y>150</y> <minSize>300 300</minSize> <maxSize>800 800</maxSize> </initialWindow> Gli elementi secondari dell'elemento initialWindow impostano le proprietà della finestra in cui viene caricato il file del contenuto principale. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 53 Impostazione delle proprietà dell'applicazione AIR content Il valore specificato per l'elemento content è l'URL del file di contenuto principale dell'applicazione. Può trattarsi di un file SWF o HTML. L'URL è specificato in relazione al livello principale della cartella di installazione dell'applicazione. (Quando si esegue un'applicazione AIR con ADL, l'URL è relativo alla cartella contenente il file descrittore dell'applicazione. È possibile utilizzare il parametro root-dir di ADL per specificare una directory principale diversa.) Nota: poiché il valore dell'elemento content viene trattato come URL, i caratteri nel file del contenuto devono essere codificati come URL in base alle regole definite in RFC 1738. Ad esempio, i caratteri di spazio devono essere codificati come %20. title (Opzionale) Il titolo della finestra. systemChrome (Opzionale) Se si imposta questo attributo su standard, viene visualizzato lo stile visivo standard del sistema sistema operativo. Se si imposta su none, non viene visualizzato lo stile visivo di sistema. L'impostazione dello stile visivo del sistema non può essere modificata in fase runtime. transparent (Opzionale) Impostate questo elemento su "true" se desiderate che la finestra dell'applicazione supporti la fusione del canale alfa. Una finestra con trasparenza viene visualizzata più lentamente e richiede più memoria. L'impostazione della trasparenza non può essere modificata in fase runtime. Importante: potete impostare transparent su true solo quando systemChrome è none. visible (Opzionale) Impostate su questo elemento su true se volete rendere visibile la finestra principale non appena viene creata. Il valore predefinito è false. Potete scegliere di mantenere la finestra principale nascosta inizialmente, in modo che non siano visibili i cambiamenti relativi alla posizione e alle dimensioni della finestra e al layout del relativo contenuto. Successivamente potete visualizzare la finestra chiamando il metodo activate() della finestra o impostando la proprietà visible su true. Per informazioni dettagliate, consultate “Operazioni con le finestre native” a pagina 61. x, y, width, height (Opzionale) I limiti iniziali della finestra principale dell'applicazione. Se non si impostano questi valori, le dimensioni della finestra sono determinate dalle impostazioni del file SWF principale oppure, nel caso di HTML, dal sistema operativo. minSize, maxSize (Opzionale) Le dimensioni massime e minime della finestra. Se non impostate questi valori, vengono determinati dal sistema operativo. minimizable, maximizable, resizable (Opzionale) Specificano se la finestra può essere ridotta, ingrandita o ridimensionata. Per impostazione predefinita, queste impostazioni utilizzano il valore predefinito true. Nota: nei sistemi operativi (ad esempio Mac OS X) in cui l'ingrandimento delle finestre è un'operazione di ridimensionamento, i valori maximizable e resizable devono essere impostati su false per impedire che la finestra venga ingrandita o ridimensionata. Specifica dei file di icona La proprietà icon specifica uno o più file di icona da utilizzare per l'applicazione. L'inclusione di un'icona è opzionale. Se non si specifica una proprietà icon, il sistema operativo visualizza un'icona predefinita. Il percorso specificato è relativo alla directory principale dell'applicazione. I file di icona devono essere in formato PNG. Potete specificare tutte le dimensioni seguenti per le icone: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 54 Impostazione delle proprietà dell'applicazione AIR <icon> <image16x16>icons/smallIcon.png</image16x16> <image32x32>icons/mediumIcon.png</image32x32> <image48x48>icons/bigIcon.png</image48x48> <image128x128>icons/biggestIcon.png</image128x128> </icon> Se è presente un elemento per una determinata dimensione, l'immagine nel file deve essere esattamente della dimensione specificata. Se non vengono specificate tutte le dimensioni, quelle più simili vengono adattate per un determinato uso dell'icona da parte del sistema operativo. Nota: le icone specificate non vengono aggiunte automaticamente al pacchetto AIR. I file di icona devono essere inclusi nelle posizioni relative corrette nel momento in cui viene creato il pacchetto dell'applicazione. Per ottenere un risultato ottimale, specificate un'immagine per ciascuna delle dimensioni disponibili. Inoltre, assicuratevi che le icone siano visualizzabili nelle modalità a colori a 16 e a 32 bit. Realizzazione di un'interfaccia utente personalizzata per gli aggiornamenti dell'applicazione AIR installa e aggiorna le applicazioni utilizzando le finestre di dialogo di installazione predefinite. Tuttavia, potete creare un'interfaccia utente personalizzata per l'aggiornamento di un'applicazione. Per indicare che l'applicazione deve gestire autonomamente il processo di aggiornamento, impostate l'elemento customUpdateUI su true: <customUpdateUI>true</customUpdateUI> Quando la versione installata dell'applicazione ha l'elemento customUpdateUI impostato su true e l'utente fa doppio clic sul file AIR di una nuova versione o installa un aggiornamento dell'applicazione mediante la funzionalità di installazione invisibile, il runtime apre la versione installata dell'applicazione invece che il programma di installazione applicazioni AIR predefinito. La logica dell'applicazione può quindi determinare come procedere con l'operazione di aggiornamento. (Affinché sia possibile procedere all'aggiornamento, l'ID applicazione e l'ID autore del file AIR devono corrispondere a quelli dell'applicazione installata.) Nota: il meccanismo customUpdateUI entra in funzione solo quando l'applicazione è già installata e l'utente fa doppio clic sul file di installazione AIR contenente un aggiornamento oppure installa un aggiornamento dell'applicazione mediante la funzionalità di installazione invisibile. Potete scaricare e avviare un aggiornamento mediante una logica di applicazione personalizzata, visualizzando la vostra nterfaccia utente nel modo desiderato, a prescindere dal fatto che customUpdateUI sia impostato su true o meno. Per ulteriori informazioni, consultate “Aggiornamento delle applicazioni AIR” a pagina 332. Autorizzazione dell'applicazione a chiamare il browser Se specificate la seguente impostazione, l'applicazione AIR installata può essere avviata tramite la funzione di chiamata browser, ovvero quando l'utente fa clic su collegamento in una pagina all'interno di un browser Web): <allowBrowserInvocation>true</allowBrowserInvocation> Il valore predefinito è false. Se impostate questo valore su true, assicuratevi di considerare le implicazioni di sicurezza, descritte in “Chiamata del browser” a pagina 297. Per ulteriori informazioni, consultate “Installazione ed esecuzione di applicazioni AIR da una pagina Web” a pagina 317. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 55 Impostazione delle proprietà dell'applicazione AIR Dichiarazione delle associazioni di tipo file L'elemento fileTypes consente di dichiarare i tipi di file ai quali è possibile associare un'applicazione AIR. Quando un'applicazione AIR viene installata, qualsiasi tipo di file dichiarato viene registrato nel sistema operativo e, se questi tipi di file non sono già associati a un'altra applicazione, vengono associati all'applicazione AIR. Per sostituire un'associazione esistente tra un tipo di file e un'altra applicazione, utilizzate il metodo NativeApplication.setAsDefaultApplication() in fase runtime (preferibilmente con il permesso dell'utente). Nota: i metodi runtime possono gestire le associazioni solo per i tipi di file dichiarati nel descrittore dell'applicazione. <fileTypes> <fileType> <name>adobe.VideoFile</name> <extension>avf</extension> <description>Adobe Video File</description> <contentType>application/vnd.adobe.video-file</contentType> <icon> <image16x16>icons/AIRApp_16.png</image16x16> <image32x32>icons/AIRApp_32.png</image32x32> <image48x48>icons/AIRApp_48.png</image48x48> <image128x128>icons/AIRApp_128.png</image128x128> </icon> </fileType> </fileTypes> L'elemento fileTypes è opzionale. Può contenere qualsiasi numero di elementi fileType. Gli elementi name e extension sono necessari per ciascuna dichiarazione fileType inclusa. Lo stesso nome è utilizzabile per più estensioni. L'estensione identifica in modo univoco il tipo di file. (Notate che l'estensione non è preceduta da un punto.) L'elemento description è opzionale e viene visualizzato all'utente dall'interfaccia utente del sistema operativo. L'elemento contentType è obbligatorio in AIR 1.5 (era facoltativo in AIR 1.0 e 1.1). La proprietà consente al sistema operativo di individuare l'applicazione migliore per l'apertura di un file in determinate circostanze. Il valore deve essere il tipo MIME del contenuto del file. Tenete presente che il valore viene ignorato in Linux se il tipo di file è già registrato ed è stato associato a un tipo MIME. È possibile specificare le icone per l'estensione del file, utilizzando lo stesso formato dell'elemento icon dell'applicazione. I file di icona devono inoltre essere inclusi nel file di installazione AIR (non vengono inclusi automaticamente nel pacchetto). Quando un tipo di file è associato a un'applicazione AIR, l'applicazione viene chiamata ogni volta che un utente apre un file di tale tipo. Se l'applicazione è già in esecuzione, AIR invia l'oggetto InvokeEvent all'istanza in esecuzione. In caso contrario, AIR avvia prima l'applicazione. In entrambi i casi, il percorso del file può essere recuperato dall'oggetto InvokeEvent inviato dall'oggetto NativeApplication. Potete utilizzare questo percorso per aprire il file. Per ulteriori informazioni, consultate “Gestione delle associazioni di file” a pagina 303 e “Acquisizione degli argomenti della riga di comando” a pagina 295. 56 Capitolo 9: Funzionalità specifiche di Adobe AIR L'argomento fornisce una panoramica delle funzionalità di Adobe® AIR™ che non sono disponibili per il contenuto SWF in esecuzione in Adobe® Flash® Player. Classi specifiche di AIR Le seguenti classi di runtime sono specifiche per Adobe AIR. Non sono disponibili per il contenuto SWF in esecuzione nel browser: Classe Pacchetto ApplicationUpdater air.update ApplicationUpdaterUI air.update BrowserInvokeEvent flash.events Clipboard flash.desktop ClipboardFormats flash.desktop ClipboardTransferMode flash.desktop CompressionAlgorithm flash.utils DockIcon flash.desktop DownloadErrorEvent air.update.events DRMAuthenticateEvent flash.events DRMErrorEvent flash.events DRMStatusEvent flash.events EncryptedLocalStore flash.data File flash.filesystem FileListEvent flash.events FileMode flash.filesystem FileStream flash.filesystem FocusDirection flash.display HTMLHistoryItem flash.html HTMLHost flash.html HTMLLoader flash.html HTMLPDFCapability flash.html HTMLUncaughtScriptExceptionEvent flash.events SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 57 Funzionalità specifiche di Adobe AIR Classe Pacchetto HTMLWindowCreateOptions flash.html Icon flash.desktop InteractiveIcon flash.desktop InvokeEvent flash.events NativeApplication flash.desktop NativeDragActions flash.desktop NativeDragEvent flash.events NativeDragManager flash.desktop NativeDragOptions flash.desktop NativeMenu flash.display NativeMenuItem flash.display NativeWindow flash.display NativeWindowBoundsEvent flash.events NativeWindowDisplayState flash.display NativeWindowDisplayStateEvent flash.events NativeWindowInitOptions flash.display NativeWindowResize flash.display NativeWindowSystemChrome flash.display NativeWindowType flash.display NotificationType flash.desktop OutputProgressEvent flash.events RevocationCheckSettings flash.security Screen flash.display ScreenMouseEvent flash.events SignatureStatus flash.security SignerTrustSettings flash.security SQLCollationType flash.data SQLColumnNameStyle flash.data SQLColumnSchema flash.data SQLConnection flash.data SQLError flash.errors SQLErrorEvent flash.events SQLErrorOperation flash.errors SQLEvent flash.events SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 58 Funzionalità specifiche di Adobe AIR Classe Pacchetto SQLIndexSchema flash.data SQLResult flash.data SQLSchema flash.data SQLSchemaResult flash.data SQLStatement flash.data SQLTableSchema flash.data SQLTransactionLockType flash.data SQLTriggerSchema flash.data SQLUpdateEvent flash.events SQLViewSchema flash.data StatusFileUpdateErrorEvent air.update.events StatusFileUpdateEvent air.update.events StatusUpdateErrorEvent air.update.events StatusUpdateEvent air.update.events SystemTrayIcon flash.desktop UpdateEvent air.update.events Updater flash.desktop URLRequestDefaults flash.net XMLSignatureValidator flash.utils Il pacchetto flash.security, inoltre, include l'interfaccia IURIDereferencer, che è specifica per AIR. Classi di runtime con funzionalità specifiche per AIR Le classi seguenti sono disponibili per il contenuto SWF in esecuzione nel browser, ma AIR offre proprietà o metodi aggiuntivi: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 59 Funzionalità specifiche di Adobe AIR Classe Proprietà o metodo Capabilities linguaggi Event DISPLAYING EXITING HTML_BOUNDS_CHANGE HTML_DOM_INITIALIZE HTML_RENDER LOCATION_CHANGE NETWORK_CHANGE USER_IDLE USER_PRESENT FileReference uploadUnencoded() HTTPStatusEvent HTTP_RESPONSE_STATUS responseURL responseHeaders KeyboardEvent commandKey controlKey LoaderContext allowLoadBytesCodeExecution LoaderInfo parentSandboxBridge childSandboxBridge NetStream resetDRMVouchers() setDRMAuthenticationCredentials() URLRequest followRedirects manageCookies shouldAuthenticate shouldCacheResponse userAgent userCache setLoginCredentials() URLStream evento httpResponseStatus Stage nativeWindow Security APPLICATION Per la maggior parte, questi nuovi metodi e proprietà sono disponibili solo per il contenuto della sandbox di sicurezza di AIR. I nuovi membri delle classi URLRequest, tuttavia, sono disponibili anche per il contenuto in esecuzione in altre sandbox. I metodi ByteArray.compress() e ByteArray.uncompress() includono ciascuno un nuovo parametro algorithm che consente di scegliere tra la compressione di tipo deflate e zlib. Questo parametro è disponibile soltanto per il contenuto in esecuzione in AIR. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 60 Funzionalità specifiche di Adobe AIR Classi con struttura per il monitoraggio del servizio Il pacchetto air.net contiene classi per il rilevamento della rete. Questo pacchetto è disponibile solo per il contenuto in esecuzione in Adobe AIR. Esso è incluso nel file ServiceMonitor.swc. Il pacchetto contiene le seguenti classi: • ServiceMonitor • SocketMonitor • URLMonitor 61 Capitolo 10: Operazioni con le finestre native Potete creare e gestire le finestre desktop con le classi fornite dall'API della finestra nativa di Adobe® AIR®. Informazioni in linea aggiuntive sulle finestre native Ulteriori informazioni sull'API della finestra nativa e sulle operazioni con le finestre native sono disponibili dalla seguenti origini: Guide introduttive (Adobe AIR Developer Connection) • Interazione con una finestra • Personalizzazione dell'aspetto di una finestra nativa • Creazione di finestre stile toast • Controllo dell'ordine di visualizzazione delle finestre • Creazione di finestre ridimensionabili, non rettangolari Guida di riferimento • Nativewindow • NativeWindowInitOptions Articoli ed esempi Adobe Developer Connection • Adobe AIR Developer Connection per Flash (cercate 'AIR' windows) Nozioni di base sulle finestre AIR AIR fornisce un'API della finestra multipiattaforma semplice da usare per la creazione di finestre del sistema operativo native utilizzando le tecnologie di programmazione Flash®, Flex™ e HTML. AIR consente all'utente un'ampia libertà di sviluppo dell'aspetto dell'applicazione. Le finestre che create possono avere l'aspetto di un'applicazione desktop standard, riflettendo lo stile Apple quando vengono eseguite in Macintosh, rispettando le convenzioni Microsoft quando vengono eseguite in Windows e armonizzandosi con il gestore di finestre in Linux, senza dover includere una sola riga di codice specifico per la piattaforma. Oppure potete creare uno stile personalizzato, indipendente dal sistema su cui l'applicazione viene eseguita, utilizzando il chrome estensibile che supporta gli skin fornito dal framework Flex. Grazie al supporto completo delle funzioni di trasparenza e fusione alfa sul desktop, potete anche disegnare un chrome della finestra personalizzato utilizzando grafica bitmap e vettoriale. Stanchi delle solite finestre rettangolari? Disegnatene una rotonda. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 62 Operazioni con le finestre native Finestre in AIR AIR supporta tre API distinte per le operazioni con le finestre: • La classe NativeWindow che supporta ActionScript fornisce l'API della finestra al livello più basso. Utilizzate NativeWindow nelle applicazioni create con ActionScript e Flash CS. Considerate la possibilità di estendere la classe NativeWindow per personalizzare le finestre utilizzate nell'applicazione. • Le classi mx:WindowedApplication e mx:Window del framework Flex forniscono un “wrapper” Flex per la classe NativeWindow. Il componente WindowedApplication sostituisce il componente Application quando create un'applicazione AIR con Flex e deve essere sempre utilizzato come finestra iniziale nell'applicazione Flex. • Nell'ambiente HTML potete usare la classe JavaScript Window, come in un'applicazione Web basata su browser. Le chiamate ai metodi JavaScript Window vengono inoltrate al sottostante oggetto window nativo. Finestre ActionScript Durante la creazione di finestre con la classe NativeWindow, potete utilizzare lo stage Flash Player e visualizzare l'elenco direttamente. Per aggiungere un oggetto visivo a una classe NativeWindow, aggiungete l'oggetto all'elenco di visualizzazione dello stage della finestra o a un altro contenitore dell'oggetto di visualizzazione sullo stage. Finestre del framework Flex Il framework Flex definisce i propri componenti della finestra che racchiudono l'API NativeWindow. Questi componenti, mx:WindowedApplication e mx:Window, non possono essere usati al di fuori del framework e pertanto nemmeno in applicazioni AIR sviluppate con Flash CS. Finestre HTML Durante la creazione di finestre HTML, potete utilizzare HTML, CSS e JavaScript per visualizzare il contenuto. Per aggiungere un oggetto visivo a una finestra HTML, aggiungete il contenuto al DOM HTML. Le finestre HTML sono una categoria speciale di NativeWindow. L'host AIR definisce una proprietà nativeWindow nelle finestre HTML che fornisce l'accesso all'istanza NativeWindow sottostante. Potete utilizzare questa proprietà per accedere alle proprietà, ai metodi ed agli eventi NativeWindow descritti di seguito. Nota: l'oggetto Window JavaScript dispone di metodi per la creazione degli script della finestra che lo contiene, ad esempio moveTo() e close(). Se sono disponibili dei metodi sovrapposti, potete utilizzare quello più conveniente. Finestra dell'applicazione iniziale La prima finestra dell'applicazione viene creata automaticamente da AIR. AIR imposta le proprietà e il contenuto della finestra utilizzando i parametri specificati nell'elemento initialWindow del file descrittore dell'applicazione. Se il contenuto principale è un file SWF, AIR crea un'istanza NativeWindow, carica il file SWF e lo aggiunge allo stage della finestra. Se il contenuto principale è un file HTML, AIR crea una finestra HTML e carica l'HTML. Per ulteriori informazioni sulle proprietà della finestra specificate nel descrittore dell'applicazione, consultate “Struttura del file descrittore dell'applicazione” a pagina 46. Classi delle finestre native L'API della finestra nativa contiene le classi seguenti: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 63 Operazioni con le finestre native Pacchetto Classi flash.display • NativeWindow • NativeWindowInitOptions • NativeWindowDisplayState • NativeWindowResize • NativeWindowSystemChrome • NativeWindowType Costanti stringa della finestra sono definite nelle classi seguenti: flash.events • NativeWindowDisplayState • NativeWindowResize • NativeWindowSystemChrome • NativeWindowType • NativeWindowBoundsEvent • NativeWindowDisplayStateEvent Flusso di eventi delle finestre native Le finestre native inviano eventi per segnalare ai componenti interessati che una modifica importante sta per verificarsi o si è già verificata. Numerosi eventi relativi alle finestre sono inviati a coppie. Il primo evento avvisa che si sta per verificare una modifica. Il secondo evento annuncia che la modifica è stata eseguita. Potete annullare un evento di avviso, ma non un evento di notifica. Le sequenza seguente illustra il flusso di eventi che si verifica quando un utente fa clic sul pulsante di ingrandimento di una finestra: 1 L'oggetto NativeWindow invia un evento displayStateChanging. 2 Se nessun listener registrato annulla l'evento, la finestra viene ingrandita. 3 L'oggetto NativeWindow invia un evento displayStateChange. Inoltre, l'oggetto NativeWindow invia eventi per modifiche correlate alle dimensioni e alla posizione della finestra. La finestra non invia eventi di avviso per queste modifiche correlate. Gli eventi correlati sono: a Un evento move viene inviato se l'angolo superiore sinistro della finestra è stato spostato a causa dell'operazione di ingrandimento. b Un evento resize viene inviato se le dimensioni della finestra sono state modificate a causa dell'operazione di ingrandimento. Un oggetto NativeWindow invia una sequenza di eventi simili quando una finestra viene ridotta a icona, ripristinata, chiusa, spostata o ridimensionata. Gli eventi di avviso vengono inviati solo quando una modifica viene avviata tramite il chrome della finestra o altri meccanismi controllati dal sistema operativo. Quando chiamate a un metodo della finestra per modificare la dimensione, la posizione o lo stile di visualizzazione della finestra, la finestra invia solo un evento per annunciare la modifica. Se necessario, potete inviare un evento di avviso utilizzando il metodo dispatchEvent() della finestra e quindi controllare se questo evento è stato annullato prima di procedere con la modifica. Per ulteriori informazioni sulle classi, i metodi, le proprietà e gli eventi dell'API della finestra, consultate la Guida di riferimento del linguaggio e dei componenti ActionScript 3.0 (http://www.adobe.com/go/learn_flash_aslr_it). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 64 Operazioni con le finestre native Per informazioni generali sull'utilizzo dell'elenco di visualizzazione Flash, consultate la sezione “Programmazione degli elementi visivi” nel manuale Programmazione in Adobe ActionScript 3.0 (http://www.adobe.com/go/learn_fl_cs4_programmingAS3_it). Proprietà che controllano lo stile e il comportamento delle finestre native Le proprietà seguenti controllano l'aspetto e il comportamento di base di una finestra: • type • systemChrome • transparent Durante la creazione di una finestra, potete impostare queste proprietà sull'oggetto NativeWindowInitOptions passato alla funzione di costruzione della finestra. In AIR, le proprietà relative alla finestra iniziale dell'applicazione vengono lette dal descrittore dell'applicazione (ad eccezione della proprietà type che non può essere impostata nel descrittore dell'applicazione e che è sempre impostata su normal). Dopo che la finestra è stata creata, non è più possibile modificare le proprietà. Alcune impostazioni di queste proprietà sono reciprocamente incompatibili: systemChrome non può essere impostata su standard quando transparent è impostata su true o type è impostata su lightweight. Tipi di finestre I tipi di finestre AIR combinano gli attributi chrome e di visibilità del sistema operativo nativo per creare tre tipi funzionali di finestre. All'interno del codice, potete fare riferimento ai nomi di tipo utilizzando le costanti definite nella classe NativeWindowType. AIR fornisce i tipi di finestre seguenti: Tipo Descrizione Normale Una finestra tipica. Le finestre normali utilizzano il chrome di dimensioni regolari e compaiono sulla barra delle applicazioni di Windows e nel menu delle finestre di Mac OS X. Utilità Una palette strumenti. Le finestre di utilità utilizzano una versione più snella del chrome di sistema e non compaiono sulla barra delle applicazioni di Windows e nel menu delle finestre di Mac OS X. Leggera Le finestre leggere non dispongono di chrome e non compaiono sulla barra delle applicazioni di Windows o nel menu delle finestre di Mac OS X. Inoltre, le finestre leggere non dispongono del menu di sistema (Alt+spazio) in Windows. Le finestre leggere sono adatte per la notifica di fumetti e controlli, ad esempio le caselle combinate che aprono un'area di visualizzazione momentanea. Per il tipo di finestre leggere, impostate systemChrome su none. Chrome della finestra Il chrome della finestra è un insieme di controlli che consentono agli utenti di modificare una finestra nell'ambiente desktop. Gli elementi del chrome includono la barra del titolo, i pulsanti della barra del titolo e le maniglie di ridimensionamento. Chrome di sistema Potete impostare la proprietà systemChrome su standard o none. Per fornire alla finestra l'insieme di controlli standard creati e progettati dal sistema operativo dell'utente, scegliete il chrome di sistema standard. Per fornire un chrome personalizzato per la finestra, scegliete none. All'interno del codice, potete fare riferimento alle impostazioni del chrome di sistema utilizzando le costanti definite nella classe NativeWindowSystemChrome. Il chrome di sistema è gestito dal sistema. L'applicazione non dispone dell'accesso diretto ai controlli, ma può reagire a eventi inviati quando si utilizzano i controlli. Se utilizzate chrome standard per una finestra, la proprietà transparent deve essere impostata su false e la proprietà type deve essere impostata su normal o utility. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 65 Operazioni con le finestre native Chrome personalizzato Se create una finestra senza alcun chrome di sistema, aggiungete controlli chrome personalizzati per gestire le interazioni tra un utente e la finestra. Siete anche liberi di creare finestre trasparenti non rettangolari. Trasparenza della finestra Per consentire la fusione alfa di una finestra con il desktop o un'altra finestra, impostate la proprietà transparent della finestra su true. La proprietà transparent deve essere impostata prima che la finestra venga creata e non può essere modificata. In una finestra trasparente non esiste alcuno sfondo predefinito. Qualsiasi area della finestra che non contiene un oggetto disegnato dall'applicazione è invisibile. Se l'impostazione alfa di un oggetto visualizzato è inferiore a uno, qualunque cosa si trova sotto l'oggetto traspare, compresi altri oggetti di visualizzazione nella stessa finestra, altre finestre e il desktop. Poiché il rendering di aree con fusione alfa di grandi dimensioni può essere lento, si consiglia di utilizzare questo effetto con cautela. Le finestre trasparenti sono utili per creare applicazioni con bordi di forma irregolare, “sfumati” o che non sono visibili. Importante: In Linux gli eventi del mouse non vengono passati per pixel completamente trasparenti. È consigliabile evitare di creare finestre con grandi aree completamente trasparenti in quando è possibile bloccare in modo invisibile l'accesso dell'utente ad altre finestre o altri elementi presenti sul desktop. In Mac OS X e Windows gli eventi del mouse vengono passati per pixel completamente trasparenti. La trasparenza non può essere utilizzata con finestre associate a chrome di sistema. Il contenuto SWF e PDF in HTML inoltre non viene visualizzato in finestre trasparenti. Per ulteriori informazioni, consultate “Considerazioni relative al caricamento di contenuto SWF o PDF in una pagina HTML” a pagina 262. La trasparenza potrebbe non essere supportata in alcuni sistemi operativi a causa della configurazione hardware o software o delle opzioni di visualizzazione utente. Quando la trasparenza non è supportata, l'applicazione viene composta su uno sfondo scuro. In questi casi, tutte le aree completamente trasparenti dell'applicazione vengono visualizzate in nero opaco. La proprietà NativeWindow.supportsTransparency statica segnala se la trasparenza della finestra è disponibile. Se il test di questa proprietà restituisce false, ad esempio, potete visualizzare una finestra di dialogo di avviso all'utente o un'interfaccia utente di fallback, rettangolare, non trasparente. Notate che la trasparenza è sempre supportata dai sistemi operativi Mac e Windows. Il supporto sui sistemi operativi Linux richiede un gestore di finestre che supporta effetti compositi, tuttavia anche quando questo componente è attivo, la trasparenza potrebbe non essere disponibile a causa delle opzioni di visualizzazione dell'utente o della configurazione hardware. Trasparenza in una finestra dell'applicazione HTML Per impostazione predefinita, lo sfondo del contenuto HTML visualizzato nelle finestre HTML e negli oggetti HTMLLoader è opaco, anche se la finestra che li contiene è trasparente. Per disattivare lo sfondo predefinito visualizzato per il contenuto HTML, impostate la proprietà paintsDefaultBackground su false. L'esempio seguente crea un oggetto HTMLLoader e disattiva lo sfondo predefinito: var html:HTMLLoader = new HTMLLoader(); html.paintsDefaultBackground = false; Questo esempio utilizza JavaScript per disattivare lo sfondo predefinito di una finestra HTML: window.htmlLoader.paintsDefaultBackground = false; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 66 Operazioni con le finestre native Se un elemento del documento HTML imposta un colore di sfondo, lo sfondo dell'elemento non è trasparente. L'impostazione di un valore di trasparenza parziale (o opacità) non è supportata. Tuttavia, potete utilizzare un grafico in formato PNG trasparente come sfondo di una pagina o di un elemento della pagina per ottenere un effetto visivo simile. Catalogo finestre visivo Nella tabella seguente sono illustrati gli effetti visivi di diverse combinazioni di impostazioni di proprietà della finestra nei sistemi operativi Mac OS X, Linux e Windows: Impostazioni finestra Tipo: normale SystemChrome: standard Transparent: false Tipo: utilità SystemChrome: standard Transparent: false Mac OS X Microsoft Windows Linux* SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 67 Operazioni con le finestre native Impostazioni finestra Mac OS X Microsoft Windows Linux* Tipo: qualsiasi SystemChrome: none Transparent: false Tipo: qualsiasi SystemChrome: none Transparent: true mxWindowedApplication o mx:Window Tipo: qualsiasi SystemChrome: none Transparent: true * Gestore di finestre Ubuntu con Compiz Nota: gli elementi del chrome di sistema seguenti non sono supportati da AIR: la barra degli strumenti di Mac OS X, l'icona proxy di Mac OS X, le icone della barra del titolo di Windows e il chrome di sistema alternativo. Creazione di finestre In AIR la prima finestra di un'applicazione viene creata automaticamente, ma potete create tutte le finestre aggiuntive necessarie. Per creare una finestra nativa, potete utilizzare il metodo di costruzione della classe NativeWindow. Per creare una finestra HTML potete utilizzare il metodo createRootWindow() di HTMLLoader o chiamare il metodo window.open() di JavaScript da un documento HTM. Specifica delle proprietà di inzializzazione della finestra Le proprietà di inzializzazione di una finestra non possono essere modificate dopo che la finestra desktop è stata creata. Nella tabella seguente sono elencate le proprietà immutabili e i corrispondenti valori predefiniti: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 68 Operazioni con le finestre native Proprietà Valore predefinito systemChrome standard type normal transparent false maximizable true minimizable true resizable true Potete impostare le proprietà della finestra iniziale creata da AIR nel file descrittore dell'applicazione. La finestra principale di un'applicazione AIR è sempre del tipo normale (proprietà della finestra aggiuntive possono essere specificate nel file descrittore, ad esempio visible, width e height, e modificate in qualsiasi momento). Per impostare le proprietà di altre finestre native e HTML create dall'applicazione potete utilizzare la classe NativeWindowInitOptions. Durante la creazione di una finestra, potete passare un oggetto NativeWindowInitOptions che specifica le proprietà della finestra alla funzione di costruzione NativeWindow o al metodo createRootWindow() della classe HTMLLoader. Il codice riportato di seguito crea un oggetto NativeWindowInitOptions per una finestra di utilità: var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = NativeWindowSystemChrome.STANDARD; options.type = NativeWindowType.UTILITY options.transparent = false; options.resizable = false; options.maximizable = false; L'impostazione di systemChrome su standard quando transparent è impostato su true o type è impostato su lightweight non è supportata. Nota: non potete impostare le proprietà di inizializzazione di una finestra creata con la funzione window.open() di JavaScript. Potete, tuttavia, ignorare la modalità di creazione di queste finestre implementando una classe HTMLHost personalizzata. Per ulteriori informazioni, consultate “Gestione delle chiamate JavaScript a window.open()” a pagina 271. Creazione della finestra iniziale dell'applicazione AIR consente di creare la finestra iniziale dell'applicazione in base alle proprietà specificate nel descrittore dell'applicazione e di caricare il file indicato nell'elemento content. L'elemento content deve fare riferimento a un file SWF o HTML. La finestra iniziale può essere la finestra principale dell'applicazione o servire semplicemente per avviare una o più finestre. Non occorre renderla visibile. Lo strumento di creazione Flash consente di creare automaticamente il file SWF e aggiungere il riferimento appropriato al descrittore dell'applicazione quando eseguite il test o pubblicate un progetto per AIR. La sequenza temporale principale funge da punto di ingresso per l'applicazione. Quando l'applicazione viene avviata, AIR consente di creare una finestra e caricare il file SWF dell'applicazione. Per controllare la finestra desktop con ActionScript, potete utilizzare la proprietà nativeWindow dell'oggetto Stage per ottenere un riferimento all'oggetto NativeWindow. Potete quindi impostare le proprietà della finestra e chiamare i metodi della finestra. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 69 Operazioni con le finestre native L'esempio seguente attiva la finestra principale nello stato ingrandita (dal primo frame di un Flash FLA): import flash.display.NativeWindow; var mainWindow:NativeWindow = this.stage.nativeWindow; mainWindow.maximize(); mainWindow.activate(); Creazione di una classe NativeWindow Potete creare una classe NativeWindow passando un oggetto NativeWindowInitOptions al costruttore NativeWindow: var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = NativeWindowSystemChrome.STANDARD; options.transparent = false; var newWindow:NativeWindow = new NativeWindow(options); Per visualizzare la finestra, impostate la proprietà visible su true o chiamate il metodo activate(). Dopo che la finestra è stata creata, potete inizializzare le sue proprietà e caricare il contenuto nella finestra utilizzando la proprietà stage e le tecniche dell'elenco di visualizzazione di Flash. In quasi tutti i casi, occorre impostare la proprietà scaleMode dello stage di una nuova finestra nativa su noScale (utilizzate la costante StageScaleMode.NO_SCALE). Le modalità scala di Flash sono progettate per situazioni in cui l'autore dell'applicazione non conosce in anticipo le proporzioni dello spazio di visualizzazione dell'applicazione. Le modalità scala consentono all'autore di scegliere il compromesso migliore: ritagliare il contenuto, allungarlo o schiacciarlo, oppure riempirlo con spazio vuoto. Poiché AIR fornisce il controllo dello spazio di visualizzazione (la cornice della finestra), potete adattare le dimensioni della finestra al contenuto, o viceversa, senza compromessi. Nota: per determinare le dimensioni massime e minime della finestra consentite nel sistema operativo corrente, potete utilizzare le proprietà NativeWindow statiche seguenti: var maxOSSize:Point = NativeWindow.systemMaxSize; var minOSSize:Point = NativeWindow.systemMinSize; Creazione di una finestra HTML Per creare una finestra HTML, potete chiamare il metodo Window.open() di JavaScript o il metodo createRootWindow() della classe HTMLLoader di AIR. Il contenuto HTML in una sandbox di sicurezza può usare il metodo Window.open() di JavaScript standard. Se il contenuto viene eseguito al di fuori della sandbox dell'applicazione, il metodo open() può essere chiamato solo in risposta all'interazione utente, ad esempio il clic del mouse o la pressione di un tasto. Quando il metodo open() viene chiamato, viene creata una finestra con chrome di sistema per visualizzare il contenuto a livello dell'URL specificato. Ad esempio: newWindow = window.open("xmpl.html", "logWindow", "height=600, width=400, top=10, left=10"); Nota: potete estendere la classe HTMLHost in ActionScript per personalizzare la finestra creata con la funzione window.open() di JavaScript. Consultate “Informazioni sull'estensione della classe HTMLHost” a pagina 266. Il contenuto della sandbox di sicurezza dell'applicazione ha accesso al più potente metodo di creazione delle finestre, HTMLLoader.createRootWindow(). Grazie a questo metodo, potete specificare tutte le opzioni di creazione per una nuova finestra. Ad esempio, il codice JavaScript riportato di seguito crea una finestra di tipo leggero senza chrome di sistema con una dimensione di 300x400 pixel: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 70 Operazioni con le finestre native var options = new air.NativeWindowInitOptions(); options.systemChrome = "none"; options.type = "lightweight"; var windowBounds = new air.Rectangle(200,250,300,400); newHTMLLoader = air.HTMLLoader.createRootWindow(true, options, true, windowBounds); newHTMLLoader.load(new air.URLRequest("xmpl.html")); Nota: se il contenuto caricato da una nuova finestra è esterno alla sandbox di sicurezza dell'applicazione, l'oggetto window non dispone delle proprietà AIR: runtime, nativeWindow o htmlLoader. Le finestre create con il metodo createRootWindow() rimangono indipendenti rispetto alla finestra di apertura. Le proprietà parent e opener dell'oggetto Window JavaScript sono null. La finestra di apertura può accedere all'oggetto Window della nuova finestra utilizzando il riferimento HTMLLoader restituito dalla funzione createRootWindow(). Nel contesto dell'esempio precedente, l'istruzione newHTMLLoader.window fa riferimento all'oggetto Window JavaScript della finestra creata. Nota: la funzione createRootWindow() può essere chiamata da JavaScript e ActionScript. Aggiunta di contenuto a una finestra La modalità utilizzata per aggiungere contenuto a una finestra AIR dipende dal tipo di finestra. Potete creare un clip filmato e utilizzare la linea temporale per controllare lo stato dell'applicazione. HTML consente di definire il contenuto di base della finestra tramite dichiarazioni. Potete incorporare risorse nel file SWF dell'applicazione oppure caricarle da file dell'applicazione separati. Tutto il contenuto Flash e HTML può essere creato al volo e aggiunto dinamicamente a una finestra. Durante il caricamento di contenuto SWF, o contenuto HTML contenente JavaScript, occorre considerare il modello di sicurezza AIR. Tutto il contenuto nella sandbox di sicurezza dell'applicazione, ovvero, contenuto installato con l'applicazione e caricabile con lo schema URL app:, dispone di privilegi per accedere a tutte le API di AIR. L'eventuale contenuto caricato dall'esterno della sandbox non può accedere alle API di AIR. Il contenuto JavaScript esterno alla sandbox dell'applicazione non è in grado di utilizzare le proprietà runtime, nativeWindow o htmlLoader dell'oggetto Window di JavaScript. Per consentire il cross-scripting protetto, potete usare un bridge sandbox per fornire un'interfaccia limitata tra il contenuto dell'applicazione e quello esterno all'applicazione. Nel contenuto HTML, potete anche mappare pagine dell'applicazione in una sandbox non dell'applicazione per consentire al codice della pagina di eseguire il cross-script di contenuto esterno. Consultate “Sicurezza in AIR” a pagina 25. Caricamento di un file SWF o di un'immagine Per caricare file SWF di Flash o immagini nell'elenco di visualizzazione di una finestra nativa, potete utilizzare la classe flash.display.Loader: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 71 Operazioni con le finestre native package { import import import import flash.display.Sprite; flash.events.Event; flash.net.URLRequest; flash.display.Loader; public class LoadedSWF extends Sprite { public function LoadedSWF(){ var loader:Loader = new Loader(); loader.load(new URLRequest("visual.swf")); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loadFlash); } private function loadFlash(event:Event):void{ addChild(event.target.loader); } } } Potete caricare un file SWF che contiene il codice della libreria per l'utilizzo in un'applicazione basata su HTML. Il modo più semplice per caricare un file SWF in una finestra HTML consiste nell'uso del tag script, tuttavia potete anche usare direttamente l'API Loader. Nota: file SWF precedenti creati utilizzando ActionScript 1 o 2 condividono stati globali quali definizioni di classe, singleton e variabili globali se sono caricati nella stessa finestra. Un file SWF che si basa su stati globali inalterati per funzionare correttamente non può essere caricato più volte nella stessa finestra, o caricato nella stessa finestra come un altro file SWF utilizzando definizioni di classi e variabili sovrapposte. Questo contenuto può essere, tuttavia, caricato in finestre separate. Caricamento di contenuto HTML in una classe NativeWindow Per caricare contenuto HTML in una classe NativeWindow, potete aggiungere un oggetto HTMLLoader allo stage della finestra e caricare il contenuto HTML nella classe HTMLLoader, oppure creare una finestra che contiene già un oggetto HTMLLoader utilizzando il metodo HTMLLoader.createRootWindow(). L'esempio seguente visualizza il contenuto HTML all'interno di un'area di visualizzazione di 300 x 500 pixel sullo stage di una finestra nativa: //newWindow is a NativeWindow instance var htmlView:HTMLLoader = new HTMLLoader(); html.width = 300; html.height = 500; //set the stage so display objects are added to the top-left and not scaled newWindow.stage.align = "TL"; newWindow.stage.scaleMode = "noScale"; newWindow.stage.addChild( htmlView ); //urlString is the URL of the HTML page to load htmlView.load( new URLRequest(urlString) ); Nota: il contenuto SWF o PDF in un file HTML non viene visualizzato se la finestra utilizza la trasparenza (ovvero la proprietà transparent della finestra è impostata su true) o se il controllo HTMLLoader è stato ridimensionato. Aggiunta di contenuto SWF come sovrapposizione in una finestra HTML Poiché le finestre HTML sono contenute all'interno di un'istanza NativeWindow, potete aggiungere oggetti di visualizzazione Flash sopra e sotto il livello HTML nell'elenco di visualizzazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 72 Operazioni con le finestre native Per aggiungere un oggetto di visualizzazione sopra il livello HTML, potete utilizzare il metodo addChild() della proprietà window.nativeWindow.stage. Il metodo addChild() consente di aggiungere contenuto su più livelli sopra qualsiasi contenuto esistente nella finestra. Per aggiungere un oggetto di visualizzazione sotto il livello HTML, potete utilizzare il metodo addChildAt() della proprietà window.nativeWindow.stage, passando un valore zero per il parametro index. Il posizionamento di un oggetto in corrispondenza dell'indice zero consente di spostare il contenuto esistente, compresa la visualizzazione HTML, di un livello verso l'alto e di inserire il nuovo contenuto nella parte inferiore. Per rendere visibile il contenuto disposto su più livelli sotto la pagina HTML, potete impostare la proprietà paintsDefaultBackground dell'oggetto HTMLlLoader su false. Inoltre, tutti gli elementi della pagina che impostano un colore di sfondo non sono trasparenti. Se, ad esempio, impostate un colore di sfondo per il corpo della pagina, nessuna delle pagine sarà trasparente. L'esempio seguente illustra come aggiungere oggetti di visualizzazione Flash come overlay e underlay a una pagina HTML. L'esempio crea due semplici oggetti shape, aggiungendone uno sotto il contenuto HTML e uno sopra. L'esempio inoltre aggiorna la posizione degli oggetti in base all'evento enterFrame. <html> <head> <title>Bouncers</title> <script src="AIRAliases.js" type="text/javascript"></script> <script language="JavaScript" type="text/javascript"> air.Shape = window.runtime.flash.display.Shape; function Bouncer(radius, color){ this.radius = radius; this.color = color; //velocity this.vX = -1.3; this.vY = -1; //Create a Shape object and draw a circle with its graphics property this.shape = new air.Shape(); this.shape.graphics.lineStyle(1,0); this.shape.graphics.beginFill(this.color,.9); this.shape.graphics.drawCircle(0,0,this.radius); this.shape.graphics.endFill(); //Set the starting position this.shape.x = 100; this.shape.y = 100; //Moves the sprite by adding (vX,vY) to the current position this.update = function(){ this.shape.x += this.vX; this.shape.y += this.vY; //Keep the sprite within the window if( this.shape.x - this.radius < 0){ this.vX = -this.vX; } if( this.shape.y - this.radius < 0){ this.vY = -this.vY; } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 73 Operazioni con le finestre native if( this.shape.x + this.radius > window.nativeWindow.stage.stageWidth){ this.vX = -this.vX; } if( this.shape.y + this.radius > window.nativeWindow.stage.stageHeight){ this.vY = -this.vY; } }; } function init(){ //turn off the default HTML background window.htmlLoader.paintsDefaultBackground = false; var bottom = new Bouncer(60,0xff2233); var top = new Bouncer(30,0x2441ff); //listen for the enterFrame event window.htmlLoader.addEventListener("enterFrame",function(evt){ bottom.update(); top.update(); }); //add the bouncing shapes to the window stage window.nativeWindow.stage.addChildAt(bottom.shape,0); window.nativeWindow.stage.addChild(top.shape); } </script> <body onload="init();"> <h1>de Finibus Bonorum et Malorum</h1> <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p> <p style="background-color:#FFFF00; color:#660000;">This paragraph has a background color.</p> <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.</p> </body> </html> Questo esempio fornisce un'introduzione di base ad alcune tecniche avanzate non esclusive di JavaScript o ActionScript in AIR. Se non avete famigliarità con l'uso degli oggetti di visualizzazione di ActionScript, fate riferimento alla sezione Programmazione degli elementi visivi nel manuale Programmazione in Adobe ActionScript 3.0 per ulteriori informazioni. Esempio: creazione di una finestra nativa L'esempio seguente illustra come creare una finestra nativa: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 74 Operazioni con le finestre native public function createNativeWindow():void { //create the init options var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.transparent = false; options.systemChrome = NativeWindowSystemChrome.STANDARD; options.type = NativeWindowType.NORMAL; //create the window var newWindow:NativeWindow = new NativeWindow(options); newWindow.title = "A title"; newWindow.width = 600; newWindow.height = 400; newWindow.stage.align = StageAlign.TOP_LEFT; newWindow.stage.scaleMode = StageScaleMode.NO_SCALE; //activate and show the new window newWindow.activate(); } Gestione delle finestre Potete utilizzare le proprietà e i metodi della classe NativeWindow per gestire l'aspetto, il comportamento e il ciclo di vita delle finestre desktop. Ottenere un'istanza NativeWindow Per modificare una finestra, occorre innanzitutto ottenere l'istanza della finestra. Potete ottenere un'istanza della finestra da una delle posizioni seguenti: • Il metodo di costruzione della finestra nativa usato per creare la finestra: var win:NativeWindow = new NativeWindow(initOptions); • La proprietà nativeWindow dello stage della finestra: var win:NativeWindow = stage.nativeWindow; • La proprietà stage di un oggetto di visualizzazione nella finestra: var win:NativeWindow = displayObject.stage.nativeWindow; • La proprietà target dell'evento window nativo inviato dalla finestra: private function onNativeWindowEvent(event:NativeWindowBoundsEvent):void { var win:NativeWindow = event.target as NativeWindow; } • La proprietà nativeWindow di una pagina HTML visualizzata nella finestra: var win:NativeWindow = htmlLoader.window.nativeWindow; • Le proprietà activeWindow e openedWindows dell'oggetto NativeApplication: var nativeWin:NativeWindow = NativeApplication.nativeApplication.activeWindow; var firstWindow:NativeWindow = NativeApplication.nativeApplication.openedWindows[0]; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 75 Operazioni con le finestre native NativeApplication.nativeApplication.activeWindow fa riferimento alla finestra attiva di un'applicazione (ma restituisce null se la finestra attiva non è una finestra dell'applicazione AIR). L'array NativeApplication.nativeApplication.openedWindows contiene tutte le finestre di un'applicazione AIR che non è stata chiusa. Attivare, mostrare e nascondere finestre Per attivare una finestra, potete chiamare il metodo activate() della classe NativeWindow. L'operazione di attivazione porta una finestra in primo piano, attiva la tastiera e il mouse, e, se necessario, rende la finestra visibile ripristinandola o impostando la proprietà visiblesu true. L'attivazione di una finestra non cambia l'ordine delle altre finestre nell'applicazione. La chiamata al metodo activate() causa l'invio di un evento activate. Per mostrare o nascondere una finestra senza attivarla, potete impostare la proprietà visible su true. Questa operazione porta la finestra in primo piano senza però attivarla. Per nascondere una finestra, potete impostare la sua proprietà visible su false. Nascondere una finestra significa non visualizzare la finestra, le eventuali icone della barra delle applicazioni correlate e, in Mac OS X, le voci del menu Finestre. Nota: in Mac OS X, non è possibile nascondere completamente una finestra ridotta a icona che presenta un'icona nella parte finestra del dock. Se, in una finestra ridotta a icona, la proprietà visible è impostata su false, l'icona del dock per la finestra è ancora visualizzata. Se l'utente fa clic sull'icona, la finestra viene ripristinata in una stato visibile e visualizzata. Modifica dell'ordine di visualizzazione delle finestre AIR fornisce diversi metodi per modificare direttamente l'ordine di visualizzazione delle finestre. Potete spostare una finestra in primo piano o sullo sfondo nell'ordine di visualizzazione; potete spostare una finestra sopra o dietro un'altra finestra. Allo stesso tempo, l'utente può riordinare le finestre attivandole. Potete tenere una finestra in primo piano rispetto alle altre finestre impostando la sua proprietà alwaysInFront su true. Se più finestre hanno questa impostazione, l'ordine di visualizzazione di queste finestre è definito tra loro stesse, ma comunque sempre sopra le finestre la cui proprietà alwaysInFront è impostata su false. Le finestre nel gruppo in primo piano sono sempre visualizzate sopra le finestre di altre applicazioni, anche quando l'applicazione AIR non è attiva. Poiché questo comportamento può disturbare il lavoro dell'utente, è opportuno impostare alwaysInFront su true solo quando è necessario e appropriato. Esempi di uso giustificato includono: • Finestre popup temporanee per controlli quali descrizioni comandi, elenchi popup, menu personalizzati o caselle combinate. Poiché queste finestre si devono chiudere quando non sono più attive, è possibile evitare di bloccare la visualizzazione di altre finestre. • Messaggi di errore e avvisi estremamente urgenti. Se la mancata risposta dell'utente in un tempo utile causa una modifica irrevocabile, potrebbe essere giustificato visualizzare una finestra di avviso in primo piano. Tuttavia, la maggior parte degli errori e avvisi può essere gestito nel normale ordine di visualizzazione delle finestre. • Finestre stile toast momentanee. Nota: AIR non impone il corretto utilizzo della proprietà alwaysInFront. Tuttavia, se l'applicazione disturba il flusso di lavoro di un utente, è probabile che finisca nel cestino. La classe NativeWindow fornisce le proprietà e i metodi seguenti per l'impostazione dell'ordine di visualizzazione di una finestra in relazione alle altre finestre: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 76 Operazioni con le finestre native Membro Descrizione proprietà alwaysInFront Specifica se la finestra è visualizzata nel gruppo di finestre in primo piano. In quasi tutti i casi, false è la migliore impostazione. Modificando il valore da false a true, la finestra viene portata in primo piano rispetto a tutte le altre finestre (senza che venga attivata). Modificando il valore da true a false, la finestra viene portata in secondo piano rispetto alle finestre restanti nel gruppo in primo piano, ma ancora in primo piano rispetto alle altre finestre. Se si imposta la proprietà sul suo valore corrente per una finestra, l'ordine di visualizzazione delle finestre non cambia. orderToFront() Porta la finestra in primo piano. orderInFrontOf() Porta la finestra direttamente in primo piano rispetto a una particolare finestra. orderToBack() Manda la finestra in secondo piano rispetto alle altre finestre. orderBehind() Manda la finestra direttamente in secondo piano rispetto a una particolare finestra. activate() Porta la finestra in primo piano (oltre a renderla visibile e attiva). Nota: se una finestra è nascosta (visible è false) o ridotta a icona, la chiamata dei metodi di ordinamento della visualizzazione non ha effetto. Nel sistema operativo Linux, diversi gestori di finestre applicano regole diverse per quanto riguarda l'ordine di visualizzazione delle finestre: • In alcuni gestori di finestre, le finestre di utilità vengono visualizzate in primo piano rispetto alle finestre normali. • In alcuni gestori di finestre, una finestra a schermo intero con la proprietà alwaysInFront impostata su true viene sempre visualizzata in primo piano rispetto ad altre finestre la cui proprietà alwaysInFront è impostata su true. Chiusura di una finestra Per chiudere una finestra, potete utilizzare il metodo NativeWindow.close(). La chiusura di una finestra consente di scaricane il contenuto, ma se altri oggetti contengono riferimenti a questo contenuto, gli oggetti contenuto non vengono distrutti. Il metodo NativeWindow.close() viene eseguito in maniera asincrona, l'applicazione contenuta nella finestra continua a essere eseguita durante il processo di chiusura. Il metodo close invia un evento close quando l'operazione di chiusura è terminata. L'oggetto NativeWindow è ancora tecnicamente valido, ma l'accesso alla maggior parte delle proprietà e dei metodi di una finestra chiusa genera un IllegalOperationError. Non potete riaprire una finestra chiusa. Potete verificare se una finestra è stata chiusa controllando la proprietà closed. Per nascondere una finestra, potete impostare la proprietà NativeWindow.visible su false. Se la proprietà Nativeapplication.autoExit è true (impostazione predefinita), l'applicazione esce quando viene chiusa l'ultima finestra. Annullamento delle operazioni sulla finestra Quando una finestra utilizza il chrome di sistema, l'interazione con l'utente può essere annullata intercettando e annullando il comportamento predefinito degli eventi appropriati. Ad esempio, se un utente fa clic sul pulsante di chiusura del chrome di sistema, viene inviato l'evento closing. Se qualsiasi listener registrato chiama il metodo preventDefault() dell'evento, la finestra non si chiude. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 77 Operazioni con le finestre native Se una finestra non utilizza il chrome di sistema, gli eventi di notifica per le modifiche designate non vengono inviati automaticamente prima che venga apportata la modifica. Pertanto, se si chiamano i metodi per chiudere una finestra, modificare lo stato della finestra o impostare le proprietà dei limiti della finestra, la modifica non può essere annullata. Per inviare notifiche ai componenti dell'applicazione prima di apportare una modifica alla finestra, la logica dell'applicazione può inviare l'evento di notifica relativo utilizzando il metodo dispatchEvent() della finestra. Ad esempio, la logica seguente implementa un gestore eventi annullabile per un pulsante di chiusura della finestra: public function onCloseCommand(event:MouseEvent):void{ var closingEvent:Event = new Event(Event.CLOSING,true,true); dispatchEvent(closing); if(!closingEvent.isDefaultPrevented()){ win.close(); } } Il metodo dispatchEvent() restituisce false se il metodo preventDefault() dell'evento viene chiamato da un listener. Tuttavia, può anche restituire false per altri motivi, pertanto è preferibile utilizzare in modo esplicito il metodo isDefaultPrevented() per verificare se la modifica deve essere annullata. Ingrandimento, riduzione a icona e ripristino di una finestra Per ingrandire la finestra, potete utilizzare il metodo maximize() della classe NativeWindow. myWindow.maximize(); Per ridurre a icona la finestra, potete utilizzare il metodo minimize() della classe NativeWindow. myWindow.minimize(); Per ripristinare la finestra (ovvero, riportarla alle dimensioni che aveva prima di essere ridotta a icona o ingrandita), potete utilizzare il metodo restore() della classe NativeWindow. myWindow.restore(); Nota: il comportamento che deriva dall'ingrandimento di una finestra AIR è diverso dal comportamento standard di Mac OS X. Anziché passare da una dimensione “standard” definita dall'applicazione all'ultima dimensione impostata dall'utente, e viceversa, le finestre AIR passano dall'ultima dimensione impostata dall'applicazione o dall'utente all'area utilizzabile dello schermo, e viceversa. Nel sistema operativo Linux, diversi gestori di finestre applicano regole diverse per quanto riguarda l'impostazione dello stato di visualizzazione delle finestre: • In alcuni gestori di finestre, le finestre di utilità non possono essere ingrandite. • Se vengono impostate le dimensioni massime per la finestra, alcune finestre non consentono l'ingrandimento. Altri gestori di finestre impostano lo stato di visualizzazione su ingrandita, ma non ridimensionano la finestra. In entrambi i casi, non viene inviato alcun evento di modifica dello stato. • Alcuni gestori di finestre non rispettano l'impostazione maximizable o minimizable relativa alle finestre. Esempio: riduzione a icona, ingrandimento, ripristino e chiusura di una finestra L'esempio ActionScript seguente per Flash crea quattro campi di testo selezionabili che attivano i metodi minimize(), maximize(), restore() e close() della classe NativeWindow: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 78 Operazioni con le finestre native package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.text.TextField; public class MinimizeExample extends Sprite { public function MinimizeExample():void { var minTextBtn:TextField = new TextField(); minTextBtn.x = 10; minTextBtn.y = 10; minTextBtn.text = "Minimize"; minTextBtn.background = true; minTextBtn.border = true; minTextBtn.selectable = false; addChild(minTextBtn); minTextBtn.addEventListener(MouseEvent.CLICK, onMinimize); var maxTextBtn:TextField = new TextField(); maxTextBtn.x = 120; maxTextBtn.y = 10; maxTextBtn.text = "Maximize"; maxTextBtn.background = true; maxTextBtn.border = true; maxTextBtn.selectable = false; addChild(maxTextBtn); maxTextBtn.addEventListener(MouseEvent.CLICK, onMaximize); var restoreTextBtn:TextField = new TextField(); restoreTextBtn.x = 230; restoreTextBtn.y = 10; restoreTextBtn.text = "Restore"; restoreTextBtn.background = true; restoreTextBtn.border = true; restoreTextBtn.selectable = false; addChild(restoreTextBtn); restoreTextBtn.addEventListener(MouseEvent.CLICK, onRestore); var closeTextBtn:TextField = new TextField(); closeTextBtn.x = 340; closeTextBtn.y = 10; closeTextBtn.text = "Close Window"; closeTextBtn.background = true; closeTextBtn.border = true; closeTextBtn.selectable = false; addChild(closeTextBtn); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 79 Operazioni con le finestre native closeTextBtn.addEventListener(MouseEvent.CLICK, onCloseWindow); } function onMinimize(event:MouseEvent):void { this.stage.nativeWindow.minimize(); } function onMaximize(event:MouseEvent):void { this.stage.nativeWindow.maximize(); } function onRestore(event:MouseEvent):void { this.stage.nativeWindow.restore(); } function onCloseWindow(event:MouseEvent):void { this.stage.nativeWindow.close(); } } } Ridimensionamento e spostamento di una finestra Il chrome di sistema di una finestra fornisce i controlli di trascinamento per il ridimensionamento e lo spostamento della finestra sul desktop. Se una finestra non utilizza il chrome di sistema, occorre aggiungere controlli personalizzati per consentire all'utente di ridimensionare e spostare la finestra. Nota: prima di ridimensionare o spostare una finestra, occorre ottenere un riferimento all'istanza NativeWindow. Per informazioni su come ottenere un riferimento alla finestra, consultate “Ottenere un'istanza NativeWindow” a pagina 74. Ridimensionamento di una finestra Per consentire all'utente di ridimensionare una finestra in modo interattivo, usate il metodo startResize() della classe NativeWindow. Quando questo metodo viene chiamato da un evento mouseDown, l'operazione di ridimensionamento viene guidata dal mouse e terminata quando il sistema riceve un evento mouseUp. La chiamata al metodo startResize() prevede il passaggio di un argomento che specifica il bordo o l'angolo da cui ridimensionare la finestra. Per impostare le dimensioni della finestra a livello di codice, impostate la proprietà width, height o bounds della finestra sulle dimensioni desiderate. Quando impostate i limiti, potete modificare contemporaneamente sia le dimensioni che la posizione della finestra. Non è tuttavia garantito l'ordine in cui vengono applicate le modifiche. Alcuni gestori di finestre in Linux non consentono l'estensione delle finestra oltre i limiti dello schermo del desktop. In questi casi, le dimensioni finali della finestra possono essere limitate a causa dell'ordine in cui vengono impostate le proprietà, anche se l'effetto delle modifiche avrebbe, diversamente, prodotto una finestra valida. Se, ad esempio, modificate sia l'altezza che la posizione y di una finestra vicina alla parte inferiore dello schermo, la modifica dell'altezza completa potrebbe non avvenire se viene applicata prima della modifica della posizione y. Nota: in Linux, le proprietà delle finestre vengono modificate in modo asincrono. Se impostate una proprietà in una riga del programma e leggete il valore nella riga successiva, il valore letto continua a riflettere l'impostazione precedente. Potete usare gli eventi generati dalla finestra per rilevare quando la modifica viene applicata. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 80 Operazioni con le finestre native La modalità scala dello stage determina il comportamento dello stage della finestra e del suo contenuto quando una finestra viene ridimensionata. Tenete presente che le modalità scala dello stage sono progettate per situazioni, come un browser Web, in cui l'applicazione non controlla le dimensioni o le proporzioni del suo spazio di visualizzazione. In generale, potete ottenere i risultati migliori impostando la proprietà scaleMode dello stage su StageScaleMode.NO_SCALE. Se desiderate che il contenuto della finestra venga ridimensionato, potete ancora impostare i parametri scaleX e scaleY del contenuto in risposta alle modifiche dei limiti della finestra. Spostamento di una finestra Per spostare una finestra senza ridimensionarla, potete utilizzare il metodo startMove() della classe NativeWindow. Analogamente al metodo startResize(), quando il metodo startMove() viene chiamato da un evento mouseDown, il processo di spostamento è guidato dal mouse e termina quando il sistema operativo riceve un evento mouseUp. Per ulteriori informazioni sui metodi startResize e startMove, consultate la Guida di riferimento del linguaggio e dei componenti ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_it). Esempio: ridimensionamento e spostamento di finestre L'esempio seguente mostra come avviare le operazioni di ridimensionamento e spostamento in una finestra: package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.display.NativeWindowResize; public class NativeWindowResizeExample extends Sprite { public function NativeWindowResizeExample():void { // Fills a background area. this.graphics.beginFill(0xFFFFFF); this.graphics.drawRect(0, 0, 400, 300); this.graphics.endFill(); // Creates a square area where a mouse down will start the resize. var resizeHandle:Sprite = createSprite(0xCCCCCC, 20, this.width - 20, this.height - 20); resizeHandle.addEventListener(MouseEvent.MOUSE_DOWN, onStartResize); // Creates a square area where a mouse down will start the move. var moveHandle:Sprite = createSprite(0xCCCCCC, 20, this.width - 20, 0); moveHandle.addEventListener(MouseEvent.MOUSE_DOWN, onStartMove); } public function createSprite(color:int, size:int, x:int, y:int):Sprite { var s:Sprite = new Sprite(); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 81 Operazioni con le finestre native s.graphics.beginFill(color); s.graphics.drawRect(0, 0, size, size); s.graphics.endFill(); s.x = x; s.y = y; this.addChild(s); return s; } public function onStartResize(event:MouseEvent):void { this.stage.nativeWindow.startResize(NativeWindowResize.BOTTOM_RIGHT); } public function onStartMove(event:MouseEvent):void { this.stage.nativeWindow.startMove(); } } } Intercettazione degli eventi della finestra Per intercettare gli eventi inviati da una finestra, potete registrare un listener con l'istanza della finestra. Ad esempio, potete intercettare l'evento di chiusura registrando un listener con la finestra come descritto di seguito: myWindow.addEventListener(Event.CLOSING, onClosingEvent); Quando un evento viene inviato, la proprietà target fa riferimento alla finestra che invia l'evento. La maggior parte degli eventi della finestra hanno due messaggi correlati. Il primo messaggio segnala che una modifica della finestra è imminente (e può essere annullata), mentre il secondo messaggio segnala che la modifica si è verificata. Ad esempio, quando un utente fa clic sul pulsante di chiusura di una finestra, viene inviato il messaggio relativo all'evento di chiusura. Se nessun listener annulla l'evento, la finestra viene chiusa e l'evento di chiusura viene inviato a tutti i listener. In genere, gli eventi di avviso, ad esempio closing, vengono inviati solo quando il chrome di sistema è stato utilizzato per attivare un evento. La chiamata del metodo close() della finestra, ad esempio, non invia automaticamente l'evento closing, ma solo l'evento close. È possibile, tuttavia, costruire un oggetto evento di chiusura e inviarlo utilizzando il metodo dispatchEvent() della finestra. Gli eventi della finestra che inviano un oggetto Event sono: Evento Descrizione activate Inviato quando la finestra viene attivata. deactivate Inviato quando la finestra viene disattivata. closing Inviato quando la finestra sta per chiudersi. Questo si verifica automaticamente solo quando si preme il pulsante di chiusura del chrome di sistema o, in Mac OS X, quando viene invocato il comando Quit. close Inviato quando la finestra è stata chiusa. Gli eventi della finestra che inviano un oggetto NativeWindowBoundsEvent sono: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 82 Operazioni con le finestre native Evento Descrizione moving Inviato subito prima che l'angolo superiore sinistro della finestra cambi posizione, come risultato dello spostamento, ridimensionamento o modifica dello stato di visualizzazione della finestra. move Inviato dopo che l'angolo superiore sinistro ha cambiato posizione. resizing Inviato subito prima della modifica della larghezza o altezza della finestra come risultato del ridimensionamento o della modifica dello stato di visualizzazione. resize Inviato dopo che la dimensione della finestra è stata modificata. Per gli eventi NativeWindowBoundsEvent, potete utilizzare le proprietà beforeBounds e afterBounds per determinare i limiti della finestra prima e dopo la modifica imminente o completata Gli eventi della finestra che inviano un oggetto NativeWindowDisplayStateEvent sono: Evento Descrizione displayStateChanging Inviato subito prima della modifica dello stato di visualizzazione della finestra. displayStateChange Inviato dopo che lo stato di visualizzazione della finestra è stato modificato. Per gli eventi NativeWindowDisplayStateEvent, potete utilizzare le proprietà beforeDisplayState e afterDisplayState per determinare lo stato di visualizzazione della finestra prima e dopo la modifica imminente o completata. In alcuni gestori di finestre di Linux, non viene inviato un evento di modifica dello stato di visualizzazione quando viene ingrandita una finestra con un'impostazione delle dimensioni massime. (La finestra viene impostata sullo stato di visualizzazione ingrandita, ma non viene ridimensionata). Visualizzazione di finestre a schermo intero L'impostazione della proprietà displayState dello Stage su StageDisplayState.FULL_SCREEN_INTERACTIVE consente di attivare la modalità a schermo intero della finestra. In questa modalità l'input da tastiera è consentito (nel contenuto SWF eseguito in un browser, l'input da tastiera non è consentito). Per uscire dalla modalità a schermo intero, l'utente deve premere il tasto ESC. Nota: alcuni gestori di finestre di Linux non modificano le dimensioni della finestra a schermo intero se per la finestra sono impostate le dimensioni massime (viene però rimosso il chrome di sistema della finestra). Il codice ActionScript seguente per Flash simula un semplice terminale di testo a schermo intero SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 83 Operazioni con le finestre native import import import import flash.display.Sprite; flash.display.StageDisplayState; flash.text.TextField; flash.text.TextFormat; public class FullScreenTerminalExample extends Sprite { public function FullScreenTerminalExample():void { var terminal:TextField = new TextField(); terminal.multiline = true; terminal.wordWrap = true; terminal.selectable = true; terminal.background = true; terminal.backgroundColor = 0x00333333; this.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE; addChild(terminal); terminal.width = 550; terminal.height = 400; terminal.text = "Welcome to the dumb terminal application. Press the ESC key to exit.\n_"; var tf:TextFormat = new TextFormat(); tf.font = "Courier New"; tf.color = 0x00CCFF00; tf.size = 12; terminal.setTextFormat(tf); terminal.setSelection(terminal.text.length - 1, terminal.text.length); } } 84 Capitolo 11: Schermate La classe Screen di Adobe® AIR® consente di accedere alle informazioni che riguardano le schermate visualizzate sul monitor del computer. Ulteriori informazioni online sulle schermate È possibile reperire ulteriori informazioni sulla classe Screen e sull'uso delle schermate dalle seguenti fonti: Guide rapide (Centro per sviluppatori Adobe AIR) • Measuring the virtual desktop (Misurazione del desktop virtuale) Guida di riferimento del linguaggio • Screen Articoli ed esempi del Centro per sviluppatori Adobe • Centro per sviluppatori Adobe AIR per Flash (cercate 'AIR screens') Nozioni di base sulle schermate L'interfaccia API delle schermate contiene soltanto la classe Screen, che include membri statici per ottenere informazioni sulle schermate del sistema e membri di istanza per descrivere una schermata particolare. Un sistema di computer può includere svariati monitor o schermi collegati, i quali possono corrispondere a svariate schermate desktop disposte in uno spazio virtuale. La classe Screen di AIR fornisce informazioni sulle schermate, sulla loro disposizione relativa e sul loro spazio utilizzabile. Se più di un monitor viene mappato sulla stessa schermata, esiste una sola schermata. Se la schermata ha dimensioni maggiori dell'area di visualizzazione del monitor, non vi è modo di sapere quale porzione della schermata sia visibile al momento. Una schermata rappresenta un'area di visualizzazione del desktop indipendente. Le schermate vengono descritte come rettangoli all'interno del desktop virtuale. L'angolo in alto a sinistra della schermata, designato come schermo principale, è l'origine del sistema di coordinate del desktop virtuale. Tutti i valori usati per descrivere una schermata sono espressi in pixel. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 85 Schermate In questa particolare disposizione delle schermate, sul desktop virtuale sono presenti due schermate. Le coordinate dell'angolo in alto a sinistra della schermata principale (n. 1) sono sempre (0,0). Se la disposizione delle schermate viene modificata in modo che la schermata n. 2 sia la schermata principale, le coordinate della schermata n. 1 diventano negative. Barre di menu, barre degli strumenti e dock sono esclusi dalla definizione dei limiti utilizzabili per una schermata. Per informazioni dettagliate sulla classe API, i metodi, le proprietà e gli eventi relativi alle schermate, consultate la Guida di riferimento del linguaggio e dei componenti ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_it). Enumerazione delle schermate Potete enumerare le schermate del desktop virtuale con i metodi e le proprietà seguenti relativi alle schermate: Metodo o proprietà Descrizione Screen.screens Fornisce un array di oggetti Screen che descrivono le schermate disponibili. L'ordine dell'array non è rilevante. Screen.mainScreen Fornisce un oggetto Screen per la schermata principale. In Mac OS X, la schermata principale è quella che visualizza la barra dei menu. In Windows, la schermata principale è quella designata come primaria dal sistema. Screen.getScreensForRectangle() Fornisce una serie di oggetti Screen che descrivono le schermate intersecate dal rettangolo specifico. Il rettangolo passato a questo metodo è espresso secondo coordinate in pixel sul desktop virtuale. Se nessuna schermata interseca il rettangolo, la serie è vuota. Potete usare questo metodo per determinare in quali schermate viene visualizzata una finestra. Non dovreste salvare i valori restituiti dai metodi e dalle proprietà della classe Screen. L'utente o il sistema operativo possono modificare le schermate disponibili e la loro disposizione in qualsiasi momento. Nel seguente esempio viene usata l'interfaccia API della schermata per spostare una finestra tra schermate multiple in risposta alla pressione dei tasti freccia. Per spostare la finestra nella schermata successiva, l'esempio ottiene l'array screens e lo ordina in senso verticale o orizzontale (in base al tasto freccia premuto). Il codice scorre quindi l'array ordinato, confrontando ogni schermata con le coordinate della schermata corrente. Per identificare la schermata corrente della finestra, l'esempio richiama Screen.getScreensForRectangle(), specificando i limiti della finestra. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 86 Schermate package { import import import import import import flash.display.Sprite; flash.display.Screen; flash.events.KeyboardEvent; flash.ui.Keyboard; flash.display.StageAlign; flash.display.StageScaleMode; public class ScreenExample extends Sprite { public function ScreenExample() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey); } private function onKey(event:KeyboardEvent):void{ if(Screen.screens.length > 1){ switch(event.keyCode){ case Keyboard.LEFT : moveLeft(); break; case Keyboard.RIGHT : moveRight(); break; case Keyboard.UP : moveUp(); break; case Keyboard.DOWN : moveDown(); break; } } } private function moveLeft():void{ var currentScreen = getCurrentScreen(); var left:Array = Screen.screens; left.sort(sortHorizontal); for(var i:int = 0; i < left.length - 1; i++){ if(left[i].bounds.left < stage.nativeWindow.bounds.left){ stage.nativeWindow.x += left[i].bounds.left - currentScreen.bounds.left; stage.nativeWindow.y += left[i].bounds.top - currentScreen.bounds.top; } } } private function moveRight():void{ var currentScreen:Screen = getCurrentScreen(); var left:Array = Screen.screens; left.sort(sortHorizontal); for(var i:int = left.length - 1; i > 0; i--){ if(left[i].bounds.left > stage.nativeWindow.bounds.left){ stage.nativeWindow.x += SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 87 Schermate left[i].bounds.left - currentScreen.bounds.left; stage.nativeWindow.y += left[i].bounds.top - currentScreen.bounds.top; } } } private function moveUp():void{ var currentScreen:Screen = getCurrentScreen(); var top:Array = Screen.screens; top.sort(sortVertical); for(var i:int = 0; i < top.length - 1; i++){ if(top[i].bounds.top < stage.nativeWindow.bounds.top){ stage.nativeWindow.x += top[i].bounds.left - currentScreen.bounds.left; stage.nativeWindow.y += top[i].bounds.top - currentScreen.bounds.top; break; } } } private function moveDown():void{ var currentScreen:Screen = getCurrentScreen(); var top:Array = Screen.screens; top.sort(sortVertical); for(var i:int = top.length - 1; i > 0; i--){ if(top[i].bounds.top > stage.nativeWindow.bounds.top){ stage.nativeWindow.x += top[i].bounds.left - currentScreen.bounds.left; stage.nativeWindow.y += top[i].bounds.top - currentScreen.bounds.top; break; } } } private function sortHorizontal(a:Screen,b:Screen):int{ if (a.bounds.left > b.bounds.left){ return 1; } else if (a.bounds.left < b.bounds.left){ return -1; } else {return 0;} } private function sortVertical(a:Screen,b:Screen):int{ if (a.bounds.top > b.bounds.top){ return 1; } else if (a.bounds.top < b.bounds.top){ return -1; } else {return 0;} } private function getCurrentScreen():Screen{ var current:Screen; var screens:Array = Screen.getScreensForRectangle(stage.nativeWindow.bounds); (screens.length > 0) ? current = screens[0] : current = Screen.mainScreen; return current; } } } 88 Capitolo 12: Uso dei menu nativi Usate le classi nell'API dei menu nativi per definire i menu delle applicazioni, delle finestre, di scelta rapida e a comparsa. Ulteriori informazioni disponibili online sui menu nativi È possibile reperire ulteriori informazioni sulle API dei menu nativi e sull'uso dei menu nativi dalle seguenti fonti: Guide rapide (Centro per sviluppatori Adobe AIR) • Adding native menus to an AIR application (Aggiunta di menu nativi a un'applicazione AIR) Guida di riferimento del linguaggio • NativeMenu • NativeMenuItem Articoli ed esempi del Centro per sviluppatori Adobe • Centro per sviluppatori AIR per Flash (cercate 'AIR menu') Nozioni di base sui menu di AIR Le classi dei menu nativi vi consentono di accedere alle funzionalità del sistema operativo in cui l'applicazione è in esecuzione. È possibile utilizzare oggetti NativeMenu per i menu dell'applicazione (disponibili in Mac OS X), i menu delle finestre (disponibili in Windows e Linux), i menu di scelta rapida e i menu a comparsa. Classi dei menu di AIR Le classi dei menu di Adobe® AIR™ includono: Pacchetto Classi flash.display • NativeMenu • NativeMenuItem • ContextMenu • ContextMenuItem • Event • ContextMenuEvent flash.ui flash.events SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 89 Uso dei menu nativi Tipologie di menu AIR supporta le seguenti tipologie di menu: Menu dell'applicazione Un menu dell'applicazione è un menu globale che viene usato nell'intera applicazione. I menu dell'applicazione sono supportati in Mac OS X, ma non in Windows e Linux. In Mac OS X, il sistema operativo crea automaticamente un menu dell'applicazione. Potete usare l'API dei menu di AIR per aggiungere voci e menu secondari ai menu standard. Potete aggiungere listener per gestire i comandi dei menu esistenti, oppure rimuovere le voci di menu esistenti. Menu delle finestre Un menu di una finestra è associato a un'unica finestra e viene visualizzato sotto la barra del titolo. È possibile aggiungere i menu a una finestra creando un oggetto NativeMenu e assegnandolo alla proprietà menu dell'oggetto NativeWindow. I menu delle finestre sono supportati nei sistemi operativi Windows e Linux, ma non in Mac OS X. I menu delle finestre nativi possono essere utilizzati solo con finestre associate a chrome di sistema. Menu di scelta rapida I menu di scelta rapida si aprono facendo clic con il pulsante destro del mouse o facendo clic mentre si tiene premuto il tasto Comando su un oggetto interattivo in un contenuto SWF o su un elemento del documento in un contenuto HTML. Potete creare un menu di scelta rapida usando la classe NativeMenu o ContextMenu. Nel contenuto HTML, potete usare le API HTML e JavaScript di Webkit per aggiungere i menu di scelta rapida agli elementi HTML. Menu delle icone del dock e della barra delle applicazioni Questi menu a icona sono analoghi ai menu di scelta rapida e vengono assegnati a un'icona di un'applicazione nel dock di Mac OS X o nell'area di notifica della barra delle applicazioni di Windows e Linux. I menu delle icone del dock e della barra delle applicazioni usano la classe NativeMenu. In Mac OS X, le voci del menu sono aggiunte sopra le voci standard del sistema operativo. In Windows o Linux non è disponibile un menu standard. Menu a comparsa Un menu a comparsa di AIR è simile a un menu di scelta rapida, ma non è necessariamente associato a un particolare oggetto o componente dell'applicazione. I menu a comparsa possono essere visualizzati in qualunque punto di una finestra chiamando il metodo display() per un oggetto NativeMenu. Menu personalizzati I menu personalizzati sono creati interamente dal sistema operativo e pertanto esistono anche all'esterno dei modelli di rendering di Flash e HTML. Potete creare menu non nativi personalizzati anche mediante MXML, ActionScript o JavaScript. Le classi dei menu AIR non forniscono strumenti per controllare la creazione di menu nativi. Menu predefiniti I seguenti menu predefiniti sono forniti dal sistema operativo o da una classe AIR incorporata: • Menu dell'applicazione in Mac OS X • Menu delle icone del dock in Mac OS X • Menu di scelta rapida per testo selezionato e immagini in contenuto HTML • Menu di scelta rapida per testo selezionato in un oggetto TextField (o in un oggetto che estende TextField) Struttura dei menu Per loro natura, i menu hanno una struttura gerarchica. Gli oggetti NativeMenu contengono oggetti NativeMenuItem secondari. Gli oggetti NativeMenuItem che rappresentano sottomenu possono contenere a loro volta oggetti NativeMenu. L'oggetto di un menu di livello più alto o principale nella struttura rappresenta la barra dei menu per i menu dell'applicazione e delle finestre (i menu di scelta rapida, delle icone e a comparsa non prevedono una barra dei menu). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 90 Uso dei menu nativi Il seguente diagramma illustra la struttura di un menu tipico. Il menu principale rappresenta la barra dei menu e contiene due voci di menu che fanno riferimento a un sottomenu File e un sottomenu Modifica. Il sottomenu File in questa struttura contiene due comandi e una voce che richiama il sottomenu Apri recente, che a sua volta contiene tre voci. Il sottomenu Modifica contiene tre comandi e un separatore. La definizione di un sottomenu richiede sia un oggetto NativeMenu sia un oggetto NativeMenuItem. L'oggetto NativeMenuItem definisce l'etichetta visualizzata nel menu superiore e consente all'utente di aprire il sottomenu. L'oggetto NativeMenu agisce da contenitore per le voci di un sottomenu. L'oggetto NativeMenuItem fa riferimento all'oggetto NativeMenu attraverso la proprietà submenu di NativeMenuItem. Per visualizzare un esempio di codice che crea questo menu, consultate “Esempio: menu della finestra e dell'applicazione” a pagina 100. Eventi dei menu Entrambi gli oggetti NativeMenu e NativeMenuItem inviano gli eventi displaying e select: Displaying: appena prima della visualizzazione di un menu, il menu e le relative voci inviano un evento displaying a tutti i listener registrati. L'evento displaying consente di aggiornare il contenuto del menu e la visualizzazione delle voci prima che il menu venga mostrato all'utente. Ad esempio, nel listener dell'evento displaying per un menu “Open Recent” è possibile modificare le voci di menu in modo da visualizzare l'elenco aggiornato degli ultimi documenti aperti. La proprietà target dell'oggetto evento è sempre il menu che sta per essere visualizzato. currentTarget è l'oggetto su cui il listener è registrato, ovvero il menu stesso o le relative voci. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 91 Uso dei menu nativi Nota: l'evento displaying viene attivato ogni volta che si accede allo stato del menu o a una delle sue voci. Select: quando l'utente sceglie un comando, viene inviato un evento select a tutti i listener registrati. Non è possibile selezionare le voci di sottomenu e separatori, che quindi non inviano mai un evento select. Un evento select si propaga da una voce di menu al menu che la contiene, fino ad arrivare al menu principale. È possibile intercettare un evento select direttamente su una voce o in un parte precedente nella struttura dei menu. Per intercettare un evento select in corrispondenza di un menu, potete identificare la voce selezionata usando la proprietà target dell'evento. Mentre l'evento si propaga nella gerarchia dei menu, la proprietà currentTarget dell'oggetto evento identifica l'oggetto del menu corrente. Nota: gli oggetti ContextMenu e ContextMenuItem inviano eventi menuItemSelect e menuSelect oltre agli eventi select e displaying. Scelte rapide da tastiera equivalenti ai comandi dei menu Potete assegnare un equivalente da tastiera (in genere definito una scelta rapida da tastiera) a ogni comando di un menu. Quando premete il tasto o la combinazione di tasti scelta, la voce di menu invia un evento select a tutti i listener registrati. Il menu contenente la voce deve fare parte del menu dell'applicazione o del menu della finestra attiva per poter richiamare il comando. I tasti di scelta rapida sono composti da due parti: una stringa che rappresenta il tasto principale e un array di tasti modificatori che è necessario premere insieme al tasto principale. Per assegnare il tasto principale, impostate la proprietà keyEquivalent per la voce di menu sulla stringa corrispondente al carattere del tasto. Se usate una lettera maiuscola, all'array dei modificatori viene automaticamente aggiunto il tasto Maiusc. In Mac OS X, il modificatore predefinito è il tasto Comando (Keyboard.COMMAND). In Windows e Linux è il tasto Ctrl (Keyboard.CONTROL). I tasti predefiniti vengono aggiunti automaticamente all'array modificatore. Per usare tasti modificatori diversi, assegnate un nuovo array contenente i codici dei tasti desiderati alla proprietà keyEquivalentModifiers. L'array predefinito viene sovrascritto. Sia quando usate i modificatori predefiniti sia quando create un array di modificatori personalizzato, se la stringa assegnata alla proprietà keyEquivalent è una lettera maiuscola viene sempre aggiunto il tasto Maiusc. Le costanti corrispondenti ai codici dei tasti da usare per i tasti modificatori sono definite nella classe Keyboard. La stringa della scelta rapida da tastiera assegnata viene automaticamente visualizzata accanto al nome della voce di menu. Il formato dipende dal sistema operativo dell'utente e dalle preferenze di sistema impostate. Nota: se assegnate a un array di modificatori il valore Keyboard.COMMAND in Windows, nel menu non vengono visualizzate scelte rapide da tastiera. Tuttavia, per attivare il comando del menu è necessario premere il tasto Ctrl. Nel seguente esempio viene usato Ctrl+Maiusc+G come scelta rapida da tastiera per una voce di menu: var item:NativeMenuItem = new NativeMenuItem("Ungroup"); item.keyEquivalent = "G"; In questo esempio viene assegnata la combinazione Ctrl+Maiusc+G come scelta rapida da tastiera impostando direttamente l'array di modificatori: var item:NativeMenuItem = new NativeMenuItem("Ungroup"); item.keyEquivalent = "G"; item.keyEquivalentModifiers = [Keyboard.CONTROL]; Nota: le scelte rapide da tastiera vengono attivate solo per i menu dell'applicazione e delle finestre. Se aggiungete una scelta rapida da tastiera a un menu a comparsa o di scelta rapida, questa verrà visualizzata nell'etichetta del menu, ma il comando associato non sarà mai eseguito. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 92 Uso dei menu nativi Caratteri mnemonici I caratteri mnemonici sono un sistema per garantire l'interazione tra tastiera e menu. In Linux, Mac OS X e Windows, sebbene con alcune piccole differenze, gli utenti possono aprire i menu e selezionarne i comandi usando la tastiera. In Mac OS X l'utente digita la prima lettera (o le prime due) del menu o del comando e quindi preme il tasto Invio. La proprietà mnemonicIndex viene ignorata. In Windows, è significativa solo la prima lettera. Per impostazione predefinita, la lettera significativa è il primo carattere dell'etichetta, ma se si assegna un carattere mnemonico alla voce di menu, il carattere significativo diventa la lettera indicata. Se due voci di un menu hanno lo stesso carattere significativo (assegnato o meno come carattere mnemonico), l'interazione tra tastiera e menu cambia leggermente. Invece di premere una sola lettera per selezionare il menu o il comando, l'utente deve premere la lettera il numero di volte necessario per evidenziare la voce desiderata e quindi premere Invio per completare la selezione. Per garantire un comportamento coerente, si consiglia di assegnare un carattere mnemonico univoco a ogni voce di un menu per i menu delle finestre. In Linux non è presente alcun carattere mnemonico predefinito. Affinché una voce di menu comprenda un carattere mnemonico, dovete specificare un valore per la proprietà mnemonicIndex. Specificate il carattere mnemonico come indice nella stringa dell'etichetta. L'indice del primo carattere di un'etichetta è 0. Pertanto, per usare “r” come carattere mnemonico per una voce di menu con etichetta “Format”, occorre impostare la proprietà mnemonicIndex su 2. var item:NativeMenuItem = new NativeMenuItem("Format"); item.mnemonicIndex = 2; Stato delle voci di menu Le voci di menu hanno due proprietà che ne descrivono lo stato: checked e enabled. checked Impostate la proprietà su true per visualizzare un segno di spunta accanto all'etichetta della voce. var item:NativeMenuItem = new NativeMenuItem("Format"); item.checked = true; enabled Alternate il valore tra true e false per attivare o disattivare il comando. Le voci disattivate vengono “oscurate” e non inviano eventi select. var item:NativeMenuItem = new NativeMenuItem("Format"); item.enabled = false; Associazione di un oggetto a una voce di menu La proprietà data della classe NativeMenuItem consente di fare riferimento a un oggetto arbitrario in ogni voce. Ad esempio, nel menu “Open Recent” potete assegnare l'oggetto File di ogni documento a ogni voce di menu. var file:File = File.applicationStorageDirectory.resolvePath("GreatGatsby.pdf") var menuItem:NativeMenuItem = docMenu.addItem(new NativeMenuItem(file.name)); menuItem.data = file; Creazione dei menu nativi In questa sezione viene descritto come creare i vari tipi di menu nativi supportati da AIR. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 93 Uso dei menu nativi Creazione di un oggetto menu principale Per creare un oggetto NativeMenu che agisca da menu principale, usate la funzione di costruzione NativeMenu: var root:NativeMenu = new NativeMenu(); Per i menu delle applicazioni e delle finestre, il menu principale rappresenta la barra dei menu e deve contenere solo voci che aprono sottomenu. I menu di scelta rapida e a comparsa non dispongono di una barra dei menu, pertanto un menu principale può contenere comandi, separatori e sottomenu. Dopo avere creato il menu, potete aggiungere le voci. Le voci appaiono nel menu nell'ordine in cui sono state aggiunte, a meno che non le inseriate in corrispondenza di un indice specifico usando il metodo addItemAt() di un oggetto. Assegnate il menu come un menu dell'applicazione, della finestra, dell'icona o di scelta rapida, oppure visualizzatelo come un menu a comparsa come mostrato nelle seguenti sezioni: Impostazione del menu dell'applicazione NativeApplication.nativeApplication.menu = root; Nota: in Mac OS X è disponibile un menu contenente voci standard per ogni applicazione. Assegnando un nuovo oggetto NativeMenu alla proprietà menu dell'oggetto NativeApplication il menu standard viene sostituito (potete anche usare il menu standard invece di sostituirlo). Impostazione del menu della finestra nativeWindowObject.menu = root; Impostazione di un menu di scelta rapida per un oggetto interattivo interactiveObject.contextMenu = root; Impostazione di un menu per un'icona del dock DockIcon(NativeApplication.nativeApplication.icon).menu = root; Nota: in Mac OS X è disponibile un menu standard per le icone del dock delle applicazioni. Quando assegnate un nuovo oggetto NativeMenu alla proprietà menu dell'oggetto DockIcon, le voci di quel menu vengono visualizzate sopra le voci standard. Non potete rimuovere, accedere o modificare le voci del menu standard. Impostazione di un menu per un'icona della barra delle applicazioni SystemTrayIcon(NativeApplication.nativeApplication.icon).menu = root; Visualizzazione di un menu a comparsa root.display(stage, x, y); Creazione di un sottomenu Per creare un sottomenu, aggiungete un oggetto NativeMenuItem al menu principale e quindi assegnate l'oggetto NativeMenu, che definisce il sottomenu, alla proprietà submenu della voce. AIR offre due metodi per creare le voci di sottomenu e i relativi oggetti menu: Potete creare una voce di menu e il relativo oggetto con un unico passaggio usando il metodo addSubmenu(): var editMenuItem:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit"); Oppure potete creare una voce di menu e assegnare separatamente l'oggetto menu alla relativa proprietà submenu: var editMenuItem:NativeMenuItem = root.addItem("Edit", false); editMenuItem.submenu = new NativeMenu(); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 94 Uso dei menu nativi Creazione di un comando del menu Per creare un comando di un menu, aggiungete un oggetto NativeMenuItem a un menu e quindi aggiungete un listener di eventi che faccia riferimento alla funzione che implementa il comando. var copy:NativeMenuItem = new NativeMenuItem("Copy", false); copy.addEventListener(Event.SELECT, onCopyCommand); editMenu.addItem(copy); Potete intercettare l'evento select in corrispondenza del comando stesso (come mostrato nell'esempio) o potete intercettare l'evento select in corrispondenza dell'oggetto menu principale. Nota: le voci di menu che rappresentano sottomenu e separatori non inviano eventi select e pertanto non possono essere usati come comandi. Creazione di un separatore di menu Per inserire un separatore, create un oggetto NativeMenuItem, impostando il parametro isSeparator su true nella funzione di costruzione. Quindi inserite il separatore nella posizione corretta del menu: var separatorA:NativeMenuItem = new NativeMenuItem("A", true); editMenu.addItem(separatorA); L'eventuale etichetta specificata per il separatore non viene visualizzata. Informazioni sui menu di scelta rapida Nel contenuto SWF è possibile associare a qualunque oggetto che erediti da InteractiveObject un menu di scelta rapida, assegnando un oggetto menu alla relativa proprietà contextMenu. L'oggetto menu assegnato a contextMenu può essere di tipo NativeMenu o ContextMenu. Quando usate le classi ContextMenu e ContextMenuItem, potete intercettare gli eventi dei menu nativi o dei menu di scelta rapida; vengono infatti inviati entrambi. Uno dei vantaggi forniti dalle proprietà dell'oggetto ContextMenuEvent è la capacità di contextMenuOwner di identificare l'oggetto a cui è associato il menu, mentre mouseTarget identifica l'oggetto su cui è stato fatto clic per aprire il menu. Queste informazioni non sono disponibili tramite l'oggetto NativeMenuEvent. Nell'esempio che segue viene creato uno Sprite e viene aggiunto un semplice menu di scelta rapida di modifica (Edit): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 95 Uso dei menu nativi var sprite:Sprite = new Sprite(); sprite.contextMenu = createContextMenu() private function createContextMenu():ContextMenu{ var editContextMenu:ContextMenu = new ContextMenu(); var cutItem:ContextMenuItem = new ContextMenuItem("Cut") cutItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, doCutCommand); editContextMenu.customItems.push(cutItem); var copyItem:ContextMenuItem = new ContextMenuItem("Copy") copyItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, doCopyCommand); editContextMenu.customItems.push(copyItem); var pasteItem:ContextMenuItem = new ContextMenuItem("Paste") pasteItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, doPasteCommand); editContextMenu.customItems.push(pasteItem); return editContextMenu } private function doCutCommand(event:ContextMenuEvent):void{trace("cut");} private function doCopyCommand(event:ContextMenuEvent):void{trace("copy");} private function doPasteCommand(event:ContextMenuEvent):void{trace("paste");} Nota: a differenza del contenuto SWF visualizzato in ambiente browser, i menu di scelta rapida di AIR non hanno comandi incorporati. Informazioni sui menu di scelta rapida in HTML Nel contenuto HTML, è possibile usare l'evento contextmenu per visualizzare un menu di scelta rapida. Per impostazione predefinita, un menu di scelta rapida viene visualizzato automaticamente quando l'utente richiama l'evento corrispondente (facendo clic sul testo designato con il pulsante destro del mouse o tenendo premuto il tasto Comando). Per impedire l'apertura del menu predefinito, intercettate l'evento contextmenu e chiamate il metodo preventDefault() dell'oggetto dell'evento: function showContextMenu(event){ event.preventDefault(); } A questo punto potete visualizzare un menu di scelta rapida personalizzato usando le tecniche DHTML o visualizzando un menu di scelta rapida nativo di AIR. Nel seguente esempio viene visualizzato un menu di scelta rapida nativo richiamando il metodo display() del menu in risposta all'evento HTML contextmenu: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 96 Uso dei menu nativi <html> <head> <script src="AIRAliases.js" language="JavaScript" type="text/javascript"></script> <script language="javascript" type="text/javascript"> function showContextMenu(event){ event.preventDefault(); contextMenu.display(window.nativeWindow.stage, event.clientX, event.clientY); } function createContextMenu(){ var menu = new air.NativeMenu(); var command = menu.addItem(new air.NativeMenuItem("Custom command")); command.addEventListener(air.Event.SELECT, onCommand); return menu; } function onCommand(){ air.trace("Context command invoked."); } var contextMenu = createContextMenu(); </script> </head> <body> <p oncontextmenu="showContextMenu(event)" style="-khtml-user-select:auto;">Custom context menu.</p> </body> </html> Definizione dichiarativa dei menu nativi Creare codice per le proprietà e le voci di un menu può essere un processo piuttosto faticoso. Ma poiché per loro natura i menu hanno una struttura gerarchica, è abbastanza semplice scrivere una funzione che consenta di creare un menu usando una definizione in formato XML. La seguente classe estende NativeMenu usando allo scopo la funzione di costruzione di un oggetto XML: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 97 Uso dei menu nativi package { import flash.display.NativeMenu; import flash.display.NativeMenuItem; import flash.events.Event; public class DeclarativeMenu extends NativeMenu { public function DeclarativeMenu(XMLMenuDefinition:XML):void { super(); addChildrenToMenu(this, XMLMenuDefinition.children()); } private function addChildrenToMenu(menu:NativeMenu, children:XMLList):NativeMenuItem { var menuItem:NativeMenuItem; var submenu:NativeMenu; for each (var child:XML in children) { if (String(child.@label).length > 0) { menuItem = new NativeMenuItem(child.@label); menuItem.name = child.name(); } else { menuItem = new NativeMenuItem(child.name()); menuItem.name = child.name(); } menu.addItem(menuItem); if (child.children().length() > 0) { menuItem.submenu = new NativeMenu(); addChildrenToMenu(menuItem.submenu,child.children()); } } return menuItem; } } //End class } //End package Per creare un menu con questa classe, passate una definizione del menu XML come segue: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 98 Uso dei menu nativi var menuDefinition:XML = <root> <FileMenu label='File'> <NewMenu label='New'> <NewTextFile label='Text file'/> <NewFolder label='Folder'/> <NewProject label='Project'/> </NewMenu> <OpenCommand label='Open'/> <SaveCommand label='Save'/> </FileMenu> <EditMenu label='Edit'> <CutCommand label='Cut'/> <CopyCommand label='Copy'/> <PasteCommand label='Paste'/> </EditMenu> <FoodItems label='Food Items'> <Jellyfish/> <Tripe/> <Gizzard/> </FoodItems> </root>; var test:DeclarativeMenu = new DeclarativeMenu(menuDefinition); Potete intercettare gli eventi del menu a livello del menu principale e usare la proprietà event.target.name per identificare quali comandi sono stati selezionati. Potete anche cercare le voci nel menu per nome e aggiungere singoli listerner di eventi. Visualizzazione dei menu a comparsa Potete visualizzare un oggetto NativeMenu a una determinata ora e in una determinata posizione in una finestra, chiamando il metodo display() del menu. Il metodo richiede un riferimento allo stage; quindi solo il contenuto nella sandbox dell'applicazione può visualizzare menu a comparsa. Nel seguente metodo viene visualizzato il menu definito da un oggetto NativeMenu denominato popupMenu in risposta a un clic del mouse: private function onMouseClick(event:MouseEvent):void { popupMenu.display(event.target.stage, event.stageX, event.stageY); } Nota: non è necessario che il menu venga visualizzato in risposta diretta a un evento. Qualunque metodo può chiamare la funzione display(). Gestione degli eventi dei menu Un menu invia gli eventi quando l'utente seleziona il menu o quando ne seleziona una voce. Riepilogo degli eventi per classi di menu Per gestire gli eventi dei menu, è possibile aggiungere listener di eventi ai menu o alle loro singole voci. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 99 Uso dei menu nativi Oggetto Eventi inviati NativeMenu NativeMenuEvent.DISPLAYING NativeMenuEvent.SELECT (propagato da voci e sottomenu secondari) NativeMenuItem NativeMenuEvent.SELECT NativeMenuEvent.DISPLAYING (propagato dal menu principale) ContextMenu ContextMenuEvent.MENU_SELECT ContextMenuItem ContextMenuEvent.MENU_ITEM_SELECT NativeMenu.SELECT Eventi di selezione dei menu Per gestire un clic su una voce di menu, aggiungete un listener di eventi per l'evento select all'oggetto NativeMenuItem: var menuCommandX:NativeMenuItem = new NativeMenuItem("Command X"); menuCommand.addEventListener(Event.SELECT, doCommandX) Poiché gli eventi select possono propagarsi ai menu che li contengono, è possibile intercettare anche gli eventi select di un menu principale. Per intercettare a livello del menu, potete usare la proprietà target dell'oggetto evento per determinare quali comandi sono stati selezionati. Nel seguente esempio viene tracciata l'etichetta del comando selezionato: var colorMenuItem:NativeMenuItem = new NativeMenuItem("Choose a color"); var colorMenu:NativeMenu = new NativeMenu(); colorMenuItem.submenu = colorMenu; var red:NativeMenuItem = new NativeMenuItem("Red"); var green:NativeMenuItem = new NativeMenuItem("Green"); var blue:NativeMenuItem = new NativeMenuItem("Blue"); colorMenu.addItem(red); colorMenu.addItem(green); colorMenu.addItem(blue); if(NativeApplication.supportsMenu){ NativeApplication.nativeApplication.menu.addItem(colorMenuItem); NativeApplication.nativeApplication.menu.addEventListener(Event.SELECT, colorChoice); } else if (NativeWindow.supportsMenu){ var windowMenu:NativeMenu = new NativeMenu(); this.stage.nativeWindow.menu = windowMenu; windowMenu.addItem(colorMenuItem); windowMenu.addEventListener(Event.SELECT, colorChoice); } function colorChoice(event:Event):void { var menuItem:NativeMenuItem = event.target as NativeMenuItem; trace(menuItem.label + " has been selected"); } Se usate la classe ContextMenuItem, potete intercettare l'evento select o l'evento menuItemSelect. L'evento menuItemSelect vi fornisce ulteriori informazioni sull'oggetto a cui è associato il menu di scelta rapida, ma non si propaga ai menu che lo contengono. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 100 Uso dei menu nativi Eventi di visualizzazione dei menu Per gestire l'apertura di un menu, potete aggiungere un listener per l'evento displaying, che viene inviato prima della visualizzazione del menu. Potete usare l'evento displaying per aggiornare il menu, ad esempio per aggiungere o rimuovere voci o per aggiornare gli stati enabled o checked delle singole voci . Esempio: menu della finestra e dell'applicazione Nel seguente esempio viene creato il menu mostrato nella “Struttura dei menu” a pagina 89. Il menu è progettato per funzionare sia in Windows, sistema in cui sono supportati solo i menu delle finestre, sia in Mac OS X, sistema in cui sono supportati solo i menu delle applicazioni. Per fare la distinzione, la funzione di costruzione della classe MenuExample controlla le proprietà statiche supportsMenu delle classi NativeWindow e NativeApplication. Se NativeWindow.supportsMenu è true, la funzione di costruzione crea un oggetto NativeMenu per la finestra e quindi crea e aggiunge i sottomenu File ed Edit. Se NativeApplication.supportsMenu è true, la funzione di costruzione crea e aggiunge i menu File ed Edit al menu esistente fornito per il sistema operativo Mac OS X. In questo esempio è anche illustrata la gestione degli eventi dei menu. L'evento select viene gestito sia a livello di voce, che a livello di menu. Ciascun menu della sequenza, a partire dal menu contenente la voce selezionata fino al menu principale, risponde all'evento select. L'evento displaying viene usato con il menu “Open Recent”. Poco prima dell'apertura del menu, le voci del menu vengono aggiornate a partire dall'array dei documenti recenti (che in realtà in questo esempio non cambia). Sebbene non sia mostrato in questo esempio, potete anche intercettare gli eventi displaying in corrispondenza delle singole voci. package { import import import import import import import flash.display.NativeMenu; flash.display.NativeMenuItem; flash.display.NativeWindow; flash.display.Sprite; flash.events.Event; flash.filesystem.File; flash.desktop.NativeApplication; public class MenuExample extends Sprite { private var recentDocuments:Array = new Array(new File("app-storage:/GreatGatsby.pdf"), new File("app-storage:/WarAndPeace.pdf"), new File("app-storage:/Iliad.pdf")); public function MenuExample() { var fileMenu:NativeMenuItem; var editMenu:NativeMenuItem; if (NativeWindow.supportsMenu){ stage.nativeWindow.menu = new NativeMenu(); stage.nativeWindow.menu.addEventListener(Event.SELECT, selectCommandMenu); fileMenu = stage.nativeWindow.menu.addItem(new NativeMenuItem("File")); fileMenu.submenu = createFileMenu(); editMenu = stage.nativeWindow.menu.addItem(new NativeMenuItem("Edit")); editMenu.submenu = createEditMenu(); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 101 Uso dei menu nativi if (NativeApplication.supportsMenu){ NativeApplication.nativeApplication.menu.addEventListener(Event.SELECT, selectCommandMenu); fileMenu = NativeApplication.nativeApplication.menu.addItem(new NativeMenuItem("File")); fileMenu.submenu = createFileMenu(); editMenu = NativeApplication.nativeApplication.menu.addItem(new NativeMenuItem("Edit")); editMenu.submenu = createEditMenu(); } } public function createFileMenu():NativeMenu { var fileMenu:NativeMenu = new NativeMenu(); fileMenu.addEventListener(Event.SELECT, selectCommandMenu); var newCommand:NativeMenuItem = fileMenu.addItem(new NativeMenuItem("New")); newCommand.addEventListener(Event.SELECT, selectCommand); var saveCommand:NativeMenuItem = fileMenu.addItem(new NativeMenuItem("Save")); saveCommand.addEventListener(Event.SELECT, selectCommand); var openRecentMenu:NativeMenuItem = fileMenu.addItem(new NativeMenuItem("Open Recent")); openRecentMenu.submenu = new NativeMenu(); openRecentMenu.submenu.addEventListener(Event.DISPLAYING, updateRecentDocumentMenu); openRecentMenu.submenu.addEventListener(Event.SELECT, selectCommandMenu); return fileMenu; } public function createEditMenu():NativeMenu { var editMenu:NativeMenu = new NativeMenu(); editMenu.addEventListener(Event.SELECT, selectCommandMenu); var copyCommand:NativeMenuItem = editMenu.addItem(new NativeMenuItem("Copy")); copyCommand.addEventListener(Event.SELECT, selectCommand); copyCommand.keyEquivalent = "c"; var pasteCommand:NativeMenuItem = editMenu.addItem(new NativeMenuItem("Paste")); pasteCommand.addEventListener(Event.SELECT, selectCommand); pasteCommand.keyEquivalent = "v"; editMenu.addItem(new NativeMenuItem("", true)); var preferencesCommand:NativeMenuItem = editMenu.addItem(new NativeMenuItem("Preferences")); preferencesCommand.addEventListener(Event.SELECT, selectCommand); return editMenu; } private function updateRecentDocumentMenu(event:Event):void { trace("Updating recent document menu."); var docMenu:NativeMenu = NativeMenu(event.target); for each (var item:NativeMenuItem in docMenu.items) { docMenu.removeItem(item); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 102 Uso dei menu nativi for each (var file:File in recentDocuments) { var menuItem:NativeMenuItem = docMenu.addItem(new NativeMenuItem(file.name)); menuItem.data = file; menuItem.addEventListener(Event.SELECT, selectRecentDocument); } } private function selectRecentDocument(event:Event):void { trace("Selected recent document: " + event.target.data.name); } private function selectCommand(event:Event):void { trace("Selected command: " + event.target.label); } private function selectCommandMenu(event:Event):void { if (event.currentTarget.parent != null) { var menuItem:NativeMenuItem = findItemForMenu(NativeMenu(event.currentTarget)); if (menuItem != null) { trace("Select event for \"" + event.target.label + "\" command handled by menu: " + menuItem.label); } } else { trace("Select event for \"" + event.target.label + "\" command handled by root menu."); } } private function findItemForMenu(menu:NativeMenu):NativeMenuItem { for each (var item:NativeMenuItem in menu.parent.items) { if (item != null) { if (item.submenu == menu) { return item; } } } return null; } } } 103 Capitolo 13: Icone della barra delle applicazioni Numerosi sistemi operativi forniscono una barra delle applicazioni, ad esempio il dock Mac OS X, che può contenere un'icona per rappresentare un'applicazione. Adobe® AIR® fornisce un'interfaccia per l'interazione con l'icona della barra delle applicazioni tramite la proprietà NativeApplication.nativeApplication.icon. Informazioni in linea aggiuntive sulle icone della barra delle applicazioni Potete trovare ulteriori informazioni sulle operazioni con le barre delle applicazioni dalle seguenti origini: Guide introduttive (Adobe AIR Developer Connection) • Utilizzo delle icone della barra delle applicazioni e del dock Guida di riferimento • DockIcon • SystemTrayIcon Articoli ed esempi Adobe Developer Connection • Adobe AIR Developer Connection per Flash (cercate 'icone della barra delle applicazioni AIR') Informazioni sulle icone della barra delle applicazioni AIR consente di creare automaticamente gli oggetti NativeApplication.nativeApplication.icon. Il tipo di oggetto è DockIcon o SystemTrayIcon, in base al sistema operativo utilizzato. Potete determinare quali di queste sottoclassi InteractiveIcon sono supportate da AIR sul sistema operativo corrente utilizzando le proprietà NativeApplication.supportsDockIcon e NativeApplication.supportsSystemTrayIcon. La classe base InteractiveIcon fornisce le proprietà width, height e bitmaps che potete utilizzare per modificare l'immagine utilizzata per l'icona. Tuttavia, l'accesso a proprietà specifiche di DockIcon o SystemTrayIcon sul sistema operativo errato genera un errore di runtime. Per impostare o modificare l'immagine utilizzata per un'icona, potete creare un array contenente una o più immagini e assegnarlo alla proprietà NativeApplication.nativeApplication.icon.bitmaps. Le dimensioni delle icone della barra delle applicazioni possono essere diverse su sistemi operativi diversi. Per evitare la perdita di qualità delle immagini causata dal ridimensionamento, potete aggiungere immagini di diverse dimensioni all'array bitmaps. In questo caso, AIR seleziona la dimensione più simile a quella utilizzata per visualizzare l'icona della barra delle applicazioni corrente, ridimensionandola solo se necessario. L'esempio seguente imposta l'immagine per un'icona della barra delle applicazioni utilizzando due immagini: NativeApplication.nativeApplication.icon.bitmaps = [bmp16x16.bitmapData, bmp128x128.bitmapData]; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 104 Icone della barra delle applicazioni Per modificare l'immagine dell'icona, assegnate un array contenente la nuova immagine, o le immagini, alla proprietà bitmaps. Potete animare l'icona modificando l'immagine in risposta a un evento enterFrame o timer. Per rimuovere l'icona dall'area di notifica di Windows e Linux, o ripristinare l'aspetto predefinito dell'icona in Mac OS X, impostate bitmaps su un array vuoto: NativeApplication.nativeApplication.icon.bitmaps = []; Icone del dock AIR include il supporto per le icone del dock quando la proprietà NativeApplication.supportsDockIcon è impostata su true. La proprietà NativeApplication.nativeApplication.icon rappresenta l'icona dell'applicazione sul dock (non un'icona del dock della finestra). Nota: AIR non include il supporto per la modifica delle icone della finestra sul dock in Mac OS X. Inoltre, le modifiche all'icona del dock dell'applicazione possono essere applicate solo quando un'applicazione è in esecuzione; al termine dell'applicazione viene ripristinato l'aspetto originale dell'icona. Menu delle icone del dock Per aggiungere comandi al menu del dock standard, potete creare un oggetto NativeMenu contenente i comandi e assegnarlo alla proprietà NativeApplication.nativeApplication.icon.menu. Le voci nel menu vengono visualizzate sopra le voci di menu dell'icona del dock standard. Movimento sul dock Per muovere l'icona del dock, potete chiamare il metodo NativeApplication.nativeApplication.icon.bounce(). Impostando il parametro bounce() priority su informational, l'icona si muove una volta. Impostando il parametro su critical, l'icona si muove fino a quando l'utente non attiva applicazione. Le costanti per il parametro priority sono definite nella classe NotificationType. Nota: se l'applicazione è già attiva, l'icona non si muove. Eventi dell'icona del dock Quando si fa clic sull'icona del dock, l'oggetto NativeApplication invia un evento invoke. L'applicazione viene avviata dal sistema, se non è già in esecuzione. In caso contrario, l'evento invoke viene inviato all'istanza dell'applicazione in esecuzione. Icone della barra delle applicazioni AIR supporta le icone della barra delle applicazioni se la proprietà NativeApplication.supportsSystemTrayIcon è impostata su true. Questa situazione si verifica solo in Windows e nella maggior parte delle distribuzioni Linux. In Windows e Linux le icone della barra delle applicazioni sono visualizzate nell'area di notifica della barra delle applicazioni. Per impostazione predefinita non è visualizzata nessuna icona. Per mostrare un'icona, assegnate un array contenente oggetti BitmapData alla proprietà bitmaps dell'icona. Per modificare l'immagine dell'icona, assegnate un array contenente le nuove immagini a bitmaps. Per rimuovere l'icona, impostate bitmaps su null. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 105 Icone della barra delle applicazioni Menu dell'icona della barra delle applicazioni Per aggiungere un menu all'icona della barra delle applicazioni, potete creare un oggetto NativeMenu e assegnarlo alla proprietà NativeApplication.nativeApplication.icon.menu (il sistema operativo non fornisce nessun menu predefinito). Per accedere all'icona della barra delle applicazioni, fate clic con il pulsante destro del mouse sull'icona. Descrizione comandi dell'icona della barra delle applicazioni Per aggiungere una descrizione comandi a un'icona, impostate la proprietà tooltip: NativeApplication.nativeApplication.icon.tooltip = "Application name"; Eventi dell'icona della barra delle applicazioni L'oggetto SystemTrayIcon a cui fa riferimento la proprietà NativeApplication.nativeApplication.icon invia un evento ScreenMouseEvent per gli eventi click, mouseDown, mouseUp, rightClick, rightMouseDown e rightMouseUp. Potete usare questi eventi, insieme al menu di un'icona, per consentire agli utenti di interagire con l'applicazione quando questa non dispone di finestre visibili. Esempio:creazione di un'applicazione senza finestre L'esempio seguente crea un'applicazione AIR che contiene un'icona della barra delle applicazioni, ma nessuna finestra visibile. L'icona della barra delle applicazioni dispone di un menu con un singolo comando per uscire dall'applicazione. package { import import import import import import import import import import flash.display.Loader; flash.display.NativeMenu; flash.display.NativeMenuItem; flash.display.NativeWindow; flash.display.Sprite; flash.desktop.DockIcon; flash.desktop.SystemTrayIcon; flash.events.Event; flash.net.URLRequest; flash.desktop.NativeApplication; public class SysTrayApp extends Sprite { public function SysTrayApp():void{ NativeApplication.nativeApplication.autoExit = false; var icon:Loader = new Loader(); var iconMenu:NativeMenu = new NativeMenu(); var exitCommand:NativeMenuItem = iconMenu.addItem(new NativeMenuItem("Exit")); exitCommand.addEventListener(Event.SELECT, function(event:Event):void { NativeApplication.nativeApplication.icon.bitmaps = []; NativeApplication.nativeApplication.exit(); }); if (NativeApplication.supportsSystemTrayIcon) { NativeApplication.nativeApplication.autoExit = false; icon.contentLoaderInfo.addEventListener(Event.COMPLETE, iconLoadComplete); icon.load(new URLRequest("icons/AIRApp_16.png")); var systray:SystemTrayIcon = NativeApplication.nativeApplication.icon as SystemTrayIcon; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 106 Icone della barra delle applicazioni systray.tooltip = "AIR application"; systray.menu = iconMenu; } if (NativeApplication.supportsDockIcon){ icon.contentLoaderInfo.addEventListener(Event.COMPLETE,iconLoadComplete); icon.load(new URLRequest("icons/AIRApp_128.png")); var dock:DockIcon = NativeApplication.nativeApplication.icon as DockIcon; dock.menu = iconMenu; } stage.nativeWindow.close(); } private function iconLoadComplete(event:Event):void { NativeApplication.nativeApplication.icon.bitmaps = [event.target.content.bitmapData]; } } } Nota: l'esempio presuppone l'esistenza di file di immagine denominati AIRApp_16.png e AIRApp_128.png in una sottodirectory icons dell'applicazione (nell'SDK di AIR sono inclusi alcuni file icona di esempio che potete copiare nella cartella del progetto). Icone e pulsanti della barra delle applicazioni Rappresentazioni iconizzate delle finestre sono in genere visualizzate nell'area della finestra di una barra delle applicazioni o del dock per consentire agli utenti di accedere in modo semplice a finestre di sfondo o ridotte a icona. Il dock Mac OS X visualizza un'icona per l'applicazione, nonché un'icona per ciascuna finestra ridotta a icona. Nella barra delle applicazioni di Microsoft Windows e Linux è visualizzato un pulsante contenente il titolo e l'icona del programma per ogni finestra di tipo normale dell'applicazione. Evidenziazione del pulsante della finestra della barra delle applicazioni Quando una finestra è visualizzata sullo sfondo, potete inviare una notifica all'utente per indicare il verificarsi di un evento correlato alla finestra. In Mac OS X, potete inviare una notifica all'utente muovendo l'icona del dock dell'applicazione (come descritto in “Movimento sul dock” a pagina 104). In Windows e Linux potete evidenziare il pulsante della barra delle applicazioni della finestra chiamando il metodo notifyUser() dell'istanza NativeWindow. Il parametro type passato al metodo determina l'urgenza della notifica: • NotificationType.CRITICAL: l'icona della finestra lampeggia fino a quando l'utente non visualizza la finestra in primo piano. • NotificationType.INFORMATIONAL: l'icona della finestra viene evidenziata modificando il colore. Nota: in Linux è supportato solo il tipo informativo di notifica. Otterrete lo stesso effetto passando uno qualsiasi dei valori di tipo alla funzione notifyUser(). L'istruzione seguente evidenzia il pulsante della barra delle applicazioni di una finestra: stage.nativeWindow.notifyUser(NotificationType.CRITICAL); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 107 Icone della barra delle applicazioni La chiamata del metodo NativeWindow.notifyUser() in un sistema operativo che non supporta la notifica a livello di finestra non ha effetto. Potete utilizzare la proprietà NativeWindow.supportsNotification per determinare se è supportata la notifica a livello di finestra. Creazione di finestre senza pulsanti o icone della barra delle applicazioni Nel sistema operativo Windows, le finestre create con i tipi utility o lightweight non compaiono nella barra delle applicazioni. Anche le finestre invisibili non compaiono nella barra delle applicazioni. Poiché la finestra iniziale è necessariamente del tipo normal, per creare un'applicazione senza alcuna finestra visualizzata nella barra delle applicazioni, chiudete la finestra iniziale o lasciatela invisibile. Potete chiudere tutte le finestre nell'applicazione senza terminarla impostando la proprietà autoExit dell'oggetto NativeApplication su false prima di chiudere l'ultima finestra. Per impedire che la finestra iniziale diventi visibile, potete aggiungere <visible>false</visible> all'elemento <initalWindow> del file descrittore dell'applicazione (senza impostare la proprietà visible su true né chiamare il metodo activate() della finestra). Nelle nuove finestre aperte dall'applicazione, potete impostare la proprietà type dell'oggetto NativeWindowInitOption passato alla funzione di costruzione della finestra su NativeWindowType.UTILITY o NativeWindowType.LIGHTWEIGHT. In Mac OS X, le finestre ridotte a icona vengono visualizzate sulla barra delle applicazioni del dock. Per impedire la visualizzazione delle icone ridotte a icona, potete nascondere la finestra anziché ridurla a icona. L'esempio seguente intercetta un evento change nativeWindowDisplayState e lo annulla se la finestra viene ridotta a icona. Il gestore di eventi imposta invece la proprietà visible della finestra su false: private function preventMinimize(event:NativeWindowDisplayStateEvent):void{ if(event.afterDisplayState == NativeWindowDisplayState.MINIMIZED){ event.preventDefault(); event.target.visible = false; } } Se una finestra viene ridotta a icona sul dock Mac OS X quando impostate la proprietà visible su false, l'icona del dock non viene rimossa. Un utente può ancora fare clic sull'icona per far riapparire la finestra. 108 Capitolo 14: Operazioni con il file system Le classi fornite dall'API del file system di Adobe® AIR™ consentono di accedere al file system del computer host. Quando utilizzate queste classi, potete eseguire operazioni di accesso, gestione e creazione di directory e file, scrivere dati sui file e così via. Informazioni online supplementari sull'API File di AIR È possibile trovare ulteriori informazioni sull'uso delle classi API File nelle seguenti fonti: Guide rapide (Centro per sviluppatori Adobe AIR) • Building a text-file editor (Creazione di un editor di file di testo) Guida di riferimento del linguaggio • File • FileStream • FileMode Articoli ed esempi del Centro per sviluppatori Adobe • Centro per sviluppatori Adobe AIR per Flash (cercate 'AIR filesystem') Elementi di base dei file AIR Adobe AIR offre classi che consentono di eseguire operazioni di accesso, gestione e creazione di directory e file. Queste classi, contenute nel pacchetto flash.filesystem, vengono utilizzate come descritto di seguito: Classi File Descrizione File L'oggetto File rappresenta un percorso di un file o di una directory. Potete utilizzare un oggetto File per creare un puntatore a un file o una cartella, attivando l'interazione con tale file o cartella. FileMode La classe FileMode definisce costanti di stringa utilizzate nel parametro fileMode dei metodi open() e openAsync() della classe FileStream. Il parametro fileMode di questi metodi determina le funzionalità disponibili per l'oggetto FileStream una volta che il file viene aperto, ad esempio scrittura, lettura, aggiunta e aggiornamento. FileStream L'oggetto FileStream è utilizzato per aprire i file per operazioni di lettura e scrittura. Una volta creato un oggetto File che punta a un file nuovo o esistente, passate tale puntatore all'oggetto FileStream in modo da poter aprire e quindi modificare i dati all'interno del file. Alcuni metodi nella classe File presentano versioni sincrone e asincrone: • File.copyTo() e File.copyToAsync() • File.deleteDirectory() e File.deleteDirectoryAsync() • File.deleteFile() e File.deleteFileAsync() • File.getDirectoryListing() e File.getDirectoryListingAsync() SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 109 Operazioni con il file system • File.moveTo() e File.moveToAsync() • File.moveToTrash() e File.moveToTrashAsync() Inoltre, le operazioni di FileStream funzionano in modo sincrono o asincrono a seconda di come l'oggetto FileStream apre il file, ovvero chiamando il metodo open() oppure il metodo openAsync(). Le versioni asincrone consentono di inizializzare i processi eseguiti in background e inviare gli eventi quando sono completi (o in caso di eventi di errore). Altro codice può essere eseguito mentre sono in esecuzione questi processi asincroni in background. Con le versioni asincrone delle operazioni, dovete configurare dei listener di eventi utilizzando il metodo addEventListener() dell'oggetto File o FileStream che chiama la funzione. Le versioni sincrone consentono di scrivere codice più semplice che non necessita della configurazione di listener di eventi. Tuttavia, poiché non è possibile eseguire altro codice durante l'esecuzione di un metodo sincrono, i processi importanti, come il rendering degli oggetti di visualizzazione e l'animazione, potrebbero essere messi in pausa. Operazioni con oggetti File L'oggetto File è un puntatore a un file o una directory del file system. La classe File estende la classe FileReference. La classe FileReference, disponibile in Adobe® Flash® Player e AIR, rappresenta un puntatore a un file, ma la classe File aggiunge proprietà e metodi che non sono esposti in Flash Player (in un file SWF eseguito in un browser), per motivi di sicurezza. Informazioni sulla classe File Potete utilizzare la classe File per le seguenti operazioni: • Recupero del percorso di directory speciali, comprese la directory dell'utente, la directory dei documenti dell'utente, quella da cui è stata avviata l'applicazione e la directory dell'applicazione. • Copiatura di file e directory • Spostamento di file e directory • Eliminazione di file e directory (o spostamento nel cestino) • Elencazione di file e directory contenuti in una directory • Creazione di file e cartelle temporanei Una volta che l'oggetto File punta a un percorso file, potete utilizzarlo per leggere e scrivere dati di file, utilizzando la classe FileStream. Un oggetto File può puntare al percorso di un file o di una directory che non esiste ancora. Potete utilizzare un oggetto File di questo tipo per creare un file o una directory. Percorsi degli oggetti File Ogni oggetto File ha due proprietà che ne definiscono il percorso: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 110 Operazioni con il file system Proprietà Descrizione nativePath Definisce il percorso di un file per a una piattaforma specifica. Ad esempio, in Windows un percorso potrebbe essere "c:\Directory esempio\test.txt", mentre in Mac OS potrebbe essere "/Directory esempio/test.txt". Una proprietà nativePath utilizza, come carattere separatore di directory, il carattere barra rovesciata (\) in Windows e il carattere barra (/) in Mac OS e Linux. url È possibile utilizzabile lo schema URL del file per puntare a un file. Ad esempio, in Windows un percorso potrebbe essere "file:///c:/Sample%20directory/test.txt", mentre in Mac OS potrebbe essere "file:///Sample%20directory/test.txt". Il runtime comprende altri schemi URL speciali oltre a file, descritti in “Schemi URL supportati” a pagina 114 La classe File comprende proprietà che consentono di puntare a directory standard in Mac OS, Windows e Linux. Puntamento di un oggetto File a una directory Sono disponibili diversi modi per impostare un oggetto File in modo che punti a una directory. Puntamento alla directory home dell'utente È possibile puntare un oggetto File alla directory home dell'utente. In Windows, la directory home è la directory principale della cartella "Documenti" (ad esempio, "C:\Documents and Settings\Nome utente\Documenti"). In Mac OS, è la directory Utenti/Nome utente. In Linux, è la directory /home/Nome utente. Il codice seguente imposta un oggetto File che punta alla sottodirectory AIR Test della directory home: var file:File = File.userDirectory.resolvePath("AIR Test"); Puntamento alla directory Documenti dell'utente È possibile puntare un oggetto File alla directory Documenti dell'utente. In Windows, la directory predefinita è "Documenti" (ad esempio, "C:\Documents and Settings\Nome utente\Documenti"). In Mac OS, la directory predefinita è Utenti/Nome utente/Documenti. In Linux, la directory predefinita è home/Nome utente/Documenti. Il codice seguente imposta un oggetto File che punta alla sottodirectory AIR Test della directory Documenti: var file:File = File.documentsDirectory.resolvePath("AIR Test"); Puntamento alla directory del desktop È possibile puntare un oggetto File al desktop. Il codice seguente imposta un oggetto File che punta a una sottodirectory AIR Test del desktop: var file:File = File.desktopDirectory.resolvePath("AIR Test"); Puntamento alla directory di memorizzazione dell'applicazione È possibile puntare un oggetto File alla directory di memorizzazione dell'applicazione. Per ogni applicazione AIR, vi è un unico percorso associato univoco che definisce la directory di memorizzazione dell'applicazione. Tale directory è unica per ogni applicazione e per ogni utente. Potete utilizzare questa directory per memorizzare dati specifici dell'utente o dell'applicazione (ad esempio i dati dell'utente o i file delle preferenze). Ad esempio, il codice seguente punta un oggetto File a un file di preferenze, prefs.xml, contenuto nella directory di memorizzazione dell'applicazione: var file:File = File.applicationStorageDirectory; file = file.resolvePath("prefs.xml"; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 111 Operazioni con il file system Tale directory si base sul nome utente, sull'ID dell'applicazione e sull'ID dell'autore: • In Mac OS, nel seguente percorso: /Users/nome utente/Library/Preferences/IDapplicazione.IDeditore/Local Store/ Ad esempio: /Users/babbage/Library/Preferences/com.example.TestApp.02D88EEED35F84C264A183921344EEA353 A629FD.1/Local Store • In Windows, nella directory Documents and Settings, in: nome utente/Dati applicazioni/applicationID.IDeditore/Local Store/ Ad esempio: C:\Documents and Settings\babbage\Application Data\com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Local Store • In Linux - In: /home/Nome utente/.appdata/applicationID.IDeditore/Local Store/ Ad esempio: /home/babbage/.appdata/com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1/Loc al Store L'URL (e la proprietà url) di un oggetto File creato tramite File.applicationStorageDirectory utilizza lo schema URL app-storage (consultate “Schemi URL supportati” a pagina 114), come nel caso seguente: var dir:File = File.applicationStorageDirectory; dir = dir.resolvePath("preferences"); trace(dir.url); // app-storage:/preferences Puntamento alla directory dell'applicazione È possibile puntare un oggetto File alla directory in cui è stata installata l'applicazione, nota anche come directory dell'applicazione. Potete fare riferimento a questa directory mediante la proprietà File.applicationDirectory. Può essere utile utilizzare questa directory per esaminare il file descrittore dell'applicazione o altre risorse installate con l'applicazione. Ad esempio, il codice seguente punta un oggetto File a una directory denominata images nella directory dell'applicazione: var dir:File = File.applicationDirectory; dir = dir.resolvePath("images"); L'URL (e la proprietà url) di un oggetto File creato tramite File.applicationDirectory utilizza lo schema URL app (consultate “Schemi URL supportati” a pagina 114), come nel caso seguente: var dir:File = File.applicationDirectory; dir = dir.resolvePath("images"); trace(dir.url); // app:/images Puntamento al livello principale del file system Il metodo File.getRootDirectories() elenca tutti i volumi principali, come C: e i volumi montati, di un computer Windows. In Mac OS e Linux, questo metodo restituisce sempre l'unica directory principale della macchina (la directory "/"). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 112 Operazioni con il file system Puntamento a una directory esplicita È possibile puntare l'oggetto File a una directory esplicita impostandone la proprietà nativePath, come nell'esempio seguente (in Windows): var file:File = new File(); file.nativePath = "C:\\AIR Test\"; Accesso a percorsi relativi È possibile utilizzare il metodo resolvePath() per ottenere un percorso relativo a un altro percorso specifico. Ad esempio, il codice seguente imposta un oggetto File che punta alla sottodirectory "AIR Test" della directory home dell'utente: var file:File = File.userDirectory; file = file.resolvePath("AIR Test"); Potete anche utilizzare la proprietà url di un oggetto File per puntarlo a una directory in base a una stringa URL, come nel caso seguente: var urlStr:String = "file:///C:/AIR Test/"; var file:File = new File() file.url = urlStr; Per ulteriori informazioni, consultate “Modifica dei percorsi File” a pagina 114. Selezione di una directory da parte dell'utente La classe File comprende il metodo browseForDirectory(), che presenta una finestra di dialogo di sistema in cui l'utente può selezionare una directory da assegnare all'oggetto. Il metodo browseForDirectory() è asincrono. Invia un evento select se l'utente seleziona una directory e fa clic sul pulsante Apri oppure un evento cancel se l'utente fa clic sul pulsante Annulla. Ad esempio, il codice seguente consente all'utente di selezionare una directory e visualizza il percorso della directory una volta eseguita la selezione: var file:File = new File(); file.addEventListener(Event.SELECT, dirSelected); file.browseForDirectory("Select a directory"); function dirSelected(e:Event):void { trace(file.nativePath); } Puntamento alla directory da cui viene chiamata l'applicazione Potete ottenere la posizione della directory da cui viene chiamata un'applicazione selezionando la proprietà currentDirectory dell'evento InvokeEvent inviato quando l'applicazione viene chiamata. Per informazioni dettagliate, consultate “Acquisizione degli argomenti della riga di comando” a pagina 295. Puntamento di un oggetto File a un file Sono disponibili diversi modi per impostare il file a cui punta un oggetto File. Puntamento a un percorso file esplicito È possibile utilizzare il metodo resolvePath() per ottenere un percorso relativo a un altro percorso specifico. Ad esempio, il codice seguente imposta un oggetto File che punta al file log.txt nella directory di memorizzazione dell'applicazione: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 113 Operazioni con il file system var file:File = File.applicationStorageDirectory; file = file.resolvePath("log.txt"); Potete utilizzare la proprietà url di un oggetto File per puntarlo a un file o a una directory in base a una stringa URL, come nel caso seguente: var urlStr:String = "file:///C:/AIR Test/test.txt"; var file:File = new File() file.url = urlStr; Potete anche passare l'URL alla funzione di costruzione File(), come nel caso seguente: var urlStr:String = "file:///C:/AIR Test/test.txt"; var file:File = new File(urlStr); La proprietà url restituisce sempre la versione codificata URI dell'URL (ad esempio, gli spazi vuoti vengono sostituiti da "%20): file.url = "file:///c:/AIR Test"; trace(file.url); // file:///c:/AIR%20Test Potete anche utilizzare la proprietà nativePath di un oggetto File per impostare un percorso esplicito. Ad esempio, il codice seguente, se eseguito su un computer Windows, imposta un oggetto File sul file test.txt nella sottodirectory AIR Test dell'unità C: var file:File = new File(); file.nativePath = "C:/AIR Test/test.txt"; Potete anche passare questo percorso alla funzione di costruzione File(), come nel caso seguente: var file:File = new File("C:/AIR Test/test.txt"); In Windows, è possibile utilizzare il carattere barra (/) o barra rovesciata (\) come delimitatore di percorso per la proprietà nativePath. In Mac OS è Linux, potete utilizzate il carattere barra (/) come delimitatore di percorso per la proprietà nativePath: var file:File = new File(/Users/dijkstra/AIR Test/test.txt"); Per ulteriori informazioni, consultate “Modifica dei percorsi File” a pagina 114. Enumerazione dei file di una directory Potete utilizzare il metodo getDirectoryListing() di un oggetto File per recuperare un array di oggetti File che puntano ai file e alle sottodirectory al livello principale di una directory. Per ulteriori informazioni, consultate “Enumerazione delle directory” a pagina 119. Selezione di un file da parte dell'utente La classe File comprende i metodi che presentano una finestra di dialogo di sistema in cui l'utente può selezionare un file da assegnare all'oggetto. • browseForOpen() • browseForSave() • browseForOpenMultiple() SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 114 Operazioni con il file system Questi metodi sono tutti asincroni. I metodi browseForOpen() e browseForSave() inviano l'evento di selezione quando l'utente seleziona un file (o un percorso target, nel caso di browseForSave()). Con i metodi browseForOpen() e browseForSave(), a seguito della selezione l'oggetto File di destinazione punta ai file selezionati. Il metodo browseForOpenMultiple() invia un evento selectMultiple quando l'utente seleziona i file. L'evento selectMultiple è del tipo FileListEvent, che ha una proprietà files che corrisponde a un array di oggetti File (che puntano ai file selezionati). Ad esempio, il codice seguente mostra all'utente una finestra di dialogo "Apri" in cui l'utente può selezionare un file: var fileToOpen:File = File.documentsDirectory; selectTextFile(fileToOpen); function selectTextFile(root:File):void { var txtFilter:FileFilter = new FileFilter("Text", "*.as;*.css;*.html;*.txt;*.xml"); root.browseForOpen("Open", [txtFilter]); root.addEventListener(Event.SELECT, fileSelected); } function fileSelected(event:Event):void { trace(fileToOpen.nativePath); } Se nell'applicazione è aperta un'altra finestra di dialogo di consultazione file quando chiamate un metodo browse, il runtime genera un'eccezione Error. Modifica dei percorsi File Potete inoltre modificare il percorso di un oggetto File esistente chiamando il metodo resolvePath() o modificando la proprietà nativePath o url dell'oggetto, come negli esempi seguenti (in Windows): var file1:File = File.documentsDirectory; file1 = file1.resolvePath("AIR Test"); trace(file1.nativePath); // C:\Documents and Settings\userName\My Documents\AIR Test var file2:File = File.documentsDirectory; file2 = file2.resolvePath(".."); trace(file2.nativePath); // C:\Documents and Settings\userName var file3:File = File.documentsDirectory; file3.nativePath += "/subdirectory"; trace(file3.nativePath); // C:\Documents and Settings\userName\My Documents\subdirectory var file4:File = new File(); file4.url = "file:///c:/AIR Test/test.txt"; trace(file4.nativePath); // C:\AIR Test\test.txt Con la proprietà nativePath, potete utilizzare il carattere barra (/) o barra rovesciata (\) come separatore di directory in Windows; in Mac OS e Linux potete usare solo il carattere barra (/). In Windows, ricordate di digitare due volte il carattere barra rovesciata in un valore letterale di stringa. Schemi URL supportati Potete utilizzare uno qualsiasi dei seguenti schemi URL per definire la proprietà url di un oggetto File: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 115 Operazioni con il file system Schema URL Descrizione file Specifica un percorso relativo alla directory principale del file system. Ad esempio: file:///c:/AIR Test/test.txt Lo standard URL specifica che un URL di file assume la forma file://<host>/<path>. Come caso speciale, <host> può essere una stringa vuota, che viene interpretata come "il sistema da cui l'URL viene interpretato". Per questo motivo, gli URL file spesso presentano tre barre (///). app Specifica un percorso relativo alla directory principale dell'applicazione installata (la directory contenente il file application.xml dell'applicazione installata). Ad esempio, il percorso seguente punta alla sottodirectory images della directory dell'applicazione installata: app:/images app-storage Specifica un percorso relativo alla directory di memorizzazione dell'applicazione. Per ogni applicazione installata, AIR definisce un'unica directory di memorizzazione dell'applicazione, che è una posizione utile per memorizzare dati specifici dell'applicazione stessa. Ad esempio, il percorso seguente punta a un file di nome prefs.xml contenuto nella sottodirectory settings della directory di memorizzazione dell'applicazione: app-storage:/settings/prefs.xml Individuazione del percorso relativo tra due file Potete utilizzare il metodo getRelativePath() per individuare il percorso relativo tra due file: var file1:File = File.documentsDirectory.resolvePath("AIR Test"); var file2:File = File.documentsDirectory file2 = file2.resolvePath("AIR Test/bob/test.txt"); trace(file1.getRelativePath(file2)); // bob/test.txt Il secondo parametro del metodo getRelativePath(), il parametro useDotDot, consente di restituire la sintassi .. nei risultati, per indicare le directory principali: var file1:File = File.documentsDirectory; file1 = file1.resolvePath("AIR Test"); var file2:File = File.documentsDirectory; file2 = file2.resolvePath("AIR Test/bob/test.txt"); var file3:File = File.documentsDirectory; file3 = file3.resolvePath("AIR Test/susan/test.txt"); trace(file2.getRelativePath(file1, true)); // ../.. trace(file3.getRelativePath(file2, true)); // ../../bob/test.txt Recupero di versioni canoniche dei nomi di file Per i nomi di file e percorsi non viene fata distinzione tra maiuscole e minuscole in Windows e Mac OS. Nel caso seguente, due oggetti File puntano allo stesso file: File.documentsDirectory.resolvePath("test.txt"); File.documentsDirectory.resolvePath("TeSt.TxT"); Tuttavia, i nomi dei documenti e delle directory includono caratteri sia minuscoli che maiuscoli. Ad esempio, il caso seguente ipotizza che vi sia una cartella denominata AIR Test nella directory documents: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 116 Operazioni con il file system var file:File = File.documentsDirectory.resolvePath("AIR test"); trace(file.nativePath); // ... AIR test file.canonicalize(); trace(file.nativePath); // ... AIR Test Il metodo canonicalize converte l'oggetto nativePath in modo che utilizzi le maiuscole corrette per il nome del file o della directory. Nei file system che fanno distinzione tra maiuscole e minuscole (ad esempio Linux), quando sono presenti più file con nomi diversi solo per le maiuscole/minuscole, il metodo canonicalize() adatta il percorso in modo che corrisponda al primo file trovato (in un ordine determinato dal file system). Potete utilizzare il metodo canonicalize() anche per convertire i nomi file brevi (in formato "8.3") in nomi lunghi in Windows, come negli esempi seguenti: var path:File = new File(); path.nativePath = "C:\\AIR~1"; path.canonicalize(); trace(path.nativePath); // C:\AIR Test Operazioni con pacchetti e collegamenti simbolici Diversi sistemi operativi supportano file di pacchetto e file di collegamenti simbolici: Pacchetti - In Mac OS, le directory possono essere designate come pacchetti in modo da essere visualizzate nel Finder di Mac OS come file singolo anziché come directory. Collegamenti simbolici - Mac OS, Linux e Windows Vista supportano i collegamenti simbolici. I collegamenti simbolici consentono a un file di puntare a un altro file o un'altra directory presente nel disco. Sebbene simili, i collegamenti simbolici non sono identici agli alias. Un alias è sempre indicato come file (anziché come directory) e la lettura o la scrittura di un alias o un collegamento a un alias non ha mai alcun effetto sul file o sulla directory originale a cui punta. Al contrario, un collegamento simbolico si comporta esattamente come il file o la directory a cui punta. Può essere indicato come file o directory e la lettura o la scrittura di un collegamento simbolico ha effetto sul file o sulla directory a cui punta, non sul collegamento simbolico. Inoltre, in Windows la proprietà isSymbolicLink per un oggetto File che fa riferimento a un punto di congiunzione (utilizzato nel file system NTFS) è impostata su true. La classe File comprende le proprietà isPackage e isSymbolicLink, che consentono di verificare se un oggetto File fa riferimento a un pacchetto o a un collegamento simbolico. Il codice seguente esegue un'iterazione nella directory desktop dell'utente, elencando le sottodirectory che non sono pacchetti: var desktopNodes:File = File.desktopDirectory.getDirectoryListing(); for (var i:uint = 0; i < desktopNodes.length; i++) { if (desktopNodes[i].isDirectory && !!desktopNodes[i].isPackage) { trace(desktopNodes[i].name); } } Il codice seguente esegue un'iterazione nella directory desktop dell'utente, elencando i file e le directory che non sono collegamenti simbolici: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 117 Operazioni con il file system var desktopNodes:File = File.desktopDirectory.getDirectoryListing(); for (var i:uint = 0; i < desktopNodes.length; i++) { if (!desktopNodes[i].isSymbolicLink) { trace(desktopNodes[i].name); } } Il metodo canonicalize() cambia il percorso di un collegamento simbolico in modo che punti al file o alla directory a cui il collegamento fa riferimento. Il codice seguente esegue un'iterazione nella directory desktop dell'utente e restituisce i percorsi a cui fanno riferimento i file che sono collegamenti simbolici: var desktopNodes:File = File.desktopDirectory.getDirectoryListing(); for (var i:uint = 0; i < desktopNodes.length; i++) { if (desktopNodes[i].isSymbolicLink) { var linkNode:File = desktopNodes[i] as File; linkNode.canonicalize(); trace(linkNode.nativePath); } } Rilevamento dello spazio disponibile su un volume La proprietà spaceAvailable di un oggetto File corrisponde allo spazio disponibile in byte per l'utilizzo nel percorso File. Ad esempio, il codice seguente controlla lo spazio disponibile nella directory di memorizzazione dell'applicazione: trace(File.applicationStorageDirectory.spaceAvailable); Se l'oggetto File fa riferimento a una directory, la proprietà spaceAvailable indica lo spazio nella directory che i file possono utilizzare. Se l'oggetto File fa riferimento a un file, la proprietà spaceAvailable indica lo spazio in cui il file potrebbe aumentare di dimensione. Se il percorso del file non esiste, la proprietà spaceAvailable è impostata su 0. Se l'oggetto File fa riferimento a un collegamento simbolico, la proprietà spaceAvailable è impostata sullo spazio disponibile nel percorso a cui punta il collegamento simbolico. Di solito lo spazio disponibile per una directory o un file è uguale allo spazio disponibile nel volume contenente la directory o il file. Tuttavia, tale spazio può includere quote e limiti per singola directory. L'aggiunta di un file o di una directory a un volume di solito richiede più spazio delle dimensioni effettive del file o del contenuto della directory. Ad esempio, il sistema operativo può richiedere più spazio per memorizzare le informazioni di indice, oppure i settori del disco richiesti possono utilizzare altro spazio. Inoltre, lo spazio disponibile cambia in modo dinamico, quindi non è possibile prevedere di allocare tutto lo spazio indicato per la memorizzazione dei file. Per informazioni sulla scrittura nel file system, consultate “Lettura e scrittura di file” a pagina 123. Recupero di informazioni sul file system La classe File comprende le seguenti proprietà statiche che forniscono alcune informazioni utili sul file system: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 118 Operazioni con il file system Proprietà Descrizione File.lineEnding La sequenza dei caratteri di fine riga utilizzata dal sistema operativo host. In Mac OS e Linux, è il carattere di avanzamento riga. In Windows, è il carattere di ritorno a capo seguito dal carattere di avanzamento riga. File.separator Il carattere separatore del componente percorso del sistema operativo host. In Mac OS e Linux, è il carattere della barra (/). In Windows, è il carattere della barra rovesciata (\). File.systemCharset La codifica predefinita utilizzata per file dal sistema operativo host. Riguarda il set di caratteri utilizzato dal sistema operativo, corrispondente alla sua lingua. La classe Capabilities include anche utili informazioni di sistema che possono essere utilizzate quando si lavora con i file: Proprietà Descrizione Capabilities.hasIME Indica se il lettore viene eseguito su un sistema in cui è installato (true) o meno (false) un IME (Input Method Editor). Capabilities.language Indica il codice di lingua del sistema in cui è in esecuzione il lettore. Capabilities.os Indica il sistema operativo corrente. Operazioni con le directory Il runtime fornisce le funzionalità per operare con le directory del file system locale. Per informazioni dettagliate sulla creazione di oggetti File che puntano a directory, consultate “Puntamento di un oggetto File a una directory” a pagina 110. Creazione di directory Il metodo File.createDirectory() consente di creare una directory. Ad esempio, il codice seguente crea una directory denominata AIR Test quale sottodirectory della home directory dell'utente: var dir:File = File.userDirectory.resolvePath("AIR Test"); dir.createDirectory(); Se la directory è presente, il metodo createDirectory() non esegue alcuna operazione. Inoltre, in alcune modalità, un oggetto FileStream crea directory quando si aprono i file. Le directory mancanti vengono create quando si crea un'istanza FileStream con il parametro fileMode delle funzioni di costruzione FileStream() impostata su FileMode.APPEND oppure FileMode.WRITE. Per ulteriori informazioni, consultate “Flusso di lavoro per lettura e scrittura di file” a pagina 123. Creazione di una directory temporanea La classe File comprende un metodo createTempDirectory(), che crea una directory nella cartella della directory temporanea del sistema, come nell'esempio seguente: var temp:File = File.createTempDirectory(); Il metodo createTempDirectory() crea automaticamente una directory temporanea univoca (evitando l'operazione di individuare un nuovo percorso univoco). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 119 Operazioni con il file system Potete utilizzare una directory temporanea per memorizzare momentaneamente i file temporanei utilizzati per una sessione dell'applicazione. Notate che è disponibile il metodo createTempFile() per la creazione di nuovi file temporanei univoci nella directory temporanea di sistema. Potrebbe essere opportuno eliminare la directory temporanea prima della chiusura dell'applicazione, poiché non viene eliminata automaticamente. Enumerazione delle directory Potete utilizzare il metodo getDirectoryListing() oppure il metodo getDirectoryListingAsync() di un oggetto File per recuperare un array di oggetti File che puntano a file e sottocartelle di una directory. Ad esempio, il codice seguente elenca il contenuto della directory documents dell'utente (senza esaminare le sottodirectory): var directory:File = File.documentsDirectory; var contents:Array = directory.getDirectoryListing(); for (var i:uint = 0; i < contents.length; i++) { trace(contents[i].name, contents[i].size); } Quando si utilizza la versione asincrona del metodo, l'oggetto evento directoryListing presenta una proprietà files che è l'array di oggetti File relativi alle directory: var directory:File = File.documentsDirectory; directory.getDirectoryListingAsync(); directory.addEventListener(FileListEvent.DIRECTORY_LISTING, dirListHandler); function dirListHandler(event:FileListEvent):void { var contents:Array = event.files; for (var i:uint = 0; i < contents.length; i++) { trace(contents[i].name, contents[i].size); } } Copiatura e spostamento di directory Potete copiare o spostare una directory con gli stessi metodi utilizzati per copiare o spostare un file. Ad esempio, il codice seguente copia una directory in modo sincrono: var sourceDir:File = File.documentsDirectory.resolvePath("AIR Test"); var resultDir:File = File.documentsDirectory.resolvePath("AIR Test Copy"); sourceDir.copyTo(resultDir); Quando specificate il valore true per il parametro overwrite del metodo copyTo(), tutti i file e le cartelle presenti in una directory di destinazione esistente vengono eliminati e sostituiti con i file e le cartelle della cartella originale (anche se il file di destinazione non è presente in tale directory). La directory specificata come parametro newLocation del metodo copyTo() indica il percorso della directory risultante; non indica la directory principale che conterrà la directory risultante. Per informazioni dettagliate, consultate “Copiatura e spostamento di file” a pagina 121. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 120 Operazioni con il file system Eliminazione del contenuto di una directory La classe File contiene il metodo deleteDirectory() e il metodo deleteDirectoryAsync(). Questi metodi consentono di eliminare le directory; il primo funziona in modo sincrono, il secondo in modo asincrono (consultate “Elementi di base dei file AIR” a pagina 108). Entrambi i metodi comprendono un parametro deleteDirectoryContents (che accetta un valore booleano); quando è impostato su true (il valore predefinito è false), la chiamata al metodo elimina le directory non vuote, in caso contrario vengono eliminate solo quelle vuote. Ad esempio, il codice seguente elimina in modo sincrono la sottodirectory AIR Test della directory documents dell'utente: var directory:File = File.documentsDirectory.resolvePath("AIR Test"); directory.deleteDirectory(true); Il codice seguente elimina in modo asincrono la sottodirectory AIR Test della directory documents dell'utente: var directory:File = File.documentsDirectory.resolvePath("AIR Test"); directory.addEventListener(Event.COMPLETE, completeHandler) directory.deleteDirectoryAsync(true); function completeHandler(event:Event):void { trace("Deleted.") } Sono disponibili inoltre i metodi moveToTrash() e moveToTrashAsync(), che consentono di spostare una directory nel cestino del sistema. Per informazioni dettagliate, consultate “Spostamento di un file nel cestino” a pagina 122. Operazioni con i file Grazie all'API file di AIR potete aggiungere alle vostre applicazioni funzionalità di base per l'interazione con i file. Ad esempio, potete leggere, scrivere, copiare ed eliminare file, e altro ancora. Poiché le applicazioni sono in grado di accedere al file system locale, consultate il capitolo “Sicurezza in AIR” a pagina 25, se non lo avete ancora letto. Nota: potete associare un tipo di file a un'applicazione AIR (in modo da poterla aprire facendo doppio clic su un file di quel tipo). Per informazioni dettagliate, consultate “Gestione delle associazioni di file” a pagina 303. Recupero di informazioni sui file La classe File comprende le seguenti proprietà che forniscono informazioni su un file o una directory a cui punta un oggetto File: Proprietà File Descrizione creationDate La data di creazione del file sul disco locale. creator Obsoleto; utilizzate la proprietà extension. (Questa proprietà riporta il tipo di autore Macintosh del file, utilizzato solo nelle versioni Mac OS precedenti a Mac OS X.) exists Qualora sia disponibile il file o la directory di riferimento. extension L'estensione del file che fa parte del nome e segue (e non comprende) il punto finale ("."). Se non vi è alcun punto nel nome file, l'estensione è null. icon Un oggetto Icon contenente le icone definite per il file. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 121 Operazioni con il file system Proprietà File Descrizione isDirectory Qualora l'oggetto File faccia riferimento a una directory. modificationDate La data dell'ultima modifica apportata al file o alla directory sul disco locale. name Il nome del file o della directory (compresa l'eventuale estensione del file) sul disco locale. nativePath Il percorso completo nella rappresentazione del sistema operativo host. Consultate “Percorsi degli oggetti File” a pagina 109. parent La cartella che contiene la cartella o il file rappresentato dall'oggetto File. Questa proprietà è null se l'oggetto File fa riferimento a un file o a una directory nella radice del file system. size Le dimensioni del file sul disco locale, espresse in byte. type Obsoleto—utilizzate la proprietà extension. (In Macintosh, questa proprietà è di tipo file di quattro caratteri, utilizzato solo nelle versioni Mac OS precedenti a Mac OS X.) url L'URL del file o della directory. Consultate “Percorsi degli oggetti File” a pagina 109. Per informazioni dettagliate su queste proprietà, consultate la voce classe File nella sezione Guida di riferimento del linguaggio e dei componenti ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_it). Copiatura e spostamento di file La classe File comprende due metodi per la copia di file o directory: copyTo() e copyToAsync(). La classe File comprende due metodi per lo spostamento di file o directory: moveTo() e moveToAsync(). I metodi copyTo() e moveTo() operano in modo sincrono, mentre i metodi copyToAsync() e moveToAsync() in modo asincrono (consultate “Elementi di base dei file AIR” a pagina 108). Per copiare o spostare un file, configurate due oggetti File. Uno punta al file da copiare o spostare e corrisponde all'oggetto che chiama il metodo di copia o spostamento; l'altro punta al percorso di destinazione (risultato). Il caso seguente copia un file test.txt dalla sottodirectory AIR Test della directory documents dell'utente in un file denominato copy.txt presente nella stessa directory: var original:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var newFile:File = File.resolvePath("AIR Test/copy.txt"); original.copyTo(newFile, true); In questo esempio, il valore del parametro overwrite del metodo copyTo() (il secondo parametro) è impostato su true. Impostandolo su true, si sovrascrive un file target esistente. Questo parametro è opzionale. Se si imposta su false (il valore predefinito), l'operazione invia un evento IOErrorEvent, nel caso esista un file target (e il file non viene copiato). Le versioni "Async" dei metodi di copia e spostamento operano in modo asincrono. Utilizzate il metodo addEventListener() per monitorare il completamento dell'attività o delle condizioni di errore, come nel codice seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 122 Operazioni con il file system var original = File.documentsDirectory; original = original.resolvePath("AIR Test/test.txt"); var destination:File = File.documentsDirectory; destination = destination.resolvePath("AIR Test 2/copy.txt"); original.addEventListener(Event.COMPLETE, fileMoveCompleteHandler); original.addEventListener(IOErrorEvent.IO_ERROR, fileMoveIOErrorEventHandler); original.moveToAsync(destination); function fileMoveCompleteHandler(event:Event):void { trace(event.target); // [object File] } function fileMoveIOErrorEventHandler(event:IOErrorEvent):void { trace("I/O Error."); } La classe File include anche i metodi File.moveToTrash() e File.moveToTrashAsync() che spostano un file o una directory nel cestino del sistema. Eliminazione di un file La classe File comprende un metodo deleteFile() e un metodo deleteFileAsync(). Questi metodi eliminano file: il primo lavora in modo sincrono, il secondo in modo asincrono (consultate “Elementi di base dei file AIR” a pagina 108). Ad esempio, il codice seguente elimina in modo sincrono il file test.txt nella directory documents dell'utente: var file:File = File.documentsDirectory.resolvePath("test.txt"); file.deleteFile(); Il codice seguente elimina in modo asincrono il file test.txt della directory documents dell'utente: var file:File = File.documentsDirectory.resolvePath("test.txt"); file.addEventListener(Event.COMPLETE, completeHandler) file.deleteFileAsync(); function completeHandler(event:Event):void { trace("Deleted.") } Sono inclusi inoltre i metodi moveToTrash() e moveToTrashAsync() utilizzabili per spostare un file o una directory nel cestino del sistema. Per informazioni dettagliate, consultate “Spostamento di un file nel cestino” a pagina 122. Spostamento di un file nel cestino La classe File comprende un metodo moveToTrash() e un metodo moveToTrashAsync(). Questi metodi inviano un file o una directory nel cestino del sistema, il primo lavora in modo sincrono, il secondo in modo asincrono (consultate “Elementi di base dei file AIR” a pagina 108). Ad esempio, il codice seguente sposta in modo sincrono il file test.txt nella directory documents dell'utente nel cestino del sistema: var file:File = File.documentsDirectory.resolvePath("test.txt"); file.moveToTrash(); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 123 Operazioni con il file system Creazione di un file temporaneo La classe File comprende un metodo createTempDirectory(), che crea un file nella cartella della directory temporanea del sistema come nell'esempio seguente: var temp:File = File.createTempFile(); Il metodo createTempFile() crea automaticamente un file temporaneo unico (evitando l'operazione di individuare un nuovo percorso unico). È possibile utilizzare un file temporaneo per memorizzare temporaneamente le informazioni utilizzate in una sessione dell'applicazione. Notate che è disponibile anche un metodo createTempDirectory() per la creazione di una directory temporanea unica nella directory temporanea di sistema. È possibile eliminare il file temporaneo prima della chiusura dell'applicazione, poiché non viene eliminato automaticamente. Lettura e scrittura di file La classe FileStream consente alle applicazioni AIR di leggere e scrivere nel file system. Flusso di lavoro per lettura e scrittura di file Il flusso di lavoro per lettura e scrittura di file è riportato di seguito. Inizializzate un oggetto File che punti al percorso. È il percorso del file con cui si desidera lavorare (o un file che verrà creato di seguito). var file:File = File.documentsDirectory; file = file.resolvePath("AIR Test/testFile.txt"); Questo esempio utilizza la proprietà File.documentsDirectory e il metodo resolvePath() di un oggetto File per inizializzare tale oggetto. Tuttavia, sono disponibili diversi altri modi per puntare un oggetto File a un file. Per ulteriori informazioni, consultate “Puntamento di un oggetto File a un file” a pagina 112. Inizializzate un oggetto FileStream. Chiamate il metodo open() o il metodo openAsync() dell'oggetto FileStream. Il metodo chiamato dipende se si desidera aprire il file per operazioni sincrone o asincrone. Utilizzate l'oggetto File come il parametro File del metodo open. Per il parametro fileMode, specificate una costante dalla classe FileMode che indichi il modo in cui si utilizzerà il file. Ad esempio, il codice seguente inizializza un oggetto FileStream utilizzato per creare un file e sovrascrivere qualsiasi dato esistente: var fileStream:FileStream = new FileStream(); fileStream.open(file, FileMode.WRITE); Per ulteriori informazioni, consultate “Inizializzazione di un oggetto FileStream e apertura e chiusura di file” a pagina 125 e “Modalità aperte FileStream” a pagina 124. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 124 Operazioni con il file system Se il file è stato aperto in modo asincrono (mediante il metodo openAsync()), aggiungete e configurate i listener di eventi per l'oggetto FileStream. Questi metodi di listener di eventi rispondono a eventi inviati dall'oggetto FileStream in una serie di situazioni, come quando i dati vengono letti dal file, quando si verificano degli errori I/O oppure quando vengono scritti tutti i dati da scrivere. Per informazioni dettagliate, consultate “Programmazione asincrona ed eventi generati da un oggetto FileStream aperto in modo asincrono” a pagina 129. Includete il codice per lettura e scrittura di dati, secondo necessità. Sono disponibili molti metodi della classe FileStream correlati a lettura e scrittura. (Ognuno inizia con "read" o "write".) Il metodo selezionato per eseguire la lettura o scrittura dei dati dipende dal formato dei dati nel file target. Ad esempio, se i dati nel file target sono testo codificati in UTF, è possibile utilizzare i metodi readUTFBytes() e writeUTFBytes(). Per gestire i dati come array di byte, è possibile utilizzare i metodi readByte(), readBytes(), writeByte() e writeBytes(). Per informazioni dettagliate, consultate “Formati di dati e selezione dei metodi di lettura e scrittura da utilizzare” a pagina 129. Se il file è stato aperto in modo asincrono, assicuratevi che siano disponibili dati sufficienti prima di chiamare un metodo di lettura. Per informazioni dettagliate, consultate “Buffer di lettura e proprietà bytesAvailable di un oggetto FileStream” a pagina 127. Prima della scrittura in un file, per poter verificare la quantità di spazio di disco disponibile, è possibile controllare la proprietà spaceAvailable dell'oggetto File. Per ulteriori informazioni, consultate “Rilevamento dello spazio disponibile su un volume” a pagina 117. Chiamate il metodo close() dell'oggetto FileStream una volta eseguite le operazioni con il file. Questo consente di rendere il file disponibile per altre applicazioni. Per informazioni dettagliate, consultate “Inizializzazione di un oggetto FileStream e apertura e chiusura di file” a pagina 125. Per visionare un'applicazione di esempio che utilizza la classe FileStream per la lettura e scrittura di file, consultate i seguenti articoli del Centro per sviluppatori Adobe AIR: • Building a text-file editor (Creazione di un editor file-testo) Operazioni con oggetti FileStream La classe FileStream definisce i metodi di apertura, lettura e scrittura di file. Modalità aperte FileStream Ogni metodo open() e openAsync() di un oggetto FileStream comprende un parametro fileMode, che definisce alcune proprietà di file in streaming, compreso quanto segue: • Capacità di lettura dal file • Capacità di scrittura sul file • In caso di aggiunta costante dei dati alla fine del file (in scrittura) • Operazioni in mancanza del file (e in mancanza di relative directory principali) Di seguito sono riportate diverse modalità file (che potete specificare come parametro fileMode dei metodi open() e openAsync()): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 125 Operazioni con il file system Modalità File Descrizione FileMode.READ Indica che il file è aperto in sola lettura. FileMode.WRITE Indica che il file è aperto per la scrittura. Se il file non esiste, viene creato quando si apre l'oggetto FileStream. Se il file esiste, tutti i dati esistenti vengono eliminati. FileMode.APPEND Indica che il file è aperto per l'aggiunta. Il file viene creato se non esiste. Se il file è presente, i dati esistenti non vengono sovrascritti e tutti i dati scritti iniziano al termine del file. FileMode.UPDATE Indica che il file è aperto per la lettura e la scrittura. Se il file non esiste, viene creato. Specificate questa modalità per l'accesso casuale di lettura/scrittura al file. È possibile leggere da qualsiasi posizione nel file e, durante la scrittura nel file, solo i byte scritti sovrascrivono quelli esistenti (tutti gli altri non vengono modificati). Inizializzazione di un oggetto FileStream e apertura e chiusura di file Quando si apre un oggetto FileStream, rendetelo disponibile per lettura e scrittura di dati in un file. Aprite un oggetto FileStream passando un oggetto File al metodo open() o openAsync() dell'oggetto FileStream: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.READ); Il parametro fileMode (il secondo parametro dei metodi open() e openAsync()) indica la modalità in cui aprire il file: per lettura, scrittura, aggiunta o aggiornamento. Per informazioni dettagliate, consultate la sezione successiva “Modalità aperte FileStream” a pagina 124. Se utilizzate il metodo openAsync() per aprire il file per operazioni di file asincrone, configurate listener di eventi per gestire gli eventi asincroni: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(Event.COMPLETE, completeHandler); myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler); myFileStream.addEventListener(IOErrorEvent.IOError, errorHandler); myFileStream.open(myFile, FileMode.READ); function completeHandler(event:Event):void { // ... } function progressHandler(event:ProgressEvent):void { // ... } function errorHandler(event:IOErrorEvent):void { // ... } Il file viene aperto per operazioni sincrone e asincrone, a seconda che si utilizzi il metodo open() o openAsync(). Per informazioni dettagliate, consultate “Elementi di base dei file AIR” a pagina 108. Se impostate il parametro fileMode su FileMode.READ o FileMode.UPDATE nel metodo aperto dell'oggetto FileStream, i dati vengono letti nel buffer di lettura non appena si apre l'oggetto FileStream. Per informazioni dettagliate, consultate “Buffer di lettura e proprietà bytesAvailable di un oggetto FileStream” a pagina 127. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 126 Operazioni con il file system È possibile chiamare il metodo close() di un oggetto FileStream per chiudere il file associato, rendendolo disponibile per altre applicazioni. La proprietà position di un oggetto FileStream La proprietà position di un oggetto FileStream determina dove i dati vengono letti o scritti con il metodo di lettura o scrittura successivo. Prima delle operazioni di lettura o scrittura, impostate la proprietà position su qualsiasi posizione valida nel file. Ad esempio, il codice seguente scrive la stringa "hello" (in codice UTF) nella posizione 8 del file: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.UPDATE); myFileStream.position = 8; myFileStream.writeUTFBytes("hello"); Quando si apre un oggetto FileStream per la prima volta, la proprietà position è impostata su 0. Prima di un'operazione di lettura, il valore di position deve essere almeno 0 e inferiore al numero di byte presenti nel file (che corrispondono alle posizioni esistenti nel file). Il valore della proprietà position viene modificato solo nelle seguenti condizioni: • Quando si imposta esplicitamente la proprietà position • Quando si chiama un metodo di lettura • Quando si chiama un metodo di scrittura Quando si chiama un metodo di lettura o scrittura di un oggetto FileStream, la proprietà position viene immediatamente incrementata dal numero di byte letti o scritti. A seconda del metodo di lettura utilizzato, la proprietà position viene incrementata per il numero di byte specificati per la lettura o per il numero di byte disponibili. Quando si chiama successivamente un metodo di lettura o scrittura, la lettura o scrittura inizia nella nuova posizione. var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.UPDATE); myFileStream.position = 4000; trace(myFileStream.position); // 4000 myFileStream.writeBytes(myByteArray, 0, 200); trace(myFileStream.position); // 4200 Vi è, tuttavia, un'eccezione: per un FileStream aperto in modalità di aggiunta, la proprietà position non cambia dopo una chiamata a un metodo di scrittura. (Nella modalità di aggiunta, i dati sono sempre scritti alla fine del file, indipendentemente dal valore della proprietà position.) Per un file aperto per operazioni asincrone, l'operazione di scrittura non si completa prima dell'esecuzione della riga di codice successiva. Tuttavia, è possibile chiamare più metodi asincroni in modo sequenziale e il runtime li esegue in ordine: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 127 Operazioni con il file system var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.openAsync(myFile, FileMode.WRITE); myFileStream.writeUTFBytes("hello"); myFileStream.writeUTFBytes("world"); myFileStream.addEventListener(Event.CLOSE, closeHandler); myFileStream.close(); trace("started."); closeHandler(event:Event):void { trace("finished."); } L'output di tracciamento di questo codice è il seguente: started. finished. È possibile specificare il valore position subito dopo aver chiamato un metodo di lettura o scrittura (o in qualsiasi momento), e la successiva operazione di lettura o scrittura avrà luogo a partire da tale posizione. Ad esempio, notate che il codice seguente imposta la proprietà position subito dopo una chiamata all'operazione writeBytes() e position è impostata su tale valore (300) anche dopo il completamento dell'operazione di scrittura: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.openAsync(myFile, FileMode.UPDATE); myFileStream.position = 4000; trace(myFileStream.position); // 4000 myFileStream.writeBytes(myByteArray, 0, 200); myFileStream.position = 300; trace(myFileStream.position); // 300 Buffer di lettura e proprietà bytesAvailable di un oggetto FileStream Quando si apre un oggetto FileStream con funzionalità di lettura (una in cui il parametro fileMode del metodo open() o openAsync() è stato impostato su READ o UPDATE), il runtime memorizza i dati in un buffer interno. L'oggetto FileStream inizia la lettura dei dati nel buffer non appena si apre il file (chiamando il metodo open() o openAsync() dell'oggetto FileStream). Per un file aperto per operazioni sincrone (tramite il metodo open()), è possibile impostare sempre il puntatore position a una qualsiasi posizione valida (entro i limiti del file) e iniziare la lettura di una qualsiasi quantità di dati (entro i limiti del file) come illustrato nel codice seguente (il quale ipotizza che il file contenga almeno 100 byte): var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.READ); myFileStream.position = 10; myFileStream.readBytes(myByteArray, 0, 20); myFileStream.position = 89; myFileStream.readBytes(myByteArray, 0, 10); Se un file viene aperto per operazioni sincrone o asincrone, i metodi di lettura leggono sempre dai byte "disponibili", rappresentati dalla proprietà bytesAvalable. Durante la lettura in modo sincrono, tutti i byte del file sono sempre disponibili. Durante la lettura in modo asincrono, i byte diventano disponibili a partire dalla posizione specificata dalla proprietà position in una serie di riempimenti buffer segnalati da eventi progress. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 128 Operazioni con il file system Per file aperti per operazioni sincrone, la proprietà bytesAvailable è sempre impostata per rappresentare il numero di byte dalla proprietà position fino alla fine del file (tutti i byte nel file sono sempre disponibili per la lettura). Per file aperti per operazioni asincrone, è necessario garantire che il buffer di lettura abbia utilizzato un numero sufficiente di dati prima della chiamata di un metodo di lettura. Per un file aperto in modo asincrono, con l'avanzamento dell'operazione di lettura, i dati del file vengono aggiunti al buffer a partire dalla position specificata all'inizio dell'operazione di lettura e la proprietà bytesAvailable aumenta con la lettura di ciascun byte. La proprietà bytesAvailable indica il numero di byte disponibili partendo con il byte nella posizione specificata dalla posizione position alla fine del buffer. Periodicamente l'oggetto FileStream invia un evento progress. Per un file aperto in modo asincrono, quando i dati vengono resi disponibili nel buffer di lettura, l'oggetto FileStream invia periodicamente l'evento progress. Ad esempio, il codice seguente legge i dati in un oggetto ByteArray, bytes, mentre legge nel buffer: var bytes:ByteArray = new ByteArray(); var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler); myFileStream.openAsync(myFile, FileMode.READ); function progressHandler(event:ProgressEvent):void { myFileStream.readBytes(bytes, myFileStream.position, myFileStream.bytesAvailable); } Per un file aperto in modo asincrono, solo i dati nel buffer di lettura possono essere letti. Inoltre, mentre si leggono i dati, questi vengono rimossi dal buffer di lettura. Per le operazioni di lettura, è necessario garantire che i dati siano presenti nel buffer di lettura prima di chiamare tale operazione. Ad esempio, il codice seguente legge 8000 byte di dati a partire dalla posizione 4000 nel file: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler); myFileStream.addEventListener(Event.COMPLETE, completed); myFileStream.openAsync(myFile, FileMode.READ); myFileStream.position = 4000; var str:String = ""; function progressHandler(event:Event):void { if (myFileStream.bytesAvailable > 8000 ) { str += myFileStream.readMultiByte(8000, "iso-8859-1"); } } Durante un'operazione di scrittura, l'oggetto FileStream non legge dati nel buffer di lettura. Al termine di un'operazione di scrittura (tutti i dati nel buffer di scrittura vengono scritti nel file), l'oggetto FileStream inizia un nuovo buffer di lettura (supponendo che l'oggetto FileStream associato sia stato aperto con funzionalità di lettura) e inizia la lettura dei dati nel buffer di lettura, a partire dalla posizione specificata dalla proprietà position. La proprietà position può corrispondere alla posizione dell'ultimo byte scritto oppure a una posizione differente, nel caso l'utente specifichi un valore differente per l'oggetto position dopo l'operazione di scrittura. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 129 Operazioni con il file system Programmazione asincrona ed eventi generati da un oggetto FileStream aperto in modo asincrono Quando un file viene aperto in modo asincrono (mediante il metodo openAsync()), i file di lettura e scrittura vengono eseguiti in modo asincrono. Durante la lettura dei dati nel buffer di lettura e la scrittura dei dati in uscita, è possibile eseguire altro codice ActionScript. Ciò significa che è necessario eseguire la registrazione per gli eventi generati dall'oggetto FileStream aperto in modo asincrono. Con la registrazione per l'evento progress, è possibile notificare quando i nuovi dati vengono resi disponibili per la lettura come nel codice seguente: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler); myFileStream.openAsync(myFile, FileMode.READ); var str:String = ""; function progressHandler(event:ProgressEvent):void { str += myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1"); } È possibile leggere tutti i dati registrando per l'evento complete come nel codice seguente: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(Event.COMPLETE, completed); myFileStream.openAsync(myFile, FileMode.READ); var str:String = ""; function completeHandler(event:Event):void { str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1"); } Quasi contemporaneamente alla bufferizzazione dei dati in entrata per consentire la lettura asincrona, i dati scritti in uno streaming asincrono vengono bufferizzati e scritti nel file in modo asincrono. Durante la scrittura dei dati in un file, l'oggetto FileStream invia periodicamente un oggetto OutputProgressEvent. Un oggetto OutputProgressEvent comprende una proprietà bytesPending impostata sul numero di byte residui da scrivere. È possibile registrare per l'evento outputProgress da notificare mentre il buffer viene effettivamente scritto nel file, probabilmente in ordine di visualizzazione della finestra di dialogo di avanzamento. Tuttavia, in generale, non è necessario eseguire tale operazione. In particolare, è possibile chiamare il metodo close() senza preoccuparsi dei byte non scritti. L'oggetto FileStream continuerà a scrivere dati e l'evento close verrà distribuito dopo che il byte finale viene scritto nel file e quello sottostante viene chiuso. Formati di dati e selezione dei metodi di lettura e scrittura da utilizzare Ogni file è impostato su un set di byte in un disco. In ActionScript, i dati di un file possono essere sempre rappresentati come ByteArray. Ad esempio, il codice seguente legge i dati da un file in un oggetto ByteArray denominato bytes: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 130 Operazioni con il file system var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(Event.COMPLETE, completeHandler); myFileStream.openAsync(myFile, FileMode.READ); var bytes:ByteArray = new ByteArray(); function completeHandler(event:Event):void { myFileStream.readBytes(bytes, 0, myFileStream.bytesAvailable); } Ad esempio, il codice seguente scrive i dati da un ByteArray denominato bytes in un file: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.WRITE); myFileStream.writeBytes(bytes, 0, bytes.length); Tuttavia, spesso non si vuole memorizzare i dati in un oggetto ByteArray di ActionScript. E spesso il file di dati è in un formato file specificato. Ad esempio, i dati nel file possono essere in un formato file di testo ed è possibile rappresentare tali dati in un oggetto String. Per tale motivo, la classe FileStream comprende metodi di lettura e scrittura per la lettura e la scrittura di dati da e in tipi diversi da oggetti ByteArray. Ad esempio, il metodo readMultiByte() consente di leggere dati da un file e memorizzarli in una stringa, come nel codice seguente: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.addEventListener(Event.COMPLETE, completed); myFileStream.openAsync(myFile, FileMode.READ); var str:String = ""; function completeHandler(event:Event):void { str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1"); } Il secondo parametro del metodo readMultiByte() specifica il formato testo che ActionScript utilizza per interpretare i dati ("iso-8859-1" nell'esempio). ActionScript supporta codifiche di set di caratteri comuni, elencati nella Guida di riferimento del linguaggio ActionScript 3.0 (consultate Supported character sets (Set di caratteri supportati) all'indirizzo http://livedocs.macromedia.com/flex/2/langref/charset-codes.html. La classe FileStream comprende inoltre il metodo readUTFBytes() che legge i dati dal buffer di lettura in una stringa che utilizza il set di caratteri UTF-8. Poiché i caratteri nel set di caratteri UTF-8 hanno una lunghezza variabile, non utilizzate readUTFBytes() in un metodo che risponde all'evento progress perché i dati al termine del buffer di lettura possono rappresentare un carattere incompleto. (Il che è anche vero quando si utilizza il metodo readMultiByte() con una codifica di caratteri a lunghezza variabile.) Per tale motivo, leggete l'intero set di dati quando l'oggetto FileStream invia l'evento complete. Vi sono inoltre metodi di scrittura simili, writeMultiByte() e writeUTFBytes(), per operazioni con oggetti String e file di testo. I metodi readUTF() e writeUTF() (da non confondere con readUTFBytes() e writeUTFBytes()) leggono e scrivono anche i dati di testo in un file, ma ipotizzano che tali dati siano preceduti da quelli che specificano la lunghezza dei dati di testo, il che non è comune nei file di testo standard. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 131 Operazioni con il file system Alcuni file di testo codificati con UTF iniziano con un carattere "UTF-BOM" (byte order mark) che definisce l'endiannes, nonché il formato di codifica (come UTF-16 o UTF-32). Per un esempio di lettura e scrittura di un file di testo, consultate “Esempio: lettura di un file XML in un oggetto XML” a pagina 132. I metodi readObject() e writeObject() sono metodi utili per memorizzare e recuperare i dati per oggetti ActionScript complessi. I dati vengono codificati in AMF (ActionScript Message Format). Questo formato è proprietario di ActionScript. Applicazioni diverse da AIR, Flash Player, Flash Media Server e Flex Data Services non presentano API incorporate per operazioni con dati in questo formato. Vi sono altri metodi di lettura e scrittura (come readDouble() e writeDouble()). Tuttavia, se vengono utilizzati, assicuratevi che il formato file corrisponda ai formati dei dati definiti da questi metodi. I formati file sono spesso più complessi dei semplici formati di testo. Ad esempio, un file MP3 comprende dati compromessi che possono essere interpretati solo con algoritmi di decompressione e decodifica specifici dei file MP3. I file MP3 possono anche includere tag ID3 che contengono informazioni di metatag sul file (come il titolo e l'artista di un brano). Vi sono più versioni del formato ID3, ma il più semplice (versione ID3 1) è riportato nella sezione “Esempio: lettura e scrittura di dati con accesso casuale” a pagina 133. Altri formati di file (per immagini, database, documenti applicativi e altro) hanno strutture differenti e per operare con i loro dati in ActionScript, è necessario comprendere come sono strutturati i dati. Uso dei metodi load() e save() In Flash Player 10 sono stati aggiunti i metodi load() e save() alla classe FileReference. Questi metodi sono presenti anche in AIR 1.5 e la classe File eredita i metodi dalla classe FileReference. Questi metodi sono stati progettati per fornire agli utenti un mezzo sicuro per caricare e salvare i dati dei file in Flash Player. Nelle applicazioni AIR, tuttavia, questi metodi possono anche essere usati come semplice metodo per caricare e salvare i file in modo asincrono. Il codice riportato di seguito consente, ad esempio, di salvare una stringa in un file di testo: var file:File = File.applicationStorageDirectory.resolvePath("test.txt"); var str:String = "Hello."; file.addEventListener(Event.COMPLETE, fileSaved); file.save(str); function fileSaved(event:Event):void { trace("Done."); } Il parametro data del metodo save() può accettare un valore String, XML o ByteArray. Quando l'argomento è un valore String o XML, il metodo salva il file come file di testo con codifica UTF-8. All'esecuzione di questo esempio di codice, nell'applicazione viene visualizzata una finestra di dialogo in cui l'utente seleziona la destinazione del file salvato. Il codice riportato di seguito carica una stringa dal file di testo con codifica UTF-8: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 132 Operazioni con il file system var file:File = File.applicationStorageDirectory.resolvePath("test.txt"); file.addEventListener(Event.COMPLETE, loaded); file.load(); var str:String; function loaded(event:Event):void { var bytes:ByteArray = file.data; str = bytes.readUTFBytes(bytes.length); trace(str); } La classe FileStream offre più funzionalità di quelle fornite dai metodi load() e save(): • Usando la classe FileStream, potete leggere e scrivere i dati sia in modo sincrono che asincrono. • La classe FileStream consente di scrivere in modo incrementale in un file. • La classe FileStream consente di aprire un file per l'accesso casuale ai dati (sia per la lettura che per la scrittura in qualsiasi sezione del file). • La classe FileStream consente di specificare il tipo di accesso di cui disponete per un file specifico, impostando il parametro fileMode del metodo open() o openAsync(). • La classe FileStream consente di salvare i dati nei file senza presentare all'utente una finestra di dialogo Apri o Salva. • Per la lettura dei dati tramite la classe FileStream, potete usare direttamente tipi diversi dagli array di byte. Esempio: lettura di un file XML in un oggetto XML Gli esempi seguenti mostrano come leggere e scrivere in un file di testo contenente dati XML. Per la lettura dal file, inizializzate gli oggetti File e FileStream, chiamate il metodo readUTFBytes() di FileStream e convertite la stringa in un oggetto XML: var file:File = File.documentsDirectory.resolvePath("AIR Test/preferences.xml"); var fileStream:FileStream = new FileStream(); fileStream.open(file, FileMode.READ); var prefsXML:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable)); fileStream.close(); Analogamente la scrittura dei dati nel file è semplice come configurare appropriati oggetti File e FileStream e quindi chiamare un metodo di scrittura dell'oggetto FileStream. Passate la versione stringa dei dati XML al metodo di scrittura come nel codice seguente: var prefsXML:XML = <prefs><autoSave>true</autoSave></prefs>; var file:File = File.documentsDirectory.resolvePath("AIR Test/preferences.xml"); fileStream = new FileStream(); fileStream.open(file, FileMode.WRITE); var outputString:String = '<?xml version="1.0" encoding="utf-8"?>\n'; outputString += prefsXML.toXMLString(); fileStream.writeUTFBytes(outputString); fileStream.close(); Questi esempi utilizzano i metodi readUTFBytes() e writeUTFBytes(), perché ipotizzano che i file siano in formato UTF-8. In caso contrario, è possibile che sia necessario utilizzare un metodo differente (consultate “Formati di dati e selezione dei metodi di lettura e scrittura da utilizzare” a pagina 129). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 133 Operazioni con il file system Gli esempi precedenti utilizzano oggetti FileStream aperti per operazioni sincrone. È possibile inoltre aprire i file per operazioni asincrone (che fanno affidamento sulle funzione del listener di eventi per rispondere agli eventi). Ad esempio, il codice seguente mostra come leggere un file XML in modo asincrono: var file:File = File.documentsDirectory.resolvePath("AIR Test/preferences.xml"); var fileStream:FileStream = new FileStream(); fileStream.addEventListener(Event.COMPLETE, processXMLData); fileStream.openAsync(file, FileMode.READ); var prefsXML:XML; function processXMLData(event:Event):void { prefsXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable)); fileStream.close(); } Il metodo processXMLData() viene invocato quando l'intero file viene letto nel buffer di lettura (quando l'oggetto FileStream invia l'evento complete). Chiama il metodo readUTFBytes() per recuperare una versione stringa dei dati di lettura e crea un oggetto XML, prefsXML, in base a tale stringa. Esempio: lettura e scrittura di dati con accesso casuale I file MP3 possono includere tag ID3, che sono sezioni all'inizio o alla fine del file contenente i metadati che identificano la registrazione. Lo stesso formato tag ID3 ha diverse revisioni. Questo esempio descrive come leggere e scrivere da un file MP3 contenente il formato ID3 più semplice (versione ID3 1.0) mediante "accesso casuale a dati di file", il che significa che legge e scrive in posizioni arbitrarie del file. Un file MP3 contenente un tag della versione ID3 1 comprende i dati ID3 alla fine del fine, negli ultimi 128 byte. Quando si accede a un file per l'accesso casuale di lettura/scrittura, è importante specificare FileMode.UPDATE come il parametro fileMode del metodo open() o openAsync(): var file:File = File.documentsDirectory.resolvePath("My Music/Sample ID3 v1.mp3"); var fileStr:FileStream = new FileStream(); fileStr.open(file, FileMode.UPDATE); Ciò consente di eseguire sia la lettura sia la scrittura nel file. All'apertura del file, è possibile impostare il puntatore position nei 128 byte di posizione prima della fine del file: fileStr.position = file.size - 128; Questo codice imposta la proprietà position in questo percorso nel file perché il formato ID3 v1.0 specifica che i dati del tag ID3 sono memorizzati negli ultimi 128 byte del file. La specifica indica sempre quanto segue: • I primi 3 byte del tag contengono la stringa "TAG". • I successivi 30 caratteri contengono il titolo della traccia MP3, come una stringa. • I successivi 30 caratteri contengono il nome dell'artista, come una stringa. • I successivi 30 caratteri contengono il nome dell'album, come una stringa. • I successivi 4 caratteri contengono l'anno, come una stringa. • I successivi 30 caratteri contengono il commento, come una stringa. • Il byte successivo contiene un codice indicante il genere della traccia. • Tutti i dati di testo sono in formato ISO 8859-1. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 134 Operazioni con il file system Il metodo id3TagRead() controlla i dati dopo esser stati letti (in occasione dell'eventocomplete): function id3TagRead():void { if (fileStr.readMultiByte(3, "iso-8859-1").match(/tag/i)) { var id3Title:String = fileStr.readMultiByte(30, "iso-8859-1"); var id3Artist:String = fileStr.readMultiByte(30, "iso-8859-1"); var id3Album:String = fileStr.readMultiByte(30, "iso-8859-1"); var id3Year:String = fileStr.readMultiByte(4, "iso-8859-1"); var id3Comment:String = fileStr.readMultiByte(30, "iso-8859-1"); var id3GenreCode:String = fileStr.readByte().toString(10); } } È possibile inoltre eseguire una scrittura ad accesso casuale nel file. Ad esempio, è possibile analizzare la variabile id3Title per garantire che sia correttamente capitalizzata (mediante i metodi della classe String), e quindi scrivere una stringa modificata, denominata newTitle, nel file come nel caso seguente: fileStr.position = file.length - 125; // 128 - 3 fileStr.writeMultiByte(newTitle, "iso-8859-1"); Per conformarsi alla versione ID3 1 standard, la lunghezza della stringa newTitle deve avere 30 caratteri, allungata alla fine del codice di carattere 0 (String.fromCharCode(0)). 135 Capitolo 15: Trascinamento della selezione Utilizzate le classi nell'API di trascinamento per supportare i movimenti di trascinamento dell'interfaccia utente. Un movimento in tal senso è un'azione dell'utente, modificata dal sistema operativo e dall'applicazione, che esprime l'intenzione di copiare, spostare o collegare informazioni. Un movimento di trascinamento verso esterno avviene quando l'utente trascina un oggetto all'esterno di un componente o di un'applicazione. Un movimento di trascinamento verso interno avviene quando l'utente trascina un oggetto all'interno di un componente o di un'applicazione. L'API di trascinamento consente a un utente di trascinare i dati tra applicazioni e tra componenti all'interno di un'applicazione. I formati di trasferimento supportati includono: • bitmap; • file; • testo in formato HTML; • testo; • dati RTF; • URL; • oggetti serializzati; • riferimenti di oggetti (solo valido all'interno dell'applicazione di origine). Informazioni supplementari online sul trascinamento È possibile trovare ulteriori informazioni sulle operazioni con API di trascinamento nelle seguenti fonti: Guide rapide (Centro per sviluppatori Adobe AIR) • Supporting drag-and-drop and copy-and-paste (Supporto delle funzioni di trascinamento e copia-incolla) Guida di riferimento del linguaggio • NativeDragManager • NativeDragOptions • Clipboard • NativeDragEvent Articoli ed esempi di Centro per sviluppatori Adobe • Centro per sviluppatori Adobe AIR per Flash (cercate 'AIR filesystem') Elementi di base del trascinamento L'API di trascinamento contiene le seguenti classi. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 136 Trascinamento della selezione Pacchetto Classi flash.desktop • NativeDragManager • NativeDragOptions • Appunti • NativeDragActions • ClipboardFormat • ClipboardTransferModes Le costanti utilizzate con l'API di trascinamento sono definite nelle classi seguenti: flash.events • NativeDragActions • ClipboardFormat • ClipboardTransferModes NativeDragEvent Fasi del movimento di trascinamento Il movimento di trascinamento presenta tre fasi: Avvio Un utente avvia un'operazione di trascinamento partendo da un componente, oppure un elemento in un componente, tenendo premuto il pulsante del mouse. Il componente che è l'origine dell'elemento trascinato è di solito definito quale promotore (initiator) del trascinamento e invia eventi nativeDragStart e nativeDragComplete. Un'applicazione Adobe® AIR™ avvia un'operazione di trascinamento chiamando il metodo NativeDragManager.doDrag() in risposta a un evento mouseDown omouseMove. Se l'operazione di trascinamento inizia dall'esterno di un'applicazione AIR, non è presente alcun oggetto promotore che possa inviare gli eventi nativeDragStart o nativeDragComplete. Trascinamento Tenendo premuto il pulsante del mouse, l'utente sposta il cursore del mouse su un altro componente, applicazione o sul desktop. Durante lo svolgimento del trascinamento, l'oggetto promotore invia eventi nativeDragUpdate. Quando l'utente sposta il mouse su una possibile destinazione di trascinamento in un'applicazione AIR, tale destinazione invia un evento nativeDragEnter. Il gestore eventi può ispezionare l'oggetto evento al fine di determinare se sono disponibili i dati trascinati in un formato che la destinazione accetta e, in tal caso, consente all'utente di rilasciare i dati su di esso chiamando il metodo NativeDragManager.acceptDragDrop(). Mentre il movimento di trascinamento resta su un oggetto interattivo, questo invia eventi nativeDragOver. Quando il movimento di trascinamento lascia l'oggetto interattivo, invia un evento nativeDragExit. Rilascio L'utente rilascia il mouse su un'idonea destinazione di rilascio. Se la destinazione è un'applicazione o un componente AIR, l'oggetto di destinazione invia un evento nativeDragDrop. Il gestore eventi può accedere ai dati trasferiti dall'oggetto evento. Se la destinazione è esterna ad AIR, il sistema operativo o un'altra applicazione gestisce il rilascio. In entrambi i casi, l'oggetto promotore invia un evento nativeDragComplete (qualora il trascinamento sia iniziato dall'interno dell'AIR). La classe NativeDragManager controlla i movimenti di trascinamento verso interno ed esterno. Tutti i membri della classe NativeDragManager sono statici; non creano un'istanza di questa classe. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 137 Trascinamento della selezione Oggetto Clipboard I dati trascinanti all'interno o all'esterno di un'applicazione o un componente sono contenuti in un oggetto Clipboard. Un singolo oggetto Clipboard consente di rendere disponibili diverse rappresentazioni delle stesse informazioni per aumentare la probabilità che un'altra applicazione sia in grado di comprendere e utilizzare i dati. Ad esempio, è possibile includere un'immagine come dati di immagine, un oggetto Bitmap serializzato, e come file. Il rendering dei dati in un formato può essere rimandato a una funzione di rendering che non viene chiamata fino alla lettura dei dati. Una volta iniziato un movimento di trascinamento, è possibile accedere all'oggetto Clipboard solo dall'interno di un gestore eventi per eventi nativeDragEnter, nativeDragOver e nativeDragDrop. Al termine del movimento di trascinamento, non è possibile leggere o riutilizzare l'oggetto Clipboard. È possibile trasferire un oggetto applicazione come riferimento e come oggetto serializzato. I riferimenti sono validi solo all'interno dell'applicazione di origine. I trasferimenti di oggetti serializzati sono validi tra applicazioni AIR, ma possono essere utili solo con oggetti che restano validi se serializzati e deserializzati. Gli oggetti serializzati sono convertiti nell'Action Message Format per ActionScript 3 (AMF3), un formato di trasferimento dati basato su stringa. Operazioni con il framework Flex Nella maggioranza dei casi, è meglio utilizzare l'API di trascinamento Adobe® Flex™ quando si creano applicazioni Flex. Il framework Flex offre una funzione equivalente impostata quando un'applicazione Flex viene eseguita in AIR (utilizza AIR NativeDragManager internamente). Flex mantiene inoltre una funzione più limitata impostata quando si esegue un'applicazione o un componente all'interno dell'ambiente browser più restrittivo. Le classi AIR non possono essere utilizzate in componenti o applicazioni eseguiti esternamente all'ambiente di run-time AIR. Supporto del movimento di trascinamento verso esterno Per supportare il movimento di trascinamento verso esterno, è necessario creare un oggetto Clipboard in risposta a un evento mouseDown e inviarlo al metodo NativeDragManager.doDrag(). L'applicazione è in grado quindi di intercettare l'evento nativeDragComplete sull'oggetto promotore per determinare quale azione intraprendere quando l'utente completa o sospende il movimento. Preparazione di dati per trasferimento Per preparare dati o un oggetto da trascinare, creare un oggetto Clipboard e aggiungere le informazioni da trasferire in uno o più formati. È possibile utilizzare i formati di dati standard in modo da passare dati che possano essere trasferiti automaticamente a formati di appunti nativi e a formati definiti dall'applicazione per passare oggetti. Se richiede notevoli risorse di calcolo per convertire le informazioni da trasferire in un formato particolare, è possibile fornire il nome della funzione di gestore per eseguire la conversione. La funzione viene chiamata se, e solo se, il componente o l'applicazione ricevente legge il formato associato. Per ulteriori informazioni sui formati degli Appunti, consultate il capitolo Copia e incolla in Programmazione in ActionScript 3.0 (http://www.adobe.com/go/learn_fl_cs4_programmingAS3_it). L'esempio seguente mostra come creare un oggetto Clipboard contenente un bitmap in numerosi formati: un oggetto Bitmap, un formato bitmap nativo e un formato di elenco file contenente il file da cui è stato caricato originariamente il bitmap: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 138 Trascinamento della selezione import flash.desktop.Clipboard; import flash.display.Bitmap; import flash.filesystem.File; public function createClipboard(image:Bitmap, sourceFile:File):Clipboard{ var transfer:Clipboard = new Clipboard(); transfer.setData("CUSTOM_BITMAP", image, true); //Flash object by value and by reference transfer.setData(ClipboardFormats.BITMAP_FORMAT, image.bitmapData, false); transfer.setData(ClipboardFormats.FILE_LIST_FORMAT, new Array(sourceFile), false); return transfer; } Avvio dell'operazione di trascinamento verso esterno Per avviare un'operazione di trascinamento, chiamate il metodo NativeDragManager.doDrag() in risposta a un evento di pressione mouse. Il metodo doDrag() è un metodo statico che assume i seguenti parametri: Parametro Descrizione initiator L'oggetto da cui ha origine il trascinamento e che invia gli eventi dragStart e dragComplete. Il promotore deve essere un oggetto interattivo. clipboard L'oggetto Clipboard contenente i dati da trasferire. Si fa riferimento all'oggetto Clipboard negli oggetti NativeDragEvent inviati durante la sequenza di trascinamento. dragImage (Opzionale) Un oggetto BitmapData per la visualizzazione durante il trascinamento. L'immagine può specificare un valore alpha. (Nota: Microsoft Windows applica sempre una dissolvenza alpha fissa per il trascinamento delle immagini). offset (Opzionale) Un oggetto Point che indica l'offset dell'immagine trascinata dal punto attivo del mouse. Utilizzate coordinate negative per spostare l'immagine di trascinamento verso l'alto e a sinistra in base al cursore del mouse. Se non viene fornito alcun offset, l'angolo superiore sinistro dell'immagine è posizionato nel punto attivo del mouse. actionsAllowed (Opzionale) Un oggetto NativeDragOptions che indica quali azioni (copia, spostamento o collegamento) sono valide per l'operazione di trascinamento. Se non viene fornito alcun argomento, è possibile eseguire tutte le azioni. Si fa riferimento all'oggetto DragOptions in oggetti NativeDragEvent al fine di abilitare una potenziale destinazione di trascinamento per controllare che le azioni consentite siano compatibili con lo scopo del componente di destinazione. Ad esempio, un componente "cestino" potrebbe accettare solo i movimenti di trascinamento che consentono l'azione di spostamento. L'esempio seguente mostra come avviare un'operazione di trascinamento per un oggetto bitmap a partire da un file: L'esempio carica un'immagine e, su un evento mouseDown, avvia l'operazione di trascinamento. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 139 Trascinamento della selezione package { import flash.desktop.NativeDragManager; import mx.core.UIComponent; import flash.display.Sprite; import flash.display.Loader; import flash.system.LoaderContext; import flash.net.URLRequest; import flash.geom.Point; import flash.desktop.Clipboard; import flash.display.Bitmap; import flash.filesystem.File; import flash.events.Event; import flash.events.MouseEvent; public class DragOutExample extends UIComponent Sprite { protected var fileURL:String = "app:/image.jpg"; protected var display:Bitmap; private function init():void { loadImage(); } private function onMouseDown(event:MouseEvent):void { var bitmapFile:File = new File(fileURL); var transferObject:Clipboard = createClipboard(display, bitmapFile); NativeDragManager.doDrag(this, transferObject, display.bitmapData, new Point(-mouseX,-mouseY)); } public function createClipboard(image:Bitmap, sourceFile:File):Clipboard { var transfer:Clipboard = new Clipboard(); transfer.setData("bitmap", image, true); // ActionScript 3 Bitmap object by value and by reference transfer.setData(ClipboardFormats.BITMAP_FORMAT, image.bitmapData, false); // Standard BitmapData format transfer.setData(ClipboardFormats.FILE_LIST_FORMAT, SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 140 Trascinamento della selezione new Array(sourceFile), false); // Standard file list format return transfer; } private function loadImage():void { var url:URLRequest = new URLRequest(fileURL); var loader:Loader = new Loader(); loader.load(url,new LoaderContext()); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete); } private function onLoadComplete(event:Event):void { display = event.target.loader.content; var flexWrapper:UIComponent = new UIComponent(); flexWrapper.addChild(event.target.loader.content); addChild(flexWrapper); flexWrapper.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); } } } Completamento di un trasferimento di trascinamento verso esterno Quando un utente rilascia l'elemento trascinato rilasciando il mouse, l'oggetto promotore invia un evento nativeDragComplete. È possibile verificare la proprietà dropAction dell'oggetto evento e intraprendere l'azione appropriata. Ad esempio, se l'azione è NativeDragAction.MOVE,, è possibile rimuovere l'elemento originario dalla posizione originaria. L'utente può sospendere un movimento di trascinamento rilasciando il pulsante del mouse mentre il cursore si trova all'esterno di un'idonea destinazione di rilascio. Il gestore di trascinamento imposta la proprietà dropAction di un movimento sospeso perNativeDragAction.NONE. Supporto del movimento di trascinamento verso interno Per supportare il movimento di trascinamento verso interno, l'applicazione (o, più tipicamente, un componente visivo dell'applicazione) deve rispondere a eventi nativeDragEnter o nativeDragOver Fasi di una tipica operazione di rilascio La sequenza di eventi riportata di seguito è tipica di un'operazione di rilascio: 1 L'utente trascina un oggetto Clipboard su un componente. 2 Il componente invia a un evento nativeDragEnter. 3 Il gestore eventi nativeDragEnter esamina l'oggetto evento per verificare i formati di dati disponibili e le azioni consentite. Se il componente può gestire il rilascio, chiama NativeDragManager.acceptDragDrop(). 4 NativeDragManager cambia il cursore del mouse a indicare che l'oggetto può essere rilasciato. 5 L'utente rilascia l'oggetto sul componente. 6 Il componente ricevente invia a un evento nativeDragDrop. 7 Il componente ricevente legge i dati nel formato desiderato dall'oggetto Clipboard con l'oggetto evento. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 141 Trascinamento della selezione 8 Se il movimento di trascinamento originato in un'applicazione AIR, l'oggetto interattivo promotore invia un evento nativeDragComplete Se il movimento è originato all'esterno di AIR, non viene inviato alcun feedback. Riconoscimento di un movimento di trascinamento verso interno Quando un utente trascina un elemento degli appunti nei limiti di un componente visivo, il componente invia eventi nativeDragEnter e nativeDragOver. Per determinare se il componente può accettare l'elemento di appunti, il gestore di questi eventi può verificare le proprietà clipboard e allowedActions dell'oggetto evento. Per segnalare che il componente possa accettare il rilascio, il gestore eventi deve chiamare il metodo NativeDragManager.acceptDragDrop(), passando un riferimento al componente ricevente. Se più di un listener di eventi registrato chiama il metodo acceptDragDrop(), l'ultimo gestore dell'elenco ha la precedenza. La chiamata acceptDragDrop() rimane valida finché il mouse non lascia i limiti dell'oggetto accettante, attivando l'evento nativeDragExit. Se è concessa più di un'azione nel parametro allowedActions passato a doDrag(), l'utente è in grado di indicare quale delle azioni concesse intende eseguire tenendo premuto un tasto modificatore. Il gestore di trascinamento modifica l'immagine del cursore per indicare all'utente quale azione si verificherebbe una volta completato il rilascio. L'azione desiderata è riportata dalla proprietà dropAction dell'oggetto NativeDragEvent. L'azione impostata per il movimento di trascinamento è solo consultivo. I componenti coinvolti nel trasferimento devono implementare il comportamento appropriato. Per completare un'azione di spostamento, ad esempio, il promotore del trascinamento potrebbe rimuovere l'elemento trascinato e la destinazione di rilascio potrebbe aggiungerla. La destinazione di trascinamento può limitare l'azione di rilascio a una delle tre possibili azioni impostando la proprietà dropAction della classe NativeDragManager. Se un utente cerca di selezionare un'azione differente mediante la tastiera, la classe NativeDragManager visualizza il cursore non disponibile. Impostate la proprietà dropAction nei gestori per entrambi gli eventi nativeDragEnter e nativeDragOver. L'esempio seguente illustra un gestore eventi per un evento nativeDragEnter o nativeDragOver Tale gestore accetta solo un movimento di trascinamento verso interno se gli appunti trascinati contengono dati in formato testo. import flash.desktop.NativeDragManager; import flash.events.NativeDragEvent; public function onDragIn(event:NativeDragEvent):void{ NativeDragManager.dropAction = NativeDragActions.MOVE; if(event.clipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)){ NativeDragManager.acceptDragDrop(this); //'this' is the receiving component } } Completamento del rilascio Quando l'utente rilascia un elemento trascinato su un oggetto interattivo che ha accettato il movimento, l'oggetto interattivo invia un evento nativeDragDrop. Il gestore di questo evento può estrarre i dati dalla proprietà clipboard dell'oggetto evento. Quando gli appunti contengono un formato definito dall'applicazione, il parametro transferMode passato al metodo getData() dell'oggetto Clipboard determina se il gestore di trascinamento restituisce un riferimento o una versione serializzata dell'oggetto. L'esempio seguente illustra un gestore eventi per l'evento nativeDragDrop: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 142 Trascinamento della selezione import flash.desktop.Clipboard; import flash.events.NativeDragEvent; public function onDrop(event:NativeDragEvent):void { if (event.clipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)) { var text:String = String(event.clipboard.getData(ClipboardFormats.TEXT_FORMAT, ClipboardTransferMode.ORIGINAL_PREFERRED)); } Una volta chiuso il gestore eventi, l'oggetto Clipboard non è più valido. Qualsiasi tentativo di accedere all'oggetto o ai suoi dati genera un errore. Aggiornamento dell'aspetto visivo di un componente Un componente può aggiornare l'aspetto visivo in base agli eventi NativeDragEvent. La tabella seguente descrive i tipi di cambiamenti che avrebbe un componente tipico in risposta ai differenti eventi: Evento Descrizione nativeDragStart L'oggetto interattivo promotore può utilizzare l'evento nativeDragStart al fine di fornire il feedback visivo che il movimento di trascinamento originato da tale oggetto interattivo. nativeDragUpdate L'oggetto interattivo promotore può utilizzare l'evento nativeDragUpdate per aggiornarne lo stato durante il movimento. nativeDragEnter Un potenziale oggetto interattivo ricevente può utilizzare questo evento per essere evidenziato o indicare visivamente che possa o non possa accettare il rilascio. nativeDragOver Un potenziale oggetto interattivo ricevente può utilizzare questo evento per rispondere allo spostamento del mouse all'interno dell'oggetto interattivo, come quando il mouse entra in un'area "hot" di un componente complesso come la visualizzazione della mappa di una strada. nativeDragExit Un potenziale oggetto interattivo ricevente può utilizzare questo evento per ripristinarne lo stato quando un movimento di trascinamento si sposta all'esterno dei suoi limiti. nativeDragComplete L'oggetto interattivo promotore può utilizzare questo evento per aggiornarne il modello di dati associato, come la rimozione di un elemento da un elenco, e ripristinarne lo stato visivo. Monitoraggio della posizione del mouse durante un movimento di trascinamento verso interno Mentre il movimento di trascinamento resta su un componente, questo invia eventi nativeDragOver. Questi eventi vengono inviati con un intervallo di pochi millisecondi e anche ogni qual volta il mouse si sposta. L'oggetto evento nativeDragOver consente di determinare la posizione del mouse sul componente. L'accesso alla posizione del mouse può essere utile in situazioni in cui il componente ricevente è complesso, ma non è composto da componenti secondari. Ad esempio, se l'applicazione ha visualizzato un bitmap contenente una mappa di strada e si è voluto evidenziare zone sulla mappa quando l'utente ha trascinato informazioni all'interno, è possibile utilizzare le coordinate del mouse riportate nell'evento nativeDragOver per monitoare la posizione del mouse all'interno della mappa. Trascinamento HTML Per trascinare i dati all'interno e all'esterno di un'applicazione basata su HTML (o all'interno e all'esterno del codice HTML visualizzato in un oggetto HTMLLoader), è possibile utilizzare eventi di trascinamento HTML. L'API di trascinamento HTML consente di trascinare verso e da elementi DOM all'interno del contenuto HTML. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 143 Trascinamento della selezione Nota: è possibile inoltre utilizzare le API NativeDragEvent e NativeDragManager di AIR intercettando gli eventi sull'oggetto HTMLLoader che include il contenuto HTML. Tuttavia, l'API HTML è meglio integrata con il DOM HTML e consente di controllare il comportamento predefinito. Comportamento di trascinamento predefinito L'ambiente HTML offre un comportamento predefinito per i movimenti di trascinamento che coinvolgono testo, immagini e URL. Con il comportamento predefinito, è possibile sempre trascinare questi tipi di dati fuori da un elemento. Tuttavia, è possibile trascinare solo testo in un elemento e solo a elementi in un'area modificabile di una pagina. Quando si trascina testo tra o all'interno di aree modificabili di una pagina, il comportamento predefinito esegue un'azione di spostamento. Quando si trascina testo in un'area modificabile da un'area non modificabile o dall'esterno dell'applicazione, il comportamento predefinito esegue un'azione di copia. È possibile sostituire il comportamento predefinito gestendo da solo eventi di trascinamento. Per annullare il comportamento predefinito, è necessario chiamare i metodi preventDefault() degli oggetti inviati per gli eventi di trascinamento. È possibile quindi inserire dati nella destinazione di rilascio e rimuovere dati dall'origine del trascinamento secondo necessità al fine di eseguire l'azione selezionata. Per impostazione predefinita, l'utente può selezionare e trascinare qualsiasi testo e trascinare immagini e collegamenti. È possibile utilizzare la proprietà WebKit CSS, -webkit-user-select per controllare come si possa selezionare qualsiasi elemento HTML. Ad esempio, se si imposta -webkit-user-select su none, il contenuto dell'elemento non è selezionabile e quindi non può essere trascinato. È possibile inoltre utilizzare la proprietà CSS, -webkit-user-drag per controllare se è possibile trascinare un elemento come intero. Tuttavia, il contenuto dell'elemento viene trattato in modo separato. L'utente potrebbe ancora trascinare una porzione selezionata del testo. Per ulteriori informazioni, consultate “Estensioni in CSS” a pagina 234. Eventi di trascinamento in HTML Gli eventi, inviati dall'elemento promotore da cui ha origine un trascinamento, sono: Evento Descrizione dragstart Inviato quando l'utente inizia il movimento di trascinamento. Il gestore di questo evento può evitare il trascinamento, se necessario, chiamando il metodo preventDefault() dell'oggetto evento. Per controllare se è possibile copiare, collegare o spostare i dati trascinati, impostare la proprietà effectAllowed. Testo, immagini e collegamenti selezionati vengono posti negli Appunti dal comportamento predefinito, ma è possibile impostare dati differenti per il movimento di trascinamento mediante la proprietà dataTransfer dell'oggetto evento. drag Inviato continuamente durante il movimento di trascinamento. dragend Inviato quando l'utente rilascia il pulsante del mouse per terminare il movimento di trascinamento. Gli eventi inviati da una destinazione di trascinamento sono: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 144 Trascinamento della selezione Evento Descrizione dragover Inviato continuamente mentre il movimento di trascinamento resta all'interno dei limiti dell'elemento. Il gestore di questo evento deve impostare la proprietà dataTransfer.dropEffect a indicare se il rilascio determinerà un'azione di copia, spostamento o collegamento qualora l'utente rilasci il mouse. dragenter Inviato quando il movimento di trascinamento raggiunge i limiti dell'elemento. Se si modifica qualsiasi proprietà di un oggetto dataTransfer in un gestore eventi dragenter, queste modifiche vengono rapidamente sostituite dal successivo evento dragover. D'altro canto, vi è un breve ritardo tra un evento dragenter e il primo evento dragover che possono determinare il lampeggiare del cursore qualora vengano impostate le diverse proprietà. In molti casi, è possibile utilizzare lo stesso gestore per entrambi gli eventi. dragleave Inviato quando il movimento di trascinamento esce dai limiti dell'elemento. drop Inviato quando l'utente rilascia i dati sull'elemento. È possibile accedere ai dati solo all'interno del gestore per questo evento. L'oggetto evento inviato in risposta a questi eventi è simile a un evento di mouse. È possibile utilizzare le proprietà evento del mouse come (clientX, clientY) e (screenX, screenY), per determinare la posizione del mouse. La proprietà più importante di un oggetto evento di trascinamento è dataTransfer, contenente i dati trascinati. L'oggetto dataTransfer stesso ha le seguenti proprietà e metodi: Proprietà o metodo Descrizione effectAllowed L'effetto consentito dall'origine del trascinamento. Di solito, il gestore dell'evento dragstart imposta questo valore. consultate “Effetti di trascinamento in HTML” a pagina 145. dropEffect L'effetto consentito dalla destinazione o dall'utente. Se si imposta dropEffect in un gestore eventi dragover o dragenter, AIR quindi aggiorna il cursore del mouse a indicare l'effetto che si verifica qualora l'utente rilasci il mouse. Se l'impostazione dropEffect non soddisfa uno degli effetti consentiti, non è possibile alcun rilascio e viene visualizzato il cursore non disponibile. Se non è stato impostato un dropEffect in risposta all'ultimo evento dragover o dragenter, l'utente può quindi scegliere tra gli effetti consentiti tramite i tasti modificatore standard del sistema operativo. L'effetto finale è riportato dalla proprietà dropEffect dell'oggetto inviato per dragend. Se l'utente sospende il rilascio lasciando il mouse all'esterno di un'idonea destinazione, dropEffect è impostato su none. types Un array contenente le stringhe di tipo MIME per ciascun formato di dati presente nell'oggetto dataTransfer. getData(mimeType) Recupera i dati nel formato specificato dal parametro mimeType. Il metodo getData() può essere richiamato solo in risposta all'evento drop. setData(mimeType) Aggiunge i dati al dataTransfer nel formato specificato dal parametro mimeType. È possibile aggiungere dati in più formati chiamando setData() per ogni tipo MIME. Vengono cancellati tutti i dati posti nell'oggetto dataTransfer tramite il comportamento predefinito di trascinamento. Il metodo setData() può essere richiamato solo in risposta all'evento dragstart. clearData(mimeType) Cancella tutti i dati nel formato specificato dal parametro mimeType. setDragImage(image, offsetX, offsetY) Imposta un'immagine di trascinamento personalizzata. Il metodo setDragImage() può essere richiamato solo in risposta all'evento dragstart. Tipi MIME per trascinamento HTML I tipi MIME da utilizzare con l'oggetto dataTransfer di un evento di trascinamento HTML: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 145 Trascinamento della selezione Formato dati Tipo MIME Testo "text/plain" HTML "text/html" URL "text/uri-list" Bitmap "image/x-vnd.adobe.air.bitmap" Elenco file "application/x-vnd.adobe.air.file-list" È possibile utilizzare anche altre stringhe MIME, comprese le stringhe definite dall'applicazione. Tuttavia, altre applicazioni potrebbero non essere in grado di riconoscere o utilizzare i dati trasferiti. È vostra responsabilità aggiungere dati all'oggetto dataTransfer nel formato previsto. Importante: solo il codice eseguito nella sandbox dell'applicazione può accedere ai file rilasciati. Il tentativo di leggere o impostare qualsiasi proprietà di un oggetto File in una sandbox di non applicazione genera un errore di sicurezza. Per ulteriori informazioni, consultate “Gestione dei rilasci di file nelle sandbox HTML di non applicazione” a pagina 149. Effetti di trascinamento in HTML Il promotore del movimento di trascinamento può limitare gli effetti di trascinamento consentiti impostando la proprietà dataTransfer.effectAllowed nel gestore dell'evento dragstart. È possibile utilizzare i seguenti valori stringa: Valore stringa Descrizione "none" Non è consentita alcuna operazione di trascinamento. "copy" I dati verranno copiati alla destinazione, lasciando in posizione l'originale. "link" I dati verranno condivisi con la destinazione di rilascio mediante un collegamento all'originale. "move” I dati verranno copiati alla destinazione e rimossi dalla posizione originale. "copyLink" È possibile copiare o collegare i dati. "copyMove" È possibile copiare o spostare i dati. "linkMove" È possibile collegare o spostare i dati. "all" È possibile copiare, spostare o collegare i dati. All è l'effetto predefinito quando si evita il comportamento predefinito. La destinazione del movimento di trascinamento può impostare la proprietà dataTransfer.dropEffect per indicare l'azione da intraprendere se l'utente completa il rilascio. Se l'effetto di rilascio è una delle azioni consentite, il sistema visualizza il cursore appropriato per copia, spostamento o collegamento. In caso contrario, il sistema visualizza il cursore non disponibile. Se non è impostato alcun effetto di rilascio dalla destinazione, l'utente può scegliere tra le azioni consentite con i tasti modificatore. Impostate il valore dropEffect nei gestori per entrambi gli eventi dragover e dragenter: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 146 Trascinamento della selezione function doDragStart(event) { event.dataTransfer.setData("text/plain","Text to drag"); event.dataTransfer.effectAllowed = "copyMove"; } function doDragOver(event) { event.dataTransfer.dropEffect = "copy"; } function doDragEnter(event) { event.dataTransfer.dropEffect = "copy"; } Nota: sebbene sia necessario impostare sempre la proprietà dropEffect nel gestore perdragenter, accertatevi che l'evento dragover successivo reimposti la proprietà al suo valore predefinito. Impostate dropEffect in risposta a entrambi gli eventi. Trascinamento di dati all'esterno di un elemento HTML Il comportamento predefinito consente di copiare tramite trascinamento la maggior parte del contenuto in una pagina HTML. È possibile controllare il contenuto consentito per trascinarlo mediante proprietà CSS -webkit-user-select e -webkit-user-drag. Sostituite il comportamento predefinito del trascinamento verso l'esterno nel gestore per l'evento dragstart. Chiamate il metodo setData() della proprietà dataTransfer dell'oggetto evento al fine di inserire i dati nel movimento di trascinamento. Per indicare quali effetti di trascinamento supporta un oggetto source quando non ci si affida al comportamento predefinito, impostate la proprietà dataTransfer.effectAllowed dell'oggetto evento inviato per l'evento dragstart. È possibile scegliere qualsiasi combinazione di effetti. Ad esempio, se un elemento source supporta sia effetti copia e collegamento, impostare la proprietà su "copyLink". Impostazione dei dati trascinati Aggiungete i dati per il movimento di trascinamento nel gestore per l'evento dragstart con la proprietà dataTransfer. Utilizzate il metodo dataTransfer.setData() per inserire i dati negli Appunti, passando nel tipo MIME e i dati da trasferire. Ad esempio, se nell'applicazione vi era un elemento immagine, con l'id imageOfGeorge, è possibile utilizzare il seguente gestore eventi dragstart. Questo esempio aggiunge rappresentazioni di un'immagine di George in numerosi formati di dati che aumenta la probabilità di altre applicazioni di poter utilizzare i dati trascinati. function dragStartHandler(event){ event.dataTransfer.effectAllowed = "copy"; var dragImage = document.getElementById("imageOfGeorge"); var dragFile = new air.File(dragImage.src); event.dataTransfer.setData("text/plain","A picture of George"); event.dataTransfer.setData("image/x-vnd.adobe.air.bitmap", dragImage); event.dataTransfer.setData("application/x-vnd.adobe.air.file-list", new Array(dragFile)); } Nota: quando si chiama il metodo setData() dell'oggetto dataTransfer, nessun dato viene aggiunto dal comportamento predefinito di trascinamento. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 147 Trascinamento della selezione Trascinamento di dati in un elemento HTML Il comportamento predefinito consente solo il testo da trascinare nelle aree modificabili della pagina. È possibile specificare di poter modificare un elemento e i relativi elementi secondari compreso l'attributo contenteditable nel tag di apertura dell'elemento. È possibile inoltre rendere modificabile un intero documento impostando la proprietà designMode dell'oggetto Document su "on". È possibile supportare un comportamento alternativo di trascinamento verso l'interno in una pagina gestendo gli eventi dragenter, dragover e drop per qualsiasi elemento in grado di accettare dati trascinati. Abilitazione del trascinamento verso interno Per gestire il movimento di trascinamento verso interno, è necessario prima annullare il comportamento predefinito. Intercettate con un listener gli eventi dragenter e dragover su qualsiasi elemento HTML che desiderate utilizzare come destinazione di rilascio. Nei gestori di questi eventi, chiamate il metodo preventDefault() dell'oggetto evento inviato. L'annullamento del comportamento predefinito consente ad aree non modificabili di ricevere un rilascio. Recupero di dati rilasciati È possibile accedere ai dati rilasciati nel gestore dell'evento ondrop: function doDrop(event){ droppedText = event.dataTransfer.getData("text/plain"); } Utilizzate il metodo dataTransfer.getData() per leggere i dati negli Appunti, passando nel tipo MIME del formato dati da leggere. È possibile individuare i formati di dati disponibili mediante la proprietà types dell'oggetto dataTransfer. L'array types contiene la stringa di tipo MIME di ciascun formato disponibile. Quando si annulla il comportamento predefinito negli eventi dragenter o dragover, siete responsabili dell'inserimento di tutti i dati rilasciati nella posizione corretta del documento. Non esistono API per convertire la posizione del mouse in un punto di inserimento all'interno di un elemento. Tale limitazione può rendere difficile l'implementazione dei movimenti di trascinamento di tipo inserimento. Esempio: sostituzione del comportamento HTML predefinito di trascinamento verso l'interno Questo esempio implementa una destinazione di rilascio che visualizza una tabella che mostra tutti i formati di dati nell'elemento rilasciato. Il comportamento predefinito consente di trascinare testo, collegamenti e immagini all'interno dell'applicazione. L'esempio sostituisce il comportamento predefinito di trascinamento verso l'interno per l'elemento div che funge da destinazione di rilascio. La fase principale per consentire l'accettazione del movimento di trascinamento verso l'interno da parte del contenuto non modificabile consiste nel di chiamare il metodo preventDefault() dell'oggetto evento inviato per entrambi gli eventi dragenter e dragover. In risposta a un evento drop, il gestore converte i dati trasferiti in un elemento riga HTML e inserisce la riga in una tabella di visualizzazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 148 Trascinamento della selezione <html> <head> <title>Drag-and-drop</title> <script language="javascript" type="text/javascript" src="AIRAliases.js"></script> <script language="javascript"> function init(){ var target = document.getElementById('target'); target.addEventListener("dragenter", dragEnterOverHandler); target.addEventListener("dragover", dragEnterOverHandler); target.addEventListener("drop", dropHandler); var source = document.getElementById('source'); source.addEventListener("dragstart", dragStartHandler); source.addEventListener("dragend", dragEndHandler); emptyRow = document.getElementById("emptyTargetRow"); } function dragStartHandler(event){ event.dataTransfer.effectAllowed = "copy"; } function dragEndHandler(event){ air.trace(event.type + ": " + event.dataTransfer.dropEffect); } function dragEnterOverHandler(event){ event.preventDefault(); } var emptyRow; function dropHandler(event){ for(var prop in event){ air.trace(prop + " = " + event[prop]); } var row = document.createElement('tr'); row.innerHTML = "<td>" + event.dataTransfer.getData("text/plain") + "</td>" + "<td>" + event.dataTransfer.getData("text/html") + "</td>" + "<td>" + event.dataTransfer.getData("text/uri-list") + "</td>" + "<td>" + event.dataTransfer.getData("application/x-vnd.adobe.air.file-list") + "</td>"; var imageCell = document.createElement('td'); if((event.dataTransfer.types.toString()).search("image/x-vnd.adobe.air.bitmap") > 1){ imageCell.appendChild(event.dataTransfer.getData("image/xvnd.adobe.air.bitmap")); } row.appendChild(imageCell); var parent = emptyRow.parentNode; parent.insertBefore(row, emptyRow); } </script> </head> <body onLoad="init()" style="padding:5px"> <div> <h1>Source</h1> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 149 Trascinamento della selezione <p>Items to drag:</p> <ul id="source"> <li>Plain text.</li> <li>HTML <b>formatted</b> text.</li> <li>A <a href="http://www.adobe.com">URL.</a></li> <li><img src="icons/AIRApp_16.png" alt="An image"/></li> <li style="-webkit-user-drag:none;"> Uses "-webkit-user-drag:none" style. </li> <li style="-webkit-user-select:none;"> Uses "-webkit-user-select:none" style. </li> </ul> </div> <div id="target" style="border-style:dashed;"> <h1 >Target</h1> <p>Drag items from the source list (or elsewhere).</p> <table id="displayTable" border="1"> <tr><th>Plain text</th><th>Html text</th><th>URL</th><th>File list</th><th>Bitmap Data</th></tr> <tr id="emptyTargetRow"><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</ td></tr> </table> </div> </div> </body> </html> Gestione dei rilasci di file nelle sandbox HTML di non applicazione Il contenuto di non applicazione non riesce ad accedere agli oggetti File che si ottengono quando i file vengono trascinati in un'applicazione AIR. Né è possibile passare uno di questi oggetti File al contenuto dell'applicazione mediante un bridge sandbox. (Durante la serializzazione è necessario accedere alle proprietà di oggetto.) Tuttavia, è possibile rilasciare ancora file nell'applicazione intercettando gli eventi nativeDragDrop di AIR sull'oggetto HTMLLoader. Di solito, se un utente rilascia un file in un fotogramma che ospita contenuto di non applicazione, l'evento rilascio non si propaga dall'elemento secondario a quello principale. Tuttavia, poiché gli eventi inviati dall'HTMLLoader (ovvero il contenitore di tutto il contenuto HTML di un'applicazione AIR) non fanno parte del flusso di eventi HTML, è possibile ancora ricevere l'evento drop nel contenuto dell'applicazione. Per ricevere l'evento per il rilascio di un file, il documento principale aggiunge un listener di eventi all'oggetto HTMLLoader mediante il riferimento fornito da window.htmlLoader: window.htmlLoader.addEventListener("nativeDragDrop",function(event){ var filelist = event.clipboard.getData(air.ClipboardFormats.FILE_LIST_FORMAT); air.trace(filelist[0].url); }); L'esempio seguente utilizza un documento principale che carica una pagina secondaria in una sandbox remota (http://localhost/). Il documento principale intercetta l'evento nativeDragDrop sull'oggetto HTMLLoader e tiene traccia dell'URL del file. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 150 Trascinamento della selezione <html> <head> <title>Drag-and-drop in a remote sandbox</title> <script language="javascript" type="text/javascript" src="AIRAliases.js"></script> <script language="javascript"> window.htmlLoader.addEventListener("nativeDragDrop",function(event){ var filelist = event.clipboard.getData(air.ClipboardFormats.FILE_LIST_FORMAT); air.trace(filelist[0].url); }); </script> </head> <body> <iframe src="child.html" sandboxRoot="http://localhost/" documentRoot="app:/" frameBorder="0" width="100%" height="100%"> </iframe> </body> </html> ll documento secondario deve presentare una valida destinazione di rilascio evitando che si verifichi il metodo preventDefault() dell'oggetto Event nei gestori eventi HTML dragenter e dragover o l'evento drop. <html> <head> <title>Drag and drop target</title> <script language="javascript" type="text/javascript"> function preventDefault(event){ event.preventDefault(); } </script> </head> <body ondragenter="preventDefault(event)" ondragover="preventDefault(event)"> <div> <h1>Drop Files Here</h1> </div> </body> </html> Per ulteriori informazioni, consultate “Programmazione in HTML e JavaScript” a pagina 236. 151 Capitolo 16: Copia e incolla Utilizzare le classi nell'API degli Appunti per copiare informazioni negli e dagli Appunti del sistema. I formati di dati che è possibile trasferire in o da un'applicazione Adobe® AIR™ includono: • Bitmap • File • Testo • Testo in formato HTML • Dati RTF (Rich Text Format) • Stringhe URL • Oggetti serializzati • Riferimenti degli oggetti (validi solo all'interno dell'applicazione di origine) Funzionalità di copia e incolla aggiuntiva di Adobe Flash Player 10 che è stata introdotta in AIR 1.0. In questo capitolo viene illustrata la funzionalità di copia e incolla univoca per Adobe AIR. Per informazioni dettagliate su questa funzionalità condivisa, consultate Copia e incolla nel manuale Programmazione in Adobe ActionScript 3.0. Ulteriori informazioni online sulle operazioni di copia e incolla È possibile trovare ulteriori informazioni sulle operazioni di copia e incolla dalle origini seguenti: Argomenti di Avvio rapido (Adobe AIR Developer Connection) • Supporting drag-and-drop and copy and paste Riferimenti per i linguaggi • Clipboard • ClipboardFormats • ClipboardTransferMode Ulteriori informazioni • Copia e incolla nel manuale Programmazione in Adobe ActionScript 3.0. • Adobe AIR Developer Connection for Flash (cercate 'AIR copy and paste') SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 152 Copia e incolla Copia e incolla HTML L'ambiente HTML fornisce una serie personalizzata di eventi e comportamento predefinito per le operazioni di copia e incolla. Solo il codice in esecuzione nella sandbox dell'applicazione può accedere agli Appunti di sistema direttamente, mediante l'oggetto Clipboard.generalClipboard di AIR. Il codice JavaScript nella sandbox non dell'applicazione può accedere agli Appunti attraverso l'oggetto evento inviato in risposta a uno degli eventi di copia e incolla inviati da un elemento in un documento HTML. Gli eventi di copia e incolla includono : copy (copia), cut (taglia) e paste (incolla). L'oggetto inviato per questi eventi fornisce accesso agli Appunti mediante la proprietà clipboardData. Comportamento predefinito Per impostazione predefinita, AIR copia gli elementi selezionati in risposta al comando copy, che è possibile generare mediante un tasto di scelta rapida o un menu contestuale. Nelle aree modificabili, AIR taglia il testo in risposta al comando cut o lo incolla al cursore o alla selezione in risposta al comando paste. Per impedire il comportamento predefinito, il gestore di eventi può chiamare il metodo preventDefault() dell'oggetto evento inviato. Utilizzo della proprietà clipboardData dell'oggetto evento La proprietà clipboardData dell'oggetto evento inviato come risultato di uno degli eventi di copia e incolla consente di leggere e scrivere i dati degli Appunti. Per scrivere negli Appunti quando si gestisce un evento di copia (copy) o taglio (cut), utilizzare il metodo setData() dell'oggetto clipboardData, trasmettendo i dati da copiare e il tipo MIME: function customCopy(event){ event.clipboardData.setData("text/plain", "A copied string."); } Per accedere ai dati incollati, è possibile utilizzare il metodo getData() dell'oggetto clipboardData, trasmettendo il tipo MIME del formato di dati. I formati disponibili sono segnalati dalla proprietà types. function customPaste(event){ var pastedData = event.clipboardData("text/plain"); } È possibile accedere al metodo getData() e alla proprietà types solo nell'oggetto evento inviato dall'evento paste. Nell'esempio seguente viene illustrato come ignorare il comportamento predefinito di copia e incolla in una pagina HTML. Il gestore dell'evento copy mette in corsivo il testo copiato e lo copia negli Appunti come testo HTML. Il gestore dell'evento cut copia i dati selezionati negli Appunti e li rimuove dal documento. Il gestore dell'evento paste inserisce il contenuto degli Appunti come HTML e applica al testo inserito uno stile in grassetto. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 153 Copia e incolla <html> <head> <title>Copy and Paste</title> <script language="javascript" type="text/javascript"> function onCopy(event){ var selection = window.getSelection(); event.clipboardData.setData("text/html","<i>" + selection + "</i>"); event.preventDefault(); } function onCut(event){ var selection = window.getSelection(); event.clipboardData.setData("text/html","<i>" + selection + "</i>"); var range = selection.getRangeAt(0); range.extractContents(); event.preventDefault(); } function onPaste(event){ var insertion = document.createElement("b"); insertion.innerHTML = event.clipboardData.getData("text/html"); var selection = window.getSelection(); var range = selection.getRangeAt(0); range.insertNode(insertion); event.preventDefault(); } </script> </head> <body onCopy="onCopy(event)" onPaste="onPaste(event)" onCut="onCut(event)"> <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p> </body> </html> Comandi di menu e sequenze di tasti per le operazioni di copia e incolla La funzionalità di Copia e incolla viene comunemente attivata attraverso comandi di menu e tasti di scelta rapida. In OS X, un menu di modifica con comandi di copia e incolla viene creato automaticamente dal sistema operativo, ma spetta all'utente aggiungere listener a tali comandi per associare le funzioni di copia e incolla. In Windows, è possibile aggiungere un menu di modifica nativo a ogni finestra che utilizza il chrome del sistema. È anche possibile creare menu non nativi con Flex e ActionScript, oppure, nel contenuto HTML, utilizzare DHTML, ma queste azioni non rientrano nell'ambito della presente discussione. Per attivare i comandi di copia e incolla in risposta a tasti di scelta rapida, è possibile assegnare equivalenti dei tasti agli elementi di comando appropriati in un menu di finestra o una applicazione nativa, oppure è possibile utilizzare direttamente un listener per le sequenze di tasti. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 154 Copia e incolla Avvio di un'operazione di copia o incolla mediante un comando di menu Per attivare un'operazione di copia e incolla con un comando di menu, è necessario aggiungere listener per l'evento select sulle voci di menu che effettuano la chiamata alle funzioni di gestione. Quando la funzione di gestione viene chiamata, è possibile trovare l'oggetto da copiare o incollare utilizzando la proprietà focus dello stage. È quindi possibile chiamare il metodo appropriato dell'oggetto attivato (o un metodo di riserva generale, se nessun oggetto è attivato) per eseguire la logica di copia, taglia o incolla. Ad esempio, il seguente gestore dell'evento copy verifica se l'oggetto attivo è del tipo corretto (in questo caso una classe denominata Scrap), quindi chiama il metodo doCopy() dell'oggetto. function copyCommand(event:Event):void{ if(NativeApplication.nativeApplication.activeWindow.stage.focus is Scrap){ Scrap(NativeApplication.nativeApplication.activeWindow.stage.focus).doCopy(); } else { NativeApplication.nativeApplication.copy(); } } Se copyCommand() nell'esempio non riconosce la classe dell'oggetto attivo, effettua la chiamata al metodo copy() di NativeApplication. Il metodo copy() NativeApplication invia un comando di copia interno all'oggetto attivo. Se l'oggetto è una classe incorporata che implementa le operazioni di copia e incolla internamente, l'oggetto eseguirà il comando. Le classi Textfield e HTMLLoader sono attualmente le uniche classi incorporate di questo tipo. Altri oggetti interattivi invieranno l'evento copy. Comandi simili sono disponibili per le azioni di taglia, incolla, seleziona tutto e, solo per TextArea, cancella, annulla e ripeti operazione. Nel contenuto HTML, il comportamento di copia e incolla predefinito può essere attivato mediante i comandi di modifica di NativeApplication. Nell'esempio seguente viene creato un menu di modifica per un documento HTML modificabile: L'esempio precedente consente di sostituire il menu dell'applicazione su Mac OS X, ma è anche possibile utilizzare il menu predefinito Modifica cercando gli elementi esistenti e aggiungendo ad essi dei listener. Se si utilizza un menu contestuale per richiamare un comando di copia o incolla, è possibile utilizzare la proprietà contextMenuOwner dell'oggetto ContextMenuEvent inviato, all'apertura del menu oppure quando viene selezionato un elemento, per determinare quale oggetto sia la destinazione appropriata del comando di copia o incolla. Ricerca di elementi di menu predefiniti in Mac OS X Per trovare il menu di modifica predefinito e le voci di comando di copia, taglia e incolla nel menu dell'applicazione in Mac OS X, è possibile effettuare la ricerca nella gerarchia del menu utilizzando la proprietà label degli oggetti NativeMenuItem. La seguente funzione, ad esempio, prende un nome e cerca la voce con l'etichetta corrispondente nel menu: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 155 Copia e incolla private function findItemByName(menu:NativeMenu, name:String, recurse:Boolean = false):NativeMenuItem{ var searchItem:NativeMenuItem = null; for each (var item:NativeMenuItem in menu.items){ if(item.label == name){ searchItem = item; break; } if((item.submenu != null) && recurse){ searchItem = findItemByName(item.submenu, name); } } return searchItem; } È possibile impostare il parametro recurse su true per includere sottomenu nella ricerca, oppure false per includere solo i menu trasmessi. Avvio di un comando di copia o incolla con una sequenza di tasti Se nell'applicazione per copia e incolla vengono utilizzati menu nativi dell'applicazione o della finestra, per implementare i tasti di scelta rapida è possibile aggiungere equivalenti dei tasti. Se nell'applicazione per copia e incolla vengono utilizzati menu nativi dell'applicazione o della finestra, per implementare i tasti di scelta rapida è possibile aggiungere equivalenti dei tasti. In alternativa, è possibile "ascoltare" le sequenze di tasti pertinenti, come illustrato nell'esempio seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 156 Copia e incolla private function init():void{ stage.addEventListener(KeyboardEvent.KEY_DOWN, keyListener); } private function keyListener(event:KeyboardEvent):void{ if(event.ctrlKey){ event.preventDefault(); switch(String.fromCharCode(event.charCode)){ case "c": NativeApplication.nativeApplication.copy(); break; case "x": NativeApplication.nativeApplication.cut(); break; case "v": NativeApplication.nativeApplication.paste(); break; case "a": NativeApplication.nativeApplication.selectAll(); break; case "z": NativeApplication.nativeApplication.undo(); break; case "y": NativeApplication.nativeApplication.redo(); break; } } } Nel contenuto HTML, i tasti di scelta rapida per i comandi di copia e incolla sono implementati per impostazione predefinita. Non è possibile registrare tutte le sequenze tasti più utilizzate per il copia e incolla utilizzando un listener di eventi dei tasti. Se è necessario ignorare il comportamento predefinito, una strategia migliore consiste nell'applicare un listener per gli eventi copy e paste. 157 Capitolo 17: Utilizzo di array di byte La classe ByteArray consente di leggere e scrivere in un flusso binario di dati, che corrisponde essenzialmente a un array di byte. La classe offre un sistema per accedere ai dati al livello più elementare. Dal momento che i dati del computer sono costituiti da byte, o gruppi di 8 bit, la capacità di leggere i dati in byte indica che è possibile accedere a dati per i quali classi e metodi di accesso non esistono. La classe ByteArray consente di analizzare qualsiasi flusso di dati, da una bitmap a un flusso di dati che viaggia in rete, a livello di byte. Il metodo writeObject() consente di scrivere un oggetto in formato serializzato AMF (Action Message Format) in un ByteArray, mentre il metodo readObject() consente di leggere un oggetto serializzato da ByteArray in una variabile del tipo di dati originale. È possibile serializzare qualsiasi oggetto ad eccezione degli oggetti di visualizzazione, vale a dire gli oggetti che è possibile collocare sull'elenco di visualizzazione. È inoltre possibile riassegnare gli oggetti serializzati alle istanze della classe personalizzata se quest'ultima è disponibile al runtime. Dopo aver convertito un oggetto in AMF, è possibile trasferirlo in maniera efficiente su una connessione di rete oppure salvarlo in un file. L'applicazione di esempio Adobe® AIR™ qui descritta legge un file zip come esempio di elaborazione di un flusso di byte, estraendo un elenco dei file contenuti nello zip e scrivendoli sul desktop. Lettura e scrittura di un ByteArray La classe ByteArray fa parte del pacchetto flash.utils. Per creare un oggetto ByteArray in ActionScript 3.0, importate la classe ByteArray e chiamate il constructor, come illustrato nel seguente esempio: import flash.utils.ByteArray; var stream:ByteArray = new ByteArray(); Metodi ByteArray Un flusso di dati significativo è organizzato in un formato che è possibile analizzare per trovare le informazioni desiderate. Un record in un file di dipendenti semplice, ad esempio, include probabilmente un numero di identificazione, un nome, un indirizzo, un numero di telefono e così via, mentre un file audio MP3 contiene un tag ID3 che identifica il titolo, l'autore, l'album, la data di pubblicazione e il genere del file che si sta scaricando. Il formato consente di conoscere l'ordine in cui prevedere i dati nel flusso di dati e di leggere tale flusso in modo intelligente. La classe ByteArray include diversi metodi che semplificano la lettura e la scrittura in un flusso di dati. Alcuni di questi metodi includono readBytes() e writeBytes(), readInt() e writeInt(), readFloat() e writeFloat(), readObject() e writeObject(), and readUTFBytes() e writeUTFBytes(). Tali metodi consentono di leggere i dati dal flusso di dati in variabili di tipi di dati specifici, nonché di scrivere da tipi di dati specifici direttamente nel flusso di dati binario. Ad esempio, il codice riportato di seguito legge un semplice array di stringhe e di numeri a virgola mobile e scrive ciascun elemento in un ByteArray. L'organizzazione dell'array consente al codice di chiamare i metodi ByteArray appropriati (writeUTFBytes() e writeFloat()) per la scrittura dei dati. Il modello di dati ripetitivo rende possibile la lettura ciclica dell'array. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 158 Utilizzo di array di byte // The following example reads a simple Array (groceries), made up of strings // and floating-point numbers, and writes it to a ByteArray. import flash.utils.ByteArray; // define the grocery list Array var groceries:Array = ["milk", 4.50, "soup", 1.79, "eggs", 3.19, "bread" , 2.35] // define the ByteArray var bytes:ByteArray = new ByteArray(); // for each item in the array for (var i:int = 0; i < groceries.length; i++) { bytes.writeUTFBytes(groceries[i++]); //write the string and position to the next item bytes.writeFloat(groceries[i]);// write the float trace("bytes.position is: " + bytes.position);//display the position in ByteArray } trace("bytes length is: " + bytes.length);// display the length La proprietà position La proprietà position consente di archiviare la posizione corrente del puntatore che indicizza il ByteArray durante lettura o scrittura. Il valore iniziale della proprietà position property è 0 (zero), come illustrato nel codice seguente: var bytes:ByteArray = new ByteArray(); trace("bytes.position is initially: " + bytes.position); // 0 Quando si legge o si scrive in un ByteArray, il metodo utilizzato aggiorna la proprietà position in modo che punti al percorso immediatamente successivo all'ultimo byte letto o scritto. Ad esempio, il codice seguente scrive una stringa in un ByteArray e successivamente la proprietà position punta al byte che segue immediatamente la stringa in ByteArray: var bytes:ByteArray = new ByteArray(); trace("bytes.position is initially: " + bytes.position); // 0 bytes.writeUTFBytes("Hello World!"); trace("bytes.position is now: " + bytes.position);// 12 Analogamente, un'operazione di lettura incrementa la proprietà position in base al numero di byte letti. var bytes:ByteArray = new ByteArray(); trace("bytes.position is initially: " + bytes.position); // 0 bytes.writeUTFBytes("Hello World!"); trace("bytes.position is now: " + bytes.position);// 12 bytes.position = 0; trace("The first 6 bytes are: " + (bytes.readUTFBytes(6)));//Hello trace("And the next 6 bytes are: " + (bytes.readUTFBytes(6)));// World! Si noti che è possibile impostare la proprietà position su una posizione specifica di ByteArray in modo che la lettura o la scrittura venga effettuata a quell'offset. Le proprietà bytesAvailable e length Le proprietà length e bytesAvailable indicano quanto è lungo un ByteArray e quanti byte restano dalla posizione corrente fino alla fine. Nell'esempio seguente viene illustrato come è possibile utilizzare queste proprietà. Nell'esempio viene scritta una Stringa di testo nel ByteArray e quindi il ByteArray viene letto un byte alla volta fino a che incontra il carattere “a” oppure la fine (bytesAvailable <= 0). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 159 Utilizzo di array di byte var bytes:ByteArray = new ByteArray(); var text:String = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus etc."; bytes.writeUTFBytes(text); // write the text to the ByteArray trace("The length of the ByteArray is: " + bytes.length);// 70 bytes.position = 0; // reset position while (bytes.bytesAvailable > 0 && (bytes.readUTFBytes(1) != 'a')) { //read to letter a or end of bytes } if (bytes.position < bytes.bytesAvailable) { trace("Found the letter a; position is: " + bytes.position); // 23 trace("and the number of bytes available is: " + bytes.bytesAvailable);// 47 } La proprietà endian I computer possono presentare differenze nel modo in cui memorizzano numeri multibyte, vale a dire numeri che richiedono più di 1 byte di memoria per la memorizzazione. Un numero intero, ad esempio, può richiedere 4 byte o 32 bit di memoria. Alcuni computer memorizzano innanzitutto il byte più significativo del numero nell'indirizzo di memoria più basso, mentre altri memorizzano prima quello meno significativo. Questo attributo di un computer, o dell'ordinamento di byte, viene definito come big endian (prima il byte più significativo) o little endian (prima il byte meno significativo). Ad esempio, il numero 0x31323334 verrebbe archiviato come segue per l'ordinamento di byte big endian e little endian, laddove a0 indica l'indirizzo di memoria più basso dei 4 byte e a3 rappresenta quello più alto: Big Endian Big Endian Big Endian Big Endian a0 a1 a2 a3 31 32 33 34 Little Endian Little Endian Little Endian Little Endian a0 a1 a2 a3 34 33 32 31 La proprietà endian della classe ByteArray consente di denotare l'ordine dei byte per i numeri multibyte che si sta elaborando. I valori accettabili per questa proprietà sono "bigEndian" o "littleEndian", e la classe Endian definisce le costanti BIG_ENDIAN e LITTLE_ENDIAN per impostare la proprietà endian con tali stringhe. I metodi compress() e uncompress() Il metodo compress() consente di comprimere un ByteArray in conformità a un algoritmo di compressione specificato come parametro dall'utente. Il metodo uncompress() consente di decomprimere un ByteArray compresso in conformità a un algoritmo di compressione. Dopo aver chiamato i metodi compress() e uncompress(), la lunghezza dell'array di byte è impostata sulla nuova lunghezza, mentre la proprietà position è impostata sulla fine. La classe CompressionAlgorithm definisce le costanti che è possibile utilizzare per specificare l'algoritmo di compressione. AIR supporta gli algoritmi deflate e zlib. L'algoritmo di compressione deflate è utilizzato in diversi formati di compressione, ad esempio zlib, gzip e alcune implementazioni zip. Il formato di dati compresso zlib è descritto in http://www.ietf.org/rfc/rfc1950.txt mentre l'algoritmo di compressione deflate è descritto in http://www.ietf.org/rfc/rfc1951.txt. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 160 Utilizzo di array di byte Nell'esempio seguente viene compresso un ByteArray denominato bytes mediante l'algoritmo deflate: bytes.compress(CompressionAlgorithm.DEFLATE); Nell'esempio seguente un ByteArray compresso viene decompresso mediante l'algoritmo deflate: bytes.uncompress(CompressionAlgorithm.DEFLATE); Lettura e scrittura di oggetti I metodi readObject() e writeObject() leggono un oggetto e scrivono un oggetto in un ByteArray, codificato in linguaggio AMF (Action Message Format) serializzato. AMF è un protocollo di messaggistica proprietario creato da Adobe e utilizzato da varie classi ActionScript 3.0, incluse Netstream, NetConnection, NetStream, LocalConnection e Shared Objects. Un indicatore di tipo a un solo byte descrive il tipo di dati codificati che seguono. AMF utilizza i seguenti 13 tipi di dati: value-type = undefined-marker | null-marker | false-marker | true-marker | integer-type | double-type | string-type | xml-doc-type | date-type | array-type | object-type | xml-type | byte-array-type I dati codificati seguono l'indicatore di tipi a meno che tale indicatore non rappresenti un singolo valore possibile, ad esempio null, true o false, nel qual caso null'altro viene codificato. Sono presenti due versioni di AMF: AMF0 e AMF3. AMF 0 supporta l'invio di oggetti complessi in base a riferimento e consente agli endpoint di ripristinare le relazioni tra gli oggetti. AMF 3 migliora AMF 0 mediante l'invio di oggetti trait e stringhe in base a riferimento, oltre ai riferimenti agli oggetti, e mediante il supporto di nuovi tipi di dati introdotti in ActionScript 3.0. La proprietà ByteArray.objectEcoding consente di specificare la versione di AMF utilizzata per la codifica dei dati oggetto. La classe flash.net.ObjectEncoding definisce le costanti per la specifica della versione AMF: ObjectEncoding.AMF0 e ObjectEncoding.AMF3. import flash.filesystem.*; import flash.utils.ByteArray; // Label component must be in Library import fl.controls.Label; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 161 Utilizzo di array di byte var bytes:ByteArray = new ByteArray(); var myLabel:Label = new Label(); myLabel.move(150, 150); myLabel.width = 200; addChild(myLabel); var myXML:XML = <order> <item id='1'> <menuName>burger</menuName> <price>3.95</price> </item> <item id='2'> <menuName>fries</menuName> <price>1.45</price> </item> </order> // Write XML object to ByteArray bytes.writeObject(myXML); bytes.position = 0;//reset position to beginning bytes.compress(CompressionAlgorithm.DEFLATE);// compress ByteArray outFile("order", bytes); myLabel.text = "Wrote order file to desktop!"; function outFile(fileName:String, data:ByteArray):void { var outFile:File = File.desktopDirectory; // dest folder is desktop outFile = outFile.resolvePath(fileName); // name of file to write var outStream:FileStream = new FileStream(); // open output file stream in WRITE mode outStream.open(outFile, FileMode.WRITE); // write out the file outStream.writeBytes(data, 0, data.length); // close it outStream.close(); } Il metodo readObject() regge un oggetto in formato AMF serializzato da un ByteArray e lo archivia in un oggetto del tipo specificato. Nell'esempio seguente il file order sul desktop viene letto in un ByteArray (inBytes) e decompresso. Viene quindi effettuata la chiamata a readObject() per archiviarlo nell'oggetto XML orderXML. Nell'esempio viene utilizzato un costrutto di ciclo for each() per aggiungere ciascun nodo a un'area di testo per la visualizzazione. Inoltre, viene visualizzato il valore della proprietà objectEncoding insieme a un'intestazione per il contenuto del file order. import flash.filesystem.*; import flash.utils.ByteArray; // TextArea component must be in Library import fl.controls.TextArea; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 162 Utilizzo di array di byte var inBytes:ByteArray = new ByteArray(); // define text area for displaying XML content var myTxt:TextArea = new TextArea(); myTxt.width = 550; myTxt.height = 400; addChild(myTxt); //display objectEncoding and file heading myTxt.text = "Object encoding is: " + inBytes.objectEncoding + "\n\n" + "order file: \n\n"; readFile("order", inBytes); inBytes.position = 0; // reset position to beginning inBytes.uncompress(CompressionAlgorithm.DEFLATE); inBytes.position = 0;//reset position to beginning // read XML Object var orderXML:XML = inBytes.readObject(); //for each node in orderXML for each(var child:XML in orderXML) { // append child node to text area myTxt.text += child + "\n"; } // read specified file into byte array function readFile(fileName:String, data:ByteArray) { var inFile:File = File.desktopDirectory; // source folder is desktop inFile = inFile.resolvePath(fileName); // name of file to read var inStream:FileStream = new FileStream(); inStream.open(inFile, FileMode.READ); inStream.readBytes(data, 0, data.length); inStream.close(); } Esempio di ByteArray: lettura di un file zip In questo esempio viene illustrato come leggere un file zip semplice contenente vari file di tipi diversi. A tale scopo, è sufficiente estrarre dati pertinenti dai metadati per ciascun file, decomprimere ciascun file in un ByteArray e scrivere il file sul desktop. La struttura generale di un file zip si basa sulle specifiche fornite da PKWARE Inc., riportate in http://www.pkware.com/documents/casestudies/APPNOTE.TXT. In primo luogo sono presenti un'intestazione file e dati file per il primo file nell'archivio zip, seguiti da una coppia 'intestazione file e dati file per ciascun file aggiuntivo (la struttura dell'intestazione file verrà descritta in seguito). In secondo luogo, il file zip include facoltativamente un record di descrizione dei dati (di solito quando il file zip di output viene creato in memoria anziché salvato sul disco). Sono quindi presenti diversi elementi opzionali aggiuntivi: intestazione di decrittazione dell'archivio, record dei dati extra dell'archivio, struttura di directory centrale, record di fine della directory centrale in formato Zip64, localizzatore di fine della directory centrale in formato Zip64 e record di fine della directory centrale. Il codice in questo esempio è scritto solo per analizzare i file zip che non contengono cartelle, non prevede record di descrizione dei dati e ignora ogni tipo di informazione che segue gli ultimi dati dei file. Il formato dell'intestazione per ciascun file è il seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 163 Utilizzo di array di byte firma dell'intestazione del file 4 byte versione richiesta 2 byte flag di bit di scopo generale 2 byte metodo di compressione 2 byte (8=DEFLATE; 0=UNCOMPRESSED) ora dell'ultima modifica del file 2 byte data dell'ultima modifica del file 2 byte crc-32 4 byte dimensione compressa 4 byte dimensione non compressa 4 byte lunghezza del nome file 2 byte lunghezza del campo extra 2 byte nome file variabile campo extra variabile L'intestazione del file è seguita dai dati del file veri e propri, che possono essere compressi o non compressi, a seconda del flag del metodo di compressione. Il valore de flag è 0 (zero) se i dati del file non sono compressi, 8 se sono compressi mediante l'algoritmo DEFLATE oppure hanno un valore diverso se è stato usato un altro algoritmo di compressione. L'interfaccia utente per questo esempio è costituita da un'etichetta e un'area di testo (taFiles). L'applicazione scrive le seguenti informazioni nell'area di testo per ciascun file incontrato nel file zip: il nome del file, la dimensione compressa e quella non compressa. L'inizio del programma effettua le seguenti operazioni: • Importa le classi richieste import flash.filesystem.*; import flash.utils.ByteArray; import flash.events.Event; • Definisce l'interfaccia utente import fl.controls.*; //requires TextArea and Label components in the Library var taFiles = new TextArea(); var output = new Label(); taFiles.setSize(320, 150); taFiles.move(10, 30); output.move(10, 10); output.width = 150; output.text = "Contents of HelloAir.zip"; addChild(taFiles); addChild(output); • Definisce il ByteArray bytes var bytes:ByteArray = new ByteArray(); • Definisce le variabili per archiviare i metadati dall'intestazione del file SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 164 Utilizzo di array di byte // var var var var var var var var variables for reading fixed portion of file header fileName:String = new String(); flNameLength:uint; xfldLength:uint; offset:uint; compSize:uint; uncompSize:uint; compMethod:int; signature:int; • Definisce gli oggetti File (zfile) e FileStream (zStream) per rappresentare il file zip, quindi specifica la posizione del file zip da cui i file vengono estratti: un file denominato “HelloAIR.zip” nella directory del desktop. // File variables for accessing .zip file var zfile:File = File.desktopDirectory.resolvePath("HelloAIR.zip"); var zStream:FileStream = new FileStream(); Il programma viene avviato aprendo il file zip in modalità di lettura (READ). zStream.open(zfile, FileMode.READ); Imposta quindi la proprietà endian di bytes su LITTLE_ENDIAN, a indicare che nell'ordine dei byte dei campi numerici il byte meno significativo è il primo. bytes.endian = Endian.LITTLE_ENDIAN; Successivamente, un'istruzione while() avvia un ciclo che continua fino a che la posizione corrente nel flusso di file è maggiore o·uguale alla dimensione del file. while (zStream.position < zfile.size) { La prima istruzione all'interno del ciclo legge i primi 30 byte del flusso di file nel valore bytes di ByteArray. I primi 30 byte costituiscono la parte di dimensione fissa dell'intestazione del primo file. // read fixed metadata portion of local file header zStream.readBytes(bytes, 0, 30); In seguito, il codice legge un valore intero (signature) dai primi byte dell'intestazione di 30 byte. La definizione del formato ZIP consente di specificare che la firma per ogni intestazione file è costituita dal valore esadecimale 0x04034b50; se la firma è diversa, ciò significa che il codice è stato spostato al di là della parte file del file zip e che non ci sono altri file da estrarre. In quel caso il codice esce dal ciclo while anziché attendere la fine dell'array di byte. bytes.position = 0; signature = bytes.readInt(); // if no longer reading data files, quit if (signature != 0x04034b50) { break; } La parte seguente del codice legge il byte di intestazione alla posizione di offset 8 e memorizza il valore nella variabile compMethod. Questo byte contiene un valore che indica il metodo di compressione utilizzato per il file. Sono consentiti diversi metodi di compressione, tuttavia in pratica quasi tutti i file zip utilizzano l'algoritmo di compressione DEFLATE. Se il file corrente è compresso mediante l'algoritmo DEFLATE, il valore di compMethod è 8; se il file non è compresso,compMethod sarà 0. bytes.position = 8; compMethod = bytes.readByte(); // store compression method (8 == Deflate) SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 165 Utilizzo di array di byte Dopo i primi 30 byte è presente una parte dell'intestazione di lunghezza variabile che contiene il nome del file ed eventualmente un campo aggiuntivo. Nella variabile offset è memorizzata la dimensione di questa parte. La dimensione viene calcolata aggiungendo la lunghezza del nome file e del campo extra, letta dall'intestazione agli offset 26 e 28. offset = 0;// stores length of variable portion of metadata bytes.position = 26; // offset to file name length flNameLength = bytes.readShort();// store file name offset += flNameLength; // add length of file name bytes.position = 28;// offset to extra field length xfldLength = bytes.readShort(); offset += xfldLength;// add length of extra field In seguito, il programma legge la parte di lunghezza variabile dell'intestazione del file per il numero di byte archiviati nella variabile offset. // read variable length bytes between fixed-length header and compressed file data zStream.readBytes(bytes, 30, offset); Il programma legge il nome del file dalla parte a lunghezza variabile dell'intestazione e lo visualizza nell'area di testo insieme alle dimensioni del file compresso e non compresso (originale). bytes.position = 30; fileName = bytes.readUTFBytes(flNameLength); // read file name taFiles.appendText(fileName + "\n"); // write file name to text area bytes.position = 18; compSize = bytes.readUnsignedInt(); // store size of compressed portion taFiles.appendText("\tCompressed size is: " + compSize + '\n'); bytes.position = 22; // offset to uncompressed size uncompSize = bytes.readUnsignedInt(); // store uncompressed size taFiles.appendText("\tUncompressed size is: " + uncompSize + '\n'); L'esempio legge il resto del file dal flusso del file in bytes per la lunghezza specificata dalla dimensione compressa, sovrascrivendo l'intestazione del file nei primi 30 byte. La dimensione compressa è accurata anche se il file non è compresso, in quanto in quel caso la dimensione compressa del file è uguale a quella non compressa. // read compressed file to offset 0 of bytes; for uncompressed files // the compressed and uncompressed size is the same zStream.readBytes(bytes, 0, compSize); Successivamente, nell'esempio, il file compresso viene decompresso e viene chiamata la funzione outfile() per scriverlo nel flusso di file di output. Vengono quindi trasmessi a outfile() il nome del file e l'array di byte contenente i dati del file. if (compMethod == 8) // if file is compressed, uncompress { bytes.uncompress(CompressionAlgorithm.DEFLATE); } outFile(fileName, bytes); // call outFile() to write out the file La parentesi graffa di chiusura indica la fine del ciclo while e del codice dell'applicazione, ad eccezione del metodo outFile(). L'esecuzione torna all'inizio del ciclo while e continua l'elaborazione dei byte seguenti nel file zip, mediante l'estrazione di un altro file oppure terminando l'elaborazione del file zip se l'ultimo file è stato elaborato. } // end of while loop SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 166 Utilizzo di array di byte La funzione outfile() apre un file di output nella modalità WRITE sul desktop, attribuendo ad esso il nome fornito dal parametro filename. I dati del file vengono quindi scritti dal parametro data al flusso di file di output (outStream) e il file viene chiuso. function outFile(fileName:String, data:ByteArray):void { var outFile:File = File.desktopDirectory; // destination folder is desktop outFile = outFile.resolvePath(fileName); // name of file to write var outStream:FileStream = new FileStream(); // open output file stream in WRITE mode outStream.open(outFile, FileMode.WRITE); // write out the file outStream.writeBytes(data, 0, data.length); // close it outStream.close(); } 167 Capitolo 18: Utilizzo dei database SQL locali Adobe AIR comprende funzioni per la creazione e l'utilizzo di database SQL locali. Il runtime comprende un motore di database SQL che offre il supporto di molte funzioni SQL standard mediante il sistema database open source SQLite. È possibile utilizzare un database SQL locale per memorizzare i dati locali permanenti. Potete utilizzarlo ad esempio per i dati delle applicazioni, le impostazioni degli utenti di tali applicazioni, i documenti e qualsiasi altro tipo di dati che l'applicazione deve salvare localmente. Ulteriori informazioni online riguardanti i database SQL Ulteriori informazioni sull'utilizzo dei database SQL locali sono reperibili presso le seguenti fonti. Guide rapide (Centro per sviluppatori Adobe AIR) • Lavoro asincrono in un database SQL locale • Lavoro sincrono in un database SQL locale • Uso di un database crittografato Guide di riferimento sul linguaggio • SQLCollationType • SQLColumnNameStyle • SQLColumnSchema • SQLConnection • SQLError • SQLErrorEvent • SQLErrorOperation • SQLEvent • SQLIndexSchema • SQLMode • SQLResult • SQLSchema • SQLSchemaResult • SQLStatement • SQLTableSchema • SQLTransactionLockType • SQLTriggerSchema • SQLUpdateEvent SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 168 Utilizzo dei database SQL locali • SQLViewSchema Articoli ed esempi disponibili sul Centro per sviluppatori Adobe AIR • Adobe AIR Developer Connection for Flash (Centro per sviluppatori Adobe AIR su Flash – cercare "SQL AIR") Introduzione ai database SQL locali Adobe AIR comprende un motore di database relazionale basato su SQL che viene eseguito all'interno del runtime e e i cui dati vengono memorizzati localmente in file di database nel computer su cui l'applicazione AIR viene eseguita, ad esempio sul disco fisso. Poiché il database viene eseguito localmente e anche i file sono memorizzati localmente, il database può essere utilizzato dalle applicazioni AIR indipendentemente dalla disponibilità o meno di una connessione di rete. In tal modo il motore di database SQL locale del runtime offre un metodo comodo per la memorizzazione dei dati permanenti e locali delle applicazioni, in particolar modo se si ha una certa dimestichezza con SQL e i database relazionali. Vari usi dei database SQL locali La funzionalità di database SQL locale di AIR può essere utilizzata in tutti i casi in cui si desideri memorizzare i dati delle applicazioni sul computer locale dell'utente. Adobe AIR dispone di vari metodi per la memorizzazione locale dei dati, ciascuno dei quali presenta vantaggi diversi. Di seguito suggeriamo alcuni impieghi possibili dei database SQL locali nelle applicazioni AIR. • Nel caso delle applicazioni la cui funzione principale è la gestione dei dati, ad esempio le rubriche, è possibile utilizzare un database per memorizzare i dati fondamentali dell'applicazione. • Nel caso delle applicazioni la cui funzione principale è la gestione dei documenti che vengono creati dagli utenti a scopo di memorizzazione e magari condivisione, ciascun documento può essere salvato come file di database in un percorso designato dall'utente. (Tenete tuttavia presente che, a meno che il database sia crittografato, qualsiasi applicazione AIR è in grado di aprire il file di database. La crittografia è consigliata per i documenti potenzialmente riservati). • Nel caso delle applicazioni che esistono su una rete, il database può essere impiegato per la memorizzazione di una cache locale di dati delle applicazioni o per la memorizzazione temporanea di dati nei momenti in cui la rete non è disponibile. È possibile poi creare un metodo che garantisca la sincronizzazione del database locale con i dati memorizzati centralmente sulla rete. • In tutti i tipi di applicazioni, il database può venire utilizzato per memorizzare per ciascun utente le impostazioni dell'applicazione come le opzioni utente o le informazioni sulle dimensioni e la posizione della finestra principale. File di database e database AIR I database SQL locali di Adobe AIR individuali vengono memorizzati sotto forma di file singolo nel file system del computer. Il runtime comprende il motore di database SQL che gestisce la creazione e la struttura dei file di database e la manipolazione e il recupero dei dati da tali file. Il runtime non specifica le modalità di memorizzazione o la posizione dei dati del database nel file system; ciascun database viene invece memorizzato interamente all'interno di un solo file. È l'utente a specificare la posizione all'interno del file system in cui il file di database viene memorizzato. Una singola applicazione AIR può accedere a un singolo database o a più database diversi (cioè a più file di database separati). Dal momento che il runtime memorizza ciascun database come file singolo nel file system, è possibile scegliere la posizione del database secondo le esigenze del design dell'applicazione in oggetto e i vincoli di accesso ai SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 169 Utilizzo dei database SQL locali file in vigore nel sistema operativo. A ciascun utente può essere assegnato un file di database separato per i suoi dati specifici o, in alternativa, è possibile fare sì che tutti gli utenti dell'applicazione abbiano accesso a un file di database che risiede su un solo computer, al fine di condividere i dati. Poiché i dati sono locali per un solo computer, essi non vengono automaticamente condivisi dagli utenti su computer diversi. Il motore di database SQL locale non fornisce funzioni che eseguano le istruzioni SQL nell'ambito di un database remoto o basato su un server. Database relazionali Il database relazionale è un metodo che rende possiblle la memorizzazione e il recupero dei dati su un computer. I dati sono organizzati in tabelle: le righe rappresentano i record (o gli elementi) e le colonne (dette talvolta “campi”) dividono ciascun record nei singoli valori che lo costituiscono. Ad esempio, un'applicazione rubrica può contenere una tabella "amici". Ciascuna riga della tabella rappresenta un amico memorizzato nel database. Le colonne della tabella contengono dati come il nome, il cognome, la data di nascita e così via. Per ciascuna riga (amico) della tabella, il database memorizza un valore diverso per ciascuna colonna. I database relazionali sono progettati in modo da essere in grado di gestire dati complessi in cui un elemento è associato o correlato a elementi di un altro tipo. Nei database relazionali, i dati che hanno una relazione "uno a molti", cioè in cui un singolo record può essere correlato a più record di tipo diverso, devono venire divisi fra tabelle diverse. Supponiamo ad esempio di volere che l'applicazione rubrica memorizzi più numeri di telefono per ciascun amico: si tratta di una relazione uno a molti. La tabella "amici" conterrà tutte le informazioni personali di ciascun amico. Una tabella separata, "numeri di telefono", conterrà tutti i numeri di tutti gli amici. Oltre a memorizzare i dati degli amici e i numeri di telefono, ciascuna tabella necessiterà di un gruppo di dati che tengano traccia della relazione fra le due tabelle al fine di far corrispondere i record dei singoli amici con i relativi numeri di telefono. Tali dati sono detti "chiave primaria" e costituiscono un identificatore univoco che distingue ciascuna riga di una tabella dalle altre righe di quella stessa tabella. La chiave primaria può essere una “chiave naturale”, vale a dire uno degli elementi di dati che distingue naturalmente ciascun record della tabella. Nella tabella "amici", se ad esempio nessuno degli amici ha la stessa data di nascita, si può usare la colonna della data di nascita come chiave primaria (chiave naturale) della tabella "amici". Se non è presente una chiave naturale, create una colonna di chiave primaria distinta, ad esempio "friend id", ovvero un valore artificiale di cui l'applicazione fa uso per distinguere le diverse righe. Tramite la chiave primaria potete impostare relazioni tra più tabelle. Supponete ad esempio che la tabella "friends" comprenda una colonna "friend id" che contiene un numero univoco per ciascuna riga (cioè ciascun amico). La tabella correlata "numeri di telefono" può avere una struttura su due colonne, una con l'"id amico" della persona a cui appartiene il numero di telefono e una con il numero di telefono in questione. In questo modo, tutti i numeri di telefono di un singolo amico, indipendentemente dalla quantità, possono essere memorizzati nella tabella "numeri di telefono" ed essere collegati all'amico in oggetto tramite la chiave primaria "id amico". Quando si utilizza la chiave primaria di una tabella in una tabella correlata, al fine di specificare il collegamento fra i record, il valore contenuto nella tabella correlata è detto "chiave esterna". A differenza di molti altri database, il motore di database locale AIR non consente la creazione di vincoli per la chiave esterna, cioè di vincoli che controllano automaticamente che un certo valore della chiave esterna inserito o aggiornato possieda una riga corrispondente nella tabella della chiave primaria. Ciò nonostante, le relazioni con chiave esterna rappresentano una parte importante della struttura dei database relazionali e, quando si crea un database, si devono utilizzare le chiavi esterne per la creazione delle relazioni tra le tabelle. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 170 Utilizzo dei database SQL locali Informazioni su SQL Structured Query Language (SQL) viene impiegato nei database relazionali per la manipolazione e il recupero dei dati. SQL è un linguaggio descrittivo e non procedurale: invece di dare istruzioni al computer descrivendo il modo in cui deve recuperare i dati, le istruzioni SQL descrivono il gruppo di dati che si desidera recuperare. È il motore del database a decidere in che modo recuperarli. Il linguaggio SQL è stato standardizzato dall'American National Standards Institute (ANSI). Il database SQL locale di Adobe AIR supporta gran parte dello standard SQL-92. Per una descrizione specifica dei modi in cui il linguaggio SQL è supportato in Adobe AIR, consultate l'appendice “Supporto SQL nei database locali“ nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. Classi di database SQL Per lavorare con i database SQL locali in ActionScript 3.0 si utilizzano le seguenti classi nel pacchetto flash.data. Classe Descrizione flash.data.SQLConnection Consente la creazione di database (file di database) aperti e offre metodi per l'esecuzione di operazioni a livello di database e per la gestione delle transazioni dei database. flash.data.SQLStatement Rappresenta una singola istruzione SQL (una singola query o un singolo comando) che viene eseguita sul database e comprende la definizione del testo dell'istruzione e l'impostazione dei valori dei parametri. flash.data.SQLResult Consente di ottenere le informazioni o i risultati a seguito dell'esecuzione di un'istruzione, ad esempio le righe risultanti dall'istruzione SELECT, il numero di righe interessate dai comandi UPDATE o DELETE e così via. Per ottenere informazioni di schema che descrivono la struttura di un database si utilizzano le seguenti classi del pacchetto flash.data. Classe flash.data.SQLSchemaResult Descrizione Serve da contenitore per i risultati dello schema del database generati chiamando il metodo SQLConnection.loadSchema(). flash.data.SQLTableSchema Fornisce informazioni che descrivono una tabella individuale in un database. flash.data.SQLViewSchema Fornisce informazioni che descrivono una visualizzazione individuale in un database. flash.data.SQLIndexSchema Fornisce informazioni che descrivono una singola colonna di una tabella o di una visualizzazione in un database. flash.data.SQLTriggerSchem a Fornisce informazioni che descrivono un trigger individuale in un database. Altre classi contenute nel pacchetto flash.data forniscono costanti utilizzate con la classe SQLConnection e la classe SQLColumnSchema, come segue. Classe Descrizione flash.data.SQLMode Definisce un set di costanti che rappresentano i valori possibili del parametro openMode dei metodi SQLConnection.open() e SQLConnection.openAsync(). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 171 Utilizzo dei database SQL locali Classe Descrizione flash.data.SQLColumnNameStyle Definisce un set di costanti che rappresentano i valori possibili della proprietà SQLConnection.columnNameStyle. flash.data.SQLTransactionLockType Definisce un set di costanti che rappresentano i valori possibili del parametro di opzione del metodo SQLConnection.begin(). flash.data.SQLCollationType Definisce un set di costanti che rappresentano i valori possibili della proprietà SQLColumnSchema.defaultCollationType e del parametro defaultCollationType del costruttore SQLColumnSchema(). Inoltre, le seguenti classi del pacchetto flash.events rappresentano gli eventi (e le costanti di supporto) da utilizzare, come segue. Classe Descrizione flash.data.SQLEvent Definisce gli eventi creati da un'istanza di SQLConnection o SQLStatement quando una delle operazioni ad essa relative viene eseguita correttamente. A ciascuna operazione è associata una costante tipo di evento definita nella classe SQLEvent. flash.data.SQLErrorEvent Definisce l'evento creato da un'istanza di SQLConnection o SQLStatement quando una delle operazioni ad essa relative produce un errore. flash.data.SQLUpdateEvent Definisce l'evento creato da un'istanza di SQLConnection quando i dati nelle tabelle in uno dei database ad essa connessi vengono modificati in seguito all'esecuzione dell'istruzione SQL INSERT, UPDATE o DELETE. Per concludere, le seguenti classi del pacchetto flash.errors forniscono informazioni sugli errori relativi alle operazioni del database. Classe Descrizione flash.data.SQLError Fornisce informazioni sugli errori relativi alle operazioni del database, descrivendo l'operazione che si tentava di eseguire e il motivo della mancata riuscita. flash.data.SQLErrorEvent Definisce un set di costanti che rappresentano i valori possibili della proprietà operation della classe SQLError, che indica quale operazione del database ha dato luogo a un errore. Modalità di esecuzione sincrona e asincrona Quando si crea il codice per l'utilizzo con un database SQL locale, si deve specificare l'esecuzione delle operazioni di tale database in una di due modalità: esecuzione asincrona o sincrona. In genere, gli esempi che illustrano il codice mostrano come eseguire l'operazione in entrambi i modi, così da dare la possibilità di scegliere l'esempio del tipo più appropriato alle necessità del momento. Nella modalità di esecuzione asincrona l'utente dà un'istruzione al runtime ed esso crea un evento dopo che l'operazione richiesta viene completata o non riesce. Prima di tutto, si comanda al motore del database di eseguire un'operazione. Il motore esegue il comando in background, mentre l'applicazione continua ad essere in esecuzione. Alla fine, dopo che l'operazione è stata completata o non è riuscita, il motore del database crea un evento. Il codice creato dall'utente, attivato dall'evento, esegue poi le operazioni successive. Questo approccio presenta un notevole vantaggio: il runtime esegue le operazioni del database in background mentre il codice dell'applicazione principale continua ad essere in esecuzione. Anche se l'operazione del database impiega molto tempo, l'applicazione continua comunque ad essere eseguita; inoltre, cosa molto importante, l'utente può continuare a interagire con essa senza che il display si blocchi. Il problema è che il codice per le operazioni asincrone è in genere più complesso e difficile da compilare degli altri tipi. La complessità è di solito in evidenza nei casi in cui è necessario dividere più operazioni dipendenti fra vari metodi listener degli eventi. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 172 Utilizzo dei database SQL locali Dal punto di vista concettuale, è più facile creare il codice per le operazioni in una sequenza di passi singola, cioè un set di operazioni sincrone, invece che un set di operazioni divise fra vari metodi listener degli eventi. Oltre a consentire l'esecuzione delle operazioni di database asincrone, Adobe AIR consente anche quella delle operazioni sincrone. Nella modalità di esecuzione sincrona le operazioni non vengono eseguite in background: vengono invece eseguite nell'ambito della stessa sequenza di esecuzione del codice di tutte le altre applicazioni. Per prima cosa, si comanda al motore del database di eseguire un'operazione. Il codice si ferma quindi a quel punto in attesa che il motore esegua il comando. Al termine dell'operazione, l'esecuzione prosegue con la riga successiva del codice. L'esecuzione sincrona o asincrona delle operazioni si imposta al livello SQLConnection. Se si usa una sola connessione per il database, non è possibile eseguire alcune delle operazioni o delle istruzioni in modo sincrono ed altre in modo asincrono. Per specificare se SQLConnection opera in modalità di esecuzione sincrona o asincrona si chiama un metodo SQLConnection per l'apertura del database. Se si chiama SQLConnection.open(), la connessione funziona in modalità di esecuzione sincrona e se si chiama SQLConnection.openAsync() la modalità sarà invece asincrona. Una volta che l'istanza SQLConnection è connessa al database tramite open() o openAsync(), la modalità di esecuzione viene fissata su sincrona o asincrona a meno che non si chiuda e poi si riapra la connessione al database. Ciascuna modalità di esecuzione presenta dei vantaggi. Sebbene vi siano moltissime similarità, quando si lavora in ciascuna modalità è bene tenere presenti alcune importanti differenze. Per ulteriori informazioni su questi argomenti, e per ulteriori suggerimenti per lavorare in ciascuna delle modalità, consultate “Utilizzo delle operazioni di database sincrone e asincrone” a pagina 193. Creazione e modifica di un database Prima che l'applicazione sia in grado di aggiungere o recuperare dati, deve essere presente un database all'interno del quale siano state definite tabelle a cui l'applicazione possa avere accesso. Descriviamo qui le attività di creazione di un database e di creazione della struttura dei dati all'interno del database stesso. Sebbene queste attività siano usate meno di frequente dell'inserimento e del recupero dei dati, sono comunque necessarie per la maggior parte delle applicazioni. Creazione di un database Per creare un file di database, si crea prima di tutto un'istanza SQLConnection. Si chiama il metodo open() per aprirla in modalità di esecuzione sincrona oppure il metodo openAsync() per aprirla in modalità asincrona. I metodi open() e openAsync() si usano per aprire la connessione a un database. Se si passa un'istanza File che fa riferimento alla posizione di un file che non esiste per il parametro reference (il primo parametro), sia il metodo open() che il metodo openAsync() creano un file di database in tale posizione ed aprono una connessione al database appena creato. Indipendentemente dal fatto che chiamiate il metodo open() o il metodo openAsync() per creare un database, il nome del file di database può essere qualsiasi nome di file valido e avere qualsiasi estensione. Se si chiama il metodo open() oppure openAsync() con null per il parametro reference, viene creato un nuovo database in memoria invece che un file di database su disco. Il seguente elenco di codici illustra la procedura di creazione di un file di database (un nuovo database) utilizzando la modalità di esecuzione asincrona. In questo caso il file di database viene salvato nella directory di memorizzazione dell'applicazione con il nome di file “DBSample.db”. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 173 Utilizzo dei database SQL locali import flash.data.SQLConnection; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; import flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, errorHandler); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); conn.openAsync(dbFile); function openHandler(event:SQLEvent):void { trace("the database was created successfully"); } function errorHandler(event:SQLErrorEvent):void { trace("Error message:", event.error.message); trace("Details:", event.error.details); } Per eseguire le operazioni in modalità sincrona, quando si apre una connessione di database con l'istanza SQLConnection, chiamate il metodo open(). L'esempio seguente illustra come creare e aprire un'istanza SQLConnection che esegue le operazioni in modalità sincrona. import flash.data.SQLConnection; import flash.errors.SQLError; import flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); try { conn.open(dbFile); trace("the database was created successfully"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); } Creazione di tabelle per il database La creazione di una tabella in un database implica l'esecuzione di un'istruzione SQL sul database in oggetto seguendo la stessa procedura utilizzata per eseguire un'istruzione SQL, come ad esempio SELECT, INSERT e così via. Per creare una tabella si utilizza l'istruzione CREATE TABLE, che comprende la definizione delle colonne e dei vincoli relativi alla nuova tabella. Per ulteriori informazioni sull'esecuzione delle istruzioni SQL, consultate “Utilizzo delle istruzioni SQL” a pagina 176. L'esempio seguente illustra la creazione di una tabella denominata "employees" all'interno di un file di database già esistente utilizzando la modalità di esecuzione asincrona. Tenete presente che questo codice presuppone che esista un'istanza SQLConnection denominata conn già attivata e connessa al database. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 174 Utilizzo dei database SQL locali import flash.data.SQLConnection; import flash.data.SQLStatement; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; // ... create and open the SQLConnection instance named conn ... var createStmt:SQLStatement = new SQLStatement(); createStmt.sqlConnection = conn; var sql:String = "CREATE TABLE IF NOT EXISTS employees (" + " empId INTEGER PRIMARY KEY AUTOINCREMENT, " + " firstName TEXT, " + " lastName TEXT, " + " salary NUMERIC CHECK (salary > 0)" + ")"; createStmt.text = sql; createStmt.addEventListener(SQLEvent.RESULT, createResult); createStmt.addEventListener(SQLErrorEvent.ERROR, createError); createStmt.execute(); function createResult(event:SQLEvent):void { trace("Table created"); } function createError(event:SQLErrorEvent):void { trace("Error message:", event.error.message); trace("Details:", event.error.details); } L'esempio seguente illustra la creazione di una tabella denominata "employees" all'interno di un file di database già esistente utilizzando la modalità di esecuzione sincrona. Tenete presente che questo codice presuppone che esista un'istanza SQLConnection denominata conn già attivata e connessa al database. import flash.data.SQLConnection; import flash.data.SQLStatement; import flash.errors.SQLError; // ... create and open the SQLConnection instance named conn ... var createStmt:SQLStatement = new SQLStatement(); createStmt.sqlConnection = conn; var sql:String = "CREATE TABLE IF NOT EXISTS employees (" + " empId INTEGER PRIMARY KEY AUTOINCREMENT, " + " firstName TEXT, " + " lastName TEXT, " + " salary NUMERIC CHECK (salary > 0)" + ")"; createStmt.text = sql; try { createStmt.execute(); trace("Table created"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 175 Utilizzo dei database SQL locali Manipolazione dei dati dei database SQL Quando si lavora con i database SQL locali, si eseguono alcune attività comuni che includono la connessione a un database e l'aggiunta e il recupero di dati nelle tabelle in esso contenute. È inoltre opportuno tenere presenti alcuni problemi che possono sorgere durante l'esecuzione di tali attività, ad esempio quelli relativi alla gestione dei vari tipi di dati e degli errori. Va notato che esistono anche varie attività relative al database che si incontrano meno frequentemente ma che sarà spesso necessario eseguire prima di poter passare alle attività più comuni. Ad esempio, prima che sia possibile connettersi a un database e recuperare dati da una tabella, sarà ovviamente necessario creare il database e la struttura della tabella all'interno di esso. Le attività iniziali di impostazione meno frequenti vengono trattate nella sezione “Creazione e modifica di un database” a pagina 172. Si può scegliere di eseguire le operazioni del database in modo asincrono, il che significa che il motore del database viene esguito in background e notifica l'utente creando un evento quando l'operazione riesce oppure non riesce. È inoltre possibile eseguire le operazioni in modo sincrono. In tal caso le operazioni del database vengono eseguite una dopo l'altra e l'applicazione nella sua totalità (inclusi gli aggiornamenti del display) attende che le operazioni vengano completate prima di eseguire altro codice. Gli esempi di questa sezione illustrano l'esecuzione delle operazioni in modalità sia asincrona che sincrona. Per ulteriori informazioni sull'esecuzione in modalità asincrona e sincrona, consultate “Utilizzo delle operazioni di database sincrone e asincrone” a pagina 193. Connessione a un database Prima di poter eseguire qualsiasi operazione relativa al database è necessario aprire la connessione al file del database. Si utilizza un'istanza SQLConnection per rappresentare la connessione a uno o più database. Il primo database connesso tramite l'istanza SQLConnection è detto database "principale". Questo database è connesso tramite il metodo open() per la modalità di esecuzione sincrona o il metodo openAsync() per quella asincrona. Se si apre un database utilizzando l'operazione asincrona openAsync(), è opportuno registrarlo per l'evento open dell'istanza SQLConnection per venire avvertiti del completamento dell'operazione openAsync() e registrarlo per l'evento error dell'istanza SQLConnection per venire avvertiti dell'eventuale mancata riuscita dell'operazione. L'esempio seguente illustra l'apertura di un database già esistente per l'esecuzione asincrona. Il file del database è denominato “DBSample.db” e si trova nella directory di memorizzazione dell'applicazione dell'utente. import flash.data.SQLConnection; import flash.data.SQLMode; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; import flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, errorHandler); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); conn.openAsync(dbFile, SQLMode.UPDATE); function openHandler(event:SQLEvent):void { trace("the database opened successfully"); } function errorHandler(event:SQLErrorEvent):void { trace("Error message:", event.error.message); trace("Details:", event.error.details); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 176 Utilizzo dei database SQL locali L'esempio seguente illustra l'apertura di un database già esistente per l'esecuzione sincrona. Il file del database è denominato “DBSample.db” e si trova nella directory di memorizzazione dell'applicazione dell'utente. import flash.data.SQLConnection; import flash.data.SQLMode; import flash.errors.SQLError; import flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); try { conn.open(dbFile, SQLMode.UPDATE); trace("the database opened successfully"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); } Va notato che, quando si chiama il metodo openAsync() nell'esempio asincrono e quando si chiama il metodo open() nell'esempio singolo, il secondo argomento è la costante SQLMode.UPDATE. Se si specifica SQLMode.UPDATE per il secondo parametro (openMode) si fa sì che il runtime crei un errore se il file specificato non esiste. Se si passa SQLMode.CREATE per il parametro openMode, o se si omette il parametro openMode, il runtime tenta di creare un file di database nel caso in cui il file specificato non esista. Se tuttavia il file è presente, viene aperto; corrisponde all'uso di SQLMode.Update. Si può inoltre specificare SQLMode.READ per il parametro openMode al fine di aprire in modalità di sola lettura un database già esistente. In tal caso, sarà possibile recuperare dati dal database ma non aggiungere, eliminare o modificare dati. Utilizzo delle istruzioni SQL Le istruzioni SQL individuali (le query e i comandi) sono rappresentate nel runtime sotto forma di oggetti SQLStatement. Seguite la procedura qui descritta per creare ed eseguire un'istruzione SQL. Create un'istanza SQLStatement. L'oggetto SQLStatement rappresenta l'istruzione SQL nell'applicazione in questione. var selectData:SQLStatement = new SQLStatement(); Specificate in quale database eseguire la query. A tal fine, impostate la proprietà sqlConnection dell'oggetto SQLStatement sull'istanza SQLConnection connessa al database desiderato. // A SQLConnection named "conn" has been created previously selectData.sqlConnection = conn; Specificate l'effettiva istruzione SQL. Create il testo dell'istruzione come Stringa e assegnatelo alla proprietà text dell'istanza SQLStatement. selectData.text = "SELECT col1, col2 FROM my_table WHERE col1 = :param1"; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 177 Utilizzo dei database SQL locali Definite le funzioni per la gestione del risultato dell'operazione di esecuzione (solo nel caso della modalità di esecuzione asincrona). Utilizzate il metodo addEventListener() per registrare le funzioni come listener degli eventi result ed error dell'istanza SQLStatement. // using listener methods and addEventListener(); selectData.addEventListener(SQLEvent.RESULT, resultHandler); selectData.addEventListener(SQLErrorEvent.ERROR, errorHandler); function resultHandler(event:SQLEvent):void { // do something after the statement execution succeeds } function errorHandler(event:SQLErrorEvent):void { // do something after the statement execution fails } In alternativa è possibile specificare metodi listener utilizzando un oggetto Responder. In tal caso si crea l'istanza Responder e vi si collegano i metodi listener. // using a Responder (flash.net.Responder) var selectResponder = new Responder(onResult, onError); function onResult(result:SQLResult):void { // do something after the statement execution succeeds } function onError(error:SQLError):void { // do something after the statement execution fails } Se il testo dell'istruzione comprende definizioni di parametri, assegnate dei valori a tali parametri. Per assegnare i valori ai parametri, usate la proprietà di matrice associativa parameters dell'istanza SQLStatement. selectData.parameters[":param1"] = 25; Eseguite l'istruzione SQL. Chiamate il metodo execute() dell'istanza SQLStatement. // using synchronous execution mode // or listener methods in asynchronous execution mode selectData.execute(); Inoltre, se state utilizzando un Responder invece dei listener degli eventi in modalità di esecuzione asincrona, passate l'istanza Responder al metodo execute(). // using a Responder in asynchronous execution mode selectData.execute(-1, selectResponder); Per trovare esempi specifici che illustrano questi passi, consultate i seguenti argomenti. “Recupero dei dati da un database” a pagina 180 “Inserimento dei dati” a pagina 186 “Modifica ed eliminazione dei dati” a pagina 188 SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 178 Utilizzo dei database SQL locali Utilizzo dei parametri nelle istruzioni I parametri delle istruzioni SQL consentono la creazione di istruzioni SQL riutilizzabili. Se si utilizzano parametri nelle istruzioni, i valori all'interno delle istruzioni possono variare, ad esempio con l'aggiunta di valori nell'istruzione INSERT, ma il testo di base dell'istruzione rimane invariato. Di conseguenza, l'uso di parametri offre dei vantaggi in termini di prestazioni e facilita inoltre la creazione del codice delle applicazioni. Introduzione ai parametri delle istruzioni Le applicazioni utilizzano spesso una singola istruzione ripetuta più volte con solo lievi variazioni. Ad esempio, ipotizziamo un'applicazione di gestione delle scorte tramite la quale l'utente può aggiungere al database nuovi elementi delle scorte. Il codice dell'applicazione che aggiunge gli elementi delle scorte al database esegue un'istruzione SQL INSERT che aggiunge effettivamente i dati al database. Tuttavia, ogni volta che l'istruzione viene eseguita, è presente una leggera variazione in quanto i valori effettivi che vengono inseriti nella tabella sono diversi, dato che si riferiscono specificamente a ciascun elemento delle scorte aggiunto. Nei casi in cui si abbia un'istruzione SQL che viene utilizzata più volte con diversi valori, la migliore soluzione è usare un'istruzione SQL che comprende nel testo SQL dei parametri invece che dei valori letterali. I parametri sono segnaposti nel testo dell'istruzione che vengono sostituiti da un valore effettivo ogni volta che l'istruzione viene eseguita. Per utilizzare i parametri nelle istruzioni SQL si crea normalmente l'istanza SQLStatement; per l'effettiva istruzione SQL assegnata alla proprietà text, usate segnaposti per i parametri invece che valori precisi. Si deve poi definire il valore di ciascun parametro impostando il valore di un elemento nella proprietà parameters dell'istanza SQLStatement. La proprietà parameters è una matrice associativa, il che significa che l'impostazione di un certo valore si effettua tramite la seguente sintassi. statement.parameters[parameter_identifier] = value; Il parameter_identifier è una stringa se si usa un parametro denominato o un indice intero se si usa un parametro non denominato. Utilizzo dei parametri denominati I parametri possono essere denominati, cioè possedere un nome specifico utilizzato dal database per far corrispondere il valore del parametro stesso alla posizione del relativo segnaposto nel testo dell'istruzione. I nomi dei parametri sono formati dal carattere “:” o “@” seguito da un nome come negli esempi seguenti. :itemName @firstName Il seguente elenco di codici illustra l'utilizzo dei parametri denominati. var sql:String = "INSERT INTO inventoryItems (name, productCode)" + "VALUES (:name, :productCode)"; var addItemStmt:SQLStatement = new SQLStatement(); addItemStmt.sqlConnection = conn; addItemStmt.text = sql; // set parameter values addItemStmt.parameters[":name"] = "Item name"; addItemStmt.parameters[":productCode"] = "12345"; addItemStmt.execute(); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 179 Utilizzo dei database SQL locali Utilizzo dei parametri non denominati L'alternativa all'utilizzo dei parametri denominati è l'utilizzo di quelli non denominati. Per utilizzare un parametro non denominato, lo si denota con un carattere "?" nell'istruzione SQL . A ciascun parametro viene assegnato un indice numerico che rispetta l'ordine dei parametri nell'istruzione e comincia dallo zero per il primo parametro. L'esempio seguente illustra un'altra versione dell'esempio precedente facendo uso dei parametri non denominati. var sql:String = "INSERT INTO inventoryItems (name, productCode)" + "VALUES (?, ?)"; var addItemStmt:SQLStatement = new SQLStatement(); addItemStmt.sqlConnection = conn; addItemStmt.text = sql; // set parameter values addItemStmt.parameters[0] = "Item name"; addItemStmt.parameters[1] = "12345"; addItemStmt.execute(); Vantaggi dell'uso dei parametri L'utilizzo dei parametri nelle istruzioni SQL offre diversi vantaggi. Migliori prestazioni Le istanze SQLStatement che usano i parametri possono venire eseguite in modo più efficiente rispetto a quelle che creano il testo SQL dinamicamente ogni volta che vengono eseguite. Il miglioramento delle prestazioni deriva dal fatto che l'istruzione viene preparata una sola volta e può poi venire eseguita più volte utilizzando diversi valori per i parametri senza che sia necessario ricompilarla. Assegnazione esplicita di un tipo ai dati I parametri si utilizzano per la sostituzione basata sul tipo di quei valori che risultano ignoti al momento della composizione dell'istruzione SQL e rappresentano l'unico modo di garantire la classe d'archivio dei valori passati nel database. Se non si usano i parametri, il runtime tenta di convertire tutti i valori dalla loro rappresentazione testuale ad una classe d'archivio sulla base dell'affinità del tipo della colonna ad essi associata. Per ulteriori informazioni sulle classi d'archivio e l'affinità delle colonne, consultate la sezione “Data type support (Supporto del tipo dei dati)" nell'appendice ”Supporto SQL nei database locali" nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. Migliore protezione L'utilizzo dei parametri contribuisce ad evitare che il database diventi vittima della tecnica di attacco nota come SQL injection. Nel caso di un attacco SQL injection, l'utente immette il codice SQL in una posizione accessibile agli utenti, ad esempio un campo per l'immissione dei dati. Se il codice dell'applicazione costruisce le istruzioni SQL concatenando direttamente l'immissione dell'utente nel testo SQL, il codice SQL immesso dall'utente viene eseguito nel database. L'elenco seguente mostra un esempio di concatenazione dei dati immessi dall'utente nel test SQL. Non utilizzate questa tecnica. // assume the variables "username" and "password" // contain user-entered data var sql:String = "SELECT userId " + "FROM users " + "WHERE username = '" + username + "' " + " AND password = '" + password + "'"; var statement:SQLStatement = new SQLStatement(); statement.text = sql; L'utilizzo dei parametri nelle istruzioni al posto della concatenazione dei valori immessi dall'utente nel testo dell'istruzione evita gli attacchi SQL injection. SQL injection, infatti, non può avere luogo in quanto i valori dei parametri vengono trattati in modo esplicito come valori sostituiti invece che fare parte del testo letterale dell'istruzione. Raccomandiamo di attenervi all'elenco seguente invece che a quello illustrato in precedenza. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 180 Utilizzo dei database SQL locali // assume the variables "username" and "password" // contain user-entered data var sql:String = "SELECT userId " + "FROM users " + "WHERE username = :username " + " AND password = :password"; var statement:SQLStatement = new SQLStatement(); statement.text = sql; // set parameter values statement.parameters[":username"] = username; statement.parameters[":password"] = password; Recupero dei dati da un database Il recupero dei dati da un database si svolge in due fasi. Per prima cosa si esegue l'istruzione SQL SELECT descrivendo il set di dati che si desidera trovare nel database. Successivamente si accede ai dati recuperati e li si visualizza o manipola secondo le esigenze dell'applicazione in uso. Esecuzione dell'istruzione SELECT Per recuperare da un database i dati già esistenti si usa un'istanza SQLStatement. Assegnate l'istruzione SQL SELECT appropriata alla proprietà text dell'istanza, poi chiamate il relativo metodo execute(). Per ulteriori dettagli sulla sintassi dell'istruzione SELECT, consultate l'appendice "SQL support in local databases (Supporto SQL nei database locali)" nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. L'esempio seguente illustra l'esecuzione di un'istruzione SELECT al fine di recuperare dati da una tabella denominata "products" facendo uso della modalità di esecuzione asincrona. var selectStmt:SQLStatement = new SQLStatement(); // A SQLConnection named "conn" has been created previously selectStmt.sqlConnection = conn; selectStmt.text = "SELECT itemId, itemName, price FROM products"; // The resultHandler and errorHandler are listener methods are // described in a subsequent code listing selectStmt.addEventListener(SQLEvent.RESULT, resultHandler); selectStmt.addEventListener(SQLErrorEvent.ERROR, errorHandler); selectStmt.execute(); L'esempio seguente illustra l'esecuzione di un'istruzione SELECT al fine di recuperare dati da una tabella denominata "products" facendo uso della modalità di esecuzione asincrona. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 181 Utilizzo dei database SQL locali var selectStmt:SQLStatement = new SQLStatement(); // A SQLConnection named "conn" has been created previously selectStmt.sqlConnection = conn; selectStmt.text = "SELECT itemId, itemName, price FROM products"; // This try..catch block is fleshed out in // a subsequent code listing try { selectStmt.execute(); // accessing the data is shown in a subsequent code listing } catch (error:SQLError) { // error handling is shown in a subsequent code listing } In tale modalità, quando un'istruzione finisce di essere eseguita, l'istanza SQLStatement genera un evento result (SQLEvent.RESULT) che indica la corretta esecuzione dell'istruzione in oggetto. In alternativa, se si passa un oggetto Responder come argomento nella chiamata execute(), viene chiamata la funzione gestore evento risultato dell'oggetto Responder. Nella modalità di esecuzione sincrona l'esecuzione si ferma finché l'operazione execute() non viene completata e passa poi alla linea successiva del codice. Accesso ai dati risultanti dall'uso dell'istruzione SELECT Una volta terminata l'esecuzione dell'istruzione SELECT, il passo successivo è l'accesso ai dati in tal modo recuperati. Ciascuna riga di dati del set di risultati SELECT diventa un'istanza Object. Tale oggetto ha proprietà i cui nomi corrispondono ai nomi delle colonne del set di risultati. Le proprietà, a loro volta, contengono i valori provenienti dalle colonne del set di risultati. Ad esempio, supponiamo che l'istruzione SELECT specifichi un set di risultati con tre colonne denominate “itemId”, “itemName” e “price”. Per ciascuna riga del set di risultati viene creata un'istanza Object con proprietà denominate itemId, itemName e price. Le proprietà contengono i valori provenienti dalle rispettive colonne. Il seguente elenco di codici continua l'elenco precedente per il recupero dei dati in modalità di esecuzione asincrona e mostra come si accede ai dati recuperati nell'ambito del metodo listener dell'evento risultato. function resultHandler(event:SQLEvent):void { var result:SQLResult = selectStmt.getResult(); var numResults:int = result.data.length; for (var i:int = 0; i < numResults; i++) { var row:Object = result.data[i]; var output:String = "itemId: " + row.itemId; output += "; itemName: " + row.itemName; output += "; price: " + row.price; trace(output); } } function errorHandler(event:SQLErrorEvent):void { // Information about the error is available in the // event.error property, which is an instance of // the SQLError class. } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 182 Utilizzo dei database SQL locali Il seguente elenco di codici amplia l'elenco precedente per il recupero dei dati in modalità di esecuzione sincrona ed amplia il blocco try..catch dell'esempio precedente di esecuzione sincrona illustrando come si accede ai dati recuperati. try { selectStmt.execute(); var result:SQLResult = selectStmt.getResult(); var numResults:int = result.data.length; for (var i:int = 0; i < numResults; i++) { var row:Object = result.data[i]; var output:String = "itemId: " + row.itemId; output += "; itemName: " + row.itemName; output += "; price: " + row.price; trace(output); } } catch (error:SQLError) { // Information about the error is available in the // error variable, which is an instance of // the SQLError class. } Come si vede dall'elenco di codici precedente, gli oggetti risultato sono contenuti in una matrice disponibile come proprietà data di un'istanza SQLResult. Se si sta utilizzando l'esecuzione asincrona con un listener degli eventi, per recuperare quell'istanza SQLResult si deve chiamare il metodo getResult() dell'istanza SQLStatement. Se si specifica un argomento Responder nella chiamata execute(), l'istanza SQLResult viene passata alla funzione gestore evento risultato come argomento. Nella modalità di esecuzione sincrona, invece, si chiama il metodo getResult() dell'istanza SQLStatement in qualsiasi momento dopo che si è effettuata la chiamata del metodo execute(). In tutti i casi, quando si ha l'oggetto SQLResult è possibile avere accesso alle righe dei risultati tramite la proprietà matrice data. Il seguente elenco di codici definisce un'istanza SQLStatement il cui testo è l'istruzione SELECT. L'istruzione recupera righe che contengono i valori delle colonne firstName e lastName di tutte le righe della tabella denominata employees. Questo esempio utilizza la modalità di esecuzione asincrona. Quando l'esecuzione è stata completata viene chiamato il metodo selectResult(); si accede alle righe di dati risultanti tramite SQLStatement.getResult() e le si visualizza usando il metodo trace(). Tenete presente che questo elenco presuppone che esista un'istanza SQLConnection denominata conn già attivata e connessa al database. Presuppone inoltre che la tabella “employees” sia già stata creata e che vi siano stati inseriti dati. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 183 Utilizzo dei database SQL locali import flash.data.SQLConnection; import flash.data.SQLResult; import flash.data.SQLStatement; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; // ... create and open the SQLConnection instance named conn ... // create the SQL statement var selectStmt:SQLStatement = new SQLStatement(); selectStmt.sqlConnection = conn; // define the SQL text var sql:String = "SELECT firstName, lastName " + "FROM employees"; selectStmt.text = sql; // register listeners for the result and error events selectStmt.addEventListener(SQLEvent.RESULT, selectResult); selectStmt.addEventListener(SQLErrorEvent.ERROR, selectError); // execute the statement selectStmt.execute(); function selectResult(event:SQLEvent):void { // access the result data var result:SQLResult = selectStmt.getResult(); var numRows:int = result.data.length; for (var i:int = 0; i < numRows; i++) { var output:String = ""; for (var columnName:String in result.data[i]) { output += columnName + ": " + result.data[i][columnName] + "; "; } trace("row[" + i.toString() + "]\t", output); } } function selectError(event:SQLErrorEvent):void { trace("Error message:", event.error.message); trace("Details:", event.error.details); } L'elenco di codici seguente illustra le stesse tecniche dell'esempio precedente ma utilizza la modalità di esecuzione sincrona. L'esempio definisce un'istanza SQLStatement il cui testo è l'istruzione SELECT. L'istruzione recupera righe che contengono i valori delle colonne firstName e lastName di tutte le righe della tabella denominata employees. Si accede alle righe di dati risultanti tramite SQLStatement.getResult() e le si visualizza usando il metodo trace(). Tenete presente che questo elenco presuppone che esista un'istanza SQLConnection denominata conn già attivata e connessa al database. Presuppone inoltre che la tabella “employees” sia già stata creata e che vi siano stati inseriti dati. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 184 Utilizzo dei database SQL locali import flash.data.SQLConnection; import flash.data.SQLResult; import flash.data.SQLStatement; import flash.errors.SQLError; // ... create and open the SQLConnection instance named conn ... // create the SQL statement var selectStmt:SQLStatement = new SQLStatement(); selectStmt.sqlConnection = conn; // define the SQL text var sql:String = "SELECT firstName, lastName " + "FROM employees"; selectStmt.text = sql; try { // execute the statement selectStmt.execute(); // access the result data var result:SQLResult = selectStmt.getResult(); var numRows:int = result.data.length; for (var i:int = 0; i < numRows; i++) { var output:String = ""; for (var columnName:String in result.data[i]) { output += columnName + ": " + result.data[i][columnName] + "; "; } trace("row[" + i.toString() + "]\t", output); } } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); } Definizione del tipo di dati risultanti dall'uso di SELECT Come impostazione predefinita, ciascuna riga restituita dall'istruzione SELECT viene creata come istanza Object con proprietà denominate appositamente per i nomi delle colonne del set di risultati e con il valore di ciascuna colonna come valore della proprietà associata. Tuttavia, prima di eseguire l'istruzione SQL SELECT, si può impostare su una classe la proprietà itemClass dell'istanza SQLStatement. Se si imposta la proprietà itemClass, ciascuna riga restituita dall'istruzione SELECT viene creata come istanza della classe designata. Il runtime assegna i valori delle colonne risultato ai valori delle proprietà facendo corrispondere i nomi delle colonne del set di risultati SELECT ai nomi delle proprietà della classe itemClass. Tutte le classi assegnate come valore della proprietà itemClass devono avere un costruttore che non richiede alcun parametro. Inoltre, la classe deve presentare una sola proprietà per ciascuna colonna restituita dall'istruzione SELECT. Si considera errore se una colonna dell'elenco SELECT non possiede il nome di proprietà corrispondente nella classe itemClass. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 185 Utilizzo dei database SQL locali Recupero parziale dei risultati SELECT Come impostazione predefinita, l'esecuzione dell'istruzione SELECT recupera tutte le righe del set di risultati contemporaneamente. Una volta completata l'istruzione, di solito si elaborano in qualche modo i dati recuperati, ad esempio creando oggetti o visualizzando i dati su schermo. Se l'istruzione restituisce un gran numero di righe, l'elaborazione di tutti i dati allo stesso momento può occupare gran parte delle risorse del computer, il che a sua volta avrà come conseguenza il mancato aggiornamento dell'interfaccia utente. È possibile migliorare le prestazioni apparenti dell'applicazione comandando al runtime di restituire un certo numero di righe di risultati alla volta. Così facendo, i dati dei risultati iniziali vengono restituiti più rapidamente. Inoltre, ciò consente di dividere in gruppi le righe dei risultati in modo che l'interfaccia utente venga aggiornata dopo l'elaborazione di ciascun gruppo di righe. Tenete presente che l'impiego di questa tecnica ha senso pratico solo nella modalità di esecuzione asincrona. Per recuperare i risultati SELECT in parti, specificate un valore per il primo parametro del metodo SQLStatement.execute() (cioè il parametro prefetch). Il parametro prefetch indica il numero di righe da recuperare la prima volta che l'istruzione viene eseguita. Quando chiamate il metodo execute() di un'istanza SQLStatement, specificate un valore per il parametro prefetch. In tal modo può essere recuperato solo il numero specificato di righe. var stmt:SQLStatement = new SQLStatement(); stmt.sqlConnection = conn; stmt.text = "SELECT ..."; stmt.addEventListener(SQLEvent.RESULT, selectResult); stmt.execute(20); // only the first 20 rows (or fewer) are returned L'istruzione crea l'evento result che indica che è disponibile il primo gruppo di righe di risultati. La risultante proprietà data dell'istanza SQLResult contiene le righe di dati e la relativa proprietà complete indica se vi sono altre righe di risultati ancora da recuperare. Per recuperare altre righe di risultati, chiamate il metodo next() dell'istanza SQLStatement. Analogamente al metodo execute() , il primo parametro del metodo next() si usa per indicare quante righe recuperare la volta successiva che viene creato l'evento result. function selectResult(event:SQLEvent):void { var result:SQLResult = stmt.getResult(); if (result.data != null) { // ... loop through the rows or perform other processing ... if (!result.complete) { stmt.next(20); // retrieve the next 20 rows } else { stmt.removeEventListener(SQLEvent.RESULT, selectResult); } } } L'istruzione SQLStatement crea un evento result tutte le volte che il metodo next() restituisce un gruppo successivo di righe di risultati. Di conseguenza, la stessa funzione listener può essere utilizzata per continuare ad elaborare i risultati (provenienti dalle chiamate next()) fino al recupero completo di tutte le righe. Per ulteriori informazioni, consultate la documentazione di riferimento del linguaggio relativa alla descrizione del metodo SQLStatement.execute() (la descrizione del parametro prefetch) e del metodo SQLStatement.next(). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 186 Utilizzo dei database SQL locali Inserimento dei dati Il recupero dei dati da un database implica l'esecuzione dell'istruzione SQL INSERT. Una volta che l'istruzione ha finito di essere eseguita si può accedere alla chiave primaria della riga appena inserita, se la chiave è stata generata dal database. Esecuzione dell'istruzione INSERT Per aggiungere dati a una tabella in un database, si crea ed esegue un'istanza SQLStatement il cui testo è l'istruzione SQL INSERT. L'esempio seguente utilizza un'istanza SQLStatement per aggiungere una riga di dati alla tabella "employees" già esistente. Questo esempio illustra l'inserimento dei dati nella modalità di esecuzione asincrona. Tenete presente che questo elenco presuppone che esista un'istanza SQLConnection denominata conn già attivata e connessa al database. Presuppone inoltre che la tabella “employees” sia già stata creata. import flash.data.SQLConnection; import flash.data.SQLResult; import flash.data.SQLStatement; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; // ... create and open the SQLConnection instance named conn ... // create the SQL statement var insertStmt:SQLStatement = new SQLStatement(); insertStmt.sqlConnection = conn; // define the SQL text var sql:String = "INSERT INTO employees (firstName, lastName, salary) " + "VALUES ('Bob', 'Smith', 8000)"; insertStmt.text = sql; // register listeners for the result and failure (status) events insertStmt.addEventListener(SQLEvent.RESULT, insertResult); insertStmt.addEventListener(SQLErrorEvent.ERROR, insertError); // execute the statement insertStmt.execute(); function insertResult(event:SQLEvent):void { trace("INSERT statement succeeded"); } function insertError(event:SQLErrorEvent):void { trace("Error message:", event.error.message); trace("Details:", event.error.details); } L'esempio seguente aggiunge una riga di dati alla tabella "employees" già esistente utlizzando la modalità di esecuzione sincrona. Tenere presente che questo elenco presuppone che esista un'istanza SQLConnection denominata conn già attivata e connessa al database. Presuppone inoltre che la tabella “employees” sia già stata creata. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 187 Utilizzo dei database SQL locali import flash.data.SQLConnection; import flash.data.SQLResult; import flash.data.SQLStatement; import flash.errors.SQLError; // ... create and open the SQLConnection instance named conn ... // create the SQL statement var insertStmt:SQLStatement = new SQLStatement(); insertStmt.sqlConnection = conn; // define the SQL text var sql:String = "INSERT INTO employees (firstName, lastName, salary) " + "VALUES ('Bob', 'Smith', 8000)"; insertStmt.text = sql; try { // execute the statement insertStmt.execute(); trace("INSERT statement succeeded"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); } Recupero della chiave primaria generata dal database di una riga inserita Spesso, dopo che si è inserita una riga di dati in una tabella, il codice richiede l'aggiunta di una chiave primaria generata dal database, o valore identificatore della riga, relativa alla riga appena inserita. Ad esempio, una volta che si sia inserita una riga in una tabella, si potrebbe voler aggiungere righe in una tabella correlata. In tal caso si dovrebbe inserire nella tabella correlata il valore della chiave primaria come chiave esterna. Si può recuperare la chiave primaria di una riga appena inserita facendo uso dell'oggetto SQLResult generato dall'esecuzione dell'istruzione. Si tratta dello stesso oggetto utilizzato per accedere ai dati dei risultati dopo l'esecuzione dell'istruzione SELECT. Come per tutte le istruzioni SQL, quando l'esecuzione di INSERT viene completata il runtime crea un'istanza SQLResult. Si accede all'istanza SQLResult chiamando il metodo getResult() dell'oggetto SQLStatement, se si sta utilizzando un listener degli eventi o la modalità di esecuzione sincrona. In alternativa, se si sta utilizzando la imodalità di esecuzione asincrona e si passa un'istanza Responder alla chiamata execute(), l'istanza SQLResult viene passata alla funzione gestore evento risultato come argomento. In ogni caso, l'istanza SQLResult ha una proprietà, lastInsertRowID, che contiene l'identificatore della riga inserita più di recente se l'istruzione SQL eseguita è INSERT. L'esempio seguente illustra l'accesso alla chiave primaria di una riga inserita nella modalità di esecuzione asincrona. insertStmt.text = "INSERT INTO ..."; insertStmt.addEventListener(SQLEvent.RESULT, resultHandler); insertStmt.execute(); function resultHandler(event:SQLEvent):void { // get the primary key var result:SQLResult = insertStmt.getResult(); var primaryKey:Number = result.lastInsertRowID; // do something with the primary key } L'esempio seguente illustra l'accesso alla chiave primaria di una riga inserita nella modalità di esecuzione sincrona. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 188 Utilizzo dei database SQL locali insertStmt.text = "INSERT INTO ..."; try { insertStmt.execute(); // get the primary key var result:SQLResult = insertStmt.getResult(); var primaryKey:Number = result.lastInsertRowID; // do something with the primary key } catch (error:SQLError) { // respond to the error } Tenete presente che l'identificatore della riga può anche non essere il valore della colonna designata come colonna della chiave primaria nella definizione della tabella, secondo la regola seguente. • Se la tabella è definita con una colonna della chiave primaria la cui affinità (il tipo dei dati della colonna) è INTEGER, la proprietà lastInsertRowID contiene il valore che è stato inserito nella riga in oggetto (oppure il valore generato dal runtime se si tratta di una colonna AUTOINCREMENT). • Se la tabella è defnita con più colonne della chiave primaria (chiave composta) oppure con una sola colonna della chiave primaria la cui affinità non è INTEGER, dietro le quinte il database genera un valore identificatore per la riga in oggetto. Tale valore generato è il valore della proprietà lastInsertRowID. • Il valore è sempre l'identificatore della riga inserita più di recente. Se l'istruzione INSERT produce un trigger che a sua volta inserisce una riga, la proprietà lastInsertRowID conterrà l'identificatore dell'ultima riga inserita dal trigger invece che di quella creata dall'istruzione INSERT. Di conseguenza, se si desidera avere una colonna della chiave primaria definita in modo esplicito il cui valore sia disponibile dopo il comando INSERT tramite la proprietà SQLResult.lastInsertRowID, tale colonna deve essere definita come colonna INTEGER PRIMARY KEY. Tenete presente tuttavia che, anche se la tabella non include una colonna INTEGER PRIMARY KEY esplicita, è ugualmente accettabile utilizzare l'identificatore della riga generato dal database come chiave primaria per la tabella, allo scopo di definire le relazioni con le tabelle correlate. Il valore della colonna dell'identificatore della riga è disponibile in tutte le istruzioni SQL se si usa uno dei nomi speciali delle colonne ROWID, _ROWID_ oppure OID. È possibile creare una colonna della chiave esterna in una tabella correlata ed utilizzare il valore identificatore della riga come valore della colonna della chiave esterna, esattamente come si fa nei casi in cui è presente una colonna INTEGER PRIMARY KEY dichiarata esplicitamente. Da questo punto di vista, se si sta usando un chiave primaria arbitraria invece che una chiave naturale, e se non si obietta al fatto che il runtime genera il valore della chiave primaria per conto dell'utente, non fa molta differenza che si utilizzi come chiave primaria di una tabella la colonna INTEGER PRIMARY KEY oppure l'identificatore della riga generato dal sistema, allo scopo di definire una relazione con chiave esterna fra due tabelle. Per ulteriori informazioni sulle chiavi primarie e gli identificatori di riga generati, consultate le sezioni intitolate “CREATE TABLE” e “Espressioni” nell'appendice “Supporto SQL nei database locali” nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. Modifica ed eliminazione dei dati La procedura per l'esecuzione di altre operazioni di manipolazione è identica a quella per l'esecuzione delle istruzioni SQL SELECT ed INSERT. È sufficiente sostituire una diversa istruzione SQL nella proprietà text dell'istanza SQLStatement, come segue. • Per modificare i dati già presenti in una tabella, utilizzate l'istruzione UPDATE. • Per eliminare una o più righe di dati da una tabella, utilizzate l'istruzione DELETE. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 189 Utilizzo dei database SQL locali Per una descrizione di queste istruzioni, consultate l'appendice “Supporto SQL nei database locali” nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. Operazioni con più di un database Utilizzate il metodo SQLConnection.attach() per aprire una connessione a un ulteriore database su un'istanza SQLConnection che presenta già un database aperto. Al database allegato si dà nome tramite il parametro name nella chiamata del metodo attach(). Quando si scrivono le istruzioni per manipolare quel database, è possibile utilizzare tale nome in un prefisso (tramite la maschera database-name.table-name) per qualificare gli eventuali nomi di tabelle nelle istruzioni SQL, indicando al runtime che la tabella è reperibile nel database nominato. È possibile eseguire una singola istruzione SQL che comprende le tabelle di più di un database che sono connesse alla stessa istanza SQLConnection. Se si crea una transazione sull'istanza SQLConnection, tale transazione si applica a tutte le istruzioni SQL eseguite tramite quell'istanza SQLConnection. Ciò vale indipendentemente dall'identità del database allegato su cui l'istruzione viene eseguita. In alternativa è possibile anche creare in un'applicazione più istanze SQLConnection ciascuna delle quali è connessa a uno o più database. Tuttavia, se usate più connessioni al medesimo database, tenete presente che le transazioni dei database non vengono condivise da tutte le istanze SQLConnection. Di conseguenza, se ci si connette allo stesso file di database tramite più istanze SQLConnection, le modifiche ai dati non verranno riflesse su entrambe le connessioni come ci si aspetterebbe. Ad esempio, se due istruzioni UPDATE o DELETE vengono eseguite sullo stesso database tramite diverse istanze SQLConnection, e si verifica un errore nell'applicazione dopo che ha luogo un'operazione, è possibile che i dati del database vengano lasciati in uno stato intermedio non reversibile e ciò può compromettere l'integrità dell'intero database e, di conseguenza, dell'applicazione. Gestione degli errori dei database In generale, la gestione degli errori nei database è simile a quella degli altri errori del runtime. È opportuno scrivere il codice in modo che sia in grado di affrontare eventuali errori che si possono verificare e reagire ad essi invece che lasciare che sia il runtime a farlo. È possibile dividere gli errori dei database, a grandi linee, in tre categorie: gli errori di connessione, gli errori di sintassi SQL e gli errori relativi ai vincoli. Errori di connessione La maggior parte degli errori dei database riguardano la connessione e possono verificarsi nel corso di qualsiasi operazione. Anche se esistono strategie di prevenzione degli errori di connessione, solo raramente è possibile riprendersi in modo non traumatico da tale tipo di errori se il database rappresenta una parte vitale dell'applicazione. La maggior parte degli errori di connessione riguarda il modo in cui il runtime interagisce con il sistema operativo, il file system e il file del database. Ad esempio, si verifica un errore di connessione nel caso in cui l'utente non sia autorizzato a creare un file di database in una particolare posizione nel file system. Le seguenti strategie possono contribuire ad evitare gli errori di connessione. Utilizzate file di database specifici per ciascun utente Invece che fare uso di un solo file di database per tutti gli utenti che utilizzano l'applicazione su un certo computer, fornite a ciascuno degli utenti un file di database. Il file si deve trovare in una directory associata all'account dell'utente. Ad esempio, può trovarsi nella directory di memorizzazione dell'applicazione o nella cartella dei documenti dell'utente o sul suo desktop, e così via. Prendete in considerazione i diversi tipi di utente Provate l'applicazione con tipi diversi di account utente e su diversi sistemi operativi e non partite dal presupposto che l'utente abbia le autorizzazioni di amministratore sul computer. Inoltre, non partite dal presupposto che la persona che ha installato l'applicazione sia necessariamente l'utente che la esegue. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 190 Utilizzo dei database SQL locali Prendete in considerazione diverse posizioni dei file Se consentite agli utenti di specificare il percorso di salvataggio di un file di database o di selezione di un file da aprire, considerate le varie posizioni dei file che gli utenti possono voler usare. Inoltre, prendete in considerazione la creazione di limiti alle posizioni in cui gli utenti possono memorizzare (o da cui possono aprire) i file di database. Ad esempio, si può consentire agli utenti di aprire solo i file contenuti nelle posizioni di memorizzazione nell'ambito del loro account. Se si verifica un errore di connessione, è molto probabile che abbia luogo a seguito del primo tentativo di creazione o apertura del database. Di conseguenza l'utente non sarà in grado di eseguire nell'applicazione nessuna operazione concernente il database. Per alcuni tipi di errore, come quelli di sola lettura o relativi alle autorizzazioni, una possibile tecnica di ripristino è la creazione di una copia del file del database in una posizione diversa. L'applicazione può copiare il file del database in una posizione diversa, in cui l'utente ha l'autorizzazione a creare e modificare i file, ed utilizzare tale posizione. Errori di sintassi Si verifica un errore di sintassi nei casi in cui l'istruzione SQL sia stata composta in modo errato e l'applicazione tenti di eseguirla. Poiché le istruzioni SQL dei database locali vengono create come stringhe, non è possibile il controllo della sintassi SQL al momento della compilazione. Per poterne controllare la sintassi, tutte le istruzioni SQL devono essere eseguite. Utilizzate le seguenti strategie per evitare gli errori di sintassi. Provate con cura tutte le istruzioni SQL Se possibile, nel corso dello sviluppo dell'applicazione, provate le istruzioni SQL separatamente prima di inserirle come testo delle istruzioni nel codice dell'applicazione stessa. Seguite inoltre un metodo di prova del codice come l'unit testing per creare un set di prove che eseguano tutte le possibili opzioni e variazioni del codice. Utilizzate i parametri nelle istruzioni ed evitate di concatenare (cioè generare in modo dinamico) l'SQL Se si fa uso dei parametri e si evita l'uso di istruzioni SQL costruiti in modo dinamico, tutte le volte che un'istruzione SQL viene eseguita verrà utilizzato lo stesso testo che la compone. Di conseguenza sarà molto più facile provare le istruzioni e ridurre il numero delle possibili variazioni. Se è inevitabile generare un'istruzione SQL in modo dinamico, è opportuno ridurne al minimo le parti dinamiche. Controllate inoltre la validità degli eventuali interventi dell'utente per assicurare che non provochino errori di sintassi. Per riprendersi da un errore di sintassi, l'applicazione necessita di una logica complessa che le consenta di esaminare le istruzioni SQL e correggerne la sintassi. Se vi attenete alle istruzioni generali di cui sopra per la prevenzione degli errori di sintassi, il codice sarà in grado di identificare le potenziali fonti di errori di sintassi SQL nel runtime, come ad esempio l'uso dell'intervento dell'utente in un'istruzione. Per il recupero da un errore di sintassi, date istruzioni all'utente indicandogli che cosa correggere per far sì che l'istruzione venga eseguita in modo appropriato. Errori relativi ai vincoli Gli errori di vincolo si verificano quando l'istruzione INSERT o UPDATE cerca di aggiungere dati a una colonna. L'errore ha luogo nei casi in cui i nuovi dati infrangano uno dei vincoli definiti relativamente alla tabella o alla colonna. Il set di possibili vincoli comprende i seguenti. Vincolo di univocità Indica che in tutte le righe di una tabella non possono essere presenti valori duplicati in una colonna. In alternativa, quando più colonne sono raggruppate sotto un vincolo di univocità, la combinazione dei valori di tali colonne non deve essere duplicata. Ciò vale a dire che, nell'ambito della colonna o delle colonne univoche specificate, ciascuna riga deve essere diversa dalle altre. Vincolo della chiave primaria Dal punto di vista dei dati consentiti o meno da un certo vincolo, il vincolo della chiave primaria è identico al vincolo di univocità. Vincolo valore non Null Stabilisce che una singola colonna non consenta la memorizzazione di un valore NULL e che, di conseguenza, in tutte le righe tale colonna debba avere un valore. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 191 Utilizzo dei database SQL locali Vincolo di controllo Consente di specificare un vincolo arbitrario su una o più tabelle. Un vincolo di controllo comune è la regola che stabilisce che il valore di una colonna debba rientrare in certi limiti, ad esempio che il valore di una colonna numerica sia maggiore di zero. Un altro tipo comune di tale vincolo specifica le relazioni che devono sussistere fra i valori delle colonne, ad esempio stabilendo che il valore di una certa colonna debba essere diverso da quello di un'altra colonna facente parte della stessa riga. Vincolo del tipo di dati (affinità fra colonne) Il runtime stabilisce quali tipi di dati sono consentiti nei valori delle colonne e dà luogo a un errore se si tenta di memorizzare in una colonna un valore del tipo errato. Tuttavia, in molte situazioni i valori vengono convertiti in modo da adeguarsi al tipo di dati dichiarato per la colonna a cui sono destinati. Per ulteriori informazioni, consultate “Utilizzo dei tipi di dati nei database” a pagina 192. Il runtime non applica vincoli ai valori della chiave esterna; ciò significa che non è necessario che tali valori corrispondano al valore della chiave primaria già esistente. Oltre ai tipi di vincolo predefiniti, il motore SQL del runtime supporta l'utilizzo dei trigger, che sono simili ai gestori di eventi. Si tratta di un set predefinito di istruzioni che vengono eseguite quando ha luogo una certa azione. Ad esempio, si può definire un trigger da eseguire quando vengono inseriti o eliminati dati in una particolare tabella. Un possibile utilizzo del trigger è per l'esame delle modifiche apportate ai dati e per la creazione di un errore nel caso in cui non vengano rispettate certe condizioni. Di conseguenza, il trigger può avere lo stesso scopo del vincolo e le strategie di prevenzione e recupero dagli errori relativi ai vincoli sono valide anche nel caso degli errori generati dai trigger. L'ID degli errori generati dai trigger è comunque diverso dall'ID degli errori di vincolo. Il set di vincoli che si applica ad una certa tabella si determina al momento della progettazione dell'applicazione. L'aggiunta degli appositi vincoli facilita la progettazione dell'applicazione in modo da renderla in grado di prevenire gli errori di vincolo e riprendersi da essi. La previsione e la prevenzione sistematiche degli errori di vincolo sono tuttavia difficoltose. La previsione è infatti ostacolata dal fatto che gli errori relativi ai vincoli non si presentano finché non si aggiungono dati all'applicazione: tali errori si presentano con i dati che vengono aggiunti al database dopo che è stato creato e sono spesso il risultato del rapporto fra i nuovi dati e quelli già presenti nel database. Le seguenti strategie possono contribuire ad evitare molti errori dei vincoli. Progettate con cura la struttura del database e i vincoli Lo scopo dei vincoli è di far rispettare le regole dell'applicazione e contribuire a proteggere l'integrità dei dati del database. Quando progettate l'applicazione, cercate di strutturare il database in modo che sostenga l'applicazione. Come parte di tale procedimento, identificate le regole che si applicano ai dati; decidete ad esempio se certi valori sono obbligatori, se un certo valore deve essere predefinito, se è consentita la presenza di valori duplicati, e così via. Tali regole serviranno da guida nella creazione dei vincoli del database. Specificate i nomi delle colonne in modo esplicito È possibile scrivere l'istruzione INSERT senza specificare esplicitamente le colonne nelle quali devono essere inseriti i valori; tuttavia, così facendo si corre un rischio inutile. Denominando in modo esplicito le colonne in cui inserire i valori è possibile consentire la presenza dei valori generati automaticamente, delle colonne contenenti valori predefiniti e delle colonne che accettano i valori NULL. Inoltre, così facendo si può essere sicuri che in tutte le colonne NOT NULL venga inserito un valore esplicito. Utilizzate i valori predefiniti Ogni volta che specificate il vincolo NOT NULL per una colonna, se possibile specificate nella definizione della colonna un valore predefinito. Anche il codice dell'applicazione può fornire valori predefiniti. Ad esempio, il codice può controllare se una certa variabile in una stringa è null e assegnarle un valore prima di usarla per impostare il valore del parametro di un'istruzione. Convalidate i dati immessi dall'utente Controllate in anticipo i dati immessi dall'utente per assicurare che rispettino i limiti specificati dai vincoli, specialmente nel caso dei vincoli NOT NULL e CHECK. Ovviamente, è più difficoltoso controllare l'adesione al vincolo UNIQUE, poiché per farlo è necessario eseguire una query SELECT per determinare se i dati sono univoci. Utilizzate i trigger È possibile scrivere un trigger che convalidi (e magari sostituisca) i dati inseriti o esegua altre azioni al fine di correggere i dati non validi. La convalida e la correzione possono evitare il verificarsi di errori di vincolo. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 192 Utilizzo dei database SQL locali Sotto molti punti di vista, gli errori concernenti i vincoli sono più difficoltosi da evitare degli altri tipi di errori. Fortunatamente esistono diverse strategie che consentono il recupero dagli errori di vincolo in modi che non rendono instabile o inutilizzabile l'applicazione. Utilizzate gli algoritmi di conflitto Quando si definisce un vincolo su una colonna, e quando si crea un'istruzione INSERT o UPDATE, si può scegliere di specificare un algoritmo di conflitto che definisce l'azione eseguita dal database al verificarsi della violazione di un vincolo. Il motore del database può eseguire diverse azioni possibili: può fare terminare una singola istruzione o un'intera transazione, può ignorare l'errore o può anche rimuovere i dati meno recenti e sostituirli con i dati che il codice sta tentando di memorizzare. Per ulteriori informazioni, consultate la sezione “ON CONFLICT (conflict algorithms) [CONFLITTI (algoritmi di conflitto)]” nell'appendice “SQL support in local databases (Supporto SQL nei database locali)” nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. Fornite un feedback correttivo Il set di vincoli che può influenzare un certo comando SQL può essere identificato in anticipo. È di conseguenza possibile prevedere gli errori di vincolo che possono essere provocati da una certa istruzione e costruire la logica dell'applicazione in modo tale da essere in grado di reagire a tali errori. Ad esempio, supponiamo che l'applicazione comprenda una maschera per l'immissione dei dati relativi ai nuovi prodotti. Se la colonna del nome del prodotto nel database è definita con un vincolo UNIQUE, l'inserimento nel database di una riga per un nuovo prodotto può provocare un errore di vincolo. Di conseguenza l'applicazione è progettata in modo da prevedere tale errore. Quando si verifica l'errore, l'applicazione avverte l'utente che il nome del prodotto specificato è già in uso e chiede di scegliere un nome diverso. Un'altra risposta possibile è quella di consentire all'utente di visualizzare le informazioni riguardanti l'altro prodotto che ha lo stesso nome. Utilizzo dei tipi di dati nei database Quando si crea una tabella in un database, l'istruzione SQL per la creazione della tabella definisce l'affinità, o tipo di dati, di ciascuna colonna di tale tabella. Sebbene sia possibile omettere le dichiarazioni di affinità, è consigliabile dichiarare in modo esplicito l'affinità delle colonne nelle istruzioni SQL CREATE TABLE. Come regola generale, qualsiasi oggetto memorizzato in un database tramite l'istruzione INSERT viene restituito sotto forma di istanza dello stesso tipo di dati quando si esegue l'istruzione SELECT. Tuttavia, il tipo di dati del valore recuperato può essere diverso a seconda dell'affinità della colonna del database in cui il valore è memorizzato. Quando viene memorizzato in una colonna un valore con un tipo di dati che non corrisponde all'affinità della colonna, il database tenta di convertire il valore in modo da adattarlo all'affinità della colonna. Ad esempio, se una colonna del database viene dichiarata con l'affinità NUMERIC, il database tenterà di convertire in una classe d'archivio numerica (INTEGER o REAL) i dati inseriti prima di salvarli. Se non risulta possibile convertire i dati, il database crea un errore. Secondo questa regola, se viene inserita in una colonna NUMERIC la stringa “12345”, il database la converte automaticamente nel valore intero 12345 prima di memorizzarla. Quando viene recuperato tramite l'istruzione SELECT, il valore viene restituito sotto forma di istanza del tipo di dati numerico (ad esempio Number) invece che di istanza Stringa. Il modo migliore per evitare la conversione indesiderata del tipo di dati è attenersi a due regole. Prima di tutto, definite ciascuna colonna con l'affinità che corrisponde al tipo di dati che desiderate che essa contenga. Successivamente, inserite solo valori il cui tipo di dati corrisponde all'affinità definita. Il rispetto di queste due regole offre due vantaggi. Tanto per cominciare, quando si inseriscono i dati, essi non vengono convertiti in modo inaspettato (il che poteva provocare la perdita del significato che si intendeva conferire loro). Inoltre, quando si recuperano i dati, essi vengono restituiti con il loro tipo di dati originale. Per ulteriori informazioni sui tipi di affinità delle colonne disponibili e sull'utilizzo dei tipi di dati nelle istruzioni SQL, consultate la sezione “Data type support (Supporto del tipo di dati)” nell'appendice “SQL support in local databases (Supporto SQL nei database locali)” nella Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 193 Utilizzo dei database SQL locali Utilizzo delle operazioni di database sincrone e asincrone Nelle sezioni precedenti abbiamo descritto le operazioni comuni eseguite sui database, come ad esempio il recupero, l'inserimento, l'aggiornamento e l'eliminazione dei dati, come pure la creazione del file del database, delle tabelle e di altri oggetti all'interno del database. Gli esempi forniti illustrano l'esecuzione di tali operazioni in modalità sia asincrona che sincrona. Ricapitolando: nella modalità di esecuzione asincrona si comanda al motore del database di eseguire una certa operazione. Il motore esegue quindi il comando in background, mentre l'applicazione continua ad essere in esecuzione. Al termine dell'operazione il motore del database crea un evento per avvertire di ciò l'utente. Il vantaggio chiave dell'esecuzione asincrona è che il runtime esegue le operazioni del database in background mentre il codice dell'applicazione principale continua ad essere in esecuzione. Questo serve in particolar modo nei casi in cui l'operazione impiega molto tempo ad essere eseguita. Nella modalità di esecuzione sincrona, invece, le operazioni non vengono eseguite in background. Per prima cosa, si comanda al motore del database di eseguire un'operazione. Il codice si ferma a quel punto in attesa che il motore esegua il comando. Al termine dell'operazione, l'esecuzione prosegue con la riga successiva del codice. Se è presente una sola connessione per il database, non è possibile eseguire alcune delle operazioni o delle istruzioni in modo sincrono ed altre in modo asincrono. Si specifica se SQLConnection opera in modalità di esecuzione sincrona o asincrona al momento dell'apertura della connessione al database. Se si chiama SQLConnection.open(), la connessione funziona in modalità di esecuzione sincrona e se si chiama SQLConnection.openAsync() la modalità sarà invece asincrona. Una volta che un'istanza di SQLConnection è connessa a un database tramite open() o openAsync(), la modalità di esecuzione viene fissata su sincrona o asincrona. Utilizzo delle operazioni di database sincrone Il codice effettivo utilizzato per eseguire le operazioni e rispondervi nella modalità sincrona non è molto diverso da quello utilizzato nella modalità di esecuzione asincrona. Le differenze fondamentali fra i due approcci riguardano due aspetti: il primo è l'esecuzione di un'operazione che dipende da un'altra operazione (come ad esempio le righe risultanti da SELECT o la chiave primaria della riga aggiunta dall'istruzione INSERT). Il secondo aspetto in cui vi è una differenza è la gestione degli errori. Scrittura del codice per le operazioni sincrone La differenza fondamentale tra l'esecuzione sincrona e quella asincrona è che in modalità sincrona il codice viene creato come serie singola di passi successivi. Nel codice asincrono, invece, si registrano listener degli eventi e spesso si dividono le operazioni fra vari metodi listener. Quando un database è connesso in modalità di esecuzione sincrona è possibile eseguire su di esso una serie di operazioni una dopo l'altra all'interno di un singolo blocco di codice. Questa tecnica è dimostrata nell'esempio seguente. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 194 Utilizzo dei database SQL locali var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); // open the database conn.open(dbFile, OpenMode.UPDATE); // start a transaction conn.begin(); // add the customer record to the database var insertCustomer:SQLStatement = new SQLStatement(); insertCustomer.sqlConnection = conn; insertCustomer.text = "INSERT INTO customers (firstName, lastName) " + "VALUES ('Bob', 'Jones')"; insertCustomer.execute(); var customerId:Number = insertCustomer.getResult().lastInsertRowID; // add a related phone number record for the customer var insertPhoneNumber:SQLStatement = new SQLStatement(); insertPhoneNumber.sqlConnection = conn; insertPhoneNumber.text = "INSERT INTO customerPhoneNumbers (customerId, number) " + "VALUES (:customerId, '800-555-1234')"; insertPhoneNumber.parameters[":customerId"] = customerId; insertPhoneNumber.execute(); // commit the transaction conn.commit(); Come si vede, si chiamano gli stessi metodi per eseguire le operazioni del database, sia che si stia utilizzando la modalità sincrona che quella asincrona. Le differenze chiave fra i due approcci risiedono nell'esecuzione di un'operazione che dipende da un'altra operazione e nella gestione degli errori. Esecuzione di un'operazione che dipende da un'altra Quando si usa la modalità di esecuzione sincrona non è necessario scrivere codice che rilevi gli eventi per determinare quando una certa operazione viene completata. È sufficiente invece partire dal presupposto che, se un'operazione di una riga del codice viene completata correttamente, l'esecuzione prosegue con la riga successiva del codice. Di conseguenza, per eseguire un'operazione che dipende dalla riuscita di un'altra operazione, è sufficiente scrivere il codice dipendente immediatamente dopo l'operazione da cui dipende. Ad esempio, per comandare tramite il codice a un'applicazione di dare inizio a una transazione, eseguire l'istruzione INSERT, recuperare la chiave primaria della riga inserita, inserire tale chiave in un'altra riga di una tabella diversa e infine eseguire il commit della transazione, è possibile scrivere tutto il codice sotto forma di una serie di istruzioni, come dimostrato nell'esempio seguente. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 195 Utilizzo dei database SQL locali var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); // open the database conn.open(dbFile, SQLMode.UPDATE); // start a transaction conn.begin(); // add the customer record to the database var insertCustomer:SQLStatement = new SQLStatement(); insertCustomer.sqlConnection = conn; insertCustomer.text = "INSERT INTO customers (firstName, lastName) " + "VALUES ('Bob', 'Jones')"; insertCustomer.execute(); var customerId:Number = insertCustomer.getResult().lastInsertRowID; // add a related phone number record for the customer var insertPhoneNumber:SQLStatement = new SQLStatement(); insertPhoneNumber.sqlConnection = conn; insertPhoneNumber.text = "INSERT INTO customerPhoneNumbers (customerId, number) " + "VALUES (:customerId, '800-555-1234')"; insertPhoneNumber.parameters[":customerId"] = customerId; insertPhoneNumber.execute(); // commit the transaction conn.commit(); Gestione degli errori nell'esecuzione sincrona Nella modalità di esecuzione sincrona non si rilevano gli eventi di errore per determinare se un'operazione non è riuscita. Si circondano invece le eventuali parti del codice che potrebbero dare luogo a errori con un set di blocchi try..catch..finally. Con il blocco try si circonda il codice che può dare luogo a errori. Scrivete le azioni da eseguire in risposta a ciascun tipo di errore entro blocchi catch separati. Ponete l'eventuale codice che desiderate venga sempre eseguito indipendentemente dalla riuscita o meno (ad esempio la chiusura della connessione a un database non più necessario) nel blocco finally. L'esempio che segue illustra l'uso dei blocchi try..catch..finally per la gestione degli errori. Questo esempio espande il precedente aggiungendo il codice di gestione degli errori. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 196 Utilizzo dei database SQL locali var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); // open the database conn.open(dbFile, SQLMode.UPDATE); // start a transaction conn.begin(); try { // add the customer record to the database var insertCustomer:SQLStatement = new SQLStatement(); insertCustomer.sqlConnection = conn; insertCustomer.text = "INSERT INTO customers (firstName, lastName)" + "VALUES ('Bob', 'Jones')"; insertCustomer.execute(); var customerId:Number = insertCustomer.getResult().lastInsertRowID; // add a related phone number record for the customer var insertPhoneNumber:SQLStatement = new SQLStatement(); insertPhoneNumber.sqlConnection = conn; insertPhoneNumber.text = "INSERT INTO customerPhoneNumbers (customerId, number)" + "VALUES (:customerId, '800-555-1234')"; insertPhoneNumber.parameters[":customerId"] = customerId; insertPhoneNumber.execute(); // if we've gotten to this point without errors, commit the transaction conn.commit(); } catch (error:SQLError) { // rollback the transaction conn.rollback(); } Modalità di esecuzione asincrona Si ritiene comunemente che, nella modalità di esecuzione asincrona, non sia possibile cominciare ad eseguire un'istanza SQLStatement se allo stesso momento è in esecuzione un'altra SQLStatement sulla connessione allo stesso database. Si tratta in realtà di un'informazione errata. Mentre è in esecuzione un'istanza SQLStatement non è possibile modificare la proprietà text dell'istruzione. Tuttavia, se si utilizza un'istanza SQLStatement separata per ciascuna diversa istruzione SQL che si desidera eseguire, è possibile chiamare il metodo execute() di un'istanza SQLStatement mentre un'altra è ancora in esecuzione, senza che ciò dia luogo a un errore. All'interno, quando si eseguono le operazioni sul database nella modalità asincrona, ciascuna connessione al database (cioè ciascuna istanza SQLConnection) ha una propria coda o elenco di operazioni che deve eseguire. Il runtime esegue ciascuna operazione in serie, nell'ordine in cui viene aggiunta alla coda. Quando si crea un'istanza SQLStatement e si chiama il corrispondente metodo execute(), tale operazione di esecuzione dell'istruzione viene aggiunta alla coda della connessione. Se su tale istanza SQLConnection non è al momento in esecuzione nessuna operazione, l'istruzione comincia ad essere eseguita in background. Supponiamo di creare, all'interno dello stesso blocco di codice, un'altra SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 197 Utilizzo dei database SQL locali istanza SQLStatement e inoltre di chiamare il corrispondente metodo execute(). L'operazione di esecuzione della seconda istruzione viene aggiunta alla coda dopo la prima istruzione. Non appena la prima istruzione finisce di essere eseguita, il runtime passa alla successiva operazione nella coda. L'elaborazione delle operazioni successive della coda avviene in background anche mentre l'evento result della prima operazione è ancora in corso di creazione nel codice dell'applicazione principale. Questa tecnica è dimostrata nel codice seguente. // Using asynchronous execution mode var stmt1:SQLStatement = new SQLStatement(); stmt1.sqlConnection = conn; // ... Set statement text and parameters, and register event listeners ... stmt1.execute(); // At this point stmt1's execute() operation is added to conn's execution queue. var stmt2:SQLStatement = new SQLStatement(); stmt2.sqlConnection = conn; // ... Set statement text and parameters, and register event listeners ... stmt2.execute(); // At this point stmt2's execute() operation is added to conn's execution queue. // When stmt1 finishes executing, stmt2 will immediately begin executing // in the background. Il fatto che il database esegue automaticamente le istruzioni successive presenti in coda produce un effetto collaterale importante. Se un'istruzione dipende dal risultato di un'altra operazione, non è possibile aggiungere l'istruzione alla coda (cioè non si può chiamare il corrispondente metodo execute()) finché la prima operazione non è stata completata. Ciò accade perché, una volta che si è chiamato il metodo execute() della seconda istruzione, non è possibile modificare le proprietà text e parameters dell'istruzione stessa. In tal caso è necessario attendere l'evento che indica il completamento della prima operazione prima di dare inizio all'operazione successiva. Se ad esempio desiderate eseguire un'istruzione nell'ambito di una transazione, l'esecuzione dell'istruzione dipenderà dall'operazione di apertura della transazione. Dopo aver chiamato il metodo SQLConnection.begin() per aprire la transazione, sarà necessario attendere che l'istanza SQLConnection crei il suo evento begin. Solo allora sarà possibile chiamare il metodo execute() dell'istanza SQLStatement. In questo esempio, il modo più semplice di organizzare l'applicazione in modo da assicurare la corretta esecuzione delle operazioni è quello di creare un metodo registrato come listener dell'evento begin. Il codice che chiama il metodo SQLStatement.execute() viene posto all'interno di tale metodo listener. Uso della crittografia con i database SQL Tutte le applicazioni Adobe AIR condividono lo stesso motore di database locale. Di conseguenza, qualsiasi applicazione AIR può connettersi, leggere e scrivere in un file di database non crittografato. A partire da Adobe AIR 1.5, in AIR è inclusa la capacità di creare file di database crittografati e di connettersi a tali file. Quando usate un database crittografato, per connettersi a tale database un'applicazione deve fornire la chiave di crittografia corretta. Se viene fornita la chiave di crittografica errata (o nessuna chiave), l'applicazione non può connettersi al database. Di conseguenza, l'applicazione non è in grado di leggere i dati dal database oppure di scrivere o modificare i dati nel database. Per usare un database crittografato, dovete crearlo come database crittografato. Per un database crittografato esistente, potete aprire una connessione a tale database. Potete anche modificare la chiave di crittografia di un database crittografato. A parte le operazioni relative alla creazione e connessione a un database crittografato, le tecniche per l'utilizzo di questo tipo di database sono le stesse che usate per un database non crittografato. In particolare, l'esecuzione delle istruzioni SQL è uguale per i database crittografati e non crittografati. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 198 Utilizzo dei database SQL locali Vari usi di un database crittografato La crittografia è utile ogni volta che desiderate limitare l'accesso alle informazioni archiviate in un database. La funzionalità di crittografia del database inclusa in Adobe AIR può essere usata per vari scopi. Di seguito sono riportati alcuni esempi di casi in cui è opportuno usare un database crittografato: • Cache di sola lettura di dati privati di un'applicazione scaricati da un server • Archivio dell'applicazione locale per dati privati che vengono sincronizzati con un server (i dati vengono inviati e caricati sul server) • File crittografati usati come formato di file per i documenti creati e modificati dall'applicazione. I file possono essere riservati a un solo utente o progettati per la condivisione tra tutti gli utenti dell'applicazione. • Qualsiasi altro uso di un archivio dati locale, come quelli descritti in “Vari usi dei database SQL locali” a pagina 168, in cui i dati devono essere mantenuti privati e salvaguardati dagli utenti che hanno accesso al computer o ai file di database. L'individuazione del motivo per cui è opportuno utilizzare un database crittografato vi permetterà di decidere più facilmente come progettare l'architettura di un'applicazione. In particolare, può incidere sul modo in cui l'applicazione crea, ottiene o archivia la chiave di crittografia per il database. Per ulteriori informazioni su tali considerazioni, consultate “Considerazioni sull'uso della crittografia con un database” a pagina 202. Oltre a un database crittografato, un meccanismo alternativo per mantenere privati i dati riservati consiste nell'usare un archivio locale crittografato. In un archivio locale crittografato, potete archiviare un singolo valore ByteArray usando una chiave in formato stringa. Solo l'applicazione AIR che ha memorizzato il valore può accedervi e solo nel computer in cui il valore è memorizzato. Con l'archivio locale crittografato non è necessario creare una chiave di crittografia personalizzata. Per questi motivi, un archivio locale crittografato è più adatto per archiviare in modo semplice un singolo valore o un set di valori che possono essere facilmente codificati in un ByteArray. Un database crittografato è invece più adatto per set di dati estesi in cui è preferibile disporre di funzioni strutturate per l'esecuzione di query e la memorizzazione dei dati. Per ulteriori informazioni sull'uso di un archivio locale crittografato, consultate “Memorizzazione di dati crittografati” a pagina 218. Creazione di un database crittografato Per utilizzare un database crittografato, è necessario crittografare il file di database al momento della creazione. Dopo avere creato un database non crittografato, non è possibile crittografarlo in seguito. In modo analogo, un database crittografato non può essere decrittografato in seguito. Se necessario, potete modificare la chiave di crittografia di un database crittografato. Per ulteriori dettagli, consultate “Modifica della chiave di crittografia di un database” a pagina 201. Se è presente un database non crittografato e desiderate usare la crittografia in quel database, potete creare un nuovo database crittografato e copiare i dati e la struttura delle tabelle esistenti nel nuovo database. La creazione di un database crittografato è pressoché identica a quella di un database non crittografato, come descritto in “Creazione di un database” a pagina 172. Create innanzitutto un'istanza SQLConnection che rappresenta la connessione al database. Create il database chiamando il metodo open() o openAsync() dell'oggetto SQLConnection, specificando come posizione del database un file ancora inesistente. La sola differenza quando create un database crittografato consiste nel fornire un valore per il parametro encryptionKey (il quinto parametro del metodo open() e il sesto parametro del metodo openAsync()). Un valore valido per il parametro encryptionKey è un oggetto ByteArray contenente esattamente 16 byte. Nell'esempio riportato di seguito viene illustrata la creazione di un database crittografato che viene aperto in modalità di esecuzione asincrona. Per semplicità, in questo esempio la chiave di crittografia è hardcoded nel codice dell'applicazione. Questa tecnica è tuttavia sconsigliata, non essendo sicura. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 199 Utilizzo dei database SQL locali import import import import import flash.data.SQLConnection; flash.data.SQLMode; flash.events.SQLErrorEvent; flash.events.SQLEvent; flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, errorHandler); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); var encryptionKey:ByteArray = new ByteArray(); encryptionKey.writeUTFBytes("Some16ByteString"); // This technique is not secure! conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey); function openHandler(event:SQLEvent):void { trace("the database was created successfully"); } function errorHandler(event:SQLErrorEvent):void { trace("Error message:", event.error.message); trace("Details:", event.error.details); } Nell'esempio riportato di seguito viene illustrata la creazione di un database crittografato che viene aperto in modalità di esecuzione sincrona. Per semplicità, in questo esempio la chiave di crittografia è hardcoded nel codice dell'applicazione. Questa tecnica è tuttavia sconsigliata, non essendo sicura. import flash.data.SQLConnection; import flash.data.SQLMode; import flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); var encryptionKey:ByteArray = new ByteArray(); encryptionKey.writeUTFBytes("Some16ByteString"); // This technique is not secure! try { conn.open(dbFile, SQLMode.CREATE, false, 1024, encryptionKey); trace("the database was created successfully"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); } Per un esempio che illustra un metodo consigliato per generare una chiave di crittografia, consultate “Esempio: Generazione e uso di una chiave di crittografia.” a pagina 203. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 200 Utilizzo dei database SQL locali Connessione a un database crittografato Come per la creazione di un database crittografato, la procedura per aprire una connessione a un database crittografato è simile a quella per un database non crittografato. Tale procedura è descritta più dettagliatamente in “Connessione a un database” a pagina 175. Utilizzate il metodo open() per aprire una connessione in modalità di esecuzione sincrona oppure il metodo openAsync() per aprire una connessione in modalità di esecuzione asincrona. La sola differenza è data dal fatto che quando aprite un database crittografato dovete specificare il valore corretto per il parametro encryptionKey (il quinto parametro del metodo open() e il sesto parametro del metodo openAsync()). Se la chiave di crittografia specificata non è corretta, si verifica un errore. Per il metodo open(), viene generata un'eccezione SQLError. Per il metodo openAsync(), l'oggetto SQLConnection in via un evento SQLErrorEvent, la cui proprietà error contiene un oggetto SQLError. In entrambi i casi, l'oggetto SQLError generato dall'eccezione presenta il valore 3138 della proprietà errorID. Questo ID errore corrisponde al messaggio di errore "File opened is not a database file" (Il file aperto non è un file di database). Nell'esempio riportato di seguito viene illustrata l'apertura di un database crittografato in modalità di esecuzione asincrona. Per semplicità, in questo esempio la chiave di crittografia è hardcoded nel codice dell'applicazione. Questa tecnica è tuttavia sconsigliata, non essendo sicura. import import import import import flash.data.SQLConnection; flash.data.SQLMode; flash.events.SQLErrorEvent; flash.events.SQLEvent; flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, errorHandler); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); var encryptionKey:ByteArray = new ByteArray(); encryptionKey.writeUTFBytes("Some16ByteString"); // This technique is not secure! conn.openAsync(dbFile, SQLMode.UPDATE, null, false, 1024, encryptionKey); function openHandler(event:SQLEvent):void { trace("the database opened successfully"); } function errorHandler(event:SQLErrorEvent):void { if (event.error.errorID == 3138) { trace("Incorrect encryption key"); } else { trace("Error message:", event.error.message); trace("Details:", event.error.details); } } Nell'esempio riportato di seguito viene illustrata l'apertura di un database crittografato in modalità di esecuzione sincrona. Per semplicità, in questo esempio la chiave di crittografia è hardcoded nel codice dell'applicazione. Questa tecnica è tuttavia sconsigliata, non essendo sicura. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 201 Utilizzo dei database SQL locali import flash.data.SQLConnection; import flash.data.SQLMode; import flash.filesystem.File; var conn:SQLConnection = new SQLConnection(); var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db"); var encryptionKey:ByteArray = new ByteArray(); encryptionKey.writeUTFBytes("Some16ByteString"); // This technique is not secure! try { conn.open(dbFile, SQLMode.UPDATE, false, 1024, encryptionKey); trace("the database was created successfully"); } catch (error:SQLError) { if (error.errorID == 3138) { trace("Incorrect encryption key"); } else { trace("Error message:", error.message); trace("Details:", error.details); } } Per un esempio che illustra un metodo consigliato per generare una chiave di crittografia, consultate “Esempio: Generazione e uso di una chiave di crittografia.” a pagina 203. Modifica della chiave di crittografia di un database Quando un database è crittografato, potete modificare la relativa chiave di crittografia in un secondo tempo. Per modificare la chiave di crittografia di un database, aprite innanzitutto la connessione al database creando un'istanza SQLConnection e chiamando il relativo metodo open() o openAsync(). Una volta aperta la connessione al database, chiamate il metodo reencrypt() passando la nuova chiave di crittografia come argomento. Come per tutte le operazioni relative al database, il comportamento del metodo reencrypt() varia a seconda che la connessione al database utilizzi la modalità di esecuzione sincrona o asincrona. Se usate il metodo open() per connettervi al database, l'operazione reencrypt() viene eseguita in modo sincrono. Al termine dell'operazione, l'esecuzione prosegue con la riga successiva del codice: var newKey:ByteArray = new ByteArray(); // ... generate the new key and store it in newKey conn.reencrypt(newKey); D'altra parte, se la connessione al database viene aperta tramite il metodo openAsync(), l'operazione reencrypt() viene eseguita in modo asincrono. Se chiamate il metodo reencrypt(), viene iniziato di nuovo il processo di crittografia. Al termine dell'operazione, l'oggetto SQLConnection invia un evento reencrypt. Per determinare quando termina il processo, potete usare un listener di eventi: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 202 Utilizzo dei database SQL locali var newKey:ByteArray = new ByteArray(); // ... generate the new key and store it in newKey conn.addEventListener(SQLEvent.REENCRYPT, reencryptHandler); conn.reencrypt(newKey); function reencryptHandler(event:SQLEvent):void { // save the fact that the key changed } L'operazione reencrypt() viene eseguita in una transazione specifica. Se l'operazione viene interrotta o non riesce (ad esempio, se l'applicazione viene chiusa prima che termini l'operazione) la transazione viene annullata. In tal caso, la chiave di crittografia originale sarà ancora quella valida per il database. Non potete usare il metodo reencrypt() per rimuovere la crittografia da un database. Se passate un valore null o una chiave di crittografia che non è un ByteArray di 16 byte, il metodo reencrypt() restituisce un errore. Considerazioni sull'uso della crittografia con un database Nella sezione “Vari usi di un database crittografato” a pagina 198 vengono illustrati diversi casi in cui è opportuno usare un database crittografato. È evidente che gli scenari di impiego delle diverse applicazioni (inclusi questi e altri) presentano requisiti diversi per quanto riguarda la riservatezza. Il modo in cui progettate l'uso della crittografia nella vostra applicazione svolge un ruolo importante nel controllo del grado di riservatezza dei dati di un database. Se, ad esempio, utilizzate un database crittografato per proteggere i dati personali, anche dagli utenti dello stesso computer, dovete creare una chiave di crittografia per il database di ciascun utente. Per maggiore sicurezza, l'applicazione può generare la chiave dalla password immessa da un utente. La chiave di crittografia basata su una password assicura che qualora un'altra persona fosse in grado di rappresentare l'account di un utente del computer, non potrà comunque accedere ai dati. Da un altro punto di vista della riservatezza, supponete di voler rendere un database leggibile da parte di qualsiasi utente della vostra applicazione, ma non da altre applicazioni. In tal caso, ogni copia installata dell'applicazione deve poter accedere a una chiave di crittografia condivisa. Potete progettare la vostra applicazione, e in particolare la tecnica utilizzata per generare la chiave di crittografia, in base al livello di riservatezza che desiderate per i dati dell'applicazione. Di seguito sono riportati alcuni suggerimenti per la progettazione dei vari livelli di riservatezza dei dati: • Per rendere il database accessibile a tutti gli utenti che accedono all'applicazione su qualsiasi computer, usate un'unica chiave che sia disponibile per tutte le istanze dell'applicazione. La prima volta che l'applicazione viene eseguita, può ad esempio scaricare la chiave di crittografia condivisa da un server usando un protocollo sicuro, come SSL. La chiave può quindi essere salvata nell'archivio locale crittografato per l'uso futuro. In alternativa, crittografate i dati per ogni utente sul computer e sincronizzateli con un archivio dati remoto, ad esempio un server, in modo da consentire la portabilità dei dati. • Per rendere un database accessibile a un singolo utente su qualsiasi computer, generate la chiave di crittografia da un dato segreto dell'utente (ad esempio una password). In particolare, per generare la chiave non usate un valore qualsiasi collegato a un computer specifico (ad esempio un calore memorizzato nell'archivio locale crittografato. In alternativa, crittografate i dati per ogni utente sul computer e sincronizzateli con un archivio dati remoto, ad esempio un server, in modo da consentire la portabilità dei dati. • Per rendere un database accessibile solo a un utente su un solo computer, generate la chiave di crittografia da una password e da un valore salt generato. Per un esempio di questa tecnica, consultate “Esempio: Generazione e uso di una chiave di crittografia.” a pagina 203. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 203 Utilizzo dei database SQL locali Di seguito sono riportate alcune importanti considerazioni aggiuntive da tenere presenti durante la progettazione di un'applicazione che utilizza un database crittografato: • La sicurezza di un sistema è direttamente proporzionale alla sicurezza suo collegamento più debole. Se usate una password immessa dall'utente per generare una chiave di crittografia, considerate la possibilità di imporre una lunghezza minima e delle restrizioni relative alla complessità delle password. Una password breve che utilizza solo caratteri di base può essere individuata velocemente. • Il codice sorgente di un'applicazione AIR viene archiviato sul computer di un utente in formato testo semplice (per il contenuto HTML) o in un formato binario facilmente decompilabile (per il contenuto SWF). Poiché il codice è accessibile, occorre considerare due punti: • Non usate mai una chiave hardcoded nel codice sorgente • Partite sempre dal presupposto che la tecnica usata per generare una chiave di crittografia (ad esempio un generatore di caratteri casuali o un particolare algoritmo di hash) può essere facilmente individuata da un utente malintenzionato • Nella crittografia dei database AIR viene utilizzato AES (Advanced Encryption Standard) in modalità Counter con CCM (CBC-MAC). Questa modalità di crittografia richiede la combinazione di una chiave immessa dall'utente con un valore salt per essere sicura. Per un esempio di questa modalità, consultate “Esempio: Generazione e uso di una chiave di crittografia.” a pagina 203. • Quando decidete di crittografare un database, tutti i file su disco utilizzati dal motore di database assieme al database vengono crittografati. Il motore di database, tuttavia, mantiene alcuni dati temporaneamente in una cache in memoria per migliorare le prestazioni dei tempi di lettura e scrittura delle transazioni. Tutti i dati residenti in memoria non sono crittografati. Se un utente malintenzionato riesce ad accedere alla memoria utilizzata da un'applicazione AIR, ad esempio tramite un debugger, i dati in un database attualmente aperto e non crittografato diventano disponibili. Esempio: Generazione e uso di una chiave di crittografia. Questa applicazione di esempio dimostra una tecnica per la generazione di una chiave di crittografia. Questa applicazione è progettata per fornire il massimo livello di riservatezza e sicurezza per i dati dell'utente. Un aspetto importante relativo alla protezione dei dati privati è rappresentato dalla necessità di chiedere all'utente di immettere una password a ogni connessione dell'applicazione al database. Di conseguenza, come illustrato nell'esempio, un'applicazione che richiede questo livello di privacy non deve mai memorizzare direttamente la chiave di crittografia del database. L'applicazione è composta da due parti: una classe ActionScript che genera una chiave di crittografia (la classe EncryptionKeyGenerator) e un'interfaccia utente di base che dimostra come utilizzare la classe. Per il codice sorgente completo, consultate “Esempio di codice completo per la generazione e l'uso di una chiave di crittografia” a pagina 211. Uso della classe EncryptionKeyGenerator per ottenere una chiave di crittografia sicura La sezione “Nozioni fondamentali sulla classe EncryptionKeyGenerator” a pagina 205 include informazioni dettagliate sulle tecniche utilizzate dalla classe EncryptionKeyGenerator per generare una chiave di crittografia per un database. Non è tuttavia necessario comprendere questi dettagli per utilizzare la classe nell'applicazione. Per utilizzare la classe EncryptionKeyGenerator nell'applicazione, eseguite le operazioni riportate di seguito: 1 La classe EncryptionKeyGenerator è inclusa nel progetto della libreria chiave open source ActionScript 3.0 (as3corelib). Potete scaricare il pacchetto as3corelib che comprende il codice sorgente e la documentazione. Potete inoltre scaricare il SWC o i file del codice sorgente dalla pagina del progetto. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 204 Utilizzo dei database SQL locali 2 Inserite il codice sorgente della classe EncryptionKeyGenerator (o il file SWC di as3corelib) in un percorso accessibile da parte del codice sorgente dell'applicazione. 3 Nel codice sorgente dell'applicazione aggiungete un'istruzione import per la classe EncryptionKeyGenerator. import com.adobe.air.crypto.EncryptionKeyGenerator; 4 Prima del punto in cui il codice crea il database o apre una connessione ad esso, aggiungete codice per creare un'istanza di EncryptionKeyGenerator chiamando il costruttore EncryptionKeyGenerator(). var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); 5 Ottenete una password dall'utente: var password:String = passwordInput.text; if (!keyGenerator.validateStrongPassword(password)) { // display an error message return; } L'istanza di EncryptionKeyGenerator utilizza questa password come base per la chiave di crittografia (mostrata nel passaggio successivo). L'istanza di EncryptionKeyGenerator testa la password in base a determinati requisiti di convalida per le password avanzate. Se la convalida non riesce, si verifica un errore. Come mostrato dal codice di esempio, potete verificare la password a priori chiamando il metodo validateStrongPassword() dell'oggetto EncryptionKeyGenerator. In questo modo potete controllare se la password soddisfa i requisiti minimi delle password avanzate, evitando un errore. 6 Generate la chiave di crittografia dalla password: var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password); Il metodo getEncryptionKey() genera e restituisce la chiave di crittografia (un ByteArray a 16 byte). A questo punto potete utilizzare la chiave di crittografia per creare il nuovo database crittografato o aprire un database esistente. Il metodo getEncryptionKey() richiede un parametro obbligatorio, ovvero la password ottenuta al passaggio 5. Nota: Per garantire il livello massimo di sicurezza e riservatezza dei dati, un'applicazione deve richiedere all'utente di immettere una password per ogni connessione al database. Non memorizzate direttamente la password dell'utente o la chiave di crittografia del database per evitare rischi per la sicurezza. Come dimostrato in questo esempio, è consigliabile che un'applicazione utilizzi la stessa tecnica per derivare la chiave di crittografia dalla password sia per la creazione del database crittografato, che per la successiva connessione ad esso. Il metodo getEncryptionKey() accetta anche un secondo parametro facoltativo, ovvero overrideSaltELSKey. EncryptionKeyGenerator crea un valore casuale (detto salt) che viene utilizzato come parte della chiave di crittografia. Per poter ricreare la chiave di crittografia, il valore salt viene memorizzato nell'archivio locale crittografato (ELS, Encrypted Local Store) dell'applicazione AIR. Per impostazione predefinita, la classe EncryptionKeyGenerator utilizza una determinata stringa come chiave ELS. Sebbene sia improbabile, potrebbe presentarsi un conflitto tra la chiave e un'altra chiave utilizzata dall'applicazione. Anziché utilizzare la chiave predefinita, è consigliabile specificare una chiave ELS personalizzata. Per specificare una chiave personalizzata, passatela come secondo parametro getEncryptionKey(), come illustrato di seguito: var customKey:String = "My custom ELS salt key"; var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password, customKey); 7 Create o aprite il database SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 205 Utilizzo dei database SQL locali Con una chiave di crittografia restituita dal metodo getEncryptionKey(), il codice può creare un nuovo database crittografato o tentare di aprire il database crittografato esistente. In entrambi i casi, utilizzate il metodo open() o openAsync() della classe SQLConnection, come descritto in “Creazione di un database crittografato” a pagina 198 e “Connessione a un database crittografato” a pagina 200. In questo esempio, l'applicazione è progettata per aprire il database in modalità di esecuzione asincrona. Il codice imposta il listener di eventi appropriato e chiama il metodo openAsync(), passando la chiave di crittografia come argomento finale: conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, openError); conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey); Nei metodi listener, il codice rimuove le registrazioni del listener di eventi. Visualizza quindi un messaggio di stato per indicare se il database è stato creato o aperto oppure se si è verificato un errore. La parte più significativa di questi gestori di eventi è il metodo openError(). In questo metodo un istruzione if verifica se il database esiste (ovvero se il codice tenta di connettersi a un database esistente) e se l'ID dell'errore corrisponde alla costante EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID. Se si verificano entrambe queste condizioni, la password immessa dall'utente probabilmente non è corretta. In alternativa, il file specificato potrebbe non essere un file di database. Di seguito è riportato il codice che verifica l'ID dell'errore: if (!createNewDB && event.error.errorID == EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID) { statusMsg.text = "Incorrect password!"; } else { statusMsg.text = "Error creating or opening database."; } Per il codice completo dei listener di eventi di esempio, consultate “Esempio di codice completo per la generazione e l'uso di una chiave di crittografia” a pagina 211. Nozioni fondamentali sulla classe EncryptionKeyGenerator Non è necessario comprendere il funzionamento intrinseco della classe EncryptionKeyGenerator per utilizzarla per la creazione di una chiave di crittografia sicura per il database dell'applicazione. Il processo di utilizzo della classe è illustrato in “Uso della classe EncryptionKeyGenerator per ottenere una chiave di crittografia sicura” a pagina 203. Questi concetti potrebbero tuttavia risultare utili per comprendere le tecniche utilizzate dalla classe nel caso in cui, ad esempio, desideriate adattare la classe o incorporarne alcune tecniche per situazioni che necessitano un livello diverso di riservatezza dei dati. La classe EncryptionKeyGenerator è inclusa nel progetto della libreria di base ActionScript 3.0 open source (as3corelib). Potete scaricare il pacchetto as3corelib che include codice sorgente e documentazione. Dal sito del progetto potete inoltre visualizzare il codice sorgente o scaricarlo per seguire direttamente le spiegazioni. Quando il codice crea un'istanza di EncryptionKeyGenerator e ne chiama il metodo getEncryptionKey(), vengono eseguite diverse operazioni per garantire che l'accesso ai dati possa essere eseguito solo dall'utente che dispone dei diritti appropriati. Il processo per generare una chiave di crittografia da una password immessa dall'utente prima della creazione del database è analogo a quello di ricreazione della chiave di crittografia per l'apertura del database. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 206 Utilizzo dei database SQL locali Ottenimento e convalida di una password complessa Quando il codice chiama il metodo getEncryptionKey(), viene passata una password come parametro. La password viene usata come base per la chiave di crittografia. Usando delle informazioni che solo l'utente conosce, questo metodo di progettazione assicura che solo l'utente che conosce la password possa accedere ai dati nel database. Anche se un utente malintenzionato dovesse accedere all'account dell'utente sul computer, non potrà accedere al database senza conoscere la password. Per la massima sicurezza, l'applicazione non memorizza mai la password. Nell'applicazione di esempio passwordInput è il nome di istanza di un componente TextInput in cui l'utente immette la password. Anziché modificare direttamente il valore text del componente, l'applicazione copia la password in una variabile denominata password. var password:String = passwordInput.text; L'applicazione di esempio crea quindi un'istanza di EncryptionKeyGenerator e ne chiama il metodo getEncryptionKey(), utilizzando la variabile password come argomento: var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password); La prima operazione eseguita dalla classe EncryptionKeyGenerator quando viene chiamato il metodo getEncryptionKey() è quello di controllare la password immessa dall'utente per assicurare che soddisfi i requisiti di complessità delle password. In questo caso, la lunghezza della password deve essere compresa tra 8 e 32 caratteri. Deve contenere sia lettere maiuscole che minuscole e almeno un numero o un simbolo. L'espressione regolare che controlla questo schema è definita come costante con nome strongPasswordPattern: private static const STRONG_PASSWORD_PATTERN:RegExp = /(?=^.{8,32}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; Il codice che verifica la password si trova nel metodo validateStrongPassword() della classe EncryptionKeyGenerator. Di seguito è riportato il codice: public function vaidateStrongPassword(password:String):Boolean { if (password == null || password.length <= 0) { return false; } return STRONG_PASSWORD_PATTERN.test(password)) } Il metodo getEncryptionKey() chiama il metodo validateStrongPassword() e, se la password non è valida, genera un'eccezione. Il metodo validateStrongPassword() è un metodo pubblico, pertanto il codice può verificare una password senza chiamare il metodo getEncryptionKey() ed evitare che venga generato un errore. Espandere la password a 256 bit In una fase successiva del processo, è richiesto che la lunghezza della password sia di 256 bit. Anziché richiedere a ogni utente di immettere una password della lunghezza esatta di 256 bit (32 caratteri), il codice crea una password più lunga ripetendo i caratteri in essa contenuti. Il metodo getEncryptionKey() chiama il metodo concatenatePassword() per eseguire l'operazione di creazione della password lunga. var concatenatedPassword:String = concatenatePassword(password); Di seguito è riportato il codice del metodo concatenatePassword(): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 207 Utilizzo dei database SQL locali private function concatenatePassword(pwd:String):String { var len:int = pwd.length; var targetLength:int = 32; if (len == targetLength) { return pwd; } var repetitions:int = Math.floor(targetLength / len); var excess:int = targetLength % len; var result:String = ""; for (var i:uint = 0; i < repetitions; i++) { result += pwd; } result += pwd.substr(0, excess); return result; } Se la password è inferiore a 256 bit, il codice concatena più istanze della password per raggiungere 256 bit. Se la lunghezza non corrisponde esattamente, l'ultima parte ripetuta viene abbreviata per ottenere esattamente 256 bit. Generare o recuperare un valore salt di 256 bit Il prossimo passaggio consiste nell'ottenere un valore salt di 256 bit che in un passaggio successivo viene combinato con la password. Un valore salt è un valore casuale aggiunto o combinato con un valore immesso dall'utente per formare una password. L'uso di un valore salt con una password assicura che, anche se un utente sceglie una parola reale o un termine comune, la combinazione di password più salt usata dal sistema sia un valore casuale. Questo metodo casuale aiuta a proteggere dagli attacchi con dizionario, in cui un utente malintenzionato utilizza un elenco di parole per tentare di individuare la password. Inoltre, quando si genera il valore salt e lo si memorizza nell'archivio locale crittografato, questo viene collegato all'account dell'utente nel computer in cui si trova il file di database. Se l'applicazione chiama il metodo getEncryptionKey() per la prima volta, il codice crea un valore salt casuale di 256 bit. In caso contrario, il codice carica il valore salt dall'archivio locale crittografato. Il valore salt viene memorizzato in una variabile denominata salt. Il codice determina se il valore salt è già stato creato tentando di caricarlo dall'archivio locale crittografato: var salt:ByteArray = EncryptedLocalStore.getItem(saltKey); if (salt == null) { salt = makeSalt(); EncryptedLocalStore.setItem(saltKey, salt); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 208 Utilizzo dei database SQL locali Se il codice crea un nuovo valore salt, il metodo makeSalt() genera un valore casuale a 256 bit. Poiché il valore viene memorizzato nell'archivio locale crittografato, viene generato come un oggetto ByteArray. Il metodo makeSalt() usa il metodo Math.random() per generare il valore in modo casuale. Il metodo Math.random() non può generare 256 bit contemporaneamente. Il codice usa invece un ciclo per chiamare Math.random() otto volte. Ogni volta, viene generato un valore uint casuale compreso tra 0 e 4294967295 (il valore uint massimo). Il valore uint viene usato per praticità, in quanto utilizza esattamente 32 bit. Mediante la scrittura di otto valori uint nell'oggetto ByteArray, viene generato un valore di 256 bit. Il codice seguente si riferisce al metodo makeSalt(): private function makeSalt():ByteArray { var result:ByteArray = new ByteArray; for (var i:uint = 0; i < 8; i++) { result.writeUnsignedInt(Math.round(Math.random() * uint.MAX_VALUE)); } return result; } Quando il codice salva il valore salt nell'archivio locale crittografato o lo recupera da esso, necessità di una chiave String in cui salvare il valore. Il valore salt non può essere recuperato se la chiave non è nota. Il tal caso, la chiave di crittografia non può essere ricreata ogni volta per riaprire il database. Per impostazione predefinita, EncryptionKeyGenerator utilizza una chiave dell'archivio locale crittografato predefinita che viene definita nella costante SALT_ELS_KEY. Anziché utilizzare la chiave predefinita, il codice dell'applicazione può anche specificare una chiave dell'archivio locale crittografato da utilizzare nella chiamata al metodo getEncryptionKey(). La chiave dell'archivio locale crittografato salt predefinita o specificata dall'applicazione viene memorizzata in una variabile denominata saltKey che viene utilizzata nelle chiamate a EncryptedLocalStore.setItem() e EncryptedLocalStore.getItem(), come illustrato nel listato di codice precedente. Combinazione della password a 256 bit e del valore salt mediante l'operatore XOR Il codice a questo punto dispone di una password a 256 bit e di un valore salt a 256 bit. Utilizza quindi un'operazione XOR bit a bit per combinare il valore salt e la password concatenata in un solo valore. In realtà questa tecnica consente di creare una password a 256 bit composta da caratteri compresi nell'intera gamma dei caratteri possibili. Questa situazione si verifica anche se la password effettiva immessa è in genere composta principalmente da caratteri alfanumerici. La maggiore casualità offre il vantaggio di ampliare la gamma delle password possibili senza che l'utente debba immettere una password complessa lunga. Il risultato dell'operazione XOR è memorizzato nella variabile unhashedKey. Il processo effettivo di esecuzione di un'operazione XOR bit a bit sui due valori viene seguito nel metodo xorBytes(): var unhashedKey:ByteArray = xorBytes(concatenatedPassword, salt); L'operatore XOR bit a bit (^) accetta due valori uint e restituisce un valore uint (un valore uint contiene 32 bit). I valori di input passati come argomenti al metodo xorBytes() sono un valore String (la password) e un ByteArray (il salt). Il codice usa quindi un ciclo per estrarre 32 bit alla volta da ogni input da combinare tramite l'operatore XOR. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 209 Utilizzo dei database SQL locali private function xorBytes(passwordString:String, salt:ByteArray):ByteArray { var result:ByteArray = new ByteArray(); for (var i:uint = 0; i < 32; i += 4) { // ... } return result; } All'interno del ciclo vengono estratti i primi 32 bit (4 byte) dal parametro passwordString. Questi bit vengono estratti e convertiti in un valore uint (o1) mediante un processo composto da due parti. Il metodo charCodeAt() ottiene in primo luogo il valore numerico di ogni carattere. Tale valore viene quindi spostato nella posizione corretta del valore uint mediante l'operatore di spostamento a sinistra bit a bit (<<) e quindi il valore spostato viene aggiunto a o1. Il primo carattere (i), ad esempio, viene convertito nei primi 8 bit usando l'operatore di spostamento a sinistra bit a bit (<<) per spostare i bit verso sinistra di 24 bit e assegnando tale valore a o1. Il secondo carattere (i + 1) viene convertito nei secondi 8 bit spostando il relativo valore verso sinistra di 16 bit e aggiungendo il risultato a o1. I valori del terzo e quarto carattere vengono aggiunti nello stesso modo. // ... // Extract 4 bytes from the password string and convert to a uint var o1:uint = passwordString.charCodeAt(i) << 24; o1 += passwordString.charCodeAt(i + 1) << 16; o1 += passwordString.charCodeAt(i + 2) << 8; o1 += passwordString.charCodeAt(i + 3); // ... La variabile o1 contiene ora 32 bit del parametro passwordString. A questo punto, vengono estratti 32 bit dal parametro salt mediante la chiamata del relativo metodo readUnsignedInt(). I 32 bit vengono memorizzati nella variabile uint o2. // ... salt.position = i; var o2:uint = salt.readUnsignedInt(); // ... Infine, i due valori a 32 bit (uint) vengono combinati mediante l'operatore XOR e il risultato viene scritto in un ByteArray denominato result. // ... var xor:uint = o1 ^ o2; result.writeUnsignedInt(xor); // ... Una volta completato il ciclo, viene restituito l'oggetto ByteArray contenente il risultato di XOR. // ... } return result; } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 210 Utilizzo dei database SQL locali Hash della chiave In seguito alla combinazione della password concatenata e del valore salt, il passaggio successivo consiste nel garantire maggiore sicurezza per il valore mediante hashing, usando l'algoritmo di hash SHA-256. L'hash del valore ne rende più difficile la decodificazione da parte di un utente malintenzionato. Il codice, a questo punto, dispone di un ByteArray denominato unhashedKey che include la password concatenata combinata con il valore salt. Il progetto della libreria chiave di ActionScript 3.0 (as3corelib) comprende una classe SHA256 nel pacchetto com.adobe.crypto. Il metodo SHA256.hashBytes() esegue quindi un hash SHA-256 su un ByteArray e restituisce un valore String contenente il risultato hash a 256 bit come numero esadecimale. La classe EncryptionKeyGenerator utilizza la classe SHA256 per l'hash della chiave: var hashedKey:String = SHA256.hashBytes(unhashedKey); Estrarre la chiave di crittografia dall'hash La chiave di crittografia deve essere un ByteArray con una lunghezza esattamente di 16 byte (128 bit). Il risultato dell'algoritmo di hash SHA-256 ha sempre una lunghezza di 256 bit. Di conseguenza, il passaggio finale consiste nel selezionare 128 bit dal risultato hash da utilizzare come chiave di crittografia effettiva. Nella classe EncryptionKeyGenerator il codice riduce la chiave a 128 bit chiamando il metodo generateEncryptionKey() e restituisce il risultato di questo metodo come risultato del metodo getEncryptionKey(): var encryptionKey:ByteArray = generateEncryptionKey(hashedKey); return encryptionKey; Non è necessario usare i primi 128 bit come chiave di crittografia. Potete selezionare un intervallo di bit a partire da un punto arbitrario, selezionare un bit ogni due oppure eseguire la selezione in modo diverso. L'aspetto importante è che il codice selezioni 128 bit distinti e che vengano usati ogni volta gli stessi 128 bit. In questo caso il metodo generateEncryptionKey() usa come chiave di crittografia l'intervallo di bit a partire dal diciottesimo byte. Come accennato in precedenza, la classe SHA256 restituisce un valore String contenente un hash di 256 bit come numero esadecimale. Un singolo blocco di 128 bit contiene troppi byte da aggiungere contemporaneamente a un ByteArray. Di conseguenza, il codice usa un ciclo for per estrarre i caratteri da un valore String esadecimale, convertirli in valori numerici effettivi e aggiungerli al ByteArray. La stringa risultante SHA-256 è lunga 64 caratteri. Un intervallo a 128 bit equivale a 32 caratteri nel valore String, quindi ogni carattere rappresenta 4 bit. L'incremento di dati più piccolo che potete aggiungere a un ByteArray è un byte (8 bit), che equivale a due caratteri nell'oggetto String hash. Di conseguenza, il ciclo effettua il conteggio da 0 a 31 (32 caratteri) in incrementi di 2 caratteri. All'interno del ciclo, il codice determina innanzitutto la posizione iniziale per la coppia di caratteri corrente. Poiché l'intervallo desiderato inizia in corrispondenza del carattere nella posizione di indice 17 (il 18esimo byte), la variabile position viene assegnata al valore iterator corrente (i) più 17. Il codice usa il metodo substr() dell'oggetto String per estrarre i due caratteri nella posizione corrente. Tali caratteri vengono archiviati nella variabile hex. Il codice usa quindi il metodo parseInt() per convertire l'oggetto String hex in un valore integer decimale e memorizza tale valore nella variabile int byte. Infine, aggiunge il valore presente in byte al ByteArray result usando il relativo metodo writeByte(). Al termine del ciclo, il ByteArray result contiene 16 byte ed è pronto per essere usato come chiave di crittografia di un database. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 211 Utilizzo dei database SQL locali private function generateEncryptionKey(hash:String):ByteArray { var result:ByteArray = new ByteArray(); for (var i:uint = 0; i < 32; i += 2) { var position:uint = i + 17; var hex:String = hash.substr(position, 2); var byte:int = parseInt(hex, 16); result.writeByte(byte); } return result; } Esempio di codice completo per la generazione e l'uso di una chiave di crittografia Di seguito è riportato il codice completo per l'applicazione di esempio "Generazione e uso di una chiave di crittografia". Il codice è composto da due parti. Nell'esempio viene utilizzata la classe EncryptionKeyGenerator per creare una chiave di crittografia da una password. La classe EncryptionKeyGenerator è inclusa nel progetto della libreria chiave open source ActionScript 3.0 (as3corelib). Potete scaricare il pacchetto as3corelib che comprende il codice sorgente e la documentazione. Potete inoltre scaricare il SWC o i file del codice sorgente dalla pagina del progetto. Il file FLA dell'applicazione contiene il codice sorgente di un'applicazione semplice che crea o apre una connessione a un database crittografato. Per il file FLA sono disponibili quattro componenti sullo stage: Nome istanza Tipo di componente Descrizione instructions Label Contiene le istruzioni fornite all'utente passwordInput TextInput Campo di input in cui l'utente immette la password openButton Button Pulsante su cui l'utente fa clic dopo aver immesso la password statusMsg Label Visualizza messaggi di stato (operazione riuscita o non riuscita). Il codice dell'applicazione è definito in un fotogramma chiave sul fotogramma 1 della linea temporale principale. Di seguito è riportato il codice dell'applicazione: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 212 Utilizzo dei database SQL locali import com.adobe.air.crypto.EncryptionKeyGenerator; const dbFileName:String = "encryptedDatabase.db"; var dbFile:File; var createNewDB:Boolean = true; var conn:SQLConnection; init(); // ------- Event handling ------function init():void { passwordInput.displayAsPassword = true; openButton.addEventListener(MouseEvent.CLICK, openConnection); statusMsg.setStyle("textFormat", new TextFormat(null, null, 0x990000)); conn = new SQLConnection(); dbFile = File.applicationStorageDirectory.resolvePath(dbFileName); if (dbFile.exists) { createNewDB = false; instructions.text = "Enter your database password to open the encrypted database."; openButton.label = "Open Database"; } else { instructions.text = "Enter a password to create an encrypted database. The next time you open the application, you will need to re-enter the password to open the database again."; openButton.label = "Create Database"; } } function openConnection(event:MouseEvent):void { var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); var password:String = passwordInput.text; if (password == null || password.length <= 0) { statusMsg.text = "Please specify a password."; return; } if (!keyGenerator.validateStrongPassword(password)) { statusMsg.text = "The password must be 8-32 characters long. It must contain at least one lowercase letter, at least one uppercase letter, and at least one number or symbol."; return; } passwordInput.text = ""; passwordInput.enabled = false; openButton.enabled = false; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 213 Utilizzo dei database SQL locali var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password); conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, openError); conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey); } function openHandler(event:SQLEvent):void { conn.removeEventListener(SQLEvent.OPEN, openHandler); conn.removeEventListener(SQLErrorEvent.ERROR, openError); statusMsg.setStyle("textFormat", new TextFormat(null, null, 0x009900)); if (createNewDB) { statusMsg.text = "The encrypted database was created successfully."; } else { statusMsg.text = "The encrypted database was opened successfully."; } } function openError(event:SQLErrorEvent):void { conn.removeEventListener(SQLEvent.OPEN, openHandler); conn.removeEventListener(SQLErrorEvent.ERROR, openError); if (!createNewDB && event.error.errorID == EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID) { statusMsg.text = "Incorrect password!"; } else { statusMsg.text = "Error creating or opening database."; } } Strategie per l'utilizzo dei database SQL Esistono vari modi in cui le applicazioni possono accedere ai database SQL locali ed utilizzarli. Dal momento che il design delle applicazioni può variare dal punto di vista dell'organizzazione del codice, della sequenza e della sincronia con cui le operazioni vengono eseguite, e così via, le tecniche scelte possono avere un notevole effetto sulla facilità o meno di sviluppo dell'applicazione. Ad esempio, possono influire sulla facilità di modifica dell'applicazione nel caso si desideri aggiornarla in futuro e anche sulle sue prestazioni percepite dal punto di vista dell'utente. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 214 Utilizzo dei database SQL locali Distribuzione di database con dati già inseriti Quando si usa un database SQL AIR locale nell'applicazione, questa presuppone che il database abbia una certa struttura composta da tabelle, colonne e così via. Alcune applicazioni presuppongono inoltre che nel file del database siano già presenti certi dati. Un modo per essere certi che il database abbia la struttura corretta è quello di creare il database stesso all'interno del codice dell'applicazione. Quando l'applicazione lo carica, controlla se in una particolare posizione è presente il relativo file di database. Se tale file non esiste, l'applicazione esegue un set di comandi in modo da creare il file e la struttura del database e inserire nelle tabelle i dati iniziali. Il codice che crea il database e le relative tabelle è spesso complesso e, anche se viene utilizzato una sola volta in tutta la durata di installazione dell'applicazione, ne aumenta le dimensioni e la complessità. Come soluzione alternativa alla creazione del database, della struttura e dei dati tramite il programma, è possibile distribuire insieme all'applicazione un database in cui sono già stati inseriti i dati. Per distribuire un database predefinito è necessario includere il relativo file nel pacchetto AIR dell'applicazione. Come tutti i file inclusi nel pacchetto AIR, il file di database di corredo viene installato della directory dell'applicazione (cioè la directory rappresentata dalla proprietà File.applicationDirectory). I file di quella directory, tuttavia, sono di sola lettura. Utilizzate il file del pacchetto AIR come database "modello". La prima volta che l'utente esegue l'applicazione, copiate il file del database originale nella directory di memorizzazione dell'utente, o in una posizione diversa, ed utilizzate tale database nell'applicazione. Miglioramento delle prestazioni del database In Adobe AIR sono incorporate diverse tecniche che consentono di migliorare le prestazioni delle operazioni di database nell'applicazione. Oltre alle tecniche qui descritte, anche il modo in cui sono scritte le istruzioni SQL può influire sulle prestazioni del database. Vi sono spesso vari modi di scrivere l'istruzione SQL SELECT per recuperare un certo set di risultati e, in alcuni casi, metodi diversi richiedono livelli diversi di impegno del motore del database. Questi aspetti del miglioramento delle prestazioni dei database, cioè la progettazione delle istruzioni SQL in modo da migliorare le prestazioni, non sono trattati nella documentazione di Adobe AIR. Utilizzo di una sola istanza SQLStatement in ciascuna istruzione SQL Prima dell'esecuzione di qualsiasi istruzione SQL, il runtime la prepara (compila) al fine di determinare i passi da effettuare internamente per eseguirla. Quando si chiama SQLStatement.execute() su un'istanza SQLStatement che non è mai stata eseguita in precedenza, l'istruzione viene preparata automaticamente prima dell'esecuzione. In occasione delle successive chiamate del metodo execute(), se la proprietà SQLStatement.text non ha subito modifiche, l'istruzione risulta ancora preparata e, di conseguenza, viene eseguita più rapidamente. Per ottimizzare il riutilizzo delle istruzioni, se tra le diverse esecuzioni delle istruzioni i valori devono essere modificati, utilizzate i parametri per personalizzare le istruzioni. I parametri si specificano tramite la proprietà di matrice associativa SQLStatement.parameters. A differenza della modifica della proprietà text dell'istanza SQLStatement, se si modificano i valori dei parametri delle istruzioni, non sarà necessario che il runtime prepari di nuovo le istruzioni. Per ulteriori informazioni sull'utilizzo dei parametri nelle istruzioni, consultate “Utilizzo dei parametri nelle istruzioni” a pagina 178. Poiché la preparazione e l'esecuzione delle istruzioni sono operazioni che possono richiedere molte risorse, è consigliabile precaricare i dati iniziali e poi eseguire le altre istruzioni in background. Caricate per primi i dati di cui l'applicazione ha necessità e, quando le operazioni iniziali di avvio dell'applicazione sono state completate oppure in occasione di un altro momento di basso utilizzo, eseguite le altre istruzioni. Ad esempio, se l'applicazione non accede affatto al database quando deve visualizzare la schermata iniziale, attendete che la schermata appaia e poi aprite la SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 215 Utilizzo dei database SQL locali connessione al database; infine, create le istanze SQLStatement ed eseguitene il maggior numero possibile. In alternativa, facciamo conto che, al momento dell'avvio, l'applicazione visualizzi immediatamente dei dati, ad esempio i risultati di una determinata query. In tal caso, procedete all'esecuzione dell'istanza SQLStatement relativa a quella query. Dopo il caricamento e la visualizzazione dei dati iniziali, create le istanze SQLStatement per le altre operazioni di database e, se possibile, eseguite altre istruzioni necessarie in un secondo momento. Quando si riutilizza un'istanza SQLStatement, l'applicazione deve tenere un riferimento a tale istanza dopo che essa è stata preparata. Per tenere un riferimento all'istanza, dichiarate la variabile come variabile di classe-ambito invece che di funzione-ambito. Un modo consigliabile di farlo è di strutturare l'applicazione in modo tale che l'istruzione SQL sia conteuta in una sola classe. Anche i gruppi di istruzioni che vengono eseguite unitamente possono essere contenuti in una sola classe. Se si definisce l'istanza o le istanze SQLStatement come variabili elemento della classe, esse permangono per tutto il tempo in cui l'istanza della classe che le contiene continua a esistere nell'applicazione. Come minimo, è possibile semplicemente definire una variabile che contiene l'istanza SQLStatement al di fuori di una funzione, in modo che tale istanza permanga in memoria. Ad esempio, dichiarate l'istanza SQLStatement come variabile elemento in una classe ActionScript o come variabile senza funzione in un file JavaScript. È poi possibile impostare i valori dei parametri dell'istruzione e chiamare il relativo metodo execute() quando si desidera eseguire effettivamente la query. Raggruppamento di più operazioni in una singola transazione Supponiamo di stare eseguendo un gran numero di istruzioni SQL che implicano l'aggiunta o la modifica di dati (cioè istruzioni INSERT o UPDATE). È possibile ottenere un notevole aumento delle prestazioni eseguendo tutte le istruzioni nell'ambito di una transazione esplicita. Se non si dà inizio esplicitamente a una transazione, ciascuna istruzione viene eseguita in una propria transazione individuale creata automaticamente. Dopo che ciascuna transazione (ciascuna istruzione) finisce di essere eseguita, il runtime memorizza i dati risultanti nel file del database sul disco. Consideriamo invece ora gli sviluppi a seguito della creazione esplicita di una transazione e dell'esecuzione delle istruzioni nell'ambito di tale transazione. Il runtime apporta tutte le modifiche in memoria, poi le scrive tutte insieme, contemporaneamente, nel file del database una volta che è stato eseguito il commit della transazione. La scrittura dei dati sul disco rappresenta di solito la fase dell'operazione che richiede più tempo. Di conseguenza, una sola operazione di scrittura su disco, invece che un'operazione di scrittura per ciascuna istruzione SQL, consente un notevole miglioramento delle prestazioni. Riduzione al minimo dell'elaborazione del runtime Le tecniche descritte qui di seguito possono ridurre l'impegno eccessivo del motore del database e migliorare le prestazioni delle applicazioni. • Specificate sempre in modo esplicito nelle istruzioni il nome dei database insieme al nome delle tabelle. Utilizzate “main” se si tratta del database principale. Ad esempio, utilizzate SELECT employeeId FROM main.employees invece che SELECT employeeId FROM employees. Se si specifica il nome del database esplicitamente si evita che il runtime sia costretto a controllare tutti i database uno dopo l'altro per trovare la tabella corrispondente. Si evita inoltre la possibilità che il runtime scelga il database errato. Seguite questa regola anche se la SQLConnection è connessa a un solo database, perché dietro le quinte la SQLConnection è connessa anche ad un database temporaneo accessibile tramite istruzioni SQL. • Specificate sempre in modo esplicito il nome delle colonne nelle istruzioni SELECT e INSERT. • Interrompete le righe restituite dalle istruzioni SELECT se è stato recuperato un gran numero di righe: consultate “Recupero parziale dei risultati SELECT” a pagina 185. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 216 Utilizzo dei database SQL locali Assenza di modifiche allo schema Se possibile, evitate di modificare lo schema (cioè la struttura delle tabelle) dopo che sono stati aggiunti dati nelle tabelle del database. Di norma, i file di database sono strutturati in modo da elencare le definizioni delle tabelle all'inizio. Quando si apre la connessione al database, il runtime carica tali definizioni. Quando si aggiungono dati alle tabelle del database, essi vengono aggiunti al file di seguito ai dati di definizione delle tabelle. Tuttavia, se si apportano modifiche allo schema (ad esempio aggiungendo una colonna a una tabella o aggiungendo una nuova tabella), i nuovi dati di definizione della tabella vengono mischiati nel file del database con quelli della tabella. Se i dati di definizione della tabella non si trovano tutti all'inizio del file del database, occorre più tempo per aprire la connessione al database stesso, in quanto il runtime deve leggere i dati di definizione della tabella da parti diverse del file. Se risulta effettivamente necessario apportare modifiche allo schema, è possibile chiamare il metodo SQLConnection.compact() dopo aver portato a termine le modifiche. Questa operazione ristruttura il file del database in modo da riunire in un solo blocco contiguo all'inizio del file i dati di definizione delle tabelle. Tuttavia, l'operazione compact() può richiedere molto tempo, specialmente man mano che il file del database aumenta di dimensioni. Metodi efficaci per l'utilizzo dei database SQL L'elenco seguente illustra una serie di tecniche che possono essere utilizzate al fine di migliorare le prestazioni, la protezione e la comodità di manutenzione delle applicazioni quando si utilizzano i database SQL locali. Per ulteriori tecniche di miglioramento delle applicazioni di database, consultate “Miglioramento delle prestazioni del database” a pagina 214. Creazione preventiva delle connessioni al database Anche se l'applicazione non esegue nessuna istruzione all'atto del primo caricamento, per evitare ritardi quando si eseguono le istruzioni, create un'istanza dell'oggetto SQLConnection e chiamate il relativo metodo open() oppure openAsync() in anticipo, ad esempio dopo l'avvio iniziale dell'applicazione. Consultate “Connessione a un database” a pagina 175. Riutilizzo delle connessioni al database Se si accede a un determinato database durante tutto il periodo in cui l'applicazione è in esecuzione, è consigliabile tenere un riferimento all'istanza SQLConnection e riutilizzarla in tutta l'applicazione, invece che chiudere e riaprire la connessione. Consultate “Connessione a un database” a pagina 175. Preferenza della modalità di esecuzione asincrona Quando si scrive il codice di accesso ai dati si può avere la tentazione di eseguire le operazioni in modo sincrono invece che asincrono, poiché l'utilizzo delle operazioni sincrone richiede spesso la scrittura di codice più breve e meno complesso. Tuttavia, come descritto nella sezione “Utilizzo delle operazioni di database sincrone e asincrone” a pagina 193, le operazioni sincrone possono avere sulle prestazioni un effetto negativo che appare evidente agli utenti e rende meno piacevole la loro esperienza dell'uso dell'applicazione. Il tempo impiegato da ciascuna operazione varia a seconda dell'operazione in oggetto e soprattutto a seconda della quantità di dati da essa interessata. Ad esempio, un'istruzione SQL INSERT che aggiunga una sola riga al database impiega meno tempo di un'istruzione SELECT che recuperi migliaia di righe di dati. Quando si usa la modalità di esecuzione sincrona per eseguire più operazioni, però, esse sono di solito legate l'una all'altra in una serie; quindi, anche se il tempo impiegato da ciascuna operazione è molto breve, l'applicazione si blocca comunque finché tutta la serie di operazioni sincrone non è stata eseguita. Il tempo totale impiegato da più operazioni legate in serie può addirittura bloccare completamente l'applicazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 217 Utilizzo dei database SQL locali Utilizzate normalmente la modalità asincrona, specialmente nel caso di operazioni che coinvolgono un gran numero di righe. Esiste una tecnica per la divisione in gruppi dell'elaborazione dei set di risultati di grandi dimensioni delle istruzioni SELECT ed è descritta nella sezione “Recupero parziale dei risultati SELECT” a pagina 185. La tecnica può però essere utilizzata solo nella modalità di esecuzione asincrona. Utilizzate operazioni sincrone solo se non è possibile ottenere le funzionalità desiderate con la programmazione asincrona, dopo aver preso in considerazione i compromessi in termini di prestazioni che gli utenti dovranno accettare e dopo aver provato l'applicazione in modo da essere sicuri dell'effetto di tale programmazione sulle prestazioni. L'utilizzo della modalità asincrona implica spesso la scrittura di un codice più complesso. Va comunque tenuto presente che il codice si scrive una volta sola ma deve venire usato molte volte dagli utenti dell'applicazione, lento o veloce che sia. In molti casi, utilizzando un'istanza SQLStatement separata per ciascuna istruzione SQL da eseguire è possibile accodare più operazioni SQL in una volta, il che rende il codice asincrono molto simile a quello sincrono dal punto di vista della scrittura. Per ulteriori informazioni, consultate “Modalità di esecuzione asincrona” a pagina 196. Utilizzo di istruzioni SQL separate e invariabilità della proprietà text di SQLStatement Create un'istanza SQLStatement separata per ciascuna istruzione SQL che viene eseguita più di una volta nell'applicazione. Utilizzate tale istanza SQLStatement tutte le volte che viene eseguito tale comando SQL. Ad esempio, supponiamo di stare creando un'applicazione che comprende quattro operazioni SQL diverse che vengono eseguite più volte. In tal caso si devono creare quattro istanze SQLStatement separate e chiamare il metodo execute() di ciascuna istruzione per eseguirla. Evitate di utilizzare una sola istanza SQLStatement per tutte le istruzioni SQL e di dover ridefinire la relativa proprietà text ogni volta prima dell'esecuzione di ciascuna istruzione. Per ulteriori informazioni, consultate “Utilizzo di una sola istanza SQLStatement in ciascuna istruzione SQL” a pagina 214. Utilizzo dei parametri quando si creano le istruzioni Utilizzate i parametri SQLStatement e non concatenate mai l'intervento dell'utente nel testo dell'istruzione. L'utilizzo dei parametri rende l'applicazione più sicura, in quanto evita la possibilità degli attacchi di SQL injection. Rende inoltre possibile l'utilizzo nelle query degli oggetti invece che dei soli valori letterali SQL. E ancora, consente alle istruzioni di essere eseguite in modo più efficiente perché possono essere riutilizzate senza bisogno di ricompilazione ogni volta che vengono eseguite. Per ulteriori informazioni, consultate “Utilizzo dei parametri nelle istruzioni” a pagina 178. Utilizzo delle costanti per il nome delle colonne e dei parametri Nei casi in cui non si specifica un itemClass per l'SQLStatement, al fine di evitare errori di ortografia, definite costanti di stringa che contengono i nomi delle colonne della tabella. Utilizzate tali costanti nel testo dell'istruzione e per i nomi delle proprietà al momento del recupero dei valori dagli oggetti risultato. Utilizzate inoltre le costanti per i nomi dei parametri. 218 Capitolo 19: Memorizzazione di dati crittografati Il runtime di Adobe® AIR™ comprende un archivio locale crittografato persistente per ogni applicazione AIR installata nel computer dell'utente. Consente di salvare e recuperare dati memorizzati sull'unità disco rigido locale dell'utente in un formato crittografato, che non possono essere facilmente decrittografati da altre applicazioni o utenti. Si utilizza un archivio locale crittografato distinto per ogni applicazione AIR e ogni applicazione AIR utilizza un archivio locale crittografato diverso per ogni utente. Nota: oltre all'archivio locale crittografato, in AIR è disponibile anche una funzione per crittografare il contenuto archiviato in database SQL. Per ulteriori dettagli, consultate “Uso della crittografia con i database SQL” a pagina 197. È possibile utilizzare l'archivio locale crittografato per memorizzare informazioni che devono essere protette, ad esempio credenziali di accesso per servizi Web. Per associare l'archivio locale crittografato a ogni applicazione e utente, AIR usa DPAPI in Windows, KeyChain in Mac OS e KeyRing o KWallet in Linux. L'archivio locale crittografato utilizza la crittografia AES-CBC a 128 bit. Le informazioni nell'archivio locale crittografato sono disponibili solo per il contenuto dell'applicazione AIR nella sandbox di sicurezza dell'applicazione. Utilizzate i metodi statici setItem() e removeItem() della classe EncryptedLocalStore per memorizzare e recuperare dati dall'archivio locale. I dati sono memorizzati in una tabella hash. Le stringhe vengono utilizzate come chiavi e i dati sono memorizzati come array di byte. Ad esempio, il codice seguente memorizza una stringa nell'archivio locale crittografato: var str:String = "Bob"; var bytes:ByteArray = new ByteArray(); bytes.writeUTFBytes(str); EncryptedLocalStore.setItem("firstName", bytes); var storedValue:ByteArray = EncryptedLocalStore.getItem("firstName"); trace(storedValue.readUTFBytes(storedValue.length)); // "Bob" Il terzo parametro del metodo setItem(), il parametro stronglyBound è opzionale. Se questo parametro è impostato su true, l'archivio locale crittografato offre un livello di sicurezza più alto, associando l'elemento memorizzato alla firma digitale e ai bit dell'applicazione AIR di memorizzazione, nonché all'ID dell'autore dell'applicazione quando: var str:String = "Bob"; var bytes:ByteArray = new ByteArray(); bytes.writeUTFBytes(str); EncryptedLocalStore.setItem("firstName", bytes, true); Per un elemento memorizzato con stronglyBound impostato su true, le chiamate successive a getItem() vengono eseguite correttamente solo se l'applicazione AIR chiamante è identica all'applicazione di memorizzazione (se non sono stati modificati dati nella directory dell'applicazione). Se l'applicazione AIR chiamante è diversa dall'applicazione di memorizzazione, viene generata un'eccezione Error quando chiamate getItem() per un elemento con un'associazione forte. Se aggiornate l'applicazione, questa non sarà più in grado di leggere i dati con associazione forte che erano stati scritti in precedenza nell'archivio locale crittografato. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 219 Memorizzazione di dati crittografati Per impostazione predefinita, un'applicazione AIR non può leggere l'archivio locale crittografato di un'altra applicazione. L'impostazione stronglyBound garantisce ulteriore associazione (ai dati nei bit dell'applicazione) per impedire a un'applicazione che esegue l'attacco di tentare la lettura nell'archivio locale crittografato dell'applicazione cercando di assumere il controllo dell'ID autore dell'applicazione. Se si aggiorna un'applicazione affinché utilizzi un certificato di firma diverso (mediante una firma di migrazione), la versione aggiornata non sarà in grado di accedere ad alcuno degli elementi presenti nell'archivio originale, anche se il parametro stronglyBound è stato impostato su false. Per ulteriori informazioni, consultate “Modifica dei certificati” a pagina 329. È possibile eliminare un valore dall'archivio locale crittografato con l'ausilio del metodo EncryptedLocalStore.removeItem(), come nell'esempio seguente: EncryptedLocalStore.removeItem("firstName"); È possibile eliminare tutti i dati dall'archivio locale crittografato chiamando il metodo EncryptedLocalStore.reset(), come nell'esempio seguente: EncryptedLocalStore.reset(); Quando si esegue il debug di un'applicazione in AIR Debug Launcher (ADL), l'applicazione utilizza un archivio locale crittografato diverso da quello utilizzato nella versione installata dell'applicazione. Le prestazioni dell'archivio locale crittografato potrebbero risultare ridotte se la dimensione dei dati memorizzati supera 10 MB. Quando si disintalla un'applicazione AIR, il programma di disinstallazione non elimina i dati memorizzati nell'archivio locale crittografato. I dati di tale archivio vengono inseriti in una sottodirectory della directory dei dati dell'applicazione dell'utente. Il percorso della sottodirectory è Adobe/AIR/ELS/ seguito dall'ID dell'applicazione. 220 Capitolo 20: Informazioni sull'ambiente HTML Adobe®AIR™, come il browser Web Safari, utilizza WebKit (www.webkit.org) per analizzare, creare il layout ed effettuare il rendering di contenuti HTML e JavaScript. L'uso di API AIR nei contenuti HTML è facoltativo. È possibile programmare nel contenuto di un oggetto HTMLLoader o di una finestra HTML interamente con HTML e·JavaScript. La maggior parte delle pagine HTML e delle applicazioni esistenti potranno essere eseguite con poche modifiche, purché utilizzino funzionalità HTML, CSS, DOM e JavaScript compatibili con WebKit. Dal momento che le applicazioni AIR vengono eseguite direttamente dal desktop, con accesso completo al file system, il modello di sicurezza per il contenuto HTML è più rigido del modello di sicurezza di un browser Web tipico. In AIR, solo il contenuto caricato dalla directory di installazione dell'applicazione viene collocato nella sandbox dell'applicazione. La sandbox dell'applicazione dispone del livello di privilegi più elevato e consente l'accesso alle API AIR. Altri contenuti vengono collocati in sandbox isolate in base alla provenienza del contenuto stesso. I file caricati dal file system vanno in una sandbox locale. I file caricati dalla rete mediante i protocolli http: o https: vanno in una sandbox in base al dominio dei server remoti. Al contenuto delle sandbox non dell'applicazione è proibito l'accesso alle API AIR e l'esecuzione è analoga a quella di un tipico browser Web. AIR usa WebKit (www.webkit.org), utilizzato anche dal browser Web Safari, per analizzare, creare il layout ed effettuare il rendering del contenuto HTML e JavaScript. Le classi host incorporate e gli oggetti AIR forniscono una API per le funzionalità tradizionalmente associate alle applicazioni desktop. Tali funzionalità includono lettura e scrittura di file e gestione di finestre. Adobe AIR eredita inoltre le API da Adobe® Flash® Player, che include funzionalità quali audio e socket binari. Il contenuto HTML in AIR non visualizza contenuto SWF o PDF se vengono applicate le impostazioni di trasparenza, l'alfa o la scala. Per ulteriori informazioni, consultate Considerazioni relative al caricamento di contenuto SWF o PDF in una pagina HTML e “Trasparenza della finestra” a pagina 65. Panoramica sull'ambiente HTML Adobe AIR fornisce un ambiente browser completo simile a JavaScript, con un renderer HTML, un DOM (document object model) e un interprete JavaScript. L'ambiente JavaScript è rappresentato dalla classe HTMLLoader di AIR. Nelle finestre HTML, un oggetto HTMLLoader contiene tutto il contenuto HTML, e a sua volta è contenuto in un oggetto NativeWindow. Nel contenuto SWF, la classe HTMLLoader, che estende la classe Sprite, può essere aggiunta all'elenco di visualizzazione di uno stage come qualsiasi altro oggetto di visualizzazione. Le proprietà ActionScript™ della classe sono descritte nel capitolo “Creazione di script per il contenitore HTML” a pagina 261 e nel manuale Flex 3 ActionScript Language Reference (Guida di riferimento del linguaggio Flex 3 ActionScript). Informazioni sull'ambiente JavaScript e il rapporto con AIR Nel diagramma seguente viene illustrato il rapporto tra l'ambiente JavaScript e l'ambiente di runtime di AIR. Sebbene sia visualizzata una sola finestra nativa, un'applicazione AIR può contenere più finestre, e una singola finestra può contenere più oggetti HTMLLoader. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 221 Informazioni sull'ambiente HTML AIR Run-time Environment NativeWindow HTMLLoader window JavaScript Environment window window body head htmlLoader native4Window runtime h1 div table p L'ambiente JavaScript dispone di oggetti Document e Window propri. Il codice JavaScript può interagire con l'ambiente di runtime di AIR attraverso le proprietà di runtime nativeWindow e htmlLoader. Il codice ActionScript può interagire con l'ambiente JavaScript attraverso la proprietà window di un oggetto HTMLLoader, che costituisce un riferimento all'oggetto Window di JavaScript. Inoltre, entrambi gli oggetti ActionScript e JavaScript fungono da listener per gli eventi inviati da oggetti AIR e JavaScript. La proprietà runtime consente l'accesso alle classi di API AIR, consentendo la creazione di nuovi oggetti AIR nonché l'accesso ai membri delle classi, denominati anche statici. Per accedere a un'API AIR, è sufficiente aggiungere il nome della classe, nonché il pacchetto, alla proprietà runtime. Ad esempio, per creare un oggetto File, si utilizza l'istruzione seguente: var file = new window.runtime.filesystem.File(); Nota: AIR SDK fornisce un file JavaScript, AIRAliases.js, che definisce gli alias più convenienti per le classi AIR più comunemente utilizzate. Quando si importa questo file, è possibile usare la forma abbreviata air.Class invece di window.runtime.package.Class. Ad esempio, è possibile creare l'oggetto File con new air.File(). L'oggetto NativeWindow fornisce le proprietà per il controllo della finestra del desktop. Da una pagina HTML è possibile accedere all'oggetto contenitore NativeWindow con la proprietà window.nativeWindow. L'oggetto HTMLLoader fornisce proprietà, metodi ed eventi per il controllo delle modalità di caricamento e rendering del contenuto. Da una pagina HTML è possibile accedere all'oggetto principale HTMLLoader con la proprietà window.htmlLoader. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 222 Informazioni sull'ambiente HTML Importante: solo le pagine installate come parte di un'applicazione dispongono delle proprietà htmlLoader, nativeWindow o runtime, e solo quando vengono caricate come documento di primo livello. Tali proprietà non vengono aggiunte quando un documento viene caricato in un frame o in un iframe. Un documento secondario potrà accedere a queste proprietà sul documento principale fintantoché si trovano nella stessa sandbox di sicurezza. Ad esempio, un documento caricato in un frame potrebbe accedere alla proprietà runtime del relativo elemento principale con parent.runtime. Informazioni sulla protezione AIR esegue tutto il codice all'interno di una sandbox di sicurezza in base al dominio di origine. Il contenuto dell'applicazione, che si limita al contenuto caricato dalla directory di installazione dell'applicazione, viene collocato nella sandbox dell'applicazione. L'accesso all'ambiente di runtime e alle API AIR è disponibile solo per HTML e JavaScript in esecuzione da questa sandbox. Allo stesso tempo, la valutazione e l'esecuzione dinamica di JavaScript è per lo più bloccata nella sandbox dell'applicazione dopo che tutti i gestori dell'evento di caricamento (load) della pagina sono stati restituiti. È possibile mappare la pagina di un'applicazione nella sandbox non dell'applicazione caricando la pagina in un frame o un iframe e impostando gli attributi sandboxRoot e documentRoot specifici di AIR del frame. Impostando il valore di sandboxRoot su un dominio remoto effettivo, è possibile consentire che il contenuto della sandbox effettui uno scambio di script con il contenuto di quel dominio. Mappando le pagine in questo modo può essere utile quando si effettua il caricamento e si creano script per il contenuto remoto, come ad esempio in un'applicazione mash-up. Un altro sistema per consentire lo scambio incrociato di script tra contenuto dell'applicazione e non dell'applicazione, e l'unico sistema per fornire accesso alle API AIR al contenuto non dell'applicazione consiste nel creare un bridge sandbox. Un bridge elemento principale-a-secondario consente al contenuto di un frame secondario, un iframe, o a una finestra, di accedere a proprietà e metodi designati definiti nella sandbox dell'applicazione. Di contro, un bridge elemento secondario-a-principale consente al contenuto dell'applicazione di accedere a proprietà e metodi designati definiti nella sandbox dell'elemento secondario. I bridge sandbox vengono stabiliti impostando le proprietà parentSandboxBridge e childSandboxBridge dell'oggetto Window. Per ulteriori informazioni, consultate “Sicurezza in HTML” a pagina 32 e “Elementi frame e iframe HTML” a pagina 230. Informazioni su plug-in e oggetti incorporati AIR supporta il plug-in per Adobe® Acrobat®. Per visualizzare contenuto in formato PDF, gli utenti devono disporre di Acrobat o Adobe® Reader® 8.1 o versione superiore. L'oggetto HTMLLoader fornisce una proprietà che consente di controllare se il sistema di un utente è in grado di visualizzare file PDF. All'interno dell'ambiente HTML è anche possibile visualizzare il contenuto di file SWF, ma questa capacità è incorporata in AIR e non richiede l'impiego di plug-in esterni. AIR non supporta altri plug-in di Webkit. Consultare anche “Sicurezza in HTML” a pagina 32 “Sandbox HTML” a pagina 223 “Elementi frame e iframe HTML” a pagina 230 “Oggetto Window di JavaScript” a pagina 229 “Oggetto XMLHttpRequest” a pagina 224 “Aggiunta di contenuto PDF” a pagina 275 SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 223 Informazioni sull'ambiente HTML Estensioni di AIR e Webkit Adobe AIR utilizza il motore Webkit open source, utilizzato anche nel browser Web Safari. AIR aggiunge varie estensioni per consentire l'accesso agli oggetti e alle classi runtime, nonché a scopo di sicurezza. Inoltre, lo stesso Webkit aggiunge funzionalità non incluse negli standard W3C per HTML, CSS e JavaScript. L'ambito di questo manuale copre esclusivamente gli elementi aggiuntivi di AIR e le estensioni di Webkit più significative. Per un'ulteriore documentazione su elementi non standard di HTML, CSS e JavaScript, consultate www.webkit.org e developer.apple.com. Per informazioni sugli standard, consultate il sito Web di W3C. Mozilla fornisce inoltre un valido riferimento generale sugli argomenti HTML, CSS e DOM (ovviamente i motori di Webkit e Mozilla non sono identici). Nota: in AIR non sono supportate le seguenti funzionalità standard ed estese di WebKit: il metodo print()dell'oggetto Window di JavaScript; i plug-in, ad eccezione di Acrobat o Adobe Reader 8.1+; SVG (Scalable Vector Graphics), e la proprietà opacity di CSS. JavaScript in AIR AIR ha introdotto diverse modifiche nel comportamento tipico degli oggetti JavaScript comuni. Molte di queste modifiche vengono apportate per semplificare la scrittura di applicazioni sicure in AIR. Allo stesso tempo, queste differenze nel comportamento indicano che alcuni modelli di codifica e le applicazioni Web esistenti che li adottano non sempre possono essere eseguiti come previsto in AIR. Per informazioni sulla correzione di questo tipo di problemi, consultate “Errori JavaScript relativi alla sicurezza da evitare” a pagina 238. Sandbox HTML AIR colloca il contenuto in sandbox isolate in base all'origine del contenuto. Le regole della sandbox sono coerenti con il criterio della stessa origine implementato dalla maggior parte dei browser Web, nonché con le regole per le sandbox implementate da Adobe Flash Player. Inoltre, AIR fornisce un nuovo tipo di sandbox dell'applicazione per contenere e proteggere il contenuto dell'applicazione. Per ulteriori informazioni sui tipi di sandbox che è possibile incontrare quando si sviluppano applicazioni AIR, consultate “Funzioni di sicurezza sandbox” a pagina 29. L'accesso all'ambiente di runtime e alle API AIR è disponibile solo per HTML e JavaScript in esecuzione nella sandbox dell'applicazione. Allo stesso tempo, tuttavia, la valutazione dinamica e l'esecuzione di JavaScript, nelle varie forme, per motivi di sicurezza è ampiamente limitata nella sandbox dell'applicazione. Queste restrizioni sono attive a prescindere se l'applicazione carichi effettivamente o meno le informazioni direttamente da un server. (Persino il contenuto dei file, le stringhe incollate e l'input diretto dell'utente possono essere inaffidabili). L'origine del contenuto in una pagina determina la sandbox a cui è consegnata. Solo il contenuto caricato dalla directory dell'applicazione (la directory di installazione a cui fa riferimento lo schema URL app:) viene collocato nella sandbox dell'applicazione. Il contenuto caricato dal file system viene collocato nella sandbox locale-con-filesystem oppure nella sandbox locale-attendibile, e ciò consente l'accesso e l'interazione con il contenuto sul file system locale, ma non con il contenuto remoto. Il contenuto caricato dalla rete viene collocato in una sandbox remota che corrisponde al relativo dominio di origine. Per consentire la libera interazione della pagina di un'applicazione con il contenuto di una sandbox remota, è possibile mappare la pagina allo stesso dominio del contenuto remoto. Ad esempio, se si scrive un'applicazione per la visualizzazione dei dati di mappa da un servizio Internet, la pagina dell'applicazione che consente di caricare e visualizzare il contenuto dal servizio potrebbe essere mappata sul dominio del servizio. Gli attributi per la mappatura delle pagine in un dominio e una sandbox remoti sono attributi nuovi aggiunti agli elementi HTML di frame e iframe. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 224 Informazioni sull'ambiente HTML Per consentire al contenuto di una sandbox non dell'applicazione di utilizzare in modo sicuro le funzionalità AIR, è possibile impostare un bridge sandbox principale. Per consentire al contenuto di un'applicazione di effettuare chiamate sicure a metodi e proprietà di accesso del contenuto in altre sandbox, è possibile impostare un bridge sandbox secondario. Per sicurezza qui si intende che il contenuto remoto non può ottenere inavvertitamente riferimenti ad oggetti, proprietà o metodi non esposti esplicitamente. Il bridge consente unicamente il passaggio di oggetti anonimi, funzioni e tipi di dati semplici. È tuttavia necessario evitare l'esposizione esplicita di funzioni potenzialmente pericolose. Se, ad esempio, è stata esposta un'interfaccia che consentiva al contenuto remoto di leggere e scrivere file in un punto qualsiasi del sistema di un utente, il contenuto remoto potrebbe aver ricevuto i mezzi per danneggiare in maniera considerevole gli utenti. JavaScript, funzione eval() L'utilizzo della funzione eval() nella sandbox di una applicazione è limitato a dopo che una pagina ha effettuato il caricamento. Sono consentiti alcuni impieghi in modo che i dati formattati con JSON possano essere analizzati in maniera sicura, ma qualsiasi valutazione che abbia come risultato istruzioni eseguibili genera un errore. Nella sezione “Restrizioni relative al codice per il contenuto presente in diverse sandbox” a pagina 34 vengono descritti gli impieghi consentiti della funzione eval(). Costruttori di funzioni Nella sandbox dell'applicazione, i costruttori di funzioni possono essere utilizzati prima che il caricamento di una pagina sia terminato. Quando tutti i gestori dell'evento load sono terminati, non è possibile creare nuove funzioni. Caricamento di script esterni La pagine HTML nella sandbox dell'applicazione non possono utilizzare il tag script per caricare i file JavaScript dall'esterno della directory dell'applicazione. Per consentire a una pagina dell'applicazione di caricare uno script dall'esterno della directory dell'applicazione, è necessario che la pagina sia mappata a una sandbox non dell'applicazione. Oggetto XMLHttpRequest AIR fornisce un oggetto XMLHttpRequest (XHR) che le applicazioni possono utilizzare per effettuare richieste di dati. Nell'esempio seguente è illustrata una richiesta di dati semplice: xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "http:/www.example.com/file.data", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { //do something with data... } } xmlhttp.send(null); Contrariamente a un browser, AIR consente al contenuto in esecuzione nella sandbox di un'applicazione di richiedere i dati da un dominio qualsiasi. Il risultato di un XHR che contiene una stringa JSON può essere valutato negli oggetti dati a meno che i risultati non contengano anche codice eseguibile. Se nel risultato XHR sono presenti istruzioni eseguibili, viene generato un errore e il tentativo di valutazione non riesce. Per impedire l'inserimento accidentale di codice da origini remote, XHR sincroni creati prima che sia terminato il caricamento di una pagina restituiscono un risultato vuoto. Dopo che una pagina è stata caricata, vengono sempre restituiti XHR asincroni. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 225 Informazioni sull'ambiente HTML Per impostazione predefinita, AIR blocca gli oggetti XMLHttpRequests tra i domini nelle sandbox non dell'applicazione. Una finestra principale della sandbox dell'applicazione può scegliere di consentire le richieste tra domini in un frame secondario che include il contenuto di una sandbox non dell'applicazione impostando allowCrossDomainXHR, un attributo aggiunto da AIR, su true nell'elemento contenitore frame o iframe: <iframe id="mashup" src="http://www.example.com/map.html" allowCrossDomainXHR="true" </iframe> Nota: se conviene, anche la classe URLStream può essere utilizzata per scaricare i dati. Se si invia un oggetto XMLHttpRequest a un server remoto da un frame o un iframe che include contenuto dell'applicazione mappato a una sandbox remota, accertarsi che l'URL di mappatura non mascheri l'indirizzo server utilizzato nell'XHR. Si consideri ad esempio la seguente definizione iframe, che mappa il contenuto dell'applicazione in una sandbox remota per il dominio example.com: <iframe id="mashup" src="http://www.example.com/map.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/" allowCrossDomainXHR="true" </iframe> Dal momento che l'attributo sandboxRoot rimappa l'URL principale dell'indirizzo www.example.com, tutte le richieste vengono caricate dalla directory dell'applicazione e non dal server remoto. Le richieste vengono rimappate sia che derivino dall'esplorazione della pagina che da un oggetto XMLHttpRequest. Per evitare il blocco accidentale delle richieste di dati nel server remoto, mappare sandboxRoot a una sottodirectory dell'URL remoto anziché alla radice. Non è necessario che la directory esista. Ad esempio, per consentire il caricamento delle richieste a www.example.com dal server remoto anziché dalla directory dell'applicazione, cambiare l'iframe precedente nel seguente: <iframe id="mashup" src="http://www.example.com/map.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/" allowCrossDomainXHR="true" </iframe> In questo caso, viene caricato a livello locale solo il contenuto della sottodirectory air. Per ulteriori informazioni sulla mappatura di sandbox, consultate “Elementi frame e iframe HTML” a pagina 230 e “Sicurezza in HTML” a pagina 32. L'oggetto Canvas L'oggetto Canvas (area di lavoro) definisce un'API per la tracciatura di forme geometriche quali linee, archi, ellissi e poligoni. Per utilizzare l'API dell'oggetto canvas, è necessario innanzitutto aggiungere un elemento canvas al documento e quindi trascinarlo al suo interno utilizzando l'API Canvas di JavaScript. Per molti altri aspetti, l'oggetto Canvas si comporta come un'immagine. Nell'esempio seguente viene tracciato un triangolo mediante un oggetto Canvas: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 226 Informazioni sull'ambiente HTML <html> <body> <canvas id="triangleCanvas" style="width:40px; height:40px;"></canvas> <script> var canvas = document.getElementById("triangleCanvas"); var context = canvas.getContext("2d"); context.lineWidth = 3; context.strokeStyle = "#457232"; context.beginPath(); context.moveTo(5,5); context.lineTo(35,5); context.lineTo(20,35); context.lineTo(5,5); context.lineTo(6,5); context.stroke(); </script> </body> </html> Per documentarsi ulteriormente sull'API Canvas, consultate Safari JavaScript Reference (guida di riferimento a Safari JavaScript) di Apple. Si noti che il progetto Webkit ha apportato di recente modifiche all'API Canvas al fine di creare uno standard sulla base del documento HTML 5 Working Draft proposto dai consorzi WHATWG (Web Hypertext Application Technology Working Group) e W3C. Di conseguenza, alcuni documenti presenti nei riferimenti JavaScript a Safari potrebbero non essere coerenti con la versione dei canvas presenti in AIR. Cookie Nelle applicazioni AIR ,solo il contenuto delle sandbox remote (caricato dalle origini http: e https:) può utilizzare i cookie (proprietà document.cookie). Nella sandbox dell'applicazione, le API AIR forniscono altri sistemi per l'archiviazione dei dati persistenti (ad esempio le classi EncryptedLocalStore e FileStream). L'oggetto Clipboard L'API Clipboard di WebKit viene attivata mediante i seguenti eventi: copy (copia), cut (taglia) e paste (incolla). L'oggetto evento trasmesso in questi eventi fornisce accesso agli Appunti mediante la proprietà clipboardData. Utilizzare i seguenti metodi dell'oggetto clipboardData per leggere o scrivere dati degli Appunti: Metodo Descrizione clearData(mimeType) Cancella i dati degli Appunti. Impostare il parametro mimeType sul tipo MIME dei dati da cancellare. getData(mimeType) Richiama i dati degli Appunti. Questo metodo può essere chiamato solo in un gestore dell'evento paste. Impostare il parametro mimeType sul tipo MIME dei dati da restituire. setData(mimeType, data) Copia i dati negli Appunti. Impostate il parametro mimeType sul tipo di dati MIME. Il codice JavaScript esterno alla sandbox dell'applicazione può accedere agli Appunti solo attraverso questi eventi. Tuttavia, il contenuto della sandbox dell'applicazione può accedere agli Appunti di sistema direttamente tramite la classe Clipboard AIR. Ad esempio, è possibile utilizzare la seguente istruzione per ottenere dati in formato testo sugli Appunti: var clipping = air.Clipboard.generalClipboard.getData("text/plain", air.ClipboardTransferMode.ORIGINAL_ONLY); I tipi di dati MIME validi sono: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 227 Informazioni sull'ambiente HTML Tipo MIME Valore Testo "text/plain" HTML "text/html" URL "text/uri-list" Bitmap "image/x-vnd.adobe.air.bitmap" Elenco file "application/x-vnd.adobe.air.file-list" Importante: solo il contenuto della sandbox dell'applicazione può accedere ai dati di un file presente negli Appunti. Se il contenuto non dell'applicazione tenta di accedere a un oggetto file dagli Appunti, viene generato un errore di protezione. Per ulteriori informazioni sull'uso degli Appunti, consultate “Copia e incolla” a pagina 151 e Using the Pasteboard from JavaScript (Apple Developer Center) (Utilizzo del modulo Pasteboard di JavaScript nel Centro per sviluppatori Apple). Trascinamento della selezione I movimenti di trascinamento della selezione all'interno e all'esterno di file HTML producono i seguenti eventi DOM: dragstart, drag, dragend, dragenter, dragover, dragleave e drop. L'oggetto evento trasmesso in questi eventi fornisce accesso ai dati trascinati mediante la proprietà dataTransfer. La proprietà dataTransfer fa riferimento a un oggetto che fornisce gli stessi metodi dell'oggetto clipboardData associato a un evento degli Appunti. Ad esempio, è possibile utilizzare la seguente funzione per ottenere dati in formato testo da un evento drop: function onDrop(dragEvent){ return dragEvent.dataTransfer.getData("text/plain", air.ClipboardTransferMode.ORIGINAL_ONLY); } L'oggetto dataTransfer dispone dei seguenti membri importanti: Membro Descrizione clearData(mimeType) Cancella i dati. Impostate il parametro mimeType sul tipo MIME della rappresentazione dei dati da cancellare. getData(mimeType) Richiama i dati trascinati. Questo metodo può essere chiamato solo in un gestore per l'evento drop. Impostate il parametro mimeType sul tipo MIME dei dati da richiamare. setData(mimeType, data) Imposta i dati da trascinare. Impostate il parametro mimeType sul tipo di dati MIME. types Un array di stringhe contenente i tipi MIME di tutte le rappresentazioni dei dati attualmente disponibili nell'oggetto dataTransfer. effectsAllowed Specifica se i dati trascinati possono essere copiati, spostati, collegati o possono subire una combinazione di qualche azione di cui sopra. Impostate la proprietà effectsAllowed nel gestore per l'evento dragstart. dropEffect Specifica quali degli effetti drop consentiti sono supportati da una destinazione di trascinamento. Impostate la proprietà dropEffect nel gestore per l'evento dragEnter. Durante il trascinamento della selezione, il cursore cambia aspetto, ad indicare l'effetto che risulterebbe dal rilascio del mouse. Se nessun effetto dropEffect è specificato, viene scelto un effetto della proprietà effectsAllowed. L'effetto di copia ha la priorità sull'effetto di spostamento, che a sua volta ha la priorità sull'effetto di collegamento. L'utente può modificare la priorità predefinita utilizzando la tastiera. Per ulteriori informazioni sull'aggiunta di supporto per operazioni di trascinamento della selezione in un'applicazione AIR, consultate “Trascinamento della selezione” a pagina 135 e Using the Drag-and-Drop from JavaScript (Apple Developer Center) (Utilizzo della funzione di trascinamento della selezione in JavaScript nel Centro per sviluppatori Apple). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 228 Informazioni sull'ambiente HTML innerHTML e outerHTML, proprietà AIR pone limiti di sicurezza sull'uso delle proprietà innerHTML e outerHTML per il contenuto in esecuzione nella sandbox dell'applicazione. Prima dell'evento di caricamento della pagina, nonché durante l'esecuzione di qualsiasi gestore di eventi di carico, l'utilizzo delle proprietà innerHTML e outerHTML è illimitato. Tuttavia, dopo che la pagina è stata caricata, per aggiungere contenuto statico al documenti è possibile utilizzare solo le proprietà innerHTML o outerHTML. Qualsiasi istruzione nella stringa assegnata a innerHTML o outerHTML che restituisca codice eseguibile viene ignorata. Ad esempio, se si include un attributo di callback di un evento nella definizione di un elemento, il listener di eventi non viene aggiunto. Analogamente, i tag <script> incorporati non vengono valutati. Per ulteriori informazioni, consultate “Sicurezza in HTML” a pagina 32. Document.write() e Document.writeln(), metodi L'utilizzo dei metodi write() e writeln() non è limitato nella sandbox dell'applicazione prima dell'evento load della pagina. Tuttavia, dopo che la pagina è stata caricata, la chiamata a uno di questi metodi non determina la cancellazione della pagina o la creazione di una nuova pagina. Nella sandbox non dell'applicazione, come nella maggior parte dei browser Web, la chiamata di document.write() o writeln() dopo che è stato effettuato il caricamento di una pagina cancella la pagina corrente e ne apre una nuova, vuota. Document.designMode, proprietà Impostate la proprietà document.designMode su un valore on per rendere modificabili tutti gli elementi del documento. Il supporto editor incorporato include modifica del testo, copia, incolla e trascinamento della selezione. L'impostazione di designMode su on equivale ad impostare la proprietà contentEditable dell'elemento body su true. Per definire quali sezioni sono modificabili, è possibile utilizzare la proprietà contentEditable sulla maggior parte degli elementi HTML. Per ulteriori informazioni, consultate “Attributo contentEditable di HTML” a pagina 233. unload, eventi (per oggetti body e frameset) Nel tag di primo livello frameset o body di una finestra, inclusa la finestra principale dell'applicazione, non utilizzate l'evento unload per rispondere alla chiusura della finestra (o dell'applicazione). Utilizzate al suo posto l'evento exiting dell'oggetto NativeApplication per rilevare quando un'applicazione è in fase di chiusura. In alternativa, utilizzate l'evento closing dell'oggetto NativeWindow, che consente di rilevare quando una finestra è in fase di chiusura. Ad esempio, il seguente codice JavaScript consente di visualizzare un messaggio di saluto ("Goodbye.") quando l'utente chiude l'applicazione: var app = air.NativeApplication.nativeApplication; app.addEventListener(air.Event.EXITING, closeHandler); function closeHandler(event) { alert("Goodbye."); } Tuttavia, gli script possono rispondere all'evento unload causato dall'esplorazione del contenuto di un frame, un iframe o una finestra di primo livello. Nota: queste limitazioni potrebbero essere rimosse in una versione successiva di Adobe AIR. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 229 Informazioni sull'ambiente HTML Oggetto Window di JavaScript L'oggetto Window resta l'oggetto globale nel contesto di esecuzione di JavaScript. Nella sandbox dell'applicazione, AIR aggiunge nuove proprietà all'oggetto Window di JavaScript per fornire accesso alle classi incorporate di AIR nonché ad importanti oggetti host. Inoltre, alcuni metodi e proprietà hanno un comportamento diverso a seconda se si trovano o meno nella sandbox dell'applicazione. Proprietà Window.runtime La proprietà runtime consente di effettuare istanze e utilizzare le classi di runtime incorporate dalla sandbox dell'applicazione. Queste classi includono le API AIR e Flash Player, ma non, ad esempio, la struttura Flex. Ad esempio, la seguente istruzione consente di creare un oggetto file AIR: var preferencesFile = new window.runtime.flash.filesystem.File(); Il file AIRAliases.js, fornito in AIR SDK, contiene definizioni di alias che consentono di abbreviare tali riferimenti. Quando AIRAliases.js viene importato in una pagina, ad esempio, è possibile creare un oggetto File con la seguente istruzione: var preferencesFile = new air.File(); La proprietà window.runtime è definita solo per il contenuto all'interno della sandbox dell'applicazione e solo per il documento principale di una pagina con frame o iframe. Consultate “Uso del file AIRAliases.js” a pagina 242. Proprietà Window.nativeWindow La proprietà nativeWindow fornisce un riferimento all'oggetto native window sottostante. Mediante questa proprietà è possibile creare script di funzioni della finestra e di proprietà quali posizione dello schermo, dimensione e visibilità. Consente inoltre di gestire eventi quali chiusura, ridimensionamento e spostamento. L'istruzione seguente, ad esempio, consente la chiusura della finestra: window.nativeWindow.close(); Nota: le funzionalità di controllo della finestra fornite dall'oggetto NativeWindow si sovrappongono alle funzionalità fornite dall'oggetto Window di JavaScript. In tali casi è possibile utilizzare il metodo che si ritiene più conveniente. La proprietà window.nativeWindow è definita solo per il contenuto all'interno della sandbox dell'applicazione e solo per il documento principale di una pagina con frame o iframe. Proprietà Window.htmlLoader La proprietà htmlLoader offre un riferimento all'oggetto HTMLLoader AIR che include il contenuto HTML. Grazie a questa proprietà è possibile creare script per l'aspetto e il comportamento dell'ambiente HTML. Ad esempio, è possibile utilizzare la proprietà htmlLoader.paintsDefaultBackground per determinare se il controllo dipinge uno sfondo bianco predefinito: window.htmlLoader.paintsDefaultBackground = false; Nota: lo stesso oggetto HTMLLoader dispone di una proprietà window che fa riferimento all'oggetto Window di JavaScript del contenuto HTML che include. È possibile utilizzare questa proprietà per accedere all'ambiente JavaScript attraverso un riferimento all'HTMLLoader contenitore. La proprietà window.htmlLoader è definita solo per il contenuto all'interno della sandbox dell'applicazione e solo per il documento principale di una pagina con frame o iframe. Proprietà Window.parentSandboxBridge e Window.childSandboxBridge Le proprietà parentSandboxBridge e childSandboxBridge consentono di definire un'interfaccia tra un frame principale e uno secondario. Per ulteriori informazioni, consultate “Scambio di script per il contenuto presente in sandbox di sicurezza diverse” a pagina 251. Funzioni Window.setTimeout() e Window.setInterval() AIR pone limiti di sicurezza sull'uso delle funzioni setTimeout() e setInterval() nella sandbox dell'applicazione. Non è possibile definire il codice da eseguire come stringa quando si effettua la chiamata a setTimeout() o setInterval(). È necessario utilizzare un riferimento a una funzione. Per ulteriori informazioni, consultate “setTimeout() e setInterval()” a pagina 240. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 230 Informazioni sull'ambiente HTML Funzione Window.open() Se chiamato da un codice in esecuzione in una sandbox non dell'applicazione, il metodo open() apre una finestra solo quando viene chiamato come risultato di un'interazione utente (ad esempio, un clic del mouse o la pressione di un tasto sulla tastiera). Il titolo della finestra, inoltre, è preceduto da un prefisso con il titolo dell'applicazione, per impedire che le finestre aperte dal contenuto remoto "impersonino" finestre aperte dall'applicazione). Per ulteriori informazioni, consultate “Restrizioni relative alla chiamata al metodo JavaScript window.open()” a pagina 37. Oggetto air.NativeApplication L'oggetto NativeApplication fornisce informazioni sullo stato dell'applicazione, distribuisce diversi importanti eventi a livello di applicazione e fornisce funzioni utili per il controllo del comportamento delle applicazioni. Viene creata automaticamente una singola istanza dell'oggetto NativeApplication, e ad essa è possibile accedere tramite la proprietà NativeApplication.nativeApplication definita dalla classe. Per accedere all'oggetto dal codice JavaScript è possibile utilizzare quanto segue: var app = window.runtime.flash.desktop.NativeApplication.nativeApplication; In alternativa, se lo script AIRAliases.js è stato importato, è possibile scegliere la forma abbreviata: var app = air.NativeApplication.nativeApplication; All'oggetto NativeApplication è possibile accedere solo dall'interno della sandbox dell'applicazione. L'interazione con il sistema operativo in “Uso delle informazioni di runtime e del sistema operativo” a pagina 303 descrive nei dettagli l'oggetto NativeApplication. Lo schema URL di JavaScript L'esecuzione di codice definito in uno schema URL di JavaScript (come in href="javascript:alert('Test')") viene bloccata all'interno della sandbox dell'applicazione. Non viene generato alcun errore. Estensioni in HTML AIR e WebKit definiscono alcuni elementi ed attributi HTML non standard, tra cui: “Elementi frame e iframe HTML” a pagina 230 “Elemento Canvas HTML” a pagina 232 “Gestori di evento di elementi HTML” a pagina 233 Elementi frame e iframe HTML AIR aggiunge nuovi attributi agli elementi di contenuto frame e iframe nella sandbox dell'applicazione: Attributo sandboxRoot L'attributo sandboxRoot specifica un dominio di origine alternativo non dell'applicazione per il file specificato dall'attributo del frame src. Il file viene caricato nella sandbox non dell'applicazione corrispondente al dominio specificato. Tra il contenuto del file e il contenuto caricato dal dominio specificato può essere effettuato uno scambio di script. Importante: se si imposta il valore di sandboxRoot sull'URL di base del dominio, tutte le richieste di contenuto da quel dominio vengono caricate dalla directory dell'applicazione invece del server remoto (se la richiesta deriva dall'esplorazione della pagina, da un XMLHttpRequest o da qualsiasi altro sistema di caricamento del contenuto). Attributo documentRoot L'attributo documentRoot specifica la directory locale da cui caricare gli URL che vengono risolti ai file nel percorso specificato da sandboxRoot. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 231 Informazioni sull'ambiente HTML Quando si risolvono gli URL, sia nell'attributo src del frame che nel contenuto caricato nel frame stesso, la parte di URL che corrisponde al valore specificato in sandboxRoot viene sostituita dal valore specificato in documentRoot. Pertanto, nel seguente tag del frame: <iframe src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/"/> child.html viene caricato dalla sottodirectory sandbox della cartella di installazione dell'applicazione. Gli URL relativi in child.html vengono risolti in base alla directory sandbox. Si noti che i file sul server remoto all'indirizzo www.example.com/air non sono accessibili nel frame, dal momento che AIR tenta di caricarli dalla directory app:/sandbox/. Attributo allowCrossDomainXHR Includere allowCrossDomainXHR="allowCrossDomainXHR" nel tag di apertura del frame per consentire al contenuto del frame di effettuare XMLHttpRequests a qualsiasi dominio remoto. Per impostazione predefinita, il contenuto non dell'applicazione può solo effettuare tali richieste al relativo dominio di origine. Consentire XHR tra domini ha implicazioni di sicurezza serie. Il codice presente nella pagina è in grado di scambiare dati con qualsiasi dominio. Se nella pagina viene inserito in qualche modo contenuto dannoso, tutti i dati accessibili al codice nella sandbox corrente possono essere danneggiati. Attivate XHR tra i domini solo per le pagine create e controllate direttamente, e solo quando il caricamento dei dati tra domini è davvero necessario. Inoltre, convalidate attentamente tutti i dati esterni caricati dalla pagine per impedire l'inserimento di codice o altre forme di attacco. Importante: se l'attributo allowCrossDomainXHR è incluso in un elemento frame o iframe, i XHR sono attivati, a meno che il valore assegnato sia "0" o inizino per la lettera "f" o "n". Ad esempio, l'impostazione di allowCrossDomainXHR su "deny" consentirebbe comunque XHR tra domini. Se non desiderate attivare richieste tra domini, lasciate l'attributo fuori dalla dichiarazione dell'elemento. Attributo ondominitialize Specifica un gestore eventi per l'evento dominitialize di un frame. Si tratta di un evento specifico di AIR che viene attivato quando gli oggetti window e document del frame sono stati creati, ma prima che tutti gli script siano stati analizzati o i documenti creati. Il frame dominitialize invia l'evento abbastanza presto nella sequenza di caricamento, in modo che tutti gli script della pagina secondaria possano far riferimento a oggetti, variabili e funzioni aggiunte al documento secondario dal gestore dominitialize. La pagina principale deve trovarsi nella stessa sandbox dell'elemento secondario per aggiungere o accedere direttamente a qualsiasi oggetto in un documento secondario. Un elemento principale nella sandbox dell'applicazione, tuttavia, è in grado di stabilire un bridge sandbox per comunicare con il contenuto di una sandbox non dell'applicazione. Negli esempi che seguono è illustrato l'utilizzo del tag iframe in AIR: Collocate child.html in una sandbox remota, senza mapparlo a un dominio reale su un server remoto: <iframe src="http://localhost/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://localhost/air/"/> Collocate child.html in una sandbox remota, consentendo XMLHttpRequests solo a www.example.com: <iframe src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/"/> Collocare child.html in una sandbox remota, consentendo XMLHttpRequests a qualsiasi dominio remoto: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 232 Informazioni sull'ambiente HTML <iframe src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/" allowCrossDomainXHR="allowCrossDomainXHR"/> Collocate child.html nella sandbox locale con file system: <iframe src="file:///templates/child.html" documentRoot="app:/sandbox/" sandboxRoot="app-storage:/templates/"/> Collocate child.html in una sandbox remota utilizzando l'evento dominitialize per stabilire un bridge sandbox: <html> <head> <script> var bridgeInterface = {}; bridgeInterface.testProperty = "Bridge engaged"; function engageBridge(){ document.getElementById("sandbox").parentSandboxBridge = bridgeInterface; } </script> </head> <body> <iframe id="sandbox" src="http://www.example.com/air/child.html" documentRoot="app:/" sandboxRoot="http://www.example.com/air/" ondominitialize="engageBridge()"/> </body> </html> Nel documento child.html riportato di seguito viene illustrato il modo in cui il contenuto secondario può accedere al bridge sandbox principale: <html> <head> <script> document.write(window.parentSandboxBridge.testProperty); </script> </head> <body></body> </html> Per ulteriori informazioni, consultate “Scambio di script per il contenuto presente in sandbox di sicurezza diverse” a pagina 251 e “Sicurezza in HTML” a pagina 32. Elemento Canvas HTML Definisce un'area di disegno da utilizzare con l'API Canvas di Webkit. Non è possibile specificare i comandi grafici nel tag stesso. Per disegnare nell'area di lavoro (canvas), richiamare i metodi di disegno dell'area di lavoro mediante JavaScript. <canvas id="drawingAtrium" style="width:300px; height:300px;"></canvas> Per ulteriori informazioni, consultate “L'oggetto Canvas” a pagina 225. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 233 Informazioni sull'ambiente HTML Gestori di evento di elementi HTML Gli oggetti DOM in AIR e in Webkit inviano alcuni eventi non trovati nel modello di evento DOM standard. Nella tabella seguente sono elencati gli attributi dell'evento correlato che è possibile utilizzare per specificare i gestori per tali eventi: Nome attributo di callback Descrizione oncontextmenu Chiamato quando si effettua la chiamata di un menu contestuale, ad esempio attraverso l'uso del pulsante destro del mouse o tenendo premuto il tasto Comando sul testo selezionato. oncopy Chiamato quando viene copiata una selezione in un elemento. oncut Chiamato quando viene tagliata una selezione in un elemento. ondominitialize Chiamato quando viene creato il DOM di un documento caricato in un frame o in un iframe, ma prima che venga creato qualsiasi elemento DOM o analizzato qualsiasi script. ondrag Chiamato quando viene trascinato un elemento. ondragend Chiamato quando viene rilasciato un trascinamento. ondragenter Chiamato quando un movimento di trascinamento entra nei limiti di un elemento. ondragleave Chiamato quando un movimento di trascinamento lascia i limiti di un elemento. ondragover Chiamato continuamente quando un movimento di trascinamento rientra nei limiti di un elemento. ondragstart Chiamato quando inizia un movimento di trascinamento. ondrop Chiamato quando un movimento di trascinamento viene rilasciato su un elemento. onerror Chiamato quando si verifica un errore durante il caricamento di un elemento. oninput Chiamato quando si immette testo in un elemento del form. onpaste Chiamato quando si incollano dati in un elemento. onscroll Chiamato quando si scorre il contenuto di un elemento scorrevole. onsearch Chiamato quando viene copiato un elemento onselectstart Chiamato all'avvio di una selezione. Attributo contentEditable di HTML È possibile aggiungere l'attributo contentEditable a qualsiasi elemento HTML per consentire agli utenti di modificare il contenuto dell'elemento. Ad esempio, nel seguente esempio di codice HTML l'intero documento viene impostato come modificabile, ad eccezione del primo elemento p: <html> <head/> <body contentEditable="true"> <h1>de Finibus Bonorum et Malorum</h1> <p contentEditable="false">Sed ut perspiciatis unde omnis iste natus error.</p> <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis.</p> </body> </html> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 234 Informazioni sull'ambiente HTML Nota: se si imposta la proprietà document.designMode su on, tutti gli elementi del documento sono modificabili, a prescindere dall'impostazione di contentEditable per un elemento individuale. Tuttavia, l'impostazione di designMode su off non disattiva la modifica di elementi per i quali contentEditable corrisponde a true. Per ulteriori informazioni, consultate “Document.designMode, proprietà” a pagina 228. Estensioni in CSS WebKit supporta diverse proprietà estese di CSS. Nella tabella seguente sono elencate le proprietà estese per le quali è stabilito il supporto. Proprietà aggiuntive non standard sono disponibili in WebKit ma non sono completamente supportate in AIR,o perché sono ancora in fase di sviluppo in WebKit o perché si tratta di funzionalità sperimentali che potrebbero essere rimosse in futuro. Nome della proprietà CSS Valori Descrizione -webkit-border-horizontal-spacing Unità di lunghezza non negativa Specifica il componente orizzontale della spaziatura dei bordi. -webkit-border-vertical-spacing Unità di lunghezza non negativa Specifica il componente verticale della spaziatura dei bordi. -webkit-line-break after-white-space, normal Specifica la regola per l'interruzione di riga da usare per testo cinese, giapponese e coreano (CJK). -webkit-margin-bottom-collapse collapse, discard, separate Definisce il modo in cui il margine inferiore di una cella di tabella viene compresso. -webkit-margin-collapse collapse, discard, separate Definisce il modo in cui i margini superiore e inferiore di una cella di tabella vengono compressi. -webkit-margin-start Qualsiasi unità di lunghezza. La larghezza del margine iniziale. Per il testo da sinistra a destra, questa proprietà ignora il margine sinistro. Per il testo da destra a sinistra, questa proprietà ignora il margine destro. -webkit-margin-top-collapse collapse, discard, separate Definisce il modo in cui il margine superiore di una cella di tabella viene compresso. -webkit-nbsp-mode normal, space Definisce il comportamento degli spazi unificatori all'interno del contenuto allegato. -webkit-padding-start Qualsiasi unità di lunghezza. Specifica la larghezza del riempimento iniziale. Per il testo da sinistra a destra, questa proprietà ignora il valore del riempimento sinistro. Per il testo da destra a sinistra, questa proprietà ignora il valore del riempimento destro. -webkit-rtl-ordering logical, visual Ignora la gestione predefinita del testo misto da sinistra a destra e da destra a sinistra. -webkit-text-fill-color Qualsiasi colore con nome o valore numerico del colore Specifica il colore di riempimento del testo. -webkit-text-security circle, disc, none, square Specifica la forma di sostituzione da utilizzare in un campo di immissione della password. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 235 Informazioni sull'ambiente HTML Nome della proprietà CSS Valori Descrizione -webkit-user-drag • auto: comportamento predefinito Ignora il comportamento di trascinamento automatico. • element: viene trascinato l'intero elemento • none: non è possibile trascinare l'elemento -webkit-user-modify read-only, read-write, read-writeplaintext-only Specifica se è possibile modificare il contenuto di un elemento. -webkit-user-select • auto: comportamento predefinito Specifica se un utente può selezionare il contenuto di un elemento. • none: non è possibile selezionare l'elemento • text: nell'elemento è possibile selezionare solo testo Per ulteriori informazioni, consultate il documento Apple Safari CSS Reference (Guida di riferimento ai CSS di Apple Safari) all'indirizzo http://developer.apple.com/documentation/AppleApplications/Reference/SafariCSSRef/. 236 Capitolo 21: Programmazione in HTML e JavaScript Sono molti gli argomenti di programmazione che riguardano esclusivamente lo sviluppo di applicazioni Adobe® AIR™ con i linguaggi HTML e JavaScript. Le informazioni fornite di seguito sono importanti per la programmazione sia di applicazioni AIR basate su HTML, sia di applicazioni AIR basate su SWF che eseguono codice HTML o JavaScript tramite la classe HTMLLoader (o il componente mx:HTML Flex™). Informazioni sulla classe HTMLLoader La classe HTMLLoader di Adobe AIR definisce l'oggetto di visualizzazione che può mostrare il contenuto HTML in un'applicazione AIR. Le applicazioni basate su SWF possono aggiungere un controllo HTMLLoader a una finestra esistente o creare una finestra HTML che contenga automaticamente un oggetto HTMLLoader con HTMLLoader.createRootWindow(). È possibile accedere all'oggetto HTMLLoader tramite la proprietà JavaScript window.htmlLoader dalla pagina HTML caricata. Caricamento di contenuto HTML da un URL Il codice riportato di seguito carica un URL in un oggetto HTMLLoader (aggiungete HTMLLoader come elemento secondario di stage o di un altro contenitore di oggetti di visualizzazione per visualizzare il contenuto HTML nella vostra applicazione): import flash.html.HTMLLoader; var html:HTMLLoader = new HTMLLoader; html.width = 400; html.height = 600; var urlReq:URLRequest = new URLRequest("http://www.adobe.com/"); html.load(urlReq); Per impostazione predefinita, le proprietà width e height di un oggetto HTMLLoader sono entrambe impostate su 0. Quando aggiungete un oggetto HTMLLoader allo stage, potete modificare tali dimensioni. Durante il caricamento di un pagina, l'oggetto HTMLLoader invia vari eventi che consentono di determinare quando l'interazione con la pagina caricata è sicura. Questi eventi sono descritti in “Gestione di eventi relativi a HTML” a pagina 255. Potete anche eseguire il rendering del testo HTML usando la classe TextField, sebbene questa abbia funzionalità limitate. La classe TextField di Adobe® Flash® Player supporta un sottoinsieme del codice HTML, ma a causa di limitazioni dimensionali, le sue funzionalità sono limitate (la classe HTMLLoader inclusa in Adobe AIR non è disponibile in Flash Player). Caricamento di contenuto HTML da una stringa Il metodo loadString() di un oggetto HTMLLoader carica una stringa di contenuto HTML nell'oggetto HTMLLoader: var html:HTMLLoader = new HTMLLoader(); var htmlStr:String = "<html><body>Hello <b>world</b>.</body></html>"; html.loadString(htmlStr); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 237 Programmazione in HTML e JavaScript Per impostazione predefinita, il contenuto caricato tramite il metodo loadString() viene inserito in una sandbox non dell'applicazione con le seguenti caratteristiche: • Dispone dell'accesso per caricare il contenuto dalla rete (ma non dal file system). • Non può caricare dati usando XMLHttpRequest. • La proprietà window.location è impostata su "about:blank". • Il contenuto non può accedere alla proprietà window.runtime (come invece può fare il contenuto in qualsiasi sandbox non dell'applicazione). In AIR 1.5, la classe HTMLLoader include una proprietà placeLoadStringContentInApplicationSandbox. Quando questa proprietà è impostata su true per un oggetto HTMLLoader, il contenuto caricato tramite il metodo loadString() viene inserito nella sandbox dell'applicazione. (Il valore predefinito è false). In questo modo il contenuto caricato tramite il metodo loadString() può accedere alla proprietà window.runtime e a tutte le API di AIR. Se impostate questa proprietà su true, accertatevi che l'origine dati per una stringa usata in una chiamata al metodo loadString() sia attendibile. Quando questa proprietà è impostata su true, le istruzioni del codice nella stringa HTML vengono eseguite con tutti i privilegi dell'applicazione. Impostate questa proprietà su true quando siete certi che la stringa non può contenere codice dannoso. Nelle applicazioni compilate con l'SDK di AIR 1.0 o di AIR 1.1, il contenuto caricato tramite il metodo loadString() viene inserito nella sandbox dell'applicazione. Importanti regole di sicurezza per l'uso del codice HTML nelle applicazioni AIR I file che installate con l'applicazione AIR hanno accesso alle API di AIR. Per ragioni di sicurezza, ciò non vale per il contenuto proveniente da altre origini. Ad esempio, questa limitazione impedisce al contenuto di un dominio remoto (ad esempio, http://example.com) di leggere il contenuto della directory Desktop dell'utente o effettuare attività più dannose. Poiché esistono falle nella sicurezza che possono essere sfruttate attraverso una chiamata alla funzione eval() (e API correlate), per impostazione predefinita il contenuto installato con l'applicazione ha limitazioni relativamente all'impiego di tali metodi. Tuttavia alcuni framework Ajax usano la chiamata alla funzione eval() e alle API correlate. Per strutturare correttamente il contenuto in modo da poterlo usare in un'applicazione AIR, dovete tenere in considerazione le regole sulle limitazioni della sicurezza per il contenuto proveniente da origini diverse. Il contenuto che proviene da origini diverse viene collocato in categorie di sicurezza distinte, chiamate sandbox (consultate “Funzioni di sicurezza sandbox” a pagina 29). Per impostazione predefinita, il contenuto installato con l'applicazione si trova in una sandbox dell'applicazione, per garantire al contenuto di poter accedere alle API di AIR. La sandbox dell'applicazione in genere è la sandbox più sicura, in quanto prevede restrizioni che impediscono l'esecuzione di codice non affidabile. Il runtime vi consente di caricare il contenuto installato con l'applicazione creata in una sandbox diversa dalla sandbox dell'applicazione. Il contenuto nelle sandbox non dell'applicazione opera in un ambiente di sicurezza simile a quello di un tipico browser Web. Ad esempio, il codice nelle sandbox non dell'applicazione può usare la funzione eval() e i metodi correlati (ma allo stesso tempo non può accedere alle API di AIR). Il runtime permette al contenuto di sandbox diverse di comunicare in sicurezza in vari modi (senza esporre le API di AIR al contenuto non dell'applicazione, ad esempio). Per ulteriori informazioni, consultate “Scambio di script per il contenuto presente in sandbox di sicurezza diverse” a pagina 251. Se chiamate un codice che per ragioni di sicurezza ha limitazioni d'uso in una sandbox, il runtime invia l'errore JavaScript “Adobe AIR runtime security violation for JavaScript code in the application security sandbox (Violazione della sicurezza di Adobe AIR in fase di runtime per il codice JavaScript nella sandbox dell'applicazione)”. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 238 Programmazione in HTML e JavaScript Per evitare questo errore, attenetevi alle pratiche di programmazione descritte nelle sezione successiva, “Errori JavaScript relativi alla sicurezza da evitare” a pagina 238. Per ulteriori informazioni, consultate “Sicurezza in HTML” a pagina 32. Errori JavaScript relativi alla sicurezza da evitare Se chiamate un codice che per queste ragioni di sicurezza ha limitazioni d'uso in una sandbox, il runtime invia l'errore JavaScript “Adobe AIR runtime security violation for JavaScript code in the application security sandbox (Violazione della sicurezza di Adobe AIR in fase di runtime per il codice JavaScript nella sandbox dell'applicazione)”. Per evitare questo errore, attenetevi alle seguenti pratiche di programmazione. Cause degli errori JavaScript relativi alla sicurezza Il codice eseguito nella sandbox dell'applicazione ha limitazioni per quanto riguarda gran parte delle operazioni che comportano la valutazione e l'esecuzione di stringhe dopo l'attivazione dell'evento load per il documento e dopo la chiusura di tutti i gestori di eventi load. Il tentativo di usare i seguenti tipi di istruzioni JavaScript che consentono di valutare ed eseguire stringhe potenzialmente non sicure provoca errori JavaScript: • Funzione eval() • setTimeout() e setInterval() • Funzione di costruzione Function Inoltre, i seguenti tipi di istruzioni JavaScript hanno un esito negativo ma non generano errori JavaScript di sicurezza: • URL JavaScript • Callback di eventi assegnati tramite gli attributi onevent nelle istruzioni innerHTML e outerHTML • Caricamento di file JavaScript da un percorso esterno alla directory di installazione dell'applicazione • document.write() e document.writeln() • XMLHttpRequests sincrone prima dell'evento load o durante la gestione dell'evento load • Elementi dello script creati dinamicamente Nota: in alcuni casi limitati, è permessa la valutazione delle stringhe. Per ulteriori informazioni, consultate “Restrizioni relative al codice per il contenuto presente in diverse sandbox” a pagina 34. Un elenco, gestito da Adobe, di framework Ajax che supportano la funzione sandbox di sicurezza dell'applicazione è disponibile all'indirizzo http://www.adobe.com/go/airappsandboxframeworks_it. Nelle sezioni che seguono viene descritto come riscrivere gli script per evitare la generazione di errori JavaScript di sicurezza e la comparsa di problemi senza segnalazioni di errori per il codice in esecuzione nella sandbox dell'applicazione. Mappatura del contenuto dell'applicazione su una sandbox diversa Nella maggior parte delle situazioni, potete riscrivere o cambiare la struttura di un'applicazione per evitare errori JavaScript di sicurezza. Tuttavia, quando non è possibile riscrivere o cambiare la struttura, potete caricare il contenuto dell'applicazione in una sandbox diversa usando la tecnica descritta in “Caricamento del contenuto delle applicazioni in una sandbox non dell'applicazione” a pagina 251. Se il contenuto deve anche accedere alle API di AIR, potete creare un bridge sandbox, come descritto in “Impostazione dell'interfaccia per un bridge sandbox” a pagina 252. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 239 Programmazione in HTML e JavaScript Funzione eval() Nella sandbox dell'applicazione, è possibile usare la funzione eval() solo prima dell'evento load della pagina o durante la gestione di eventi load. Al termine del caricamento della pagina, le chiamate a eval() non eseguiranno il codice. Tuttavia, nei seguenti casi potete riscrivere il codice per evitare l'uso della funzione eval(). Assegnazione di proprietà a un oggetto Invece di analizzare una stringa per creare la proprietà accessor: eval("obj." + propName + " = " + val); proprietà di accesso con la notazione tra parentesi: obj[propName] = val; Creazione di una funzione con variabili disponibili nel contesto Sostituite le istruzioni simili alle seguenti: function compile(var1, var2){ eval("var fn = function(){ this."+var1+"(var2) }"); return fn; } con: function compile(var1, var2){ var self = this; return function(){ self[var1](var2) }; } Creazione di un oggetto usando il nome della classe come parametro stringa Prendete in considerazione un'ipotetica classe JavaScript definita dal seguente codice: var CustomClass = { Utils: { Parser: function(){ alert('constructor') } }, Data: { } }; var constructorClassName = "CustomClass.Utils.Parser"; Il modo più semplice per creare un'istanza sarebbe quello di usare la funzione eval(): var myObj; eval('myObj=new ' + constructorClassName +'()') Tuttavia, potete evitare la chiamata a eval() analizzando ciascun componente del nome della classe e creando il nuovo oggetto con la notazione tra parentesi quadre: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 240 Programmazione in HTML e JavaScript function getter(str) { var obj = window; var names = str.split('.'); for(var i=0;i<names.length;i++){ if(typeof obj[names[i]]=='undefined'){ var undefstring = names[0]; for(var j=1;j<=i;j++) undefstring+="."+names[j]; throw new Error(undefstring+" is undefined"); } obj = obj[names[i]]; } return obj; } Per creare l'istanza, usate: try{ var Parser = getter(constructorClassName); var a = new Parser(); }catch(e){ alert(e); } setTimeout() e setInterval() Sostituite la stringa passata come funzione del gestore con un riferimento alla funzione o un oggetto. Ad esempio, sostituite un'istruzione del tipo: setTimeout("alert('Timeout')", 10); con: setTimeout(alert('Timeout'), 10); In alternativa, quando la funzione richiede l'impostazione dell'oggetto this da parte del chiamante, sostituite un'istruzione del tipo: this.appTimer = setInterval("obj.customFunction();", 100); con la seguente: var _self = this; this.appTimer = setInterval(function(){obj.customFunction.apply(_self);}, 100); Funzione di costruzione Function Le chiamate a new Function(param, body) possono essere sostituite con una dichiarazione di funzione in linea oppure possono essere usate solo prima della gestione dell'evento load della pagina. URL JavaScript Il codice definito in un collegamento con lo schema javascript: URL viene ignorato nella sandbox dell'applicazione. Non viene generato alcun errore JavaScript. Potete sostituire i collegamenti usando gli URL javascript:, ad esempio: <a href="javascript:code()">Click Me</a> con: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 241 Programmazione in HTML e JavaScript <a href="#" onclick="code()">Click Me</a> Callback di eventi assegnati tramite gli attributi onevent nelle istruzioni innerHTML e outerHTML Quando usate innerHTML o outerHTML per aggiungere elementi a un modello DOM di un documento, tutti i callback degli eventi assegnati all'interno dell'istruzione, ad esempio onclick o onmouseover, vengono ignorati. Non vengono generati errori di protezione. Al contrario, potete assegnare un attributo id ai nuovi elementi e impostare le funzioni di callback del gestore eventi usando il metodo addEventListener(). Ad esempio, dopo avere prefissato un elemento target in un documento, quale: <div id="container"></div> Sostituite le istruzioni simili a: document.getElementById('container').innerHTML = '<a href="#" onclick="code()">Click Me.</a>'; con: document.getElementById('container').innerHTML = '<a href="#" id="smith">Click Me.</a>'; document.getElementById('smith').addEventListener("click", function() { code(); }); Caricamento di file JavaScript da un percorso esterno alla directory di installazione dell'applicazione Il caricamento di file script da un percorso esterno alla sandbox dell'applicazione non è consentito. Non vengono generati errori di protezione. Tutti i file script in esecuzione nella sandbox dell'applicazione devono essere installati nella directory dell'applicazione. Per usare script esterni in una pagina, dovete mappare la pagina su una diversa sandbox. Consultate “Caricamento del contenuto delle applicazioni in una sandbox non dell'applicazione” a pagina 251. document.write() e document.writeln() Le chiamate a document.write() o document.writeln() vengono ignorate dopo che l'evento load della pagina è stato gestito. Non vengono generati errori di protezione. In alternativa, potete caricare un nuovo file o sostituire il corpo del documento usando le tecniche di manipolazione DOM. XMLHttpRequests sincrone prima dell'evento load o durante la gestione dell'evento load Le XMLHttpRequests sincrone prima dell'avvio di un evento load della pagina o durante la gestione dell'evento load non restituiscono alcun contenuto. Le XMLHttpRequests asincrone possono essere avviate, tuttavia non restituiranno contenuto fino al completamento dell'evento load. Dopo che l'evento load è stato gestito, le XMLHttpRequests sincrone si comportano normalmente. Elementi dello script creati dinamicamente Gli elementi dello script creati dinamicamente, ad esempio con innerHTML o con il metodo document.createElement, vengono ignorati. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 242 Programmazione in HTML e JavaScript Accesso alle classi API di AIR da JavaScript Oltre agli elementi standard ed estesi del Webkit, il codice HTML e JavaScript può accedere alle classi host fornite dal runtime. Queste classi consentono di accedere alle funzionalità avanzate di AIR, tra cui: • Accesso al file system • Uso di database SQL locali • Controllo dei menu delle applicazioni e delle finestre • Accesso ai socket per la connettività di rete • Uso di classi e oggetti definiti dall'utente • Funzionalità audio Ad esempio, l'API dei file di AIR include una classe File, contenuta nel pacchetto flash.filesystem. Potete creare un oggetto File in JavaScript come segue: var myFile = new window.runtime.flash.filesystem.File(); L'oggetto runtime è un oggetto JavaScript speciale, disponibile per il contenuto HTML in esecuzione in AIR nella sandbox dell'applicazione. Vi consente di accedere alle classi di runtime da JavaScript. La proprietà flash dell'oggetto runtime dà accesso al pacchetto flash. A sua volta, la proprietà flash.filesystem dell'oggetto runtime dà accesso al pacchetto flash.filesystem (che include la classe File). I pacchetti sono un modo di organizzare le classi usate in ActionScript. Nota: la proprietà runtime non viene aggiunta automaticamente agli oggetti window delle pagine caricate in un frame o iframe. Tuttavia, finché si trova nella sandbox dell'applicazione, il documento secondario può accedere alla proprietà runtime dell'oggetto principale. Poiché la struttura del pacchetto delle classi runtime richiederebbe agli sviluppatori di digitare lunghe stringhe di codice JavaScript per accedere ad ogni classe (come window.runtime.flash.desktop.NativeApplication), il kit AIR SDK include un file AIRAliases.js che consente di accedere alle classi runtime molto più facilmente (ad esempio, digitandolo solo air.NativeApplication). Le classi API di AIR vengono descritte nei capitoli di questa guida. Altri classi dell'API di Flash Player, che possono interessare gli sviluppatori HTML, sono descritte in Adobe AIR Language Reference for HTML Developers (Guida di riferimento del linguaggio Adobe AIR per sviluppatori HTML). ActionScript è il linguaggio usato per il contenuto dei file SWF (Flash Player). La sintassi dei linguaggi JavaScript e ActionScript è tuttavia simile, in quanto si basa su versioni del linguaggio ECMAScript. Tutte le classi incorporate sono disponibili sia in JavaScript (contenuto HTML) sia in ActionScript (contenuto SWF). Nota: il codice JavaScript non può usare le classi Dictionary, XML e XMLList, che sono disponibili in ActionScript. Uso del file AIRAliases.js Le classi di runtime sono organizzate in una struttura di pacchetti simile alla seguente: • window.runtime.flash.desktop.NativeApplication • window.runtime.flash.desktop.ClipboardManager • window.runtime.flash.filesystem.FileStream • window.runtime.flash.data.SQLDatabase SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 243 Programmazione in HTML e JavaScript Il kit AIR SDK include un file AIRAliases.js contenente definizioni alternative (alias), che vi consentono di accedere alle classi di runtime in modo più semplice. Ad esempio, potete accedere alle classi elencate sopra digitando semplicemente: • air.NativeApplication • air.Clipboard • air.FileStream • air.SQLDatabase Questo elenco rappresenta solo un piccolo sottoinsieme delle classi incluse nel file AIRAliases.js. L'elenco completo delle classi e delle funzioni a livello di pacchetto è disponibile in Adobe AIR Language Reference for HTML Developers (Guida di riferimento del linguaggio Adobe AIR per sviluppatori HTML). Oltre alle classi di runtime più usate, il file AIRAliases.js include gli alias per le funzioni a livello di pacchetto usate più frequentemente, ovvero window.runtime.trace(), window.runtime.flash.net.navigateToURL() e window.runtime.flash.net.sendToURL(), i cui alias sono rispettivamente air.trace(), air.navigateToURL() e air.sendToURL(). Per usare il file AIRAliases.js, aggiungete il seguente riferimento script nella pagina HTML: <script src="AIRAliases.js"></script> Modificate il percorso del riferimento src, secondo necessità. Importante: salvo nei casi espressamente indicati, i codici JavaScript di esempio riportati nella presente documentazione presuppongono che il file AIRAliases.js sia incluso nella pagina HTML. Informazioni sugli URL in AIR Nel contenuto HTML eseguito in AIR, potete usare i seguenti schemi URL per la definizione degli attributi src per i tag img, frame, iframe e script, dell'attributo href di un tag link e ovunque potete specificare un URL. Schema URL Descrizione Esempio file Un percorso relativo alla directory principale del file system. file:///c:/AIR Test/test.txt app Un percorso relativo alla directory principale dell'applicazione app:/images installata. app-storage Un percorso relativo alla directory di memorizzazione dell'applicazione. Per ogni applicazione installata, AIR definisce una directory univoca di memorizzazione dell'applicazione, che costituisce una comoda ubicazione in cui memorizzare i dati specifici di un'applicazione. app-storage:/settings/prefs.xml http Una richiesta HTTP standard. http://www.adobe.com https Una richiesta HTTPS standard. https://secure.example.com Per ulteriori informazioni sugli schemi URL in AIR, consultate “Uso di schermi URL AIR negli URL” a pagina 310. Molte delle API di AIR, incluse le classi File, Loader, URLStream e Sound, usano un oggetto URLRequest invece di una stringa contenente l'URL. L'oggetto URLRequest stesso viene inizializzato con una stringa, che può usare uno qualunque degli stessi schemi URL. Ad esempio, la seguente istruzione crea un oggetto URLRequest che può essere usato per richiedere l'home page di Adobe: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 244 Programmazione in HTML e JavaScript var urlReq = new air.URLRequest("http://www.adobe.com/"); Per ulteriori informazioni sugli oggetti URLRequest, consultate “Richieste URL e connettività di rete” a pagina 309. Uso degli oggetti di ActionScript in JavaScript Il codice JavaScript di una pagina HTML caricato da un oggetto HTMLLoader può chiamare classi, oggetti e funzioni, definiti nel contesto di esecuzione di ActionScript, usando le proprietà window.runtime, window.htmlLoader e window.nativeWindow della pagina HTML. Potete anche rendere disponibili gli oggetti e le funzioni di ActionScript per il codice di JavaScript creando riferimenti ad essi nel contesto di esecuzione di JavaScript. Un semplice esempio di accesso agli oggetti JavaScript da ActionScript Nel seguente esempio viene illustrato come aggiungere proprietà che si riferiscono agli oggetti ActionScript all'oggetto window globale di una pagina HTML: var html:HTMLLoader = new HTMLLoader(); var foo:String = "Hello from container SWF." function helloFromJS(message:String):void { trace("JavaScript says:", message); } var urlReq:URLRequest = new URLRequest("test.html"); html.addEventListener(Event.COMPLETE, loaded); html.load(urlReq); function loaded(e:Event):void{ html.window.foo = foo; html.window.helloFromJS = helloFromJS; } Il contenuto HTML (nel file test.html) caricato nell'oggetto HTMLLoader dell'esempio precedente può accedere alla proprietà foo e al metodo helloFromJS() definiti nel file SWF principale: <html> <script> function alertFoo() { alert(foo); } </script> <body> <button onClick="alertFoo()"> What is foo? </button> <p><button onClick="helloFromJS('Hi.')"> Call helloFromJS() function. </button></p> </body> </html> Quando accedete al contesto JavaScript di un documento che si sta caricando, potete usare l'evento htmlDOMInitialize per creare gli oggetti in una fase iniziale della sequenza di creazione della pagina, così da consentire a qualunque script definito nella pagina di accedervi. Se attendete il completamento dell'evento, solo gli script nella pagina che vengono eseguiti dopo l'evento load possono accedere agli oggetti aggiunti. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 245 Programmazione in HTML e JavaScript Uso delle definizioni delle classi in JavaScript Per fare in modo che le classi ActionScript della vostra applicazione siano disponibili in JavaScript, potete assegnare il contenuto HTML caricato al dominio dell'applicazione che contiene le definizioni delle classi. Il dominio dell'applicazione del contesto di esecuzione di JavaScript può essere impostato con la proprietà runtimeApplicationDomain dell'oggetto HTMLLoader. Per impostare il dominio dell'applicazione sul dominio dell'applicazione principale, ad esempio, impostate runtimeApplicationDomain su ApplicationDomain.currentDomain, come mostrato nel seguente codice: html.runtimeApplicationDomain = ApplicationDomain.currentDomain; Dopo che la proprietà runtimeApplicationDomain è impostata, il contesto JavaScript condivide le definizioni delle classi con il dominio assegnato. Per creare un'istanza di una classe personalizzata in JavaScript, richiamate la definizione della classe tramite la proprietà window.runtime e usate l'operatore new: var customClassObject = new window.runtime.CustomClass(); Il contenuto HTML deve provenire da un dominio di sicurezza compatibile. Se il contenuto HTML proviene da un dominio di sicurezza diverso dal dominio dell'applicazione assegnato, la pagina userà un dominio dell'applicazione predefinito al suo posto. Ad esempio, se caricaste una pagina remota da Internet, non potreste assegnare ApplicationDomain.currentDomain come dominio dell'applicazione per la pagina. Eliminazione dei listener di eventi Quando aggiungete i listener di eventi JavaScript a oggetti esterni alla pagina corrente, inclusi gli oggetti di runtime, gli oggetti nel contenuto SWF caricato e anche gli oggetti JavaScript in esecuzione in altre pagine, dovete sempre rimuovere quei listerner di eventi quando la pagina viene chiusa. In caso contrario, il listener di eventi invia l'evento a una funzione del gestore che non esiste più. Se ciò accade, viene visualizzato il seguente messaggio d'errore: “The application attempted to reference a JavaScript object in an HTML page that is no longer loaded. (L'applicazione ha tentato di fare riferimento a un oggetto JavaScript in una pagina che non è più caricata)." La rimozione dei listerner di eventi non più necessari permette ad AIR di riappropriarsi della memoria associata. Per ulteriori informazioni, consultate “Rimozione di listener di eventi in pagine HTML visualizzate” a pagina 259. Accesso agli oggetti JavaScript e al modello DOM HTML da ActionScript Dopo che l'oggetto HTMLLoader invia l'evento complete, potete accedere a tutti gli oggetti nel modello DOM (Document Object Model) HTML per la pagina. Gli oggetti a cui potete accedere includono gli elementi di visualizzazione (come gli oggetti div e p della pagina), nonché le variabili e le funzioni JavaScript. L'evento complete corrisponde all'evento JavaScript load della pagina. Prima che venga inviato l'evento complete, è possibile che non siano stati analizzati o creati gli elementi DOM, le variabili e le funzioni. Se possibile, attendere l'evento complete prima di accedere al modello DOM HTML. Ad esempio, esaminate la seguente pagina HTML: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 246 Programmazione in HTML e JavaScript <html> <script> foo = 333; function test() { return "OK."; } </script> <body> <p id="p1">Hi.</p> </body> </html> Questa semplice pagina HTML definisce una variabile JavaScript denominata foo e una funzione JavaScript denominata test(). Entrambe sono proprietà dell'oggetto window globale della pagina. Inoltre, l'oggetto window.document include un elemento chiamato P (con ID p1), a cui potete accedere usando il metodo the getElementById(). Dopo che la pagina è stata caricata (quando l'oggetto HTMLLoader invia l'evento complete), potete accedere a ognuno di questi oggetti da ActionScript, come mostrato nel seguente codice ActionScript: var html:HTMLLoader = new HTMLLoader(); html.width = 300; html.height = 300; html.addEventListener(Event.COMPLETE, completeHandler); var xhtml:XML = <html> <script> foo = 333; function test() { return "OK."; } </script> <body> <p id="p1">Hi.</p> </body> </html>; html.loadString(xhtml.toString()); function completeHandler(e:Event):void { trace(html.window.foo); // 333 trace(html.window.document.getElementById("p1").innerHTML); // Hi. trace(html.window.test()); // OK. } Per accedere a l contenuto di un elemento HTML, usate la proprietà innerHTML. Ad esempio, nel codice precedente si usa html.window.document.getElementById("p1").innerHTML per ottenere il contenuto dell'elemento HTML denominato p1. Potete anche impostare le proprietà della pagina HTML da ActionScript. Nel seguente esempio viene impostato il contenuto dell'elemento p1 e il valore della variabile JavaScript foo della pagina usando un riferimento all'oggetto HTMLLoader che li contiene: html.window.document.getElementById("p1").innerHTML = "Goodbye"; html.window.foo = 66; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 247 Programmazione in HTML e JavaScript Incorporamento del contenuto SWF nel contenuto HTML Potete incorporare il contenuto SWF nel contenuto HTML all'interno di un'applicazione AIR come se si trattasse di un browser. Incorporate il contenuto SWF usando un tag object, un tag embed o entrambi. Nota: nella programmazione Web si usa in genere sia un tag object che un tag embed per visualizzare il contenuto SWF in una pagina HTML. Questa pratica non comporta alcun vantaggio in AIR. Potete usare il tag object dello standard W3C da solo nel contenuto da visualizzare in AIR. Allo stesso tempo, potete continuare a usare i tag object ed embed insieme, se necessario, anche per il contenuto HTML da visualizzare in un browser. Nel seguente esempio viene mostrato l'uso del tag HTML object per visualizzare un file SWF all'interno del contenuto HTML. Il file SWF viene caricato da una directory dell'applicazione, ma potete usare qualunque schema URL supportato da AIR. La posizione dalla quale viene caricato il file SWF determina la sandbox di sicurezza in cui AIR colloca il contenuto. <object type="application/x-shockwave-flash" width="100%" height="100%"> <param name="movie" value="app:/SWFFile.swf"></param> </object> Potete anche usare uno script per caricare il contenuto dinamicamente. Nell'esempio seguente viene caricato un nodo object per visualizzare il file SWF specificato nel parametro urlString. Nell'esempio il nodo viene aggiunto come elemento secondario dell'elemento pagina con l'ID specificato dal parametro elementID: <script> function showSWF(urlString, elementID){ var displayContainer = document.getElementById(elementID); displayContainer.appendChild(createSWFObject(urlString,650,650)); } function createSWFObject(urlString, width, height){ var SWFObject = document.createElement("object"); SWFObject.setAttribute("type","application/x-shockwave-flash"); SWFObject.setAttribute("width","100%"); SWFObject.setAttribute("height","100%"); var movieParam = document.createElement("param"); movieParam.setAttribute("name","movie"); movieParam.setAttribute("value",urlString); SWFObject.appendChild(movieParam); return SWFObject; } </script> Uso delle librerie di ActionScript in una pagina HTML AIR estende l'elemento di script HTML in modo che una pagina possa importare le classi ActionScript in un file SWF compilato. Ad esempio, per importare la libreria myClasses.swf, che si trova nella sottodirectory lib della cartella principale dell'applicazione, inserite il seguente tag script nel file HTML: <script src="lib/myClasses.swf" type="application/x-shockwave-flash"></script> Importante: l'attributo type deve essere impostato come type="application/x-shockwave-flash" affinché la libreria possa essere caricata correttamente. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 248 Programmazione in HTML e JavaScript Se il contenuto SWF viene compilato come SWF di Flash Player 10 o di AIR 1.5, dovete impostare lo spazio dei nomi XML del file descrittore dell'applicazione sullo spazio dei nomi di AIR 1.5. Per ulteriori informazioni, consultate “Definizione delle proprietà nel file descrittore dell'applicazione” a pagina 47. È necessario includere anche la directory lib e il file myClasses.swf quando viene creato il pacchetto per il file AIR. Per accedere alle classi importate, usate la proprietà runtime dell'oggetto JavaScript Window: var libraryObject = new window.runtime.LibraryClass(); Se le classi nel file SWF sono organizzate in pacchetti, è necessario includere anche il nome del pacchetto. Ad esempio, se la definizione di LibraryClass si trova in un pacchetto denominato utilities, per creare un'istanza della classe dovete usare la seguente istruzione: var libraryObject = new window.runtime.utilities.LibraryClass(); Nota: per compilare una libreria SWF di ActionScript da usare all'interno di una pagina HTML in AIR, usate il compilatore acompc. L'utilità acompc fa parte del kit Flex 3 SDK ed è descritta nella documentazione del kit Flex 3 SDK. Accesso al modello DOM HTML e agli oggetti JavaScript da un file ActionScript importato Per accedere da ActionScript agli oggetti di una pagina HTML in un file SWF importato nella pagina usando il tag <script>, passate un riferimento all'oggetto JavaScript, ad esempio window o document, a una funzione definita nel codice ActionScript. Usate il riferimento all'interno della funzione per accedere all'oggetto JavaScript (o ad altri oggetti accessibili tramite il riferimento specificato). Ad esempio, esaminate la seguente pagina HTML: <html> <script src="ASLibrary.swf" type="application/x-shockwave-flash"></script> <script> num = 254; function getStatus() { return "OK."; } function runASFunction(window){ var obj = new runtime.ASClass(); obj.accessDOM(window); } </script> <body onload="runASFunction"> <p id="p1">Body text.</p> </body> </html> In questa semplice pagina HTML sono presenti una variabile JavaScript denominata num e una funzione JavaScript denominata getStatus(). Entrambe sono proprietà dell'oggetto window della pagina. Inoltre l'oggetto window.document include un elemento chiamato P (con ID p1). Questa pagina carica il file ActionScript “ASLibrary.swf” contenente la classe ASClass. A sua volta, la classe ASClass definisce una funzione chiamata accessDOM(), che tiene traccia dei valori di questi oggetti JavaScript. Il metodo accessDOM() accetta l'oggetto JavaScript Window come argomento. Usando questo riferimento Window, ottiene l'accesso ad altri oggetti della pagina, tra cui variabili, funzioni ed elementi DOM, come indicato nella seguente definizione: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 249 Programmazione in HTML e JavaScript public class ASClass{ public function accessDOM(window:*):void { trace(window.num); // 254 trace(window.document.getElementById("p1").innerHTML); // Body text.. trace(window.getStatus()); // OK. } } Potete sia ottenere che impostare le proprietà della pagina HTML da una classe ActionScript importata. Ad esempio, la seguente funzione imposta il contenuto dell'elemento p1 e il valore della variabile JavaScript foo nella pagina: public function modifyDOM(window:*):void { window.document.getElementById("p1").innerHTML = "Bye"; window.foo = 66; Conversione degli oggetti Date e RegExp I linguaggi JavaScript e ActionScript definiscono entrambi le classi Date e RegExp, ma i relativi oggetti non vengono convertiti automaticamente tra i due contesti di esecuzione. Dovrete convertire gli oggetti Date e RegExp nei tipi equivalenti prima di usarli per impostare le proprietà o i parametri delle funzioni nell'altro contesto di esecuzione. Nel seguente codice ActionScript, ad esempio, l'oggetto Date di JavaScript denominato jsDate viene convertito nell'oggetto Date di ActionScript: var asDate:Date = new Date(jsDate.getMilliseconds()); Nel seguente codice ActionScript, l'oggetto RegExp di JavaScript denominato jsRegExp viene convertito nell'oggetto RegExp di ActionScript: var flags:String = ""; if (jsRegExp.dotAll) flags += "s"; if (jsRegExp.extended) flags += "x"; if (jsRegExp.global) flags += "g"; if (jsRegExp.ignoreCase) flags += "i"; if (jsRegExp.multiline) flags += "m"; var asRegExp:RegExp = new RegExp(jsRegExp.source, flags); Elaborazione di un foglio di stile HTML in ActionScript Dopo che l'oggetto HTMLLoader invia l'evento complete, potete esaminare e modificare gli stili CSS nella pagina. Ad esempio, esaminate il semplice documento HTML seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 250 Programmazione in HTML e JavaScript <html> <style> .style1A { font-family:Arial; font-size:12px } .style1B { font-family:Arial; font-size:24px } </style> <style> .style2 { font-family:Arial; font-size:12px } </style> <body> <p class="style1A"> Style 1A </p> <p class="style1B"> Style 1B </p> <p class="style2"> Style 2 </p> </body> </html> Dopo che un oggetto HTMLLoader carica questo contenuto, potete modificare gli stili CSS nella pagina tramite l'array cssRules dell'array window.document.styleSheets, come mostrato di seguito: var html:HTMLLoader = new HTMLLoader( ); var urlReq:URLRequest = new URLRequest("test.html"); html.load(urlReq); html.addEventListener(Event.COMPLETE, completeHandler); function completeHandler(event:Event):void { var styleSheet0:Object = html.window.document.styleSheets[0]; styleSheet0.cssRules[0].style.fontSize = "32px"; styleSheet0.cssRules[1].style.color = "#FF0000"; var styleSheet1:Object = html.window.document.styleSheets[1]; styleSheet1.cssRules[0].style.color = "blue"; styleSheet1.cssRules[0].style.font-family = "Monaco"; } In questo codice gli stili CSS vengono modificati in modo tale da conferire al documento HTML finale il seguente aspetto: Tenete presente che il codice può aggiungere stili alla pagina solo dopo che l'oggetto HTMLLoader ha inviato l'evento complete. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 251 Programmazione in HTML e JavaScript Scambio di script per il contenuto presente in sandbox di sicurezza diverse Il modello di sicurezza del runtime isola il codice con origini diverse. Grazie allo scambio di script a livello di contenuto tra le diverse sandbox di sicurezza, potete permettere al contenuto in una sandbox di accedere a determinate proprietà e determinati metodi di un'altra sandbox. Sandbox di sicurezza di AIR e codice JavaScript AIR implementa il criterio dell'origine comune, al fine di impedire che il codice in un dominio interagisca con il contenuto in altri domini. Tutti i file in una sandbox hanno un'origine comune. In termini generali, il contenuto nella sandbox dell'applicazione non può violare il principio dell'origine comune, né eseguire lo scambio di script per contenuti caricati da un percorso esterno alla directory di installazione dell'applicazione. AIR fornisce tuttavia alcune tecniche che consentono di eseguire lo scambio di script per il contenuto non dell'applicazione. Una tecnica consiste nell'usare i tag frame e iframe per mappare il contenuto dell'applicazione su una sandbox di sicurezza diversa. Tutte le pagine caricate dall'area interna alla sandbox dell'applicazione si comportano come se fossero caricate da un dominio remoto. Ad esempio, se il contenuto dell'applicazione viene mappato sul dominio example.com, tale contenuto potrà eseguire lo scambio di script per le pagine caricate da example.com. Poiché in questo modo il contenuto dell'applicazione viene collocato in una sandbox diversa, il codice all'interno del contenuto non sarà più soggetto alle restrizioni riguardanti l'esecuzione di codice nelle stringhe sottoposte a valutazione. Potete usare la tecnica di mappatura della sandbox per aggirare queste restrizioni anche nel caso in cui non dobbiate eseguire lo scambio di script per il contenuto remoto. Questo tipo di mappatura del contenuto è molto utile quando si lavora con uno dei numerosi framework JavaScript o con il codice esistente basato su stringhe di valutazione. Tuttavia, quando il contenuto viene eseguito all'esterno della sandbox dell'applicazione dovete tenere presente (e tutelarvi di conseguenza) che esiste il rischio di introduzione ed esecuzione di eventuale contenuto non affidabile. Allo stesso tempo, quando il contenuto dell'applicazione viene mappato su una sandbox diversa perde la possibilità di accedere alle API di AIR, pertanto questa tecnica di mappatura non può essere usata per esporre le funzionalità di AIR al codice eseguito all'esterno della sandbox dell'applicazione. Un'altra tecnica per lo scambio di script è quella che consente di creare un'interfaccia denominata bridge sandbox tra il contenuto di una sandbox non appartenente all'applicazione e il documento principale nella sandbox dell'applicazione. Il bridge consente al contenuto secondario di accedere a proprietà e metodi definiti dal documento principale, e al documento principale di accedere a proprietà e metodi definiti dal documento secondario. Infine potete anche eseguire richieste XMLHttpRequests tra i domini dalla sandbox dell'applicazione e, facoltativamente, da altre sandbox. Per ulteriori informazioni, consultate “Elementi frame e iframe HTML” a pagina 230, “Sicurezza in HTML” a pagina 32 e “Oggetto XMLHttpRequest” a pagina 224. Caricamento del contenuto delle applicazioni in una sandbox non dell'applicazione Per consentire lo scambio di script del contenuto dell'applicazione dall'esterno della directory di installazione dell'applicazione, potete usare gli elementi frame o iframe per caricare il contenuto dell'applicazione nella stessa sandbox di sicurezza del contenuto esterno. Se non dovete eseguire lo scambio di script di contenuto remoto, ma desiderate comunque caricare una pagina dell'applicazione all'esterno della sandbox dell'applicazione, potete usare la stessa tecnica indicando http://localhost/, o un altro valore sicuro, come dominio di origine. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 252 Programmazione in HTML e JavaScript AIR aggiunge i nuovi attributi, sandboxRoot e documentRoot, all'elemento frame che consente di stabilire se il file di un'applicazione caricato nel frame deve essere mappato su una sandbox non dell'applicazione. I file che risolvono un percorso sotto l'URL sandboxRoot sono invece caricati dalla directory documentRoot. Per ragioni di sicurezza, il contenuto dell'applicazione caricato in questo modo viene trattato come se fosse realmente caricato dall'URL sandboxRoot. La proprietà sandboxRoot specifica l'URL da usare per determinare la sandbox e il dominio in cui collocare il contenuto dell'elemento frame. È necessario usare gli schemi URL file:, http: o https:. Se specificate un URL relativo, il contenuto rimane nella sandbox dell'applicazione. La proprietà documentRoot specifica la directory da cui caricare il contenuto dell'elemento frame. È necessario usare gli schemi URL file:, app: o app-storage:. Nel seguente esempio, il contenuto installato nella sottodirectory sandbox dell'applicazione viene mappato in modo da poter essere eseguito nella sandbox remota e nel domino www.example.com: <iframe src="http://www.example.com/local/ui.html" sandboxRoot="http://www.example.com/local/" documentRoot="app:/sandbox/"> </iframe> La pagina ui.html può caricare un file javascript dalla cartella locale sandbox usando il seguente tag script: <script src="http://www.example.com/local/ui.js"></script> Può inoltre caricare contenuto da una directory del server remoto usando un tag script simile al seguente: <script src="http://www.example.com/remote/remote.js"></script> L'URL sandboxRoot nasconderà tutto il contenuto con lo stesso URL sul server remoto. Con l'esempio precedente non potete accedere al contenuto remoto presente in www.example.com/local/ (e relative sottodirectory) in quanto AIR rimappa la richiesta sulla directory locale dell'applicazione. Le richieste vengono rimappate sia che provengano dalla navigazione della pagina, da un oggetto XMLHttpRequest o da altri strumenti di caricamento del contenuto. Impostazione dell'interfaccia per un bridge sandbox Potete usare un bridge sandbox quando il contenuto nella sandbox dell'applicazione deve accedere a proprietà o metodi definiti dal contenuto in una sandbox non dell'applicazione, o quando il contenuto di una sandbox non dell'applicazione deve accedere a proprietà o metodi definiti dal contenuto nella sandbox dell'applicazione. Create un bridge con le proprietà childSandboxBridge e parentSandboxBridge dell'oggetto window di un documento secondario qualunque. Impostazione di un bridge sandbox secondario La proprietà childSandboxBridge consente al documento secondario di esporre un'interfaccia al contenuto nel documento principale. Per esporre un'interfaccia, impostate la proprietà childSandbox su una funzione o un oggetto nel documento secondario. Potete quindi accedere all'oggetto o alla funzione dal contenuto nel documento principale. L'esempio seguente mostra come uno script eseguito in un documento secondario possa esporre un oggetto contenente una funzione e una proprietà al documento principale: var interface = {}; interface.calculatePrice = function(){ return ".45 cents"; } interface.storeID = "abc" window.childSandboxBridge = interface; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 253 Programmazione in HTML e JavaScript Se il contenuto secondario è stato caricato in un elemento iframe e associato a un id “child”, potete accedere all'interfaccia tramite il contenuto principale leggendo la proprietà childSandboxBridge dell'elemento frame: var childInterface = document.getElementById("child").contentWindow.childSandboxBridge; air.trace(childInterface.calculatePrice()); //traces ".45 cents" air.trace(childInterface.storeID)); //traces "abc" Impostazione di un bridge sandbox principale La proprietà parentSandboxBridge consente al documento principale di esporre un'interfaccia al contenuto nel documento secondario. Per esporre un'interfaccia, il documento principale imposta la proprietà parentSandbox del documento secondario su una funzione o un oggetto definiti nel documento principale. A questo punto potete accedere all'oggetto o alla funzione dal contenuto nel documento secondario. L'esempio seguente mostra come uno script eseguito in un documento principale possa esporre un oggetto contenente una funzione a un documento secondario: var interface = {}; interface.save = function(text){ var saveFile = air.File("app-storage:/save.txt"); //write text to file } document.getElementById("child").contentWindow.parentSandboxBridge = interface; Usando questa interfaccia, il contenuto nel frame secondario potrebbe salvare il testo in un file denominato save.txt, ma non avrebbe alcun altro tipo di accesso al file system. Il contenuto secondario può chiamare la funzione save nel seguente modo: var textToSave = "A string."; window.parentSandboxBridge.save(textToSave); Il contenuto dell'applicazione deve esporre alle altre sandbox un'interfaccia il più ridotta possibile. Il contenuto non dell'applicazione deve essere considerato non affidabile, in quanto può essere soggetto all'inserimento accidentale o deliberato di codice dannoso. È necessario salvaguardarsi in modo adeguato per prevenire qualunque abuso dell'interfaccia esposta con il bridge sandbox principale. Impostazione di un bridge sandbox principale durante il caricamento della pagina Affinché lo script di un documento secondario possa accedere a un bridge sandbox secondario, il bridge deve essere impostato prima dell'esecuzione dello script. Gli oggetti Window, frame e iframe inviano un evento dominitialize quando viene creato un modello DOM per una nuova pagina, ma prima dell'analisi di qualunque script o dell'aggiunta degli elementi DOM. Potete usare l'evento dominitialize per impostare il bridge nelle fasi iniziali della sequenza di creazione della pagina, così da permettere a tutti gli script del documento secondario di accedervi. Il seguente esempio mostra come creare un bridge sandbox principale in risposta a un evento dominitialize inviato dal frame secondario: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 254 Programmazione in HTML e JavaScript <html> <head> <script> var bridgeInterface = {}; bridgeInterface.testProperty = "Bridge engaged"; function engageBridge(){ document.getElementById("sandbox").contentWindow.parentSandboxBridge = bridgeInterface; } </script> </head> <body> <iframe id="sandbox" src="http://www.example.com/air/child.html" documentRoot="app:/" sandboxRoot="http://www.example.com/air/" ondominitialize="engageBridge()"/> </body> </html> Nel seguente documento child.html. il contenuto secondario può accedere al bridge sandbox principale: <html> <head> <script> document.write(window.parentSandboxBridge.testProperty); </script> </head> <body></body> </html> Per intercettare l'evento dominitialize in una finestra secondaria, anziché in un frame, dovete aggiungere il listener al nuovo oggetto secondario window creato dalla funzione window.open(): var childWindow = window.open(); childWindow.addEventListener("dominitialize", engageBridge()); childWindow.document.location = "http://www.example.com/air/child.html"; In questo caso non vi è modo di mappare il contenuto dell'applicazione su una sandbox di sicurezza non dell'applicazione. Questa tecnica è utile solo nel caso in cui il file child.html venga caricato da un percorso esterno alla directory dell'applicazione. Potete sempre mappare il contenuto dell'applicazione presente nella finestra su una sandbox non dell'applicazione, ma prima dovrete caricare una pagina intermedia, anch'essa basata sui frame, per caricare il documento secondario e mapparlo sulla sandbox desiderata. Se usate la funzione createRootWindow() della classe HTMLLoader per creare una finestra, la nuova finestra non sarà secondaria rispetto al documento da cui viene chiamata la funzione createRootWindow(). Pertanto, non potete creare un bridge sandbox tra la finestra chiamante e il contenuto non dell'applicazione caricato nella nuova finestra. Dovrete invece caricare una pagina intermedia nella nuova finestra, anch'essa basata sui frame, per caricare il documento secondario. Potete impostare il bridge tra il documento principale della nuova finestra e il documento secondario caricato nel frame. 255 Capitolo 22: Gestione di eventi relativi a HTML Un sistema di gestione degli eventi permette ai programmatori di elaborare risposte adeguate all'input degli utenti e agli eventi del sistema. Il modello di eventi di Adobe® AIR™ non è solo utile, ma anche conforme agli standard. Questo modello di eventi, che si basa sulla specifica DOM (Document Object Model) Level 3, un'architettura di gestione degli eventi considerata uno standard del settore, è uno strumento di gestione degli eventi efficace e al contempo intuitivo dedicato ai programmatori. Eventi HTMLLoader Un oggetto HTMLLoader invia i seguenti eventi di Adobe® ActionScript® 3.0: Evento Descrizione htmlDOMInitialize Inviato quando si crea il documento HTML, ma prima dell'analisi di qualsiasi script o dell'aggiunta di nodi DOM alla pagina. complete Inviato quando l'HTML DOM è stato creato in risposta a un'operazione di carico, immediatamente dopo l'evento onload nella pagina HTML. htmlBoundsChanged Inviato quando si sono modificate una o entrambe le proprietà contentWidth e contentHeight. locationChange Inviato quando si è modificata la proprietà location dell'HTMLLoader. scroll Inviato ogni qual volta il motore HTML cambia la posizione di scroll. Possono essere eventi scroll per lo spostamento a collegamenti di ancoraggio (#) nella pagina o per chiamate al metodo window.scrollTo(). L'inserimento di testo in un'area testo o ingresso testo può inoltre determinare un evento scroll. uncaughtScriptException Inviato quando si verifica un'eccezione JavaScript nell'HTMLLoader e l'eccezione non viene identificata nel codice JavaScript. È possibile inoltre registrare una funzione ActionScript per un evento JavaScript (come onClick). Per informazioni dettagliate, consultate “Gestione di eventi DOM con ActionScript” a pagina 255. Gestione di eventi DOM con ActionScript È possibile registrare le funzioni ActionScript per rispondere a eventi JavaScript. Ad esempio, considerate il seguente elemento HTML: <html> <body> <a href="#" id="testLink">Click me.</a> </html> È possibile registrare una funzione ActionScript come gestore di qualsiasi evento nella pagina. Ad esempio, il codice seguente aggiunge la funzione clickHandler() come listener per l'evento onclick dell'elemento testLink nella pagina HTML: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 256 Gestione di eventi relativi a HTML var html:HTMLLoader = new HTMLLoader( ); var urlReq:URLRequest = new URLRequest("test.html"); html.load(urlReq); html.addEventListener(Event.COMPLETE, completeHandler); function completeHandler(event:Event):void { html.window.document.getElementById("testLink").onclick = clickHandler; } function clickHandler():void { trace("You clicked it!"); } È possibile utilizzare inoltre il metodo addEventListener() per registrare per questi eventi. Ad esempio, è possibile sostituire il metodo completeHandler() nell'esempio precedente con il codice seguente: function completeHandler(event:Event):void { var testLink:Object = html.window.document.getElementById("testLink"); testLink.addEventListener("click", clickHandler); } Quando un listener fa riferimento a un elemento DOM specifico, è consigliabile attendere il principale HTMLLoader per inviare l'evento complete prima di aggiungere i listener di eventi. Le pagine HTML spesso caricano più file e l'HTML DOM non è completamente realizzato finché tutti i file non vengono caricati e analizzati. L'HTMLLoader invia l'elemento complete quando sono stati creati tutti gli elementi. Risposta a eccezioni JavaScript non identificate Considerate il seguente codice HTML: <html> <head> <script> function throwError() { var x = 400 * melbaToast; } </script> </head> <body> <a href="#" onclick="throwError()">Click me.</a> </html> Contiene una funzione JavaScript, throwError(), che fa riferimento a una variabile sconosciuta, melbaToast: var x = 400 * melbaToast; Quando un'operazione JavaScript rileva un'operazione errata che non è identificata nel codice JavaScript con un struttura try/catch, l'oggetto HTMLLoader contenente la pagina invia un evento HTMLUncaughtScriptExceptionEvent. È possibile registrare un gestore per questo evento, come nel codice seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 257 Gestione di eventi relativi a HTML var html:HTMLLoader = new HTMLLoader(); var urlReq:URLRequest = new URLRequest("test.html"); html.load(urlReq); html.width = container.width; html.height = container.height; container.addChild(html); html.addEventListener(HTMLUncaughtScriptExceptionEvent.UNCAUGHT_SCRIPT_EXCEPTION, htmlErrorHandler); function htmlErrorHandler(event:HTMLUncaughtJavaScriptExceptionEvent):void { event.preventDefault(); trace("exceptionValue:", event.exceptionValue) for (var i:int = 0; i < event.stackTrace.length; i++) { trace("sourceURL:", event.stackTrace[i].sourceURL); trace("line:", event.stackTrace[i].line); trace("function:", event.stackTrace[i].functionName); } } In JavaScript, è possibile gestire lo stesso evento mediante la proprietà window.htmlLoader: <html> <head> <script language="javascript" type="text/javascript" src="AIRAliases.js"></script> <script> function throwError() { var x = 400 * melbaToast; } function htmlErrorHandler(event) { event.preventDefault(); var message = "exceptionValue:" + event.exceptionValue + "\n"; for (var i = 0; i < event.stackTrace.length; i++){ message += "sourceURL:" + event.stackTrace[i].sourceURL +"\n"; message += "line:" + event.stackTrace[i].line +"\n"; message += "function:" + event.stackTrace[i].functionName + "\n"; } alert(message); } window.htmlLoader.addEventListener("uncaughtScriptException", htmlErrorHandler); </script> </head> <body> <a href="#" onclick="throwError()">Click me.</a> </html> Il gestore eventi htmlErrorHandler() annulla il comportamento predefinito dell'evento (che deve inviare il messaggio di errore di JavaScript alcun output di tracciamento AIR) e genera il relativo messaggio di output. Emette il valore di exceptionValue dell'oggetto HTMLUncaughtScriptExceptionEvent. Emette la proprietà di ciascun oggetto nell'array stackTrace: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 258 Gestione di eventi relativi a HTML exceptionValue: ReferenceError: Can't find variable: melbaToast sourceURL: app:/test.html line: 5 function: throwError sourceURL: app:/test.html line: 10 function: onclick Gestione di eventi runtime con JavaScript Le classi runtime supportano altri gestori di eventi con il metodo addEventListener(). Per aggiungere una funzione di gestore per un evento, chiamate il metodo addEventListener() dell'oggetto che invia l'evento, offrendo il tipo di evento e la funzione di gestione. Ad esempio, per intercettare l'evento closing inviato quando un utente fa clic sul pulsante di chiusura della finestra nella barra del titolo, utilizzate la seguente istruzione: window.nativeWindow.addEventListener(air.NativeWindow.CLOSING, handleWindowClosing); Creazione di una funzione di gestore eventi Il codice seguente crea un semplice file HTML che visualizza informazioni sulla posizione della finestra principale. Un funzione gestore denominata moveHandler() intercetta un evento di spostamento (definito dalla classe NativeWindowBoundsEvent) della finestra principale. <html> <script src="AIRAliases.js" /> <script> function init() { writeValues(); window.nativeWindow.addEventListener(air.NativeWindowBoundsEvent.MOVE, moveHandler); } function writeValues() { document.getElementById("xText").value = window.nativeWindow.x; document.getElementById("yText").value = window.nativeWindow.y; } function moveHandler(event) { air.trace(event.type); // move writeValues(); } </script> <body onload="init()" /> <table> <tr> <td>Window X:</td> <td><textarea id="xText"></textarea></td> </tr> <tr> <td>Window Y:</td> <td><textarea id="yText"></textarea></td> </tr> </table> </body> </html> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 259 Gestione di eventi relativi a HTML Quando un utente sposta la finestra, gli elementi textarea visualizzano le posizioni X e Y aggiornate della finestra: Notate che l'oggetto evento viene passato come argomento al metodo moveHandler(). Il parametro evento consente alla funzione del gestore di esaminare l'oggetto evento. In questo esempio, si usa la proprietà type dell'oggetto evento per riportare che l'evento è un evento move. Eliminazione dei listener di eventi Per rimuovere i listener di eventi inutilizzati si può usare il metodo removeEventListener(). È buona norma rimuovere i listener diventati superflui. I parametri obbligatori sono eventName e listener, cioè gli stessi parametri del metodo addEventListener(). Rimozione di listener di eventi in pagine HTML visualizzate Quando si visualizza contenuto HTML o quando tale contenuto viene eliminato perché una finestra che lo contiene viene chiusa, i listener di eventi che fanno riferimento a oggetti presenti in una pagina non caricata vengono automaticamente rimossi. Quando un oggetto invia un evento a un gestore che è già stato caricato, viene visualizzato il seguente messaggio di errore: "The application attempted to reference a JavaScript object in an HTML page that is no longer loaded." (L'applicazione ha tentato di fare riferimento a un oggetto JavaScript in un pagina HTML che non è più caricata). Per evitare questo errore, eliminare i listener di eventi JavaScript in una pagina HTML prima che scompaia. Nel caso di spostamento di pagine (in un oggetto HTMLLoader), eliminare il listener di eventi durante l'evento unload dell'oggetto window. Ad esempio, il seguente codice JavaScript rimuove un listener di eventi per un oggetto uncaughtScriptException: window.onunload = cleanup; window.htmlLoader.addEventListener('uncaughtScriptException', uncaughtScriptException); function cleanup() { window.htmlLoader.removeEventListener('uncaughtScriptException', uncaughtScriptExceptionHandler); } Per evitare il verificarsi dell'errore quando si chiudono le finestre contenenti il contenuto HTML, chiamate una funzione di pulizia in risposta all'evento closing dell'oggetto NativeWindow (window.nativeWindow). Ad esempio, il seguente codice JavaScript rimuove un listener di eventi per un oggetto uncaughtScriptException: window.nativeWindow.addEventListener(air.Event.CLOSING, cleanup); function cleanup() { window.htmlLoader.removeEventListener('uncaughtScriptException', uncaughtScriptExceptionHandler); } È possibile inoltre evitare questo errore eliminando un listener di eventi non appena viene eseguito. Ad esempio, il seguente codice JavaScript crea una finestra html chiamando il metodo createRootWindow() della classe HTMLLoader e aggiunge un listener di eventi per l'evento complete. Quando viene chiamato il gestore eventi complete, elimina il relativo listener di eventi mediante la funzione removeEventListener(): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 260 Gestione di eventi relativi a HTML var html = runtime.flash.html.HTMLLoader.createRootWindow(true); html.addEventListener('complete', htmlCompleteListener); function htmlCompleteListener() { html.removeEventListener(complete, arguments.callee) // handler code.. } html.load(new runtime.flash.net.URLRequest("second.html")); La rimozione di listener di eventi non necessari consente inoltre che il garbage collector del sistema riutilizzi qualsiasi memoria associata a tali listener. Verifica della presenza di listener di eventi Il metodo hasEventListener() permette di verificare la presenza di un listener di eventi in un oggetto. 261 Capitolo 23: Creazione di script per il contenitore HTML La classe HTMLLoader funge da contenitore per il contenuto HTML in Adobe® AIR™. Questa classe fornisce molti metodi e proprietà, ereditati dalla classe Sprite, per controllare il comportamento e l'aspetto dell'oggetto nell'elenco di visualizzazione di ActionScript® 3.0. Definisce inoltre le proprietà e i metodi per attività quali il caricamento e l'interazione con il contenuto HTML e la gestione della cronologia. La classe HTMLHost definisce un insieme di comportamenti predefiniti per un HTMLLoader. Quando create un oggetto HTMLLoader, non viene fornita alcuna implementazione di HTMLHost. Pertanto, quando il contenuto HTML attiva uno dei comportamenti predefiniti, ad esempio la modifica della posizione o del titolo della finestra, non si ottiene alcun risultato. Potete estendere la classe HTMLHost per definire i comportamenti desiderati per la vostra applicazione. Viene fornita un'implementazione predefinita di HTMLHost per le finestre HTML create da AIR. Potete assegnare l'implementazione di HTMLHost a un altro oggetto HTMLLoader mediante l'impostazione della proprietà htmlHost dell'oggetto usando il nuovo oggetto creato con il parametro defaultBehavior impostato su true. Proprietà di visualizzazione degli oggetti HTMLLoader Un oggetto HTMLLoader eredita le proprietà di visualizzazione della classe Sprite di Adobe® Flash® Player. Potete ridimensionare, spostare, nascondere e modificare, ad esempio, il colore di sfondo. In alternativa potete applicare effetti avanzati come filtri, maschere, modifica in scala e rotazione. Quando applicate degli effetti, tenete presente il possibile impatto sulla leggibilità. Il contenuto SWF e PDF caricato in una pagina HTML non può essere visualizzato quando vengono applicati determinati effetti. Nelle finestre HTML è presente un oggetto HTMLLoader che esegue il rendering del contenuto HTML. Questo oggetto è vincolato all'interno dell'area della finestra, quindi la modifica delle dimensioni, della posizione, della rotazione o del fattore di scala non produce sempre risultati desiderabili. Proprietà di visualizzazione di base Le proprietà di visualizzazione di base di HTMLLoader consentono di posizionare il controllo all'interno dell'oggetto di visualizzazione principale, di impostare le dimensioni e di visualizzare o nascondere il controllo. Evitate di modificare queste proprietà per l'oggetto HTMLLoader di una finestra HTML. Le proprietà di base comprendono: Proprietà Note x, y Inserisce l'oggetto all'interno del relativo contenitore principale. width, height Modifica le dimensioni dell'area di visualizzazione. visible Controlla la visibilità dell'oggetto e dell'eventuale contenuto al suo interno. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 262 Creazione di script per il contenitore HTML Al di fuori di una finestra HTML, il valore predefinito delle proprietà width e height di un oggetto HTMLLoader è 0. Per poter visualizzare il contenuto HTML caricato, dovete impostare la larghezza e l'altezza. Il contenuto HTML viene disegnato in base alle dimensioni di HTMLLoader e disposto secondo le proprietà HTML e CSS nel contenuto. La modifica delle dimensioni di HTMLLoader comporta la ridisposizione del contenuto. Quando caricate del contenuto in un nuovo oggetto HTMLLoader (con la proprietà width impostata su 0), potreste essere tentati di impostare le proprietà di visualizzazione width e height di HTMLLoader utilizzando le proprietà contentWidth e contentHeight. Questa tecnica funziona per le pagine che, una volta disposte in base alle regole del flusso HTML e CSS, presentano una larghezza minima adeguata. Tuttavia, in assenza di una larghezza adeguata specificata mediante HTMLLoader, alcune pagine vengono disposte con un layout stretto e lungo. Nota: quando modificate la larghezza e l'altezza di un oggetto HTMLLoader, i valori scaleX e scaleY non vengono modificati come avverrebbe con la maggior parte degli altri tipi di oggetti di visualizzazione. Trasparenza del contenuto di HTMLLoader La proprietà paintsDefaultBackground di un oggetto HTMLLoader, che è true per impostazione predefinita, determina se l'oggetto HTMLLoader disegna uno sfondo opaco. Quando paintsDefaultBackground è false, lo sfondo è trasparente. Il contenitore di oggetti di visualizzazione o altri oggetti di visualizzazione al di sotto dell'oggetto HTMLLoader sono visibili dietro gli elementi di primo piano del contenuto HTML. Se l'elemento del corpo o qualsiasi altro elemento del documento HTML specifica un colore di sfondo (usando ad esempio style="background-color:gray"), lo sfondo di quella parte del contenuto HTML risulta opaco e ne viene eseguito il rendering con il colore di sfondo specificato. Se impostate la proprietà opaqueBackground dell'oggetto HTMLLoader, e paintsDefaultBackground èfalse, il colore impostato per opaqueBackground risulta visibile. Nota: potete usare un elemento grafico trasparente in formato PNG per fornire uno sfondo alfa sfumato per un elemento in un documento HTML. L'impostazione di uno stile di opacità per un elemento HTML non è supportato. Modifica in scala del contenuto di HTMLLoader Evitate di modificare in scala un oggetto HTMLLoader oltre un fattore di scala di 1.0. Il rendering del testo nel contenuto di HTMLLoader viene eseguito con una risoluzione specifica e risulta pixelizzato se l'oggetto HTMLLoader viene ingrandito in scala. Per impedire la modifica in scala di HTMLLoader, e del relativo contenuto, quando una finestra viene ridimensionata, impostate la proprietà scaleMode dello stage su StageScaleMode.NO_SCALE. Considerazioni relative al caricamento di contenuto SWF o PDF in una pagina HTML Il contenuto SWF e PDF caricato in un oggetto HTMLLoader non viene visualizzato nelle seguenti condizioni: • Modificate in scala l'oggetto HTMLLoader oltre un fattore di 1.0. • Impostate la proprietà alpha dell'oggetto HTMLLoader su un valore diverso da 1.0. • Ruotate il contenuto di HTMLLoader. Il contenuto viene visualizzato di nuovo se rimuovete l'impostazione errata della proprietà e i filtri attivi. Nota: il runtime non è in grado di visualizzare il contenuto SWF o PDF nelle finestre trasparenti. Per ulteriori informazioni sul caricamento di questi tipi di contenuto multimediale in un HTMLLoader, consultate “Incorporamento del contenuto SWF nel contenuto HTML” a pagina 247 e “Aggiunta di contenuto PDF” a pagina 275. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 263 Creazione di script per il contenitore HTML Proprietà di visualizzazione avanzate La classe HTMLLoader eredita diversi metodi che potete usare per gli effetti speciali. In generale, questi effetti presentano limitazioni se vengono usati con l'oggetto di visualizzazione HTMLLoader, ma possono risultare utili per transizioni o altri effetti temporanei. Se, ad esempio, visualizzate una finestra di dialogo per raccogliere l'input dell'utente, potete fare in modo che la visualizzazione della finestra principale risulti sfocata finché l'utente non l'avrà chiusa. In modo analogo, potete applicare alla visualizzazione una dissolvenza in uscita quando la finestra viene chiusa. Le proprietà di visualizzazione avanzate includono: Proprietà Limitazioni alpha Può ridurre la leggibilità del contenuto HTML filters In una finestra HTML, gli effetti esterni vengono troncati dal bordo della finestra graphics Le forme disegnate con comandi di grafica vengono visualizzate sotto al contenuto HTML, ivi compreso lo sfondo predefinito. La proprietà paintsDefaultBackground deve essere false per rendere visibili le forme disegnate. opaqueBackground Non modifica il colore dello sfondo predefinito. La proprietà paintsDefaultBackground deve essere false per rendere visibile questo livello di colore. rotation Gli angoli dell'area rettangolare di HTMLLoader può essere ritagliata dal bordo della finestra. Il contenuto SWF e PDF caricato nel contenuto HTML non viene visualizzato. scaleX, scaleY La visualizzazione di cui è stato eseguito il rendering può apparire pixelizzata se usate fattori di scala maggiori di 1. Il contenuto SWF e PDF caricato nel contenuto HTML non viene visualizzato. transform Può ridurre la leggibilità del contenuto HTML. La visualizzazione HTML può essere ritagliata dal bordo della finestra. Il contenuto SWF e PDF caricato nel contenuto HTML non viene visualizzato se la trasformazione comporta un effetto di rotazione, modifica in scala o inclinazione. Nel seguente esempio viene illustrato come impostare l'array filters per sfocare l'intera visualizzazione HTML: var html:HTMLLoader = new HTMLLoader(); var urlReq:URLRequest = new URLRequest("http://www.adobe.com/"); html.load(urlReq); html.width = 800; html.height = 600; var blur:BlurFilter = new BlurFilter(8); var filters:Array = [blur]; html.filters = filters; Scorrimento del contenuto HTML La classe HTMLLoader include le seguenti proprietà che consentono di controllare lo scorrimento del contenuto HTML: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 264 Creazione di script per il contenitore HTML Proprietà Descrizione contentHeight L'altezza in pixel del contenuto HTML. contentWidth La larghezza in pixel del contenuto HTML. scrollH La posizione di scorrimento orizzontale del contenuto HTML all'interno dell'oggetto HTMLLoader. scrollV La posizione di scorrimento verticale del contenuto HTML all'interno dell'oggetto HTMLLoader. Il seguente codice imposta la proprietà scrollV che consente lo scorrimento del contenuto HTML fino alla fine della pagina: var html:HTMLLoader = new HTMLLoader(); html.addEventListener(Event.HTML_BOUNDS_CHANGE, scrollHTML); const SIZE:Number = 600; html.width = SIZE; html.height = SIZE; var urlReq:URLRequest = new URLRequest("http://www.adobe.com"); html.load(urlReq); this.addChild(html); function scrollHTML(event:Event):void { html.scrollV = html.contentHeight - SIZE; } HTMLLoader non include barre di scorrimento verticali e orizzontali. Potete implementare le barre di scorrimento in ActionScript. Potete anche usare il metodo HTMLLoader.createRootWindow() per creare una finestra che contiene un oggetto HTMLLoader con barre di scorrimento (consultate “Creazione di finestra con contenuto HTML scorrevole” a pagina 273). Accesso all'elenco cronologico HTML Mentre vengono caricate nuove pagine in un oggetto HTMLLoader, il runtime mantiene un elenco cronologico per l'oggetto. L'elenco cronologico corrisponde all'oggetto window.history nella pagina HTML. La classe HTMLLoader include i seguenti metodi e proprietà che consentono di eseguire operazioni con l'elenco cronologico HTML: Membro della classe Descrizione historyLength Lunghezza totale dell'elenco cronologico, compresi gli spostamenti avanti e indietro. historyPosition Posizione corrente nell'elenco cronologico. Le voci della cronologia prima di questa posizione rappresentano lo spostamento "indietro, mentre quelli dopo questa posizione rappresentano lo spostamento "avanti". getHistoryAt() Restituisce l'oggetto URLRequest che corrisponde alla voce della cronologia nella posizione specificata nell'elenco cronologico. historyBack() Torna indietro nell'elenco cronologico, se possibile. historyForward() Procede nell'elenco cronologico, se possibile. historyGo() Procede del numero di passaggi specificato nella cronologia del browser. Procede nella cronologia se positivo, arretra se negativo. Lo spostamento a zero ricarica la pagina. Specificando una posizione oltre la fine, passa alla fine dell'elenco. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 265 Creazione di script per il contenitore HTML Le voci in questo elenco cronologico vengono archiviate come oggetti di tipo HistoryListItem. La classe HistoryListItem ha le seguenti proprietà: Proprietà Descrizione isPost Impostate su true se la pagina HTML include dati POST. originalUrl URL originale della pagina HTML, prima di qualsiasi reindirizzamento. title Titolo della pagina HTML. url URL della pagina HTML. Impostazione dell'agente utente utilizzato durante il caricamento del contenuto HTML La classe HTMLLoader ha una proprietà userAgent che consente di impostare la stringa dell'agente utente usato da HTMLLoader. Impostate la proprietà userAgent dell'oggetto HTMLLoader prima di chiamare il metodo load(). Se impostate questa proprietà sull'istanza HTMLLoader, la proprietà userAgent dell'oggetto URLRequest passata al metodo load()non viene utilizzata. Potete impostare la stringa dell'agente utente predefinito usato da tutti gli oggetti HTMLLoader in un dominio dell'applicazione impostando la proprietà URLRequestDefaults.userAgent. Le proprietà statiche URLRequestDefaults vengono applicate per impostazione predefinita per tutti gli oggetti URLRequest, non solo quelli usati con il metodo load() degli oggetti HTMLLoader. L'impostazione della proprietà userAgent di un oggetto HTMLLoader sostituisce l'impostazione predefinita URLRequestDefaults.userAgent. Se non impostate un valore dell'agente utente per la proprietà userAgent dell'oggetto HTMLLoader o per URLRequestDefaults.userAgent, viene usato il valore predefinito dell'agente utente di AIR. Questo valore predefinito varia a seconda del sistema operativo del runtime (ad esempio, Mac OS o Windows), della lingua del runtime e della versione del runtime, come indicato nei due esempi seguenti: • "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/420+ (KHTML, quale Gecko) AdobeAIR/1.0" • "Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, quale Gecko) AdobeAIR/1.0" Impostazione della codifica dei caratteri da usare per il contenuto HTML Potete specificare la codifica dei caratteri usata in una pagina HTML, includendo il tag meta come il seguente: meta http-equiv="content-type" content="text/html" charset="ISO-8859-1"; Potete ignorare l'impostazione della pagina per assicurare che venga usata una codifica dei caratteri specifica, impostando la proprietà textEncodingOverride dell'oggetto HTMLLoader: var html:HTMLLoader = new HTMLLoader(); html.textEncodingOverride = "ISO-8859-1"; SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 266 Creazione di script per il contenitore HTML Specificata la codifica dei caratteri per il contenuto di HTMLLoader da usare quando in una pagina HTML non è specificata un'impostazione con la proprietà textEncodingFallback dell'oggetto HTMLLoader: var html:HTMLLoader = new HTMLLoader(); html.textEncodingFallback = "ISO-8859-1"; La proprietà textEncodingOverride sostituisce l'impostazione nella pagina HTML e la proprietà textEncodingOverride e l'impostazione nella pagina HTML sostituiscono la proprietà textEncodingFallback. Impostate la proprietà textEncodingOverride o la proprietà textEncodingFallback prima di caricare il contenuto HTML. Definizione di interfacce simili a browser per il contenuto HTML JavaScript include diverse API per il controllo della finestra in cui è visualizzato il contenuto HTML. In AIR, queste API possono essere ignorate mediante l'implementazione di una classe HTMLHost personalizzata. Informazioni sull'estensione della classe HTMLHost Se, ad esempio, la vostra applicazione presenta più oggetti HTMLLoader in un'interfaccia a schede, può essere utile che le modifiche apportate dalle pagine HTML caricate si riflettano nella modifica dell'etichetta della scheda, anziché del titolo della finestra principale. In modo analogo, il codice potrebbe rispondere a una chiamata a window.moveTo() riposizionando l'oggetto HTMLLoader nel relativo contenitore di oggetti di visualizzazione principale, spostando la finestra che contiene l'oggetto HTMLLoader, non eseguendo alcuna operazione o effettuando una qualsiasi altra operazione. La classe AIR HTMLHost controlla i seguenti metodi e proprietà JavaScript: • window.status • window.document.title • window.location • window.blur() • window.close() • window.focus() • window.moveBy() • window.moveTo() • window.open() • window.resizeBy() • window.resizeTo() Quando create un oggetto HTMLLoader usando new HTMLLoader(), i metodi o le proprietà JavaScript non vengono abilitati. La classe HTMLHost fornisce un'implementazione predefinita simile a un browser di queste API JavaScript. Potete anche estendere la classe HTMLHost per personalizzare il comportamento. Per creare un oggetto HTMLHost che supporta il comportamento predefinito, impostate il parametro defaultBehaviors su true nella funzione di costruzione HTMLHost: var defaultHost:HTMLHost = new HTMLHost(true); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 267 Creazione di script per il contenitore HTML Quando create una finestra HTML in AIR con il metodo createRootWindow() della classe HTMLLoader, viene assegnata automaticamente un'istanza HTMLHost che supporta i comportamenti predefiniti. Potete modificare il comportamento dell'oggetto host assegnando una diversa implementazione di HTMLHost alla proprietà htmlHost di HTMLLoader, oppure potete assegnare null per disabilitare completamente le funzioni. Nota: AIR assegna un oggetto HTMLHost predefinito alla finestra iniziale creata per un'applicazione AIR basata su HTML e a qualsiasi finestra creata dall'implementazione predefinita del metodo JavaScript window.open(). Esempio: estensione della classe HTMLHost Il seguente esempio mostra come personalizzare il modo in cui un oggetto HTMLLoader ha effetto sull'interfaccia utente, mediante l'estensione della classe HTMLHost: 1 Create un file Flash per AIR. Impostate la classe document su CustomHostExample, quindi salvate il file come CustomHostExample.fla. 2 Create un file con nome CustomHost.as contenente una classe che estende la classe HTMLHost (una sottoclasse). Questa classe sostituisce determinati metodi della nuova classe per gestire le modifiche nelle impostazioni correlate all'interfaccia utente. La seguente classe CustomHost, ad esempio, definisce i comportamenti per le chiamate a window.open() e le modifiche a window.document.title. Le chiamate al metodo window.open() aprono la pagina HTML in una nuova finestra e le modifiche alla proprietà window.document.title (inclusa l'impostazione dell'elemento <title> di una pagina HTML) impostano il titolo di tale finestra. package { import import import import import import import import import import flash.display.StageScaleMode; flash.display.NativeWindow; flash.display.NativeWindowInitOptions; flash.events.Event; flash.events.NativeWindowBoundsEvent; flash.geom.Rectangle; flash.html.HTMLLoader; flash.html.HTMLHost; flash.html.HTMLWindowCreateOptions; flash.text.TextField; public class CustomHost extends HTMLHost { public var statusField:TextField; public function CustomHost(defaultBehaviors:Boolean=true) { super(defaultBehaviors); } override public function windowClose():void { htmlLoader.stage.nativeWindow.close(); } override public function createWindow( windowCreateOptions:HTMLWindowCreateOptions ):HTMLLoader { var initOptions:NativeWindowInitOptions = new NativeWindowInitOptions(); var bounds:Rectangle = new Rectangle(windowCreateOptions.x, windowCreateOptions.y, windowCreateOptions.width, windowCreateOptions.height); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 268 Creazione di script per il contenitore HTML var htmlControl:HTMLLoader = HTMLLoader.createRootWindow(true, initOptions, windowCreateOptions.scrollBarsVisible, bounds); htmlControl.htmlHost = new HTMLHostImplementation(); if(windowCreateOptions.fullscreen){ htmlControl.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE; } return htmlControl; } override public function updateLocation(locationURL:String):void { trace(locationURL); } override public function set windowRect(value:Rectangle):void { htmlLoader.stage.nativeWindow.bounds = value; } override public function updateStatus(status:String):void { statusField.text = status; trace(status); } override public function updateTitle(title:String):void { htmlLoader.stage.nativeWindow.title = title + "- Example Application"; } override public function windowBlur():void { htmlLoader.alpha = 0.5; } override public function windowFocus():void { htmlLoader.alpha = 1; } } } 3 Create un altro file ActionScript con nome CustomHostExample.as per contenere la classe document dell'applicazione. Questa classe crea un oggetto HTMLLoader e imposta la relativa proprietà host su un'istanza della classe CustomHost definita nel passaggio precedente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 269 Creazione di script per il contenitore HTML package { import import import import flash.display.Sprite; flash.html.HTMLLoader; flash.net.URLRequest; flash.text.TextField; public class CustomHostExample extends Sprite { function CustomHostExample():void { var html:HTMLLoader = new HTMLLoader(); html.width = 550; html.height = 380; var host:CustomHost = new CustomHost(); html.htmlHost = host; var urlReq:URLRequest = new URLRequest("Test.html"); html.load(urlReq); addChild(html); var statusTxt:TextField = new TextField(); statusTxt.y = 380; statusTxt.height = 20; statusTxt.width = 550; statusTxt.background = true; statusTxt.backgroundColor = 0xEEEEEEEE; addChild(statusTxt); host.statusField = statusTxt; } } } Per verificare il codice qui descritto, includete un file HTML con il seguente contenuto nella directory dell'applicazione: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 270 Creazione di script per il contenitore HTML <html> <head> <title>Test</title> <script> function openWindow() { document.title = "Test" window.open('Test.html'); } </script> </head> <body bgColor="#EEEEEE"> <a href="#" onclick="window.open('Test.html')">window.open('Test.html')</a> <br/><a href="#" onclick="window.document.location='http://www.adobe.com'"> window.document.location = 'http://www.adobe.com'</a> <br/><a href="#" onclick="window.moveBy(6, 12)">moveBy(6, 12)</a> <br/><a href="#" onclick="window.close()">window.close()</a> <br/><a href="#" onclick="window.blur()">window.blur()</a> <br/><a href="#" onclick="window.focus()">window.focus()</a> <br/><a href="#" onclick="window.status = new Date().toString()">window.status=new Date().toString()</a> </body> </html> Gestione delle modifiche alla proprietà window.location Sostituite il metodo locationChange() per gestire le modifiche dell'URL della pagina HTML. Il metodo locationChange() viene chiamato quando il codice JavaScript in una pagina modifica il valore di window.location. Il seguente esempio carica semplicemente l'URL richiesto: override public function updateLocation(locationURL:String):void { htmlLoader.load(new URLRequest(locationURL)); } Nota: potete usare la proprietà htmlLoader dell'oggetto HTMLHost per fare riferimento all'oggetto HTMLLoader corrente. Gestione delle chiamate JavaScript a window.moveBy(), window.moveTo(), window.resizeTo(), window.resizeBy() Sostituite il metodo set windowRect() per gestire le modifiche nei limiti del contenuto HTML. Il metodo set windowRect() viene chiamato quando il codice JavaScript in una pagina chiama window.moveBy(), window.moveTo(), window.resizeTo() o window.resizeBy(). Il seguente esempio aggiorna semplicemente i limiti della finestra del desktop: override public function set windowRect(value:Rectangle):void { htmlLoader.stage.nativeWindow.bounds = value; } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 271 Creazione di script per il contenitore HTML Gestione delle chiamate JavaScript a window.open() Sostituite il metodo createWindow() per gestire le chiamate JavaScript a window.open(). Le implementazioni del metodo createWindow() hanno il compito di creare e restituire un nuovo oggetto HTMLLoader. In genere, l'oggetto HTMLLoader viene visualizzato in una nuova finestra, tuttavia non è obbligatorio creare una nuova finestra. L'esempio seguente illustra come implementare la funzione createWindow() usando HTMLLoader.createRootWindow() per creare sia la finestra che l'oggetto HTMLLoader. Potete anche creare separatamente un oggetto NativeWindow e aggiungere HTMLLoader allo stage della finestra. override public function createWindow(windowCreateOptions:HTMLWindowCreateOptions):HTMLLoader{ var initOptions:NativeWindowInitOptions = new NativeWindowInitOptions(); var bounds:Rectangle = new Rectangle(windowCreateOptions.x, windowCreateOptions.y, windowCreateOptions.width, windowCreateOptions.height); var htmlControl:HTMLLoader = HTMLLoader.createRootWindow(true, initOptions, windowCreateOptions.scrollBarsVisible, bounds); htmlControl.htmlHost = new HTMLHostImplementation(); if(windowCreateOptions.fullscreen){ htmlControl.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE; } return htmlControl; } Nota: questo esempio assegna l'implementazione personalizzata di HTMLHost a tutte le nuove finestre create con window.open(). Potete anche usare un'implementazione diversa o impostare la proprietà htmlHost su null per le nuove finestre, se necessario. L'oggetto passato come parametro al metodo createWindow() è un oggetto HTMLWindowCreateOptions. La classe HTMLWindowCreateOptions include delle proprietà che riportano i valori impostati nella stringa del parametro features nella chiamata a window.open(): Proprietà HTMLWindowCreateOptions Impostazione corrispondente nella stringa features nella chiamata JavaScript a window.open() fullscreen fullscreen height height locationBarVisible location menuBarVisible menubar resizeable resizable scrollBarsVisible scrollbars statusBarVisible status toolBarVisible barra degli strumenti width width x left o screenX y top o screenY La classe HTMLLoader non implementa tutte le funzioni che possono essere specificate nella stringa delle funzioni. La vostra applicazione deve contenere le barre di scorrimento, dell'indirizzo, dei menu, di stato e degli strumenti appropriate. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 272 Creazione di script per il contenitore HTML Gli altri argomenti del metodo JavaScript window.open() sono gestiti dal sistema. Un'implementazione di createWindow() non deve caricare contenuto nell'oggetto HTMLLoader o impostare il titolo della finestra. Chiamate Handling JavaScript a window.close() Sostituite windowClose() per gestire le chiamate JavaScript al metodo window.close(). Il seguente esempio chiude la finestra del desktop quando viene chiamato il metodo window.close(): override public function windowClose():void { htmlLoader.stage.nativeWindow.close(); } Le chiamate JavaScript a window.close() non devono chiudere la finestra contenitore. Potete, ad esempio, rimuovere HTMLLoader dall'elenco di visualizzazione, lasciando aperta la finestra (che può avere altro contenuto), come nel codice seguente: override public function windowClose():void { htmlLoader.parent.removeChild(htmlLoader); } Gestione delle modifiche alla proprietà window.status Sostituite il metodo updateStatus() per gestire le modifiche JavaScript al valore di window.status. Il seguente esempio traccia il valore dello stato: override public function updateStatus(status:String):void { trace(status); } Lo stato richiesto viene passato come stringa al metodo updateStatus(). L'oggetto HTMLLoader non fornisce una barra di stato. Gestione delle modifiche alla proprietà window.document.title Sostituite il metodo updateTitle() per gestire le modifiche JavaScript al valore di window.document.title. Il seguente esempio modifica il titolo della finestra e aggiunge la stringa "Sample" al titolo: override public function updateTitle(title:String):void { htmlLoader.stage.nativeWindow.title = title + " - Sample"; } Quando document.title è impostata su una pagina HTML, il titolo richiesto viene passato come stringa al metodo updateTitle(). Le modifiche a document.title non devono modificare il titolo della finestra che contiene l'oggetto HTMLLoader. Potreste, ad esempio, modificare un altro elemento dell'interfaccia, ad esempio un campo di testo. Gestione delle chiamate JavaScript a window.blur() e window.focus() Sostituite i metodi windowBlur() e windowFocus() in modo da gestire le chiamate JavaScript a window.blur() e window.focus(), come illustrato nel seguente esempio: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 273 Creazione di script per il contenitore HTML override public function windowBlur():void { htmlLoader.alpha = 0.5; } override public function windowFocus():void { htmlLoader.alpha = 1.0; NativeApplication.nativeApplication.activate(htmlLoader.stage.nativeWindow); } Nota: AIR non fornisce un'API per la disattivazione di una finestra o un'applicazione. Creazione di finestra con contenuto HTML scorrevole La classe HTMLLoader include un metodo statico, HTMLLoader.createRootWindow(), che consente di aprire una nuova finestra (rappresentata da un oggetto NativeWindow) che contiene un oggetto HTMLLoader e definisce alcune impostazioni dell'interfaccia utente per quella finestra. Il metodo accetta quattro parametri, che consentono di definire l'interfaccia utente: Parametro Descrizione visible Valore booleano che specifica se la finestra è inizialmente visibile (true) o non visibile (false). windowInitOptions Oggetto NativeWindowInitOptions. La classe NativeWindowInitOptions definisce le opzioni di inizializzazione per un oggetto NativeWindow, incluse le seguenti: se la finestra può essere ridotta a icona, ingrandita o ridimensionata, se dispone di un chrome di sistema o personalizzato, se è trasparente o meno (per quelle che non usano chrome di sistema, oltre al tipo di finestra. scrollBarsVisible Se sono presenti bare di scorrimento (true) o non sono presenti (false). bounds Oggetto Rectangle che definisce la posizione e le dimensioni di una nuova finestra. Il seguente codice, ad esempio, usa il metodo HTMLLoader.createRootWindow() per creare una finestra con contenuto HTMLLoader che utilizza barre di scorrimento: var initOptions:NativeWindowInitOptions = new NativeWindowInitOptions(); var bounds:Rectangle = new Rectangle(10, 10, 600, 400); var html2:HTMLLoader = HTMLLoader.createRootWindow(true, initOptions, true, bounds); var urlReq2:URLRequest = new URLRequest("http://www.example.com"); html2.load(urlReq2); html2.stage.nativeWindow.activate(); Nota: le finestre create mediante una chiamata a createRootWindow() direttamente in JavaScript rimangono indipendenti dalla finestra HTML che viene aperta. Le proprietà JavaScript Window opener e parent, ad esempio, sono null. Tuttavia, se chiamate createRootWindow() indirettamente mediante la sostituzione del metodo createWindow() di HTMLHost per chiamare createRootWindow(), le proprietà opener e parent fanno riferimento alla finestra HTML che viene aperta. Creazione di sottoclassi della classe HTMLLoader Per creare nuovi comportamenti, potete creare una sottoclasse della classe HTMLLoader. Potete, ad esempio, creare una sottoclasse che definisce dei listener di eventi predefiniti per gli eventi HTMLLoader (ad esempio, quelli inviati a seguito del rendering del contenuto HTML o del clic su un utente su un collegamento). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 274 Creazione di script per il contenitore HTML Il seguente esempio estende la classe HTMLHost per fornire un comportamento normale quando viene chiamato il metodo JavaScript window.open(). L'esempio definisce quindi una sottoclasse di HTMLLoader che usa la classe dell'implementazione personalizzata di HTMLHost: package { import flash.html.HTMLLoader; public class MyHTMLHost extends HTMLHost { public function MyHTMLHost() { super(false); } override public function createWindow(opts:HTMLWindowCreateOptions):void { var initOptions:NativeWindowInitOptions = new NativeWindowInitOptions(); var bounds:Rectangle = new Rectangle(opts.x, opts.y, opts.width, opts.height); var html:HTMLLoader = HTMLLoader.createRootWindow(true, initOptions, opts.scrollBarsVisible, bounds); html.stage.nativeWindow.orderToFront(); return html } } Il seguente esempio definisce una sottoclasse della classe HTMLLoader che assegna un oggetto MyHTMLHost alla relativa proprietà htmlHost: package { import flash.html.HTMLLoader; import MyHTMLHost; import HTMLLoader; public class MyHTML extends HTMLLoader { public function MyHTML() { super(); htmlHost = new MyHTMLHost(); } } } Per informazioni dettagliate sulla classe HTMLHost e sul metodo HTMLLoader.createRootWindow() usati in questo esempio, consultate “Definizione di interfacce simili a browser per il contenuto HTML” a pagina 266. 275 Capitolo 24: Aggiunta di contenuto PDF Le applicazioni eseguite in Adobe® AIR™ possono eseguire il rendering non soltanto del contenuto SWF e HTML, ma anche del contenuto PDF. Le applicazioni AIR eseguono il rendering del contenuto PDF usando la classe HTMLLoader, il motore WebKit e il plug-in per browser Adobe® Reader®. In un'applicazione AIR, il contenuto PDF può estendersi per tutta l'altezza e la larghezza dell'applicazione o, in alternativa, può rappresentare una porzione dell'interfaccia. Il plug-in per browser Adobe Reader controlla la visualizzazione dei file PDF in un'applicazione AIR, pertanto le modifiche apportate all'interfaccia delle barre degli strumenti di Reader (relative, ad esempio, a posizione, ancoraggio e visibilità) persistono nelle visualizzazioni successive dei file PDF, sia nelle applicazioni AIR che nel browser. Importante: per poter eseguire il rendering del contenuto PDF in AIR, l'utente deve avere installato Adobe Reader o Adobe® Acrobat® versione 8.1 o superiore. Rilevamento della funzionalità PDF Se l'utente non ha installato una versione di Adobe Reader o Adobe Acrobat 8.1 o superiore, il contenuto PDF non verrà visualizzato in un'applicazione AIR. Per verificare se un utente sia o meno in grado di eseguire il rendering del contenuto PDF, per prima cosa controllate la proprietà HTMLLoader.pdfCapability. Questa proprietà è impostata su una delle seguenti costanti della classe HTMLPDFCapability: Costante Descrizione HTMLPDFCapability.STATUS_OK È stata rilevata una versione adeguata (8.1 o superiore) di Adobe Reader e il contenuto PDF può essere caricato in un oggetto HTMLLoader. HTMLPDFCapability.ERROR_INSTALLED_READER_NOT_FOUND Non è stata rilevata nessuna versione di Adobe Reader. Un oggetto HTMLLoader non è in grado di visualizzare il contenuto PDF. HTMLPDFCapability.ERROR_INSTALLED_READER_TOO_OLD È stato rilevato Adobe Reader, ma la versione non è sufficientemente aggiornata. Un oggetto HTMLLoader non è in grado di visualizzare il contenuto PDF. HTMLPDFCapability.ERROR_PREFERRED_READER_TOO_OLD È stata rilevata una versione adeguata (8.1 o successiva) di Adobe Reader, tuttavia la versione di Adobe Reader che è configurata per la gestione del contenuto PDF è antecedente a Reader 8.1. Un oggetto HTMLLoader non è in grado di visualizzare il contenuto PDF. In Windows, se nel sistema dell'utente è in esecuzione Adobe Acrobat o Adobe Reader versione 7.x o superiore, verrà usata questa versione anche se è installata una versione successiva che supporta il caricamento del contenuto PDF. In questo caso, se il valore della proprietà pdfCapability è HTMLPDFCapability.STATUS_OK, quando un'applicazione AIR tenta di caricare il contenuto PDF, la versione precedente di Acrobat o di Reader visualizza un avviso (ma non vengono generate eccezioni nell'applicazione AIR). Se è possibile che si verifichi questa situazione per gli utenti finali, informateli della necessità di chiudere Acrobat mentre è in esecuzione la vostra applicazione. Queste istruzioni dovrebbero essere visualizzate quando il caricamento del contenuto PDF non viene completato entro un determinato periodo di tempo. In Linux, AIR cerca Adobe Reader nella proprietà PATH esportata dall'utente (se contiene il comando acroread) e nella directory /opt/Adobe/Reader. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 276 Aggiunta di contenuto PDF Il seguente codice determina se un utente è in grado di visualizzare il contenuto PDF in un'applicazione AIR. In caso negativo, rintraccia il codice dell'errore che corrisponde all'oggetto HTMLPDFCapability: if(HTMLLoader.pdfCapability == HTMLPDFCapability.STATUS_OK) { trace("PDF content can be displayed"); } else { trace("PDF cannot be displayed. Error code:", HTMLLoader.pdfCapability); } Caricamento di contenuto PDF È possibile aggiungere un PDF a un'applicazione AIR creando un'istanza HTMLLoader, impostandone le dimensioni e caricando il percorso di un PDF. L'esempio seguente carica un PDF da un sito esterno. Specificate per URLRequest il percorso di un PDF esterno disponibile. var request:URLRequest = new URLRequest("http://www.example.com/test.pdf"); pdf = new HTMLLoader(); pdf.height = 800; pdf.width = 600; pdf.load(request); container.addChild(pdf); Potete inoltre caricare il contenuto da URL di file e schermi URL specifici di AIR, quali app e app-storage. Ad esempio, il seguente codice carica il file test.pdf presente nella sottodirectory dei PDF nella directory dell'applicazione: app:/js_api_reference.pdf Per ulteriori informazioni sugli schemi URL di AIR, consultate “Uso di schermi URL AIR negli URL” a pagina 310. Uso di script nel contenuto PDF Potete usare JavaScript per controllare il contenuto PDF esattamente come fareste in una pagina Web nel browser. Le estensioni JavaScript in Acrobat forniscono le funzioni seguenti, tra le altre: • Controllo della navigazione e dell'ingrandimento della pagina • Elaborazione dei form all'interno del documento • Controllo degli eventi multimediali I dettagli completi sulle estensioni JavaScript per Adobe Acrobat sono disponibili presso il Centro per sviluppatori Adobe Acrobat, all'indirizzo http://www.adobe.com/devnet/acrobat/javascript.html. Nozioni di base sulla comunicazione HTML-PDF Il codice JavaScript in una pagina HTML può inviare un messaggio al codice JavaScript nel contenuto PDF richiamando il metodo postMessage() dell'oggetto DOM che rappresenta il contenuto PDF. Analizzate, ad esempio, il seguente contenuto PDF incorporato: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 277 Aggiunta di contenuto PDF <object id="PDFObj" data="test.pdf" type="application/pdf" width="100%" height="100%"/> Il seguente codice JavaScript nel contenuto HTML che lo contiene invia un messaggio al codice JavaScript nel file PDF: pdfObject = document.getElementById("PDFObj"); pdfObject.postMessage(["testMsg", "hello"]); Il file PDF può includere codice JavaScript per ricevere questo messaggio. Potete aggiungere codice JavaScript ai file PDF in alcuni contesti, tra i quali i contesti a livello di documento, cartella, pagina, campo e batch. In questa sede tratteremo soltanto il contesto a livello di documento, che definisce gli script che vengono valutati all'apertura del documento PDF. Un file PDF può aggiungere una proprietà messageHandler all'oggetto hostContainer. La proprietà messageHandler è un oggetto che definisce le funzioni di gestore per rispondere ai messaggi. Ad esempio, il seguente codice definisce la funzione di gestione dei messaggi che il file PDF riceve dal contenitore host (in pratica il contenuto HTML che incorpora il file PDF): this.hostContainer.messageHandler = {onMessage: myOnMessage}; function myOnMessage(aMessage) { if(aMessage[0] == "testMsg") { app.alert("Test message: " + aMessage[1]); } else { app.alert("Error"); } } Il codice JavaScript nella pagina HTML può richiamare il metodo postMessage() dell'oggetto PDF contenuto nella pagina. Richiamando questo metodo, viene inviato un messaggio ("Hello from HTML") al codice JavaScript del livello documento nel file PDF: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 278 Aggiunta di contenuto PDF <html> <head> <title>PDF Test</title> <script> function init() { pdfObject = document.getElementById("PDFObj"); try { pdfObject.postMessage(["alert", "Hello from HTML"]); } catch (e) { alert( "Error: \n name = " + e.name + "\n message = " + e.message ); } } </script> </head> <body onload='init()'> <object id="PDFObj" data="test.pdf" type="application/pdf" width="100%" height="100%"/> </body> </html> Per un esempio più dettagliato e per ulteriori informazioni sull'uso di Acrobat 8 per aggiungere codice JavaScript a un file PDF, consultate Cross-scripting PDF content in Adobe AIR (Scambio di script per il contenuto PDF in Adobe AIR). Script di ActionScript nel contenuto PDF Il codice ActionScript (nel contenuto SWF) non comunica direttamente con il codice JavaScript nel contenuto PDF. Tuttavia il codice ActionScript può comunicare con il codice JavaScript nella pagina HTML caricata in un oggetto HTMLLoader che carica il contenuto PDF, pertanto quel codice JavaScript può comunicare con il codice JavaScript nel file PDF. Per ulteriori informazioni, consultate “Programmazione in HTML e JavaScript” a pagina 236. Limiti noti per il contenuto PDF in AIR Il contenuto PDF in Adobe AIR presenta i seguenti limiti: • Il contenuto PDF non viene visualizzato in una finestra (un oggetto NativeWindow) che sia trasparente (la cui proprietà transparent è impostata su true). • L'ordine di visualizzazione di un file PDF è diverso rispetto ad altri oggetti visualizzati in un'applicazione AIR. Sebbene il contenuto PDF venga ritagliato correttamente in base all'ordine di visualizzazione HTML, resterà sempre in primo piano nell'ordine di visualizzazione del contenuto nell'applicazione AIR. • Il contenuto PDF non viene visualizzato in una finestra in modalità a schermo intero (quando la proprietà displayState dell'oggetto Stage è impostata su StageDisplayState.FULL_SCREEN o su StageDisplayState.FULL_SCREEN_INTERACTIVE). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 279 Aggiunta di contenuto PDF • Se determinate proprietà visive di un oggetto HTMLLoader che contiene un documento PDF vengono modificate, il documento PDF diventa invisibile. Tali proprietà comprendono: filters, alpha, rotatione scaling. La modifica di queste proprietà rende invisibile il file PDF, finché non saranno ripristinate. Lo stesso vale per la modifica di queste proprietà per i contenitori dell'oggetto Display che contengono l'oggetto HTMLLoader. • Il contenuto PDF è visibile solo quando la proprietà scaleMode dell'oggetto Stage dell'oggetto NativeWindow che include il contenuto PDF è impostata su StageScaleMode.NO_SCALE. Quando è impostata su qualsiasi altro valore, il contenuto PDF non è visibile. • Facendo clic sui collegamenti al contenuto all'interno del file PDF verrà aggiornata la posizione di scorrimento del contenuto PDF. Facendo clic sui collegamenti al contenuto all'esterno del file PDF verrà reindirizzato l'oggetto HTMLLoader che contiene il PDF (anche se la destinazione di un collegamento è una nuova finestra). • I flussi di lavoro dei commenti PDF non funzionano in AIR. 280 Capitolo 25: Uso della funzionalità DRM (Digital Rights Management) Adobe® Flash® Media Rights Management Server (FMRMS) offre agli editori multimediali la possibilità di distribuire contenuto, soprattutto file FLV e MP4 e di recuperare costi di produzione tramite compensazione diretta (pagata dall'utente) o indiretta (pagata dalla pubblicità) dai propri utenti. Gli editori distribuiscono contenuto multimediale sottoforma di FLV crittografato scaricabile e riproducibile in Adobe® Media Player™ o in qualsiasi applicazione AIR che API per DRM. Con FMRMS, i fornitori di contenuto possono utilizzare l'acquisto di licenze in base all'identità per proteggere il contenuto tramite le credenziali dell'utente. Ad esempio, un utente desidera visualizzare un programma televisivo, ma non vuole vedere gli annunci a essi associati. Per evitare la visione di annunci, l'utente registra e paga un premio all'autore del contenuto. L'utente può quindi utilizzare le proprie credenziali di autenticazione per ottenere l'accesso e riprodurre il programma senza annunci pubblicitari. Un altro utente può voler visualizzare il contenuto non in linea durante la navigazione senza accesso internet. Dopo la registrazione e il pagamento all'autore del contenuto del servizio premium, le credenziali di autenticazione dell'utente consentono di accedere e scaricare il programma dal sito web dell'autore. L'utente può quindi visualizzare il contenuto non in linea durante il periodo consentito. Tale contenuto è anche protetto dalle credenziali dell'utente e non può essere condiviso con altri utenti. Quando un utente cerca di riprodurre un file crittografato con DRM, l'applicazione contatta il server FMRMS che a sua volta contatta il sistema dell'autore del contenuto tramite l'interfaccia del fornitore di servizi (SPI, Service Provider Interface) al fine di autenticare e recuperare la licenza, un voucher che determina se l'utente può accedere al contenuto e, in tal caso, per quanto tempo. Il voucher determina inoltre se l'utente può accedere al contenuto non in linea e, in tal caso, per quanto tempo. Pertanto, le credenziali dell'utente sono necessarie per determinare l'accesso al contenuto crittografato. L'acquisto di licenze in base all'identità consente inoltre l'accesso anonimo. Ad esempio, il fornitore può utilizzare l'accesso anonimo per distribuire contenuto con supporto pubblicitario o per consentire l'accesso libero al contenuto corrente per un numero specificato di giorni. Il materiale di archivio potrebbe essere considerato contenuto premium che deve essere pagato e richiede credenziali dell'utente. Il fornitore di contenuto può anche specificare e limitare il tipo e la versione del lettore necessario per il contenuto. Di seguito è riportata la descrizione sulla modalità di attivazione dell'applicazione AIR per la riproduzione di contenuto protetto con la crittografia DRM. Non è necessario comprendere come crittografare il contenuto mediante DRM, ma si ipotizza di avere l'accesso al contenuto crittografato con DRM e di comunicare tramite FMRMS per autenticare l'utente e recuperare il voucher. Per una panoramica di FMRMS, comprese le linee guida di creazione, consultate la documentazione inclusa nel FMRMS. Per informazioni su Adobe Media Player, consultate la Guida di Adobe Media Player disponibile nell'Adobe Media Player. Informazioni supplementari online sul DRM È possibile trovare ulteriori informazioni sul DRM nelle seguenti fonti: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 281 Uso della funzionalità DRM (Digital Rights Management) Guida di riferimento del linguaggio • AuthenticationMethod • DRMAuthenticationCompleteEvent • DRMAuthenticationErrorEvent • DRMAuthenticateEvent • DRMContentData • DRMErrorEvent • DRMManager • DRMPlaybackTimeWindow • DRMStatusEvent • DRMVoucher • LoadVoucherSetting • NetStream Articoli ed esempi di Centro per sviluppatori Adobe • Centro per sviluppatori Adobe AIR per Flex (cercate ‘digital rights management’ o ‘drm’) Flusso di lavoro FLV crittografato Sono disponibili quattro tipi di eventi, StatusEvent. DRMAuthenticateEvent, DRMErrorEvent e DRMStatusEvent, che possono essere inviati quando un'applicazione AIR tenta di riprodurre un file crittografato con DRM. Per supportare questi file, l'applicazione deve aggiungere i listener di eventi per la gestione di eventi DRM. Di seguito è riportato il flusso di lavoro sulla modalità con cui l'applicazione AIR riesce a recuperare e riprodurre il contenuto protetto con la crittografia DRM: 1 L'applicazione tenta tramite un oggetto NetStream di riprodurre un file FLV o MP4. Se il contenuto è crittografato, viene inviato un evento events.StatusEvent con il codice, DRM.encryptedFLV, a indicare che il file FLV è crittografato. Nota: se un'applicazione non riesce a riprodurre il file crittografato con DRM, può rimanere in ascolto dell'evento di stato inviato in caso di contenuto crittografato e quindi comunicare all'utente che il file non è supportato e chiudere la connessione. 2 Se il file è crittografato in modo anonimo, a indicare che tutti gli utenti possono visualizzare il contenuto senza inserire le credenziali di autenticazione, l'applicazione AIR passa alla fase successiva di questo flusso di lavoro. Se tuttavia il file richiede una licenza basata su identità, ovvero sono necessarie le credenziali dell'utente, l'oggetto NetStream invia un oggetto DRMAuthenticateEvent. L'utente deve fornire le proprie credenziali di autenticazione prima di iniziare nuovamente la riproduzione. 3 L'applicazione AIR deve offrire un meccanismo di raccolta delle credenziali di autenticazione necessarie. È possibile utilizzare le proprietà usernamePrompt, passwordPrompt e urlPrompt della classe DRMAuthenticationEvent, offerta dal server di contenuto, per indicare all'utente finale le informazioni relative ai dati necessari. Queste proprietà possono essere utilizzate per creare un'interfaccia utente al fine di recuperare le credenziali utente necessarie. Ad esempio, con la stringa valore usernamePrompt potete indicare che il nome utente deve essere rappresentato da un indirizzo e-mail. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 282 Uso della funzionalità DRM (Digital Rights Management) Nota: AIR non offre un'interfaccia utente predefinita per la raccolta delle credenziali di autenticazione. Lo sviluppatore dell'applicazione deve scrivere l'interfaccia utente e gestire gli eventi DRMAuthenticateEvent. Se l'applicazione non offre un listener di eventi per gli oggetti DRMAuthenticateEvent, l'oggetto crittografato con DRM resta nello stato di "attesa delle credenziali" e il contenuto non è pertanto disponibile. 4 Quando l'applicazione ottiene le credenziali dell'utente, le passa con il metodo setDRMAuthenticationCredentials() all'oggetto NetStream. Questa condizione segnala all'oggetto NetStream che deve tentare di autenticare l'utente alla successiva opportunità disponibile. AIR passa quindi le credenziali al server FMRMS per l'autenticazione. Se l'utente è stato autenticato, l'applicazione passa alla fase successiva. Se l'autenticazione non riesce, l'oggetto NetStream invia un nuovo oggetto DRMAuthenticateEvent e l'applicazione torna al passaggio 3. Questo processo si ripete ininterrottamente. L'applicazione deve fornire un meccanismo per gestire e limitare i tentativi di autenticazione ripetuti. Ad esempio, potrebbe consentire all'utente di annullare il tentativo e quindi chiudere la connessione NetStream. 5 In seguito all'autenticazione dell'utente o se viene utilizzata la crittografia anonima, il sottosistema DRM recupera il voucher utilizzato per controllare se l'utente è autorizzato a visualizzare il contenuto. Le informazioni nel voucher si possono applicare sia agli utenti autenticati sia a quelli anonimi. Ad esempio, entrambi gli utenti autenticati e anonimi possono avere accesso al contenuto per un periodo di tempo specificato prima della scadenza del contenuto o possono avere accesso al contenuto perché il fornitore non può supportare la versione dell'applicazione di visualizzazione. Qualora non si sia verificato alcun errore e l'utente sia stato autorizzato a visualizzare il contenuto, l'oggetto NetStream invia un oggetto DRMStatusEvent e l'applicazione AIR inizia la riproduzione. L'oggetto DRMStatusEvent contiene le informazioni del voucher correlate che identificano i criteri e le autorizzazioni dell'utente. Ad esempio, contiene informazioni riguardanti l'eventualità di rendere il contenuto disponibile non in linea oppure la data di scadenza del voucher e se il contenuto non può più essere visualizzato. L'applicazione può utilizzare questi dati per informare l'utente sullo stato dei criteri. Ad esempio, l'applicazione può visualizzare in una barra di stato il numero di giorni rimanenti per cui l'utente può visualizzare il contenuto. Se all'utente viene concesso l'accesso non in linea, il voucher viene memorizzato nella cache e il contenuto crittografato viene scaricato nel computer dell'utente e reso accessibile per la durata definita nel periodo di leasing non in linea. La proprietà detail dell'evento contiene "DRM.voucherObtained". Il contenuto viene memorizzato localmente in modo automatico affinché possa essere disponibile non in linea. In AIR 1.5 è inoltre possibile precaricare voucher mediante la classe DRMManager. Tutti gli errori correlati a DRM determinano l'invio di un oggetto evento DRMErrorEvent da parte dell'applicazione. AIR gestisce gli errori di autenticazione rilevati in caso di utilizzo del metodo setDRMAuthenticationCredentials() di NetStream inviando nuovamente l'oggetto DRMAuthenticationEvent. Tutti gli altri eventi di errore devono essere gestiti in modo esplicito dall'applicazione. Sono inclusi i casi in cui l'utente immette credenziali valide, ma il voucher di protezione del contenuto crittografato limita l'accesso al contenuto. Ad esempio, un utente autenticato non può ancora avere accesso al contenuto perché non sono stati ancora pagati i diritti. Ciò può accadere anche quando due utenti, entrambi i membri registrati con lo stesso autore multimediale, tentano di condividere il contenuto per cui ha pagato solo uno dei membri. L'applicazione deve informare l'utente dell'errore, come le restrizioni al contenuto, nonché fornire un'alternativa, come le istruzioni su come registrare e pagare i diritti per la visualizzazione del contenuto. Precaricamento di voucher per la riproduzione non in linea Potete precaricare i voucher necessari per riprodurre il contenuto protetto da DRM. I voucher precaricati consentono agli utenti di visualizzare il contenuto, con o senza una connessione Internet attiva. (Il processo stesso di precaricamento richiede, ovviamente, una connessione Internet). Utilizzate il metodo preloadEmbeddedMetadata() della classe NetStream e la classe DRMManager di AIR 1.5 per precaricare i voucher. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 283 Uso della funzionalità DRM (Digital Rights Management) Di seguito viene descritto il flusso di lavoro per precaricare il voucher per un file multimediale protetto da DRM: 1 Scaricate e archiviate il file multimediale. (I metadati DRM possono essere precaricati solo da file archiviati localmente). 2 Create gli oggetti NetConnection e NetStream, fornendo le implementazioni per le funzioni di callback onDRMContentData() e onPlayStatus() dell'oggetto client NetStream. 3 Create un oggetto NetStreamPlayOptions e impostate la proprietà stream sull'URL del file multimediale locale. 4 Chiamate il metodo preloadEmbeddedMetadata()della classe NetStream, passando l'oggetto NetStreamPlayOptions che identifica il file multimediale da analizzare. 5 Se il file multimediale contiene metadati DRM, viene richiamata la funzione di callback onDRMContentData(). I metadati vengono passati a questa funzione come un oggetto DRMContentData. 6 Utilizzate l'oggetto DRMContentData per ottenere il voucher, utilizzando il metodo loadVoucher() della classe DRMManager. Se il valore della proprietà authenticationMethod dell'oggetto DRMContentData è userNameAndPassword, dovete autenticare l'utente sul server di gestione dei diritti multimediali prima di caricare il voucher. Le proprietà serverURL e domain dell'oggetto DRMContentData possono essere passate al metodo DRMManager authenticate() della classe DRMManager insieme alle credenziali dell'utente. 7 La funzione di callback onPlayStatus() viene richiamata al termine dell'analisi del file. Se la funzione onDRMContentData() non è stata chiamata, il file non contiene i metadati richiesti per ottenere un voucher (e potrebbe non essere protetto da DRM). L'esempio di codice riportato di seguito illustra come precaricare un voucher DRM per un file multimediale locale: package { import flash.display.Sprite; import flash.events.DRMAuthenticationCompleteEvent; import flash.events.DRMAuthenticationErrorEvent; import flash.events.DRMErrorEvent; import flash.ev ents.DRMStatusEvent; import flash.events.NetStatusEvent; import flash.net.NetConnection; import flash.net.NetStream; import flash.net.NetStreamPlayOptions; import flash.net.drm.AuthenticationMethod; import flash.net.drm.DRMContentData; import flash.net.drm.DRMManager; import flash.net.drm.LoadVoucherSetting; public class DRMPreloader extends Sprite { private var videoURL:String = "app-storage:/video.flv"; private var userName:String = "user"; private var password:String = "password"; private var preloadConnection:NetConnection; private var preloadStream:NetStream; private var drmManager:DRMManager = DRMManager.getDRMManager(); private var drmContentData:DRMContentData; public function DRMPreloader():void { drmManager.addEventListener( DRMAuthenticationCompleteEvent.AUTHENTICATION_COMPLETE, onAuthenticationComplete ); drmManager.addEventListener( DRMAuthenticationErrorEvent.AUTHENTICATION_ERROR,onAuthenticationError ); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 284 Uso della funzionalità DRM (Digital Rights Management) drmManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); drmManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError); preloadConnection = new NetConnection(); preloadConnection.addEventListener(NetStatusEvent.NET_STATUS, onConnect); preloadConnection.connect(null); } private function onConnect( event:NetStatusEvent ):void { preloadMetadata(); } private function preloadMetadata():void { preloadStream = new NetStream( preloadConnection ); preloadStream.client = this; var options:NetStreamPlayOptions = new NetStreamPlayOptions(); options.streamName = videoURL; preloadStream.preloadEmbeddedData( options ); } public function onDRMContentData( drmMetadata:DRMContentData ):void { drmContentData = drmMetadata; if ( drmMetadata.authenticationMethod == AuthenticationMethod.USERNAME_AND_PASSWORD ) { authenticateUser(); } else { getVoucher(); } } private function getVoucher():void { drmManager.loadVoucher( drmContentData, LoadVoucherSetting.ALLOW_SERVER ); } private function authenticateUser():void { drmManager.authenticate( drmContentData.serverURL, drmContentData.domain, userName, password ); } private function onAuthenticationError( event:DRMAuthenticationErrorEvent ):void { trace( "Authentication error: " + event.errorID + ", " + event.subErrorID ); } private function onAuthenticationComplete( event:DRMAuthenticationCompleteEvent ):void { SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 285 Uso della funzionalità DRM (Digital Rights Management) trace( "Authenticated to: " + event.serverURL + ", domain: " + event.domain ); getVoucher(); } private function onDRMStatus( event:DRMStatusEvent ):void { trace( "DRM Status: " + event.detail); trace("--Voucher allows offline playback = " + event.isAvailableOffline ); trace("--Voucher already cached = " + event.isLocal ); trace("--Voucher required authentication = " + !event.isAnonymous ); } private function onDRMError( event:DRMErrorEvent ):void { trace( "DRM error event: " + event.errorID + ", " + event.subErrorID + ", " + event.text ); } public function onPlayStatus( info:Object ):void { preloadStream.close(); } } } Membri ed eventi della classe NetStream correlati a DRM La classe NetStream fornisce una connessione in streaming unidirezionale tra Flash Player o un'applicazione AIR e Flash Media Server o il file system locale. (La classe NetStream supporta anche il download progressivo.) Un oggetto NetStream è come un canale all'interno di un oggetto NetConnection. In un'applicazione AIR, la classe NetStream invia quattro eventi correlati a DRM: Evento Descrizione drmAuthenticate Definito nella classe DRMAuthenticateEvent, questo evento viene inviato quando un oggetto NetStream tenta di riprodurre contenuto crittografato con DRM che richiede una credenziale utente per l'autenticazione prima della riproduzione. Le proprietà di questo evento includono header, usernamePrompt, passwordPrompt e urlPrompt utilizzabili per ottenere e impostare le credenziali dell'utente. Tale evento si verifica ripetutamente finché l'oggetto NetStream riceve credenziali utente valide. drmError Definito nella classe DRMErrorEvent e inviato quando un oggetto NetStream, il tentativo di riprodurre un file crittografato con DRM determina un errore correlato a DRM. Ad esempio, l'oggetto evento dell'errore DRM è inviato in caso di errore dell'autorizzazione utente. Questo può accadere se l'utente non ha acquistato i diritti per visualizzare il contenuto o perché il fornitore del contenuto non supporta l'applicazione di visualizzazione. drmStatus Definito nella classe DRMStatusEvent, è inviato quando il contenuto crittografato da DRM inizia la riproduzione (quando l'utente è autenticato e autorizzato per la riproduzione del contenuto). L'oggetto DRMStatusEvent contiene informazioni riguardanti il voucher, come rendere il contenuto disponibile non in linea oppure la data di scadenza del voucher e se il contenuto non può più essere visualizzato. status Definito in events.StatusEvent e inviato solo quando l'applicazione tenta di riprodurre contenuto crittografato con DRM, tramite l'invocazione del metodo NetStream.play(). Il valore della proprietà del codice di stato è "DRM.encryptedFLV". La classe NetStream comprende i seguenti metodi specifici di DRM: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 286 Uso della funzionalità DRM (Digital Rights Management) Metodo Descrizione resetDRMvouchers() Elimina tutti i dati del voucher DRM (Digital Rights Management) memorizzati nella cache locale. L'applicazione deve scaricare di nuovo i voucher affinché l'utente possa accedere al contenuto crittografato. Il codice seguente ad esempio rimuove tutti i voucher dalla cache: NetStream.resetDRMvouchers(); setDRMAuthenticationCredentials() Passa un set di credenziali di autenticazione, ovvero nome utente, password e tipo di autenticazione, all'oggetto NetStream per l'autenticazione. I tipi di autenticazione validi sono "drm" e "proxy" . Con il tipo di autenticazione "drm" , le credenziali fornite sono autenticate da FMRMS. Con il tipo di autenticazione "proxy" , le credenziali autenticano il server proxy e deve corrispondere a quelle necessarie per il server proxy. Ad esempio, l'opzione proxy consente all'applicazione di essere autenticata tramite un proxy server se un'azienda richiede tale operazione prima che l'utente possa accedere a Internet. A meno che non si utilizzi l'autenticazione anonima, dopo l'autenticazione tramite proxy, l'utente deve ancora autenticarsi tramite FMRMS al fine di ottenere il voucher e riprodurre il contenuto. È possibile utilizzare setDRMAuthenticationcredentials() una seconda volta, insieme all'opzione "drm", al fine di eseguire l'autenticazione tramite FMRMS. preloadEmbeddedMetadata() Analizza il file multimediale locale per la ricerca dei metadati incorporati. Quando vengono trovati i metadati correlati a DRM, AIR chiama la funzione di callback onDRMContentData(). Inoltre, un oggetto NetStream richiama le funzioni di callback onDRMContentData() e onPlayStatus() a seguito di una chiamata al metodo preloadEmbeddedMetaData(). La funzione onDRMContentData() viene chiamata quando vengono rilevati metadati DRM in un file multimediale. La funzione onPlayStatus() viene chiamata dopo che il file è stato completamente analizzato. Le funzioni onDRMContentData() e onPlayStatus() devono essere definite nell'oggetto client assegnato all'istanza NetStream. Se utilizzate lo stesso oggetto NetStream per precaricare voucher e riprodurre contenuto, per avviare la riproduzione dovete attendere la chiamata onPlayStatus() generata da preloadEmbeddedMetaData(). Nel seguente codice, nome utente ("administrator"), password ("password") e tipo di autenticazione "drm" sono impostati per l'autenticazione dell'utente. Il metodo setDRMAuthenticationCredentials() deve fornire credenziali che corrispondano a quelle note e accettate dal fornitore del contenuto (le stesse credenziali utente che hanno consentito di visualizzare il contenuto). Non è compreso il codice che riproduce il video e assicura l'avvenuta esecuzione di una corretta connessione al video streaming. var connection:NetConnection = new NetConnection(); connection.connect(null); var videoStream:NetStream = new NetStream(connection); videoStream.addEventListener(DRMAuthenticateEvent.DRM_AUTHENTICATE, drmAuthenticateEventHandler) private function drmAuthenticateEventHandler(event:DRMAuthenticateEvent):void { videoStream.setDRMAuthenticationCredentials("administrator", "password", "drm"); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 287 Uso della funzionalità DRM (Digital Rights Management) Uso della classe DRMStatusEvent Un oggetto NetStream invia un oggetto DRMStatusEvent quando il contenuto protetto tramite DRM inizia la corretta riproduzione (quando il voucher è verificato autenticato e quando l'utente è autenticato e autorizzato a visualizzare il contenuto). L'oggetto DRMStatusEvent viene anche inviato per utenti anonimi in casi sia concesso loro l'accesso. Il voucher viene controllato per verificare se l'utente anonimo, che non richiede autenticazione, possiede i permessi di accesso per la riproduzione di contenuto. Probabilmente agli utenti anonimi è stato negato l'accesso per una serie di motivi. Ad esempio, un utente anonimo non può avere accesso al contenuto perché è scaduto. L'oggetto DRMStatusEvent contiene informazioni riguardanti il voucher, come rendere il contenuto disponibile non in linea oppure la data di scadenza del voucher e se il contenuto non può più essere visualizzato. L'applicazione può utilizzare questi dati per comunicare lo stato di policy dell'utente e relativi permessi. Proprietà DRMStatusEvent La classe DRMStatusEvent comprende le seguenti proprietà: Proprietà Descrizione contentData Oggetto DRMContentData contenente i metadati DRM incorporati nel contenuto. detail Stringa che spiega il contesto dell'evento status. In DRM 1.0, l'unico valore valido è DRM.voucherObtained. isAnonymous Indica se il contenuto, protetto da crittografia DRM, è disponibile senza che l'utente debba fornire (true) o meno (false) credenziali di autenticazione. Un valore false indica che l'utente deve fornire un nome utente e una password che corrispondano a quelli noti e previsti dal fornitore del contenuto. isAvailableOffline Indica se il contenuto, protetto da crittografia DRM, può essere reso disponibile non in linea (true) o meno (false). Affinché il contenuto protetto digitalmente sia disponibile non in linea, il relativo voucher deve essere memorizzato nella macchina locale dell'utente. isLocal Indica se il voucher necessario per riprodurre il contenuto è memorizzato nella cache locale. offlineLeasePeriod Il numero restante di giorni in cui il contenuto è visualizzabile non in linea. policy Oggetto personalizzato che può contenere proprietà DRM personalizzate. voucher Oggetto DRMVoucher. voucherEndDate La data certa in cui il voucher scade e il contenuto non è più disponibile. Creazione di un gestore DRMStatusEvent L'esempio seguente crea un gestore eventi che fornisce informazioni di stato del contenuto DRM per l'oggetto NetStream che ha originato l'evento. Aggiungete questo gestore eventi a un oggetto NetStream che punti al contenuto crittografato DRM. function drmStatusEventHandler(event:DRMStatusEvent):void { trace(event); } function drmStatusEventHandler(event:DRMStatusEvent):void { trace(event); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 288 Uso della funzionalità DRM (Digital Rights Management) Uso della classe DRMAuthenticateEvent L'oggetto DRMAuthenticateEvent viene inviato quando un oggetto NetStream tenta di riprodurre contenuto crittografato con DRM (Digital Rights Management) che richiede una credenziale utente per l'autenticazione prima della riproduzione. Il gestore DRMAuthenticateEvent è responsabile della raccolta delle credenziali necessarie (nome utente, password e tipo) e di passare i valori al metodo NetStream.setDRMAuthenticationCredentials() per la convalida. Ogni applicazione AIR deve offrire un meccanismo per il recupero delle credenziali utente. Ad esempio, l'applicazione potrebbe fornire a un utente una semplice interfaccia utente in cui immettere i valori del nome utente e della password e opzionalmente anche il valore del tipo. L'applicazione AIR deve inoltre fornire un meccanismo per gestire e limitare i tentativi di autenticazione ripetuti. Proprietà DRMAuthenticateEvent La classe DRMAuthenticateEvent comprende le seguenti proprietà: Proprietà Descrizione authenticationType Indica se le credenziali fornite sono per l'autenticazione tramite FMRMS (“drm”) o un proxy server (“proxy”). Ad esempio, l'opzione "proxy" consente all'applicazione di essere autenticata tramite un proxy server se un'azienda richiede tale operazione prima che l'utente possa accedere a Internet. A meno che non si utilizzi l'autenticazione anonima, dopo l'autenticazione tramite proxy, l'utente deve ancora autenticarsi tramite FMRMS al fine di ottenere il voucher e riprodurre il contenuto. È possibile utilizzare setDRMAuthenticationcredentials() una seconda volta, insieme all'opzione "drm", per eseguire l'autenticazione tramite FMRMS. header L'intestazione del file del contenuto crittografato fornito dal server. Contiene informazioni sul contesto del contenuto crittografato. netstream L'oggetto NetStream che ha iniziato questo evento. passwordPrompt Una richiesta di una credenziale password, fornita dal server. La stringa può comprende l'istruzione per il tipo di password necessaria. urlPrompt Una richiesta di una stringa URL, fornita dal server. La stringa che fornisce il percorso in cui vengono inviati il nome utente e la password. usernamePrompt Una richiesta di una credenziale nome utente, fornita dal server. La stringa può comprende l'istruzione per il tipo di nome utente necessario. Ad esempio, un fornitore di contenuto può richiedere un indirizzo e-mail per il nome utente. Creazione di un gestore DRMAuthenticateEvent L'esempio seguente crea un gestore eventi che passa una serie di credenziali di autenticazione codificate per l'oggetto NetStream che ha originato l'evento (non è compreso il codice che riproduce il video e assicura l'avvenuta connessione allo streaming video). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 289 Uso della funzionalità DRM (Digital Rights Management) var connection:NetConnection = new NetConnection(); connection.connect(null); var videoStream:NetStream = new NetStream(connection); videoStream.addEventListener(DRMAuthenticateEvent.DRM_AUTHENTICATE, drmAuthenticateEventHandler) private function drmAuthenticateEventHandler(event:DRMAuthenticateEvent):void { videoStream.setDRMAuthenticationCredentials("administrator", "password", "drm"); } Creazione di un'interfaccia per il recupero di credenziali utente Nel caso in cui il contenuto DRM richieda l'autenticazione utente, l'applicazione AIR deve in genere recuperare le credenziali di autenticazione dell'utente tramite un'interfaccia utente. Uso della classe DRMErrorEvent AIR invia un oggetto DRMErrorEvent quando un oggetto NetStream rileva un errore correlato a DRM durante il tentativo di riprodurre un file crittografato con DRM. Nel caso di credenziali utente non valide, l'oggetto DRMAuthenticateEvent gestisce l'errore inviandolo ripetutamente finché l'utente non immette credenziali valide o l'applicazione nega altri tentativi. L'applicazione deve intercettare qualsiasi altro evento di errore DRM per rilevare, identificare e gestire errori correlati a DRM. Se un utente immette credenziali valide, è possibile che queste non gli consentano comunque la visualizzazione di contenuto crittografato, in base ai termini del voucher DRM, ad esempio nel caso in cui l'utente tenti di visualizzare contenuto in un'applicazione non autorizzata, ovvero un'applicazione che non è convalidata dall'autore del contenuto crittografato. In tal caso, viene inviato un oggetto DRMErrorEvent. Gli eventi di errore possono essere generati anche se il contenuto è danneggiato o se la versione dell'applicazione non corrisponde a quanto specificato nel voucher. L'applicazione deve fornire un meccanismo appropriato per la gestione degli errori. Proprietà DRMErrorEvent La tabella seguente elenca gli errori che riporta l'oggetto DRMErrorEvent: Codici di errore principali Codici di errori secondari Dettagli errore 1001 non utilizzato Autenticazione utente non riuscita. 1002 non utilizzato Flash Media Rights Management Server (FMRMS) non supporta Secure Sockets Layer (SSL). 1003 non utilizzato Il contenuto è scaduto e non è più disponibile per la visualizzazione. 1004 non utilizzato Errore di autorizzazione utente. Può accadere, ad esempio, se l'utente non ha acquistato il contenuto e pertanto non ha i diritti di visualizzarlo. 1005 non utilizzato Server URL Descrizione Impossibile connettersi al server. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 290 Uso della funzionalità DRM (Digital Rights Management) Codici di errore principali Codici di errori secondari Dettagli errore 1006 non utilizzato È necessario l'aggiornamento del client, ovvero Flash Media Rights Management Server (FMRMS) richiede un nuovo motore DRM (Digital Rights Management). 1007 non utilizzato Errore interno generico. 1008 Codice di errore dettagliato di decrittografia Codice di licenza non corretto. 1009 non utilizzato Il contenuto FLV è corrotto. 1010 non utilizzato 1011 non utilizzato La versione dell'applicazione non corrisponde a quanto specificato nella policy. 1012 non utilizzato La verifica del voucher associato al contenuto crittografato non è riuscita, a indicare che il contenuto potrebbe essere corrotto. 1013 non utilizzato Il voucher associato con il contenuto crittografato potrebbe non essere salvato. 1014 non utilizzato La verifica dell'integrità dell'intestazione FLV non è riuscita, a indicare che il contenuto potrebbe essere corrotto. Codici di errore principali ID errore secondari Dettagli errore Descrizione 3300 Codice di errore di Adobe Policy Server L'applicazione ha rilevato un voucher non valido associato al contenuto. 3301 non utilizzato Autenticazione utente non riuscita. 3302 non utilizzato Flash Media Rights Management Server (FMRMS) non supporta Secure Sockets Layer (SSL). 3303 non utilizzato Il contenuto è scaduto e non è più disponibile per la visualizzazione. 3304 non utilizzato Errore di autorizzazione utente. Può verificarsi anche se l'utente è autenticato, ad esempio, nel caso l'utente non abbia acquistato i diritti di visualizzazione del contenuto. 3305 non utilizzato 3306 non utilizzato È necessario l'aggiornamento del client, ovvero Flash Media Rights Management Server (FMRMS) richiede un nuovo motore client DRM (Digital Rights Management). 3307 non utilizzato Errore interno generico di DRM. 3308 Codice di errore dettagliato di decrittografia Codice di licenza non corretto. publisherID:applicationID Server URL Descrizione L'ID dell'applicazione di visualizzazione non corrisponde a un ID valido supportato dall'autore del contenuto. Impossibile connettersi al server. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 291 Uso della funzionalità DRM (Digital Rights Management) Codici di errore principali ID errore secondari Dettagli errore Descrizione 3309 non utilizzato Il contenuto video di Flash è corrotto. 3310 non utilizzato publisherID:applicationID L'ID dell'applicazione di visualizzazione non corrisponde a un ID valido supportato dall'autore del contenuto. In altre parole, l'autore del contenuto non supporta l'applicazione di visualizzazione. 3311 non utilizzato min=x:max=y La versione dell'applicazione non corrisponde a quanto specificato nel voucher. 3312 non utilizzato La verifica del voucher associato al contenuto crittografato non è riuscita, a indicare che il contenuto potrebbe essere corrotto. 3313 non utilizzato Il voucher associato con il contenuto crittografato potrebbe non essere salvato in Microsafe. 3314 non utilizzato La verifica dell'integrità dell'intestazione FLV non è riuscita, a indicare che il contenuto potrebbe essere corrotto. 3315 non utilizzato Non è consentita la riproduzione remota di contenuto protetto da DRM. 3316 non utilizzato Modulo AdobeCP mancante. 3317 non utilizzato Caricamento modulo AdobeCP non riuscito. 3318 non utilizzato Rilevata versione AdobeCP incompatibile. 3319 non utilizzato Punto di ingresso API AdobeCP mancante. 3320 non utilizzato Il modulo AdobeCP non è autenticato. Creazione di un gestore DRMErrorEvent L'esempio seguente crea un gestore eventi per l'evento NetStream che ha originato l'evento. Viene chiamato quando si verifica un errore durante il tentativo del NetStream di riprodurre il contenuto crittografato da DRM. Di solito, quando in un'applicazione si verifica un errore, questa esegue una serie di attività di pulizia, informa l'utente dell'errore e fornisce opzioni per la risoluzione del problema. private function drmErrorEventHandler(event:DRMErrorEvent):void { trace(event.toString()); } Uso della classe DRMManager Potete usare la classe DRMManager per gestire i voucher e le sessioni del server di gestione dei diritti multimediali in un'applicazione AIR. La classe DRMManager è disponibile in AIR versione 1.5 o successiva. Gestione dei voucher SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 292 Uso della funzionalità DRM (Digital Rights Management) Quando un utente riproduce online un file multimediale protetto da DRM, AIR ottiene e memorizza nella cache il voucher della licenza necessario per visualizzare il contenuto. Se il file viene salvato localmente dall'applicazione e il voucher consente la riproduzione non in linea, l'utente può visualizzare il contenuto anche se non è disponibile una connessione al server di gestione dei diritti multimediali. Usando la classe DRMManager e il metodo preloadEmbeddedMetadata() della classe NetStream, potete memorizzare preventivamente il voucher nella cache, in modo da evitare che l'applicazione avvii la riproduzione per ottenere la licenza necessaria per la visualizzazione del contenuto. L'applicazione può, ad esempio, scaricare il file multimediale, quindi ottenere il voucher mentre l'utente è online. Per precaricare un voucher, usate il metodo preloadEmbeddedMetadata() della classe NetStream per ottenere un oggetto DRMContentData. L'oggetto DRMContentData contiene l'URL e il dominio del server di gestione dei diritti multimediali che può fornire la licenza e indica se è richiesta l'autenticazione. Con queste informazioni potete chiamare il metodo loadVoucher() della classe DRMManager per ottenere il voucher e memorizzarlo nella cache. Il flusso di lavoro per precaricare i voucher è descritto più dettagliatamente in “Precaricamento di voucher per la riproduzione non in linea” a pagina 282. Gestione delle sessioni Potete usare la classe DRMManager anche per autenticare l'utente su un server di gestione dei diritti multimediali e gestire le sessioni persistenti. Chiamate il metodo authenticate() della classe DRMManager per stabilire una sessione con il server di gestione dei diritti multimediali. Una volta completata correttamente l'autenticazione, DRMManager invia un oggetto DRMAuthenticationCompleteEvent. Questo oggetto contiene un token di sessione. Potete salvare questo token per stabilire le sessioni successive, in modo che l'utente non debba fornire le credenziali del proprio account. Passate il token al metodo setAuthenticationToken() per stabilire una nuova sessione autenticata. (La scadenza del token e altri attributi sono determinai dalle impostazioni del server che genera il token. La struttura di dati del token non viene interpretata dal codice dell'applicazione AIR e potrebbe essere modificata negli aggiornamenti futuri di AIR). I token di autenticazione possono essere trasferiti ad altri computer. Per proteggere i token, potete archiviarli nell'archivio locale crittografato di AIR. Per ulteriori informazioni, consultate “Memorizzazione di dati crittografati” a pagina 218. Eventi DRMStatus DRMManager invia un oggetto DRMStatusEvent dopo che una chiamata al metodo loadVoucher() è stata completata correttamente. Se si ottiene un voucher, la proprietà detail dell'oggetto event presenta il valore "DRM.voucherObtained" e la proprietà voucher contiene l'oggetto DRMVoucher. Se non si ottiene un voucher, la proprietà detail ha comunque il valore "DRM.voucherObtained", tuttavia la proprietà voucher è null. Non è possibile ottenere un voucher, ad esempio, se utilizzate LoadVoucherSetting di localOnly e non sono presenti voucher memorizzati nella cache locale. Se la chiamata a loadVoucher() non viene completata correttamente, ad esempio a causa di un errore di autenticazione o di comunicazione, DRMManager invia un oggetto DRMErrorEvent. Eventi DRMAuthenticationComplete DRMManager invia un oggetto DRMAuthenticationCompleteEvent quando un utente viene autenticato correttamente tramite una chiamata al metodo authenticate(). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 293 Uso della funzionalità DRM (Digital Rights Management) In AIR 1.5 l'oggetto DRMAuthenticationCompleteEvent contiene un token riutilizzabile che può essere usato per fare in modo che l'autenticazione dell'utente persista in tutte le sessioni dell'applicazione. Passate questo token al metodo setAuthenticationToken() di DRMManager per stabilire nuovamente la sessione. Gli attributi del token, ad esempio la scadenza, sono impostati dal creatore del token. AIR non comprende un'API per l'esame degli attributi dei token. Eventi DRMAuthenticationError DRMManager invia un oggetto DRMAuthenticationErrorEvent quando un utente non può essere autenticato correttamente tramite una chiamata al metodo authenticate() o setAuthenticationToken(). Uso della classe DRMContentData L'oggetto DRMContentData contiene le proprietà dei metadati di un file multimediale protetto da DRM. Le proprietà DRMContentData contengono le informazioni necessarie per ottenere un voucher della licenza per visualizzare il contenuto. 294 Capitolo 26: Opzioni di avvio e di uscita dalle applicazioni In questa sezione vengono esaminate le opzioni e le considerazioni per l'avvio di un'applicazione installata di Adobe® AIR™ e per la chiusura di un'applicazione in esecuzione. Chiamata dell'applicazione Un'applicazione AIR viene chiamata quando l'utente o il sistema operativo: • Avvia l'applicazione dalla shell del desktop. • Utilizza l'applicazione come comando sulla shell della riga di comando. • Apre un tipo di file al quale l'applicazione è associata come applicazione di apertura predefinita. • (Mac OS X) Fa clic sull'icona dell'applicazione nella barra delle attività di ancoraggio, a prescindere se l'applicazione sia attualmente in esecuzione o meno. • Sceglie di avviare l'applicazione dal programma di installazione (alla fine di un nuovo processo di installazione oppure dopo aver fatto doppio clic sul file AIR per un'applicazione già installata). • Avvia un aggiornamento di un'applicazione AIR quando la versione installata segnala che sta gestendo gli aggiornamenti dell'applicazione mediante l'inclusione di una dichiarazione <customUpdateUI>true</customUpdateUI> nel file descrittore dell'applicazione. • Visita una pagina Web che ospita un badge Flash o un'applicazione che chiama il metodo com.adobe.air.AIR launchApplication() specificando le informazioni di identificazione per l'applicazione AIR. (Affinché la chiamata al browser riesca, il file descrittore dell'applicazione deve includere anche una dichiarazione <allowBrowserInvocation>true</allowBrowserInvocation>). Consultate “Avvio dal browser di un'applicazione AIR installata” a pagina 323. Ogniqualvolta viene chiamata un'applicazione AIR, AIR invia un oggetto InvokeEvent di tipo invoke attraverso l'oggetto singleton NativeApplication. Per offrire a un'applicazione tempo sufficiente a inizializzarsi e a registrare un listener di eventi, gli eventi invoke vengono inseriti in una coda anziché eliminati. Non appena il listener è stato registrato, tutti gli eventi in coda vengono consegnati. Nota: quando un'applicazione viene chiamata mediante la funzione di chiamata del browser, se l'applicazione non è già in esecuzione l'oggetto NativeApplication invia solo un evento invoke. Consultate “Avvio dal browser di un'applicazione AIR installata” a pagina 323. Per ricevere gli eventi invoke, chiamate il metodo addEventListener() dell'oggetto NativeApplication (NativeApplication.nativeApplication). Quando un listener di eventi effettua la registrazione di un evento invoke, riceve anche tutti gli eventi invoke che si sono verificati prima della registrazione. Gli eventi invoke in coda vengono inviati uno alla volta in un breve intervallo dopo che la chiamata a addEventListener() viene restituita. Se nel corso di questo processo si verifica un nuovo evento invoke, è possibile che esso venga inviato prima di uno o più eventi in coda. Questo accodamento di eventi consente di gestire eventuali eventi invoke che si sono verificati prima dell'esecuzione del codice di inizializzazione. È opportuno sottolineare che se si aggiunge un listener di eventi in una fase successiva dell'esecuzione (dopo l'inizializzazione dell'applicazione), esso riceverà comunque tutti gli eventi invoke che si sono verificati fin dall'avvio dell'applicazione. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 295 Opzioni di avvio e di uscita dalle applicazioni Viene avviata una sola istanza di un'applicazione AIR. Quando un'applicazione già in esecuzione viene richiamata, AIR invia un nuovo evento invoke all'istanza in esecuzione. Un'applicazione AIR è responsabile per la risposta a un evento invoke e l'azione appropriata da intraprendere, come ad esempio l'apertura di una nuova finestra del documento. Un oggetto InvokeEvent contiene tutti gli argomenti trasmessi all'applicazione, nonché la directory da cui l'applicazione è stata chiamata. Se l'applicazione è stata chiamata a causa di un'associazione di tipo file, il percorso completo al file viene incluso negli argomenti della riga di comando. Analogamente, se l'applicazione è stata chiamata a causa di un aggiornamento, viene fornito il percorso completo al file AIR di aggiornamento. Quando in una sola operazione vengono aperti più file, in Mac OS X viene inviato un unico oggetto InvokeEvent. Ogni file viene incluso nell'array arguments. In Windows e Linux per ogni file viene inviato un oggetto InvokeEvent distinto. L'applicazione può gestire gli eventi invoke mediante la registrazione di un listener con il relativo oggetto NativeApplication: NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvokeEvent); air.NativeApplication.nativeApplication.addEventListener(air.InvokeEvent.INVOKE, onInvokeEvent); Definendo inoltre un listener di eventi: var arguments:Array; var currentDir:File; public function onInvokeEvent(invocation:InvokeEvent):void { arguments = invocation.arguments; currentDir = invocation.currentDirectory; } Acquisizione degli argomenti della riga di comando Gli argomenti della riga di comando associati alla chiamata di un'applicazione AIR sono consegnati nell'evento invoke inviato dall'oggetto NativeApplication. La proprietà InvokeEvent.arguments contiene un array degli argomenti trasmessi dal sistema operativo quando viene chiamata un'applicazione AIR. Se gli argomenti contengono percorsi file relativi, solitamente è possibile risolvere i percorsi mediante la proprietà currentDirectory. Gli argomenti trasmessi a un'applicazione AIR vengono trattati come stringhe delimitate da spazi vuoti, a meno che non siano racchiusi tra virgolette: Argomenti Array tick tock {tick,tock} tick "tick tock" {tick,tick tock} "tick" “tock” {tick,tock} \"tick\" \"tock\" {"tick","tock"} La proprietà InvokeEvent.currentDirectory contiene un oggetto File che rappresenta la directory da cui l'applicazione è stata avviata. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 296 Opzioni di avvio e di uscita dalle applicazioni Quando un'applicazione viene chiamata perché viene aperto un file di un tipo registrato dall'applicazione, il percorso nativo al file viene incluso negli argomenti della riga di comando come stringa. (L'applicazione è responsabile per l'apertura o l'esecuzione dell'operazione prevista sul file). Analogamente, quando un'applicazione viene programmata per l'aggiornamento automatico invece di affidarsi all'interfaccia utente standard per l'aggiornamento di AIR, il percorso nativo al file AIR viene incluso quando un utente fa doppio clic su un file contenente un'applicazione con un ID applicazione corrispondente. È possibile accedere al file utilizzando il metodo resolve() dell'oggetto File currentDirectory: if((invokeEvent.currentDirectory != null)&&(invokeEvent.arguments.length > 0)){ dir = invokeEvent.currentDirectory; fileToOpen = dir.resolvePath(invokeEvent.arguments[0]); } È inoltre opportuno convalidare che un argomento sia in realtà un percorso a un file. Esempio: chiamata di un log di eventi Nell'esempio seguente viene illustrato come registrare i listener e gestire l'evento invoke. Nell'esempio vengono registrati tutti gli eventi di chiamata ricevuti e vengono visualizzati la directory corrente e gli argomenti della riga di comando. Nota: per creare l'esempio seguente mediante Adobe® Flash® CS3 Professional o Adobe® Flash® CS4 Professional, create in primo luogo un file Flash (Adobe AIR). Nel pannello Impostazioni di ActionScript 3.0 (File > Impostazioni pubblicazione... > pulsante Impostazioni) immettete il nome InvokeEventLogExample nel campo della classe Document. Salvate il file FLA con il nome InvokeEventLogExample.fla, quindi create un file ActionScript nella stessa cartella. Immettete il codice seguente nel file ActionScript, quindi salvate il file con il nome InvokeEventLogExample.as. package { import import import import flash.display.Sprite; flash.events.InvokeEvent; flash.desktop.NativeApplication; flash.text.TextField; public class InvokeEventLogExample extends Sprite { public var log:TextField; public function InvokeEventLogExample() { log = new TextField(); log.x = 15; log.y = 15; log.width = 520; log.height = 370; log.background = true; addChild(log); NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke); } public function onInvoke(invokeEvent:InvokeEvent):void { var now:String = new Date().toTimeString(); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 297 Opzioni di avvio e di uscita dalle applicazioni logEvent("Invoke event received: " + now); if (invokeEvent.currentDirectory != null) { logEvent("Current directory=" + invokeEvent.currentDirectory.nativePath); } else { logEvent("--no directory information available--"); } if (invokeEvent.arguments.length > 0) { logEvent("Arguments: " + invokeEvent.arguments.toString()); } else { logEvent("--no arguments--"); } } public function logEvent(entry:String):void { log.appendText(entry + "\n"); trace(entry); } } } Avvio all'accesso È possibile impostare un'applicazione AIR in modo che venga avviata automaticamente quando l'utente corrente accede impostando NativeApplication.nativeApplication.startAtLogin=true. Una volta effettuata tale impostazione, l'applicazione viene avviata automaticamente ogni volta che l'utente accede al sistema e continua ad essere avviata all'accesso al sistema fino a che l'impostazione viene modificata su false, l'utente modifica manualmente l'impostazione attraverso il sistema operativo oppure l'applicazione viene disinstallata. L'avvio all'accesso è un'impostazione di runtime. Nota: l'applicazione non viene eseguita quando il computer viene avviato, bensì quando l'utente accede. L'impostazione si applica solo all'utente corrente. Inoltre, per impostare la proprietà startAtLogin su true è necessario che l'applicazione sia installata. Se la proprietà viene impostata quando un'applicazione non è installata (ad esempio quando viene avviata con ADL), viene generato un errore. Chiamata del browser Mediante la funzionalità di chiamata browser un sito Web può avviare un'applicazione AIR installata attivandola mediante il browser. La chiamata browser è consentita solo se il file descrittore dell'applicazione imposta allowBrowserInvocation su true: <allowBrowserInvocation>true</allowBrowserInvocation> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 298 Opzioni di avvio e di uscita dalle applicazioni Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. Quando l'applicazione viene chiamata tramite browser, l'oggetto NativeApplication dell'applicazione invia un oggetto BrowserInvokeEvent. Per ricevere l'evento BrowserInvokeEvent, chiamate il metodo addEventListener() dell'oggetto NativeApplication (NativeApplication.nativeApplication) nell'applicazione AIR. Quando un listener di eventi effettua la registrazione di un evento BrowserInvokeEvent, riceve anche tutti gli eventi BrowserInvokeEvent che si sono verificati prima della registrazione. Questi eventi vengono inviati dopo che la chiamata a addEventListener() viene restituita, ma non necessariamente prima di altri eventi BrowserInvokeEvent che potrebbero essere stati ricevuti dopo la registrazione. Ciò consente di gestire gli eventi BrowserInvokeEvent che si sono verificati prima dell'esecuzione del codice di inizializzazione (ad esempio quando l'applicazione è stata inizialmente chiamata dal browser). Si consideri che se si aggiunge un listener di eventi in una fase successiva dell'esecuzione (dopo l'inizializzazione dell'applicazione), esso riceverà comunque tutti gli eventi BrowserInvokeEvent che si sono verificati fin dall'avvio dell'applicazione. L'oggetto BrowserInvokeEvent include le seguenti proprietà: Proprietà Descrizione arguments Un array di argomenti (stringhe) da trasmettere all'applicazione. isHTTPS Se il contenuto del browser utilizza (true) o meno (false) lo schema URL https. isUserEvent Se la chiamata browser ha avuto come risultato un evento utente (ad esempio, un clic del mouse). In AIR 1.0, il valore è sempre impostato su true; AIR richiede un evento utente per la funzionalità di chiamata browser. sandboxType Il tipo di sandbox per il contenuto del browser. I valori validi definiti sono gli stessi che è possibile utilizzare nella proprietà Security.sandboxType. Può trattarsi di uno dei seguenti: securityDomain • Security.APPLICATION: il contento si trova nella sandbox di sicurezza dell'applicazione. • Security.LOCAL_TRUSTED: il contenuto si trova nella sandbox di sicurezza locale con file system. • Security.LOCAL_WITH_FILE: il contenuto si trova nella sandbox di sicurezza locale con file system. • Security.LOCAL_WITH_NETWORK: il contenuto si trova nella sandbox di sicurezza locale con rete. • Security.REMOTE: il contenuto si trova in un dominio (rete) remoto. Il dominio di sicurezza per il contenuto del browser, ad esempio "www.adobe.com" o "www.example.org". La proprietà è impostata solo per il contenuto della sandbox di sicurezza remota (per il contenuto proveniente da un dominio di rete) e non per il contenuto di una sandbox di sicurezza dell'applicazione o locale. Se utilizzate la funzionalità di chiamata browser, accertatevi di considerare le implicazioni sulla sicurezza. Quando un sito Web avvia un'applicazione AIR, può inviare i dati mediante la proprietà arguments dell'oggetto BrowserInvokeEvent. Fate attenzione a utilizzare questi dati in operazioni sensibili quali API di caricamento del codice o di file. Il livello di rischio varia in base alle operazioni che l'applicazione effettuerà con i dati. Se ci si aspetta che solo uno specifico sito Web chiami l'applicazione, sarebbe opportuno che quest'ultima controllasse la proprietà securityDomain dell'oggetto BrowserInvokeEvent. È inoltre possibile richiedere che il sito Web che chiama l'applicazione utilizzi HTTPs. Ciò può essere verificato controllando la proprietà isHTTPS dell'oggetto BrowserInvokeEvent. L'applicazione dovrebbe convalidare i dati che vengono trasmessi. Ad esempio, se si prevede che un'applicazione trasmetta URL a un dominio specifico, essa dovrebbe convalidare che gli URL puntino effettivamente a quel dominio. In questo modo è possibile impedire a un utente malintenzionato di "ingannare" l'applicazione in modo che invii dati riservati. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 299 Opzioni di avvio e di uscita dalle applicazioni Nessuna applicazione dovrebbe utilizzare argomenti BrowserInvokeEvent che potrebbero puntare a risorse locali. Ad esempio, un'applicazione non dovrebbe creare oggetti File basati su un percorso trasmesso dal browser. Se si prevede che vengano trasmessi percorsi remoti dal browser, l'applicazione dovrebbe garantire che i percorsi non utilizzino il protocollo file:// invece di un protocollo remoto. Per dettagli su come chiamare un'applicazione dal browser, consultate “Avvio dal browser di un'applicazione AIR installata” a pagina 323. Terminazione dell'applicazione Il sistema più semplice per terminare un'applicazione consiste nel chiamare il metodo NativeApplication.nativeApplication.exit(). Tale sistema funziona quando l'applicazione non ha dati da salvare né risorse esterne da pulire. La chiamata al metodo exit() chiude tutte le finestre e termina l'applicazione. Tuttavia, per consentire alle finestre o ad altri componenti dell'applicazione di interrompere il processo di terminazione ed eventualmente di salvare dati critici, inviate gli eventi di avviso appropriati prima di effettuare la chiamata a exit(). Un'ulteriore considerazione in merito alla chiusura normale di un'applicazione consiste nel fornire un percorso di esecuzione singolo, a prescindere da come viene avviato il processo di arresto. L'utente, o il sistema operativo, possono attivare la terminazione dell'applicazione nei modi seguenti: • Chiudendo l'ultima finestra dell'applicazione quando NativeApplication.nativeApplication.autoExit è impostato su true. • Selezionando il comando di uscita dall'applicazione dal sistema operativo (ad esempio quando l'utente sceglie il comando di uscita dall'applicazione dal menu predefinito). Ciò accade solo su Mac OS; Windows e Linux non forniscono un comando di uscita dall'applicazione attraverso il chrome di sistema. • Mediante l'arresto del computer. Quando un comando di uscita viene mediato nel sistema operativo da uno di questi sistemi, NativeApplication invia un evento exiting. Se nessun listener annulla l'evento exiting, tutte le finestre aperte vengono chiuse. Ciascuna finestra invia un evento closing e quindi un evento close. Se qualcuna delle finestre annulla l'evento closing, il processo di arresto viene interrotto. Se l'ordine di chiusura delle finestre è un problema per l'applicazione, utilizzate listener per l'evento exiting da NativeApplication, quindi chiudete manualmente le finestre nell'ordine appropriato. Ciò può accadere, ad esempio, se si dispone di una finestra del documento con tavolozze degli strumenti. Può essere quanto meno scomodo se il sistema chiude le tavolozze, ma l'utente decide di annullare il comando di uscita per salvare alcuni dati. In Windows, l'unica volta che si otterrà l'evento exiting sarà dopo la chiusura dell'ultima finestra (quando la proprietà autoExit dell'oggetto NativeApplication è impostato su true). Per seguire un comportamento coerente su tutte le piattaforme, a prescindere se la sequenza di uscita sia avviata mediante il chrome del sistema operativo, i comandi di menu o la logica dell'applicazione, per uscire dall'applicazione è opportuno osservare le seguenti pratiche consigliate: 1 Inviate sempre un evento exiting mediante l'oggetto NativeApplication prima di chiamare il metodo exit() nel codice dell'applicazione, quindi controllate che nessun altro componente dell'applicazione annulli l'evento. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 300 Opzioni di avvio e di uscita dalle applicazioni public function applicationExit():void { var exitingEvent:Event = new Event(Event.EXITING, false, true); NativeApplication.nativeApplication.dispatchEvent(exitingEvent); if (!exitingEvent.isDefaultPrevented()) { NativeApplication.nativeApplication.exit(); } } 2 Eseguite il listener per l'evento exiting dell'applicazione dall'oggetto NativeApplication.nativeApplication, quindi, nel gestore, chiudete tutte le finestre inviando innanzitutto un evento closing. Eseguite tutte le attività di pulitura necessarie, quali il salvataggio dei dati di un'applicazione o l'eliminazione di file temporanei, dopo che tutte le finestre sono state chiuse. Durante la pulitura, utilizzate solo metodi sincroni per essere sicuri che vengano completati prima dell'uscita dall'applicazione. Se l'ordine di chiusura delle finestre non conta, è possibile iniziare a cercare nell'array NativeApplication.nativeApplication.openedWindows e chiudere ciascuna finestra a turno. Se l'ordine conta, fornite un sistema per chiudere le finestre nella sequenza corretta. private function onExiting(exitingEvent:Event):void { var winClosingEvent:Event; for each (var win:NativeWindow in NativeApplication.nativeApplication.openedWindows) { winClosingEvent = new Event(Event.CLOSING,false,true); win.dispatchEvent(winClosingEvent); if (!winClosingEvent.isDefaultPrevented()) { win.close(); } else { exitingEvent.preventDefault(); } } if (!exitingEvent.isDefaultPrevented()) { //perform cleanup } } 3 Le finestre dovrebbero sempre gestire la propria pulitura "ascoltando" i relativi eventi closing. 4 Utilizzate un solo listener exiting nell'applicazione, dal momento che i gestori non sono in grado di sapere se gestori successivi annulleranno l'evento exiting e sarebbe poco saggio affidarsi all'ordine di esecuzione. Consultare anche “Impostazione delle proprietà dell'applicazione AIR” a pagina 46 “Presentazione di un'interfaccia utente di aggiornamento dell'applicazione personalizzata” a pagina 334 301 Capitolo 27: Lettura delle impostazioni dell'applicazione Nella fase di runtime, per ciascuna applicazione è possibile ottenere le proprietà del file descrittore dell'applicazione oltreché l'ID dell'editore. Tali dati sono contenuti nelle proprietà applicationDescriptor e publisherID dell'oggetto NativeApplication. Lettura del file descrittore dell'applicazione È possibile leggere il file descrittore dell'applicazione in esecuzione al momento, come oggetto XML, ottenendo la proprietà applicationDescriptor dell'oggetto NativeApplication, come segue. var appXml:XML = NativeApplication.nativeApplication.applicationDescriptor; È poi possibile accedere ai dati del descrittore dell'applicazione come oggetto XML (E4X), come segue. var appXml:XML = NativeApplication.nativeApplication.applicationDescriptor; var ns:Namespace = appXml.namespace(); var appId = appXml.ns::id[0]; var appVersion = appXml.ns::version[0]; var appName = appXml.ns::filename[0]; air.trace("appId:", appId); air.trace("version:", appVersion); air.trace("filename:", appName); var xmlString = air.NativeApplication.nativeApplication.applicationDescriptor; Per ulteriori informazioni, consultate “Struttura del file descrittore dell'applicazione” a pagina 46. Ottenimento dell'identificatore dell'applicazione e dell'editore Congiuntamente, gli ID dell'applicazione e dell'editore identificano le applicazioni AIR in modo univoco. L'ID dell'applicazione si specifica nell'elemento <id> del descrittore dell'applicazione stessa. L'ID dell'editore viene estrapolato dal certficato tramite il quale si è firmato il pacchetto di installazione AIR. È possibile leggere l'ID dell'applicazione dalla proprietà id dell'oggetto NativeApplication, come illustrato nel codice qui di seguito. trace(NativeApplication.nativeApplication.applicationID); È possibile leggere l'ID dell'editore dalla proprietà publisherID di NativeApplication, come segue. trace(NativeApplication.nativeApplication.publisherID); Nota: se le applicazioni AIR vengono eseguite con ADL, non presentano un ID dell'editore a meno che non ne venga loro assegnato uno temporaneo tramite il flag -pubID sulla riga di comando ADL. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 302 Lettura delle impostazioni dell'applicazione L'ID dell'editore delle applicazioni installate è inoltre reperibile nel file META-INF/AIR/publisherid contenuto nella directory di installazione dell'applicazione in oggetto. Per ulteriori informazioni, consultate “Informazioni sugli identificatori di editori AIR” a pagina 326. 303 Capitolo 28: Uso delle informazioni di runtime e del sistema operativo In questa sezione vengono descritti i modi in cui un'applicazione AIR può gestire le associazioni di file del sistema operativo, rilevare l'attività dell'utente e reperire informazioni sulla fase di runtime di Adobe® AIR™. Gestione delle associazioni di file È necessario dichiarare le associazioni tra l'applicazione e un tipo di file nel descrittore dell'applicazione. Durante il processo di installazione, il programma di installazione dell'applicazione AIR associa l'applicazione AIR come applicazione di apertura predefinita per ognuno dei tipi di file dichiarati, a meno che non vi sia già un'altra applicazione predefinita. Il processo di installazione dell'applicazione AIR non esclude un'associazione del tipo di file esistente. Per sostituire l'associazione con un'altra applicazione, è possibile richiamare il metodo NativeApplication.setAsDefaultApplication() in fase di runtime. È buona prassi verificare che le associazioni di file previste siano a posto quando l'applicazione viene avviata. Il motivo è duplice: il programma di installazione dell'applicazione AIR non esclude le associazioni di file esistenti e le associazioni di file in un sistema utente possono cambiare in qualsiasi momento. Quando un'altra applicazione prevede l'attuale associazione di file, è inoltre opportuno chiedere conferma all'utente prima di sostituire l'associazione esistente. I seguenti metodi della classe NativeApplication consentono a un'applicazione di gestire le associazioni di file. Ognuno dei metodi usa come parametro l'estensione tipo file: Metodo Descrizione isSetAsDefaultApplication() Restituisce il valore true se l'applicazione AIR è attualmente associata al tipo di file specificato. setAsDefaultApplication() Crea l'associazione tra l'applicazione AIR e l'azione di apertura del tipo di file. removeAsDefaultApplication() Elimina l'associazione tra l'applicazione AIR e il tipo di file. getDefaultApplication() Indica il percorso dell'applicazione che è attualmente associata al tipo di file. AIR è in grado di gestire esclusivamente le associazioni per i tipi di file inizialmente dichiarati nel descrittore dell'applicazione. Non è possibile ottenere informazioni sulle associazioni di un tipo di file non dichiarato, neanche se un utente ha creato manualmente l'associazione tra quel tipo e l'applicazione. Se viene richiamato uno qualsiasi dei metodi di gestione dell'associazione di file con l'estensione per un tipo di file non dichiarato nel descrittore dell'applicazione, il risultato ottenuto è un'eccezione di runtime. Per informazioni su come dichiarare i tipi file nel descrittore dell'applicazione, consultate “Dichiarazione delle associazioni di tipo file” a pagina 55. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 304 Uso delle informazioni di runtime e del sistema operativo Informazioni su versione runtime e livello patch L'oggetto NativeApplication include una proprietà runtimeVersion che corrisponde alla versione runtime in cui è eseguita l'applicazione (una stringa, ad esempio "1.0.5"). L'oggetto NativeApplication include inoltre una proprietà runtimePatchLevel, che corrisponde al livello della patch di runtime (un numero, ad esempio 2960). Nel seguente codice vengono usate queste proprietà: trace(NativeApplication.nativeApplication.runtimeVersion); trace(NativeApplication.nativeApplication.runtimePatchLevel); Rilevamento delle funzionalità AIR Nel caso di un file che è abbinato a un'applicazione Adobe AIR, la proprietà Security.sandboxType è impostata sul valore definito dalla costante Security.APPLICATION. È possibile caricare il contenuto (che può contenere o meno le interfacce API specifiche di AIR) dopo aver stabilito se il file si trova nella sandbox di sicurezza di Adobe AIR, come illustrato nel seguente codice: if (Security.sandboxType == Security.APPLICATION) { // Load SWF that contains AIR APIs } else { // Load SWF that does not contain AIR APIs } Tutte le risorse che non sono installate con l'applicazione AIR vengono assegnate alle stesse sandbox di sicurezza alle quali verrebbe assegnato Adobe® Flash® Player in un browser Web. Le risorse remote vengono assegnate alle sandbox in base ai loro domini di origine, mentre le risorse locali confluiscono nelle sandbox locale con rete o locale affidabile. È possibile controllare che la proprietà statica Capabilities.playerType sia impostata su"Desktop" per verificare se il contenuto è eseguito nella fase di runtime (e non è eseguito in Flash Player in esecuzione in un browser). Per ulteriori informazioni, consultate “Sicurezza in AIR” a pagina 25. Verifica delle presenza dell'utente L'oggetto NativeApplication invia due eventi che consentono di verificare se un utente sta usando attivamente un computer. Se non viene rivelata nessuna attività del mouse o della tastiera nell'intervallo determinato dalla proprietà NativeApplication.idleThreshold, l'oggetto NativeApplication invia un evento userIdle. Non appena viene registrato un input della tastiera o del mouse, l'oggetto NativeApplication invia un evento userPresent. L'intervallo idleThreshold viene misurato in secondi e ha un valore predefinito pari a 300 (5 minuti). La proprietà NativeApplication.nativeApplication.lastUserInput permette inoltre di conoscere il numero di secondi trascorsi dall'ultimo input dell'utente. Con le seguenti righe di codice viene impostata la soglia di inattività su 2 minuti, in attesa sia dell'eventouserIdle che dell'evento userPresent : SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 305 Uso delle informazioni di runtime e del sistema operativo NativeApplication.nativeApplication.idleThreshold = 120; NativeApplication.nativeApplication.addEventListener(Event.USER_IDLE, function(event:Event) { trace("Idle"); }); NativeApplication.nativeApplication.addEventListener(Event.USER_PRESENT, function(event:Event) { trace("Present"); }); Nota: viene inviato un solo evento userIdle tra due eventi userPresent. 306 Capitolo 29: Monitoraggio della connettività di rete Adobe® AIR™ fornisce gli strumenti necessari per rilevare le modifiche che riguardano la connettività di rete di un computer sul quale è installata un'applicazione AIR. Tali informazioni sono utili per le applicazioni che usano dati ottenuti dalla rete o per le applicazioni che devono verificare la disponibilità di un servizio di rete. Rilevamento delle modifiche relative alla connettività di rete È possibile che la vostra applicazione AIR sia eseguita in ambienti caratterizzati da una connettività di rete incerta e mutevole. Per agevolare la gestione delle connessioni alle risorse online da parte di un'applicazione, Adobe AIR invia un evento modifica di rete ogni volta che una connessione di rete diventa disponibile o cessa di esserlo. L'evento modifica di rete viene inviato dall'oggetto NativeApplication dell'applicazione. In risposta a questo evento, aggiungete un listener: NativeApplication.nativeApplication.addEventListener(Event.NETWORK_CHANGE, onNetworkChange); E definite una funzione gestore eventi: function onNetworkChange(event:Event) { //Check resource availability } L'evento Event.NETWORK_CHANGE non segnala una modifica relativa a tutta l'attività della rete, ma a una singola connessione di rete. AIR non tenta di interpretare il significato della modifica di rete. È possibile che un computer della rete disponga di svariate connessioni reali e virtuali, pertanto la perdita di una connessione non comporta necessariamente la perdita una risorsa. D'altro canto, neppure le nuove connessioni garantiscono una migliore disponibilità delle risorse. Talvolta una nuova connessione può persino bloccare l'accesso a risorse che in precedenza erano disponibili (è il caso, ad esempio, di una connessione a una rete privata virtuale o VPN). In genere un'applicazione ha un solo modo per scoprire se può o meno stabilire una connessione con una risorsa remota: tentare di connettersi. A questo scopo, i framework di monitoraggio dei servizi inclusi nel pacchetto air.net forniscono alle applicazioni AIR uno strumento basato sugli eventi, attraverso il quale possono rispondere alle modifiche della connettività di rete con un host specifico. Nota: il framework di monitoraggio dei servizi determina se la risposta di un server a una richiesta è accettabile o meno. Ciò non garantisce la piena connettività. I servizi Web scalabili usano spesso strumenti per la creazione di cache e di bilanciamento del carico che consentono di reindirizzare il traffico verso un cluster di server Web. In questa situazione, i provider di servizi offrono una diagnosi soltanto parziale della connettività di rete. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 307 Monitoraggio della connettività di rete Nozioni di base sul monitoraggio dei servizi Il framework di monitoraggio dei servizi, che è indipendente dal framework AIR, risiede nel file servicemonitor.swc. Per poter usare il framework, è necessario che il file servicemonitor.swc sia incluso nel vostro processo di creazione. Importante: per usare queste classi in Adobe® Flash® CS3 Professional, trascinate il componente ServiceMonitorShim dal pannello Componenti al pannello Libreria, quindi aggiungete la seguente istruzione import al codice ActionScript 3.0: import air.net.*; Per utilizzare queste classi in Adobe® Flash® CS4 Professional: 1 Selezionate il comando File > Impostazioni pubblicazione. 2 Fate clic sul pulsante Impostazioni per ActionScript 3.0. Selezionate Percorso di libreria. 3 Fate clic sul pulsante Sfoglia e passate ad Adobe Flash CS4/AIK1.1/frameworks/libs/air/servicemoniter.swc. 4 Fate clic sul pulsante OK. 5 Aggiungete le istruzioni import seguenti al codice ActionScript 3.0: import air.net.*; La classe ServiceMonitor implementa il framework per il monitoraggio dei servizi di rete e costituisce una funzionalità di base per i monitor di servizi. Per impostazione predefinita, un'istanza della classe ServiceMonitor invia gli eventi riguardanti la connettività di rete. L'oggetto ServiceMonitor invia questi eventi quando viene creata l'istanza e ogni volta che viene rilevata una modifica della rete da Adobe AIR. È inoltre possibile impostare la proprietà pollInterval di un'istanza ServiceMonitor in modo tale che la connettività di rete venga controllata a intervalli regolari, espressi in millisecondi, indipendentemente dagli eventi relativi alla connettività di rete generale. Un oggetto ServiceMonitor non controlla la connettività di rete finché non viene chiamato il metodo start(). URLMonitor, una sottoclasse della classe ServiceMonitor, rileva le modifiche della connettività HTTP per uno specifico oggetto URLRequest. SocketMonitor, anch'essa una sottoclasse della classe ServiceMonitor, rileva le modifiche della connettività con un host specifico su una porta specifica. Rilevamento della connettività HTTP La classe URLMonitor determina se le richieste HTTP possono essere effettuate a un indirizzo specifico sulla porta 80 (la porta tradizionalmente usata per le comunicazioni HTTP). Nel codice seguente viene usata un'istanza della classe URLMonitor per rilevare le modifiche della connettività al sito Web Adobe: import air.net.URLMonitor; import flash.net.URLRequest; import flash.events.StatusEvent; var monitor:URLMonitor; monitor = new URLMonitor(new URLRequest('http://www.adobe.com')); monitor.addEventListener(StatusEvent.STATUS, announceStatus); monitor.start(); function announceStatus(e:StatusEvent):void { trace("Status change. Current status: " + monitor.available); } SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 308 Monitoraggio della connettività di rete Rilevamento della connettività socket Le applicazioni AIR possono usare anche le connessioni socket per la connettività di modello push. In genere, per motivi di sicurezza, i firewall e i router di rete limitano la comunicazione in rete sulle porte non autorizzate. Gli sviluppatori dovranno dunque mettere in conto la possibilità che gli utenti non siano in condizione di effettuare connessioni socket. Come nell'esempio URLMonitor, nel seguente codice viene usata un'istanza delle classe SocketMonitor per rilevare le modifiche della connettività a una connessione socket sulla porta 6667, tradizionalmente usata per le chat basate su IRC: import air.net.ServiceMonitor; import flash.events.StatusEvent; socketMonitor = new SocketMonitor('www.adobe.com',6667); socketMonitor.addEventListener(StatusEvent.STATUS, socketStatusChange); socketMonitor.start(); function announceStatus(e:StatusEvent):void { trace("Status change. Current status: " + socketMonitor.available); } 309 Capitolo 30: Richieste URL e connettività di rete Le nuove funzionalità Adobe AIR correlate alla specifica delle richieste URL non sono disponibili per contenuto SWF eseguito nel browser. Queste funzionalità sono disponibili solo per il contenuto della sandbox di sicurezza dell'applicazione. In questa sezione sono descritte le funzioni URLRequest nel runtime e sono illustrate le modifiche alle API di connettività di rete nel contenuto AIR. Per ulteriori informazioni sull'uso delle funzionalità di rete e di comunicazione di Adobe® ActionScript® 3.0, consultate Programmazione in Adobe ActionScript 3.0. Uso della classe URLRequest La classe URLRequest consente di definire molto più della semplice stringa URL. AIR aggiunge alcune nuove proprietà alla classe URLRequest, disponibili solo per il contenuto AIR in esecuzione nella sandbox di sicurezza dell'applicazione. Il contenuto nel runtime può definire URL utilizzando nuovi schemi URL (oltre agli schemi standard come file e http). Proprietà URLRequest La classe URLRequest include le proprietà seguenti che sono disponibili per il contenuto solo nella sandbox di sicurezza dell'applicazione AIR: Proprietà Descrizione followRedirects Specifica se seguire (true, valore predefinito) o meno (false) i reindirrizzamenti. Questa proprietà è supportata solo nel runtime. manageCookies Specifica se lo stack del protocollo HTTP deve gestire i cookie (true, valore predefinito) o no (false) per questa richiesta. Questa proprietà è supportata solo nel runtime. authenticate Specifica se le richieste di autenticazione devono essere gestite (true) per questa richiesta. Questa proprietà è supportata solo nel runtime. L'impostazione predefinita è di autenticare le richieste. Questo potrebbe determinare la visualizzazione di una finestra di dialogo di autenticazione se il server richiede delle credenziali di accesso. Potete anche impostare il nome utente e la password. Consultate “Impostazione dei valori predefiniti URLRequest” a pagina 310. cacheResponse Specifica se è necessario memorizzare nella cache i dati della risposta. Questa proprietà è supportata solo nel runtime. L'impostazione predefinita è di memorizzare la risposta nella cache (true). useCache Specifica se la cache locale deve essere consultata prima che la classe URLRequest recuperi i dati. Questa proprietà è supportata solo nel runtime. L'impostazione predefinita (true) è di utilizzare la versione memorizzata nella cache locale, se disponibile. userAgent Specifica la stringa agente utente da utilizzare nella richiesta HTTP. Le proprietà seguenti di un oggetto URLRequest possono essere impostate in base al contenuto in qualsiasi sandbox (non solo nella sandbox di sicurezza dell'applicazione AIR): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 310 Richieste URL e connettività di rete Proprietà Descrizione contentType Il tipo di contenuto MIME di qualsiasi dato inviato con la richiesta URL. data Un oggetto che contiene i dati da trasmettere con la richiesta URL. digest Un "digest" protetto a un file memorizzato nella cache per tenere traccia della cache Adobe® Flash® Player. method Controlla il metodo della richiesta HTTP, ad esempio un'operazione GET o POST. Il contenuto eseguito nel dominio di sicurezza dell'applicazione AIR può specificare stringhe diverse da "GET" o "POST" come la proprietà method. Qualsiasi verbo HTTP è consentito e "GET" è il metodo predefinito. Consultate “Sicurezza in AIR” a pagina 25. requestHeaders L'array di intestazioni di richiesta HTTP da aggiungere alla richiesta HTTP. url Specifica l'URL da richiedere. Nota: la classe HTMLLoader dispone di proprietà correlate per impostazioni attinenti al contenuto caricato da un oggetto HTMLLoader. Per ulteriori informazioni, consultate “Informazioni sulla classe HTMLLoader” a pagina 236. Impostazione dei valori predefiniti URLRequest La classe URLRequestDefaults consente di definire impostazioni predefinite per gli oggetti URLRequest. Il codice seguente, ad esempio, imposta i valori predefiniti per le proprietà manageCookies e useCache: URLRequestDefaults.manageCookies = false; URLRequestDefaults.useCache = false; air.URLRequestDefaults.manageCookies = false; air.URLRequestDefaults.useCache = false; La classe URLRequestDefaults include un metodo setLoginCredentialsForHost() che consente di specificare un nome utente e una password predefiniti da utilizzare per un host specifico. L'host, definito nel parametro hostname del metodo, può essere un dominio, ad esempio "www.example.com", o un dominio e un numero di porta, ad esempio "www.example.com:80". Notate che "example.com", "www.example.com" e "sales.example.com" sono considerati tutti host univoci. Queste credenziali sono utilizzate solo se richieste dal server. Se un utente già autenticato (ad esempio, utilizzando la finestra di dialogo di autenticazione), non potete cambiarlo chiamando il metodo setLoginCredentialsForHost(). Il codice seguente, ad esempio, imposta il nome utente e la password predefiniti da utilizzare in www.example.com: URLRequestDefaults.setLoginCredentialsForHost("www.example.com", "Ada", "love1816$X"); air.URLRequestDefaults.setLoginCredentialsForHost("www.example.com", "Ada", "love1816$X"); Tutte le proprietà delle impostazioni URLRequestDefaults si applicano solo al dominio applicazione del contenuto che imposta la proprietà. Tuttavia, il metodo setLoginCredentialsForHost() si applica a tutti i domini applicazione all'interno dell'applicazione AIR. In questo modo, un'applicazione può accedere a un host e avere tutto il contenuto all'interno dell'applicazione connesso con le credenziali specificate. Per ulteriori informazioni, consultate la classe URLRequestDefaults in Guida di riferimento del linguaggio e dei componenti ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_it). Uso di schermi URL AIR negli URL Gli schemi URL standard, com quelli riportati di seguito, sono disponibili durante la definizione degli URL in qualsiasi sandbox di sicurezza in AIR: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 311 Richieste URL e connettività di rete http: e https: Usarli allo stesso modo che in un browser Web. file: Usarlo per specificare un percorso relativo alla directory principale del file system. Ad esempio: file:///c:/AIR Test/test.txt Potete anche utilizzare gli schemi seguenti durante la definizione di un URL per il contenuto in esecuzione nella sandbox di sicurezza dell'applicazione: app: Usarlo per specificare un percorso relativo alla directory principale dell'applicazione installata (la directory che contiene il file descrittore dell'applicazione per l'applicazione installata). Ad esempio, il percorso seguente punta a una sottodirectory delle risorse della directory dell'applicazione installata: app:/resources Se eseguita nell'applicazione ADL, la directory delle risorse dell'applicazione viene impostata sulla directory che contiene il file descrittore dell'applicazione. app-storage: Usarlo per specificare il percorso relativo alla directory di memorizzazione dell'applicazione. Per ogni applicazione installata, AIR definisce una directory di memorizzazione dell'applicazione univoca per ciascun utente: un percorso utile per archiviare dati specifici dell'applicazione. Ad esempio, il percorso seguente punta a un file prefs.xml file in una sottodirectory delle impostazioni della directory di memorizzazione dell'applicazione: app-storage:/settings/prefs.xml Il percorso della directory di memorizzazione dell'applicazione è basato su nome utente, ID applicazione e ID editore: • In Mac OS, nel seguente percorso: /Users/nome utente/Library/Preferences/IDapplicazione.IDeditore/Local Store/ Ad esempio: /Users/babbage/Library/Preferences/com.example.TestApp.02D88EEED35F84C264A183921344EEA353 A629FD.1/Local Store • In Windows, nella directory Documents and Settings, in: nome utente/Dati applicazioni/applicationID.IDeditore/Local Store/ Ad esempio: C:\Documents and Settings\babbage\Application Data\com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Local Store • In Linux - In: /home/Nome utente/.appdata/applicationID.IDeditore/Local Store/ Ad esempio: /home/babbage/.appdata/com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Loc al Store L'URL (e la proprietà url) per un oggetto File creato con File.applicationStorageDirectory utilizza lo schema URL app-storage, come nell'esempio seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 312 Richieste URL e connettività di rete var dir:File = File.applicationStorageDirectory; dir = dir.resolvePath("preferences"); trace(dir.url); // app-storage:/preferences var dir = air.File.applicationStorageDirectory; dir = dir.resolvePath("prefs.xml"); air.trace(dir.url); // app-storage:/preferences mailto: Potete usare lo schema mailto negli oggetti URLRequest passati alla funzione navigateToURL(). Consultate “Apertura di un URL nel browser Web predefinito del sistema” a pagina 312 Utilizzo di schemi URL in AIR Potete usare un oggetto URLRequest che usa uno di questi schemi URL per definire la richiesta URL per un certo numero di oggetti, ad esempio un oggetto FileStream o Sound. Potete anche usare questi schemi nel contenuto HTML in esecuzione in AIR; ad esempio, nell'attributo src di un tag img. Tuttavia, potete usare gli schemi URL specifici di AIR (app: e app-storage:) solo nel contenuto della sandbox di sicurezza dell'applicazione. Per ulteriori informazioni, consultate “Sicurezza in AIR” a pagina 25. Schemi URL non consentiti Alcune API consentono di avviare contenuto in un browser Web. Per motivi di sicurezza, alcuni schemi URL non sono consentiti quando si utilizzano queste API in AIR. L'elenco degli schemi non consentiti dipende dalla sandbox di sicurezza del codice che utilizza l'API. Per ulteriori informazioni, consultate “Apertura di un URL nel browser Web predefinito del sistema” a pagina 312. Modifiche alla classe URLStream La classe URLStream fornisce l'accesso di basso livello allo scaricamento di dati da URL. Nel runtime, la classe URLStream include un nuovo evento: httpResponseStatus. A differenza dell'evento httpStatus, l'evento httpResponseStatus viene inviato prima di qualsiasi dato di risposta. L'evento httpResponseStatus (definito nella classe HTTPStatusEvent) include una proprietà responseURL, che corrisponde all'URL da cui è stata restituita la risposta, e una proprietà responseHeaders, che corrisponde a un array di oggetti URLRequestHeader che rappresentano le intestazioni di risposta che la risposta ha restituito. Apertura di un URL nel browser Web predefinito del sistema Potete usare la funzione navigateToURL() per aprire un URL nel browser Web predefinito del sistema. L'oggetto URLRequest passato come parametro request della funzione utilizza solo la proprietà url. var url = "http://www.adobe.com"; var urlReq = new air.URLRequest(url); air.navigateToURL(urlReq); Nota: quando usate la funzione navigateToURL(), il runtime gestisce un oggetto URLRequest che usa il metodo POST (che ha la proprietà method impostata su URLRequestMethod.POST) come se usasse il metodo GET. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 313 Richieste URL e connettività di rete Quando si utilizza la funzione navigateToURL(), gli schemi URL sono consentiti in base alla sandbox di sicurezza del codice che chiama la funzione navigateToURL(). Alcune API consentono di avviare contenuto in un browser Web. Per motivi di sicurezza, alcuni schemi URL non sono consentiti quando si utilizzano queste API in AIR. L'elenco degli schemi non consentiti dipende dalla sandbox di sicurezza del codice che utilizza l'API. Per ulteriori informazioni sulle sandbox si sicurezza, consultate “Sicurezza in AIR” a pagina 25. Sandbox dell'applicazione Sono consentiti gli schemi riportati di seguito. Utilizzarli allo stesso modo che in un browser Web. • http: • https: • file: • mailto: — AIR indirizza queste richieste all'applicazione di posta elettronica di sistema registrata • app: • app-storage: Tutti gli altri schemi URL non sono consentiti. Sandbox remota Sono consentiti gli schemi riportati di seguito. Utilizzarli allo stesso modo che in un browser Web. • http: • https: • mailto: — AIR indirizza queste richieste all'applicazione di posta elettronica di sistema registrata Tutti gli altri schemi URL non sono consentiti. Sandbox locale con file Sono consentiti gli schemi riportati di seguito. Utilizzarli allo stesso modo che in un browser Web. • file: • mailto: — AIR indirizza queste richieste all'applicazione di posta elettronica di sistema registrata Tutti gli altri schemi URL non sono consentiti. Sandbox locale con rete Sono consentiti gli schemi riportati di seguito. Utilizzarli allo stesso modo che in un browser Web. • http: • https: • mailto: — AIR indirizza queste richieste all'applicazione di posta elettronica di sistema registrata Tutti gli altri schemi URL non sono consentiti. Sandbox affidabile locale Sono consentiti gli schemi riportati di seguito. Utilizzarli allo stesso modo che in un browser Web. • file: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 314 Richieste URL e connettività di rete • http: • https: • mailto: — AIR indirizza queste richieste all'applicazione di posta elettronica di sistema registrata Tutti gli altri schemi URL non sono consentiti. 315 Capitolo 31: Comunicazione tra le applicazioni La classe LocalConnection abilita la comunicazione tra le applicazioni Adobe® AIR™, oltre che tra le applicazioni AIR e il contenuto SWF eseguito nel browser. Il metodo connect() della classe LocalConnection usa un parametro connectionName per identificare le applicazioni. Nel contenuto eseguito nella sandbox di sicurezza dell'applicazione (contenuto installato con l'applicazione AIR), AIR usa la stringa app#, seguita dall'ID dell'applicazione e quindi da un carattere punto (.), seguito dall'ID dell'autore per l'applicazione AIR (definito nel file descrittore dell'applicazione), al posto del dominio usato dal contenuto SWF eseguito nel browser. Ad esempio, un connectionName per un'applicazione con ID com.example.air.MyApp, un connectionName e l'ID dell'autore B146A943FBD637B68C334022D304CEA226D129B4 si risolve in"app#com.example.air.MyApp.B146A943FBD637B68C334022D304CEA226D129B4:connectionName". Per ulteriori informazioni, consultate Definizione delle informazioni di base dell'applicazione e “Ottenimento dell'identificatore dell'applicazione e dell'editore” a pagina 301. Quando consentite a un'altra applicazione AIR di comunicare con la vostra applicazione tramite la connessione locale, dovete richiamare il metodo allowDomain() dell'oggetto LocalConnection specificando il nome del dominio della connessione locale. Nel caso di un'applicazione AIR, tale nome di dominio si forma a partire dagli ID dell'applicazione e dell'autore allo stesso modo con cui si forma la stringa di connessione. Ad esempio, se l'applicazione AIR mittente ha un ID dell'applicazione com.example.air.FriendlyApp e un ID dell'autore 214649436BD677B62C33D02233043EA236D13934, la stringa di dominio che dovreste usare per consentire a questa applicazione di connettersi è: app#com.example.air.FriendlyApp.214649436BD677B62C33D02233043EA236D13934. Nota: quando eseguite l'applicazione con l'utilità ADL (o con uno strumento di sviluppo come Flash CS3, Flex Builder o Dreamweaver), l'ID dell'autore è nullo e dovete ometterlo dalla stringa di dominio. Quando installate ed eseguite l'applicazione, dovete necessariamente includere l'ID dell'autore nella stringa di dominio. Potete assegnare un ID dell'autore provvisorio usando gli argomenti della riga di comando ADL. Usate un ID dell'autore provvisorio per verificare se la stringa di connessione e il nome di dominio sono formattati correttamente. 316 Capitolo 32: Distribuzione, installazione ed esecuzione di applicazioni AIR Le applicazioni AIR vengono distribuite come un unico file di installazione AIR, che contiene il codice dell'applicazione e tutte le risorse. È possibile distribuire questo file attraverso i sistemi tipici, quali download, posta elettronica o supporti fisici come ad esempio CD-ROM. Gli utenti possono installare l'applicazione facendo doppio clic sul file AIR. È possibile utilizzare la funzionalità installazione invisibile, che consente agli utenti di installare l'applicazione AIR (e Adobe® AIR™, se necessario) facendo semplicemente clic su un singolo collegamento su una pagina Web. Prima che sia possibile distribuirlo, un file di installazione di AIR deve essere incluso in un pacchetto e firmato con un certificato con codice firmato e chiave privata. La firma digitale del file di installazione garantisce che l'applicazione non sia stata alterata dal momento della firma. Se inoltre il certificato è stato rilasciato da un'autorità di certificazione attendibile, gli utenti possono confermare la vostra identità come editore e firmatario. Il file AIR viene firmato quando l'applicazione viene inclusa in un pacchetto con AIR Developer Tool (ADT). Per informazioni su come creare un pacchetto di un'applicazione in un file AIR mediante l'aggiornamento AIR per Flash, consultate “Creazione dei file dell'applicazione e del programma di installazione AIR” a pagina 17 (Creazione di pacchetti di file di installazione e dell'applicazione AIR). Per informazioni su come creare un pacchetto di un'applicazione in un file AIR mediante Adobe® AIR™ SDK, consultate “Creazione di un pacchetto di un file di installazione AIR mediante ADT (AIR Developer Tool)” a pagina 362 (Creazione di un pacchetto di un file di installazione mediante ADT (AIR Developer Tool)). Installazione ed esecuzione di un'applicazione AIR dal desktop È possibile inviare semplicemente il file AIR al destinatario. Ad esempio, è possibile inviare il file AIR come allegato di posta elettronica o come collegamento in una pagina Web. Una volta scaricata l'applicazione AIR, seguite le istruzioni riportate di seguito per installarla: 1 Fate doppio clic sul file AIR. Adobe AIR deve essere già installato sul computer. 2 Nella finestra Installazione, lasciate selezionate le impostazioni predefinite, quindi fate clic su Continua. In Windows, AIR effettua automaticamente le seguenti operazioni: • Installa l'applicazione nella directory Programmi • Crea un collegamento al desktop per l'applicazione • Crea un collegamento al menu Start • Aggiunge una voce per l'applicazione in Installazione applicazioni di Pannello di controllo In Mac OS, per impostazione predefinita l'applicazione viene aggiunta nella directory Applicazioni. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 317 Distribuzione, installazione ed esecuzione di applicazioni AIR Se l'applicazione è già installata, il programma di installazione consente all'utente di scegliere tra aprire la versione esistente dell'applicazione o effettuare l'aggiornamento alla versione nel file AIR scaricato. L'applicazione viene identificata mediante l'ID applicazione e l'ID editore nel file AIR. 3 Al termine dell'installazione, scegliete Fine. In Mac OS, per installare una versione aggiornata di un'applicazione sono necessari privilegi di sistema adeguati per effettuare l'installazione nella directory dell'applicazione. In Windows e Linux, sono richiesti privilegi di amministratore. Un'applicazione è in grado di installare anche una nuova versione tramite ActionScript o JavaScript. Per ulteriori informazioni, consultate “Aggiornamento delle applicazioni AIR” a pagina 332. Dopo che l'applicazione AIR è stata installata, è sufficiente fare doppio clic sull'icona dell'applicazione per eseguirla, come per qualsiasi altra applicazione desktop. • In Windows, fate doppio clic sull'icona dell'applicazione (installata sul desktop o in una cartella) oppure selezionate l'applicazione dal menu Start. • In Linux, fate doppio clic sull'icona dell'applicazione (installata sul desktop o in una cartella) oppure selezionate l'applicazione dal menu delle applicazioni. • In Mac OS, fate doppio clic sull'applicazione nella cartella in cui è stata installata. La directory di installazione predefinita è /Applications. La funzionalità installazione invisibile di AIR consente di installare un'applicazione AIR facendo clic su un collegamento in una pagina Web. Le funzionalità di chiamata browser consentono a un utente di eseguire un'applicazione AIR installata facendo clic su un collegamento in una pagina Web. Tali funzionalità vengono descritte nelle sezioni che seguono. Installazione ed esecuzione di applicazioni AIR da una pagina Web La funzionalità di installazione invisibile consente di incorporare un file SWF in una pagina Web che consente all'utente di installare un'applicazione AIR dal browser. Se il runtime non è installato, questa funzionalità provvede a installarlo. La funzionalità di installazione invisibile consente agli utenti di installare l'applicazione AIR senza salvare il file AIR sul loro computer. AIR SDK include un file badge.swf che consente di utilizzare facilmente la funzionalità di installazione invisibile. Per dettagli, consultate “Utilizzo del file badge.swf per l'installazione di un'applicazione AIR” a pagina 318. Per una dimostrazione dell'uso della funzione di installazione invisibile, consultate l'articolo di esempio di Adobe AIR Quick Start Distributing an AIR Application via the Web (Distribuzione di un'applicazione AIR tramite il Web) all'indirizzo http://www.adobe.com/go/learn_air_qs_seamless_install_it. Informazioni sulla personalizzazione del file badge.swf per l'installazione invisibile Oltre a utilizzare il file badge.swf fornito con SDK, è possibile creare un file SWF personalizzato da utilizzare in una pagina browser. Tale file personalizzato può interagire con il runtime nei modi seguenti: • Installando un'applicazione AIR. Consultate “Installazione di un'applicazione AIR dal browser” a pagina 323. • Verificando se una determinata applicazione AIR è installata. Consultate “Verificare da una pagina Web se un'applicazione AIR è installata” a pagina 322. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 318 Distribuzione, installazione ed esecuzione di applicazioni AIR • Verificando se il runtime è installato. Consultate “Verificare se il runtime è installato” a pagina 321. • Avviando un'applicazione AIR installata sul sistema dell'utente. Consultate “Avvio dal browser di un'applicazione AIR installata” a pagina 323. Queste funzionalità vengono tutte fornite chiamando le API in un file SWF ospitato su adobe.com: air.swf. In questa sezione viene descritto come utilizzare e personalizzare il file badge.swf, nonché come chiamare le API del file air.swf dal file SWF personalizzato. Inoltre, un file SWF in esecuzione nel browser può comunicare con un'applicazione AIR in esecuzione mediante la classe LocalConnection. Per ulteriori informazioni, consultate “Comunicazione tra le applicazioni” a pagina 315. Importante: per l'esecuzione delle funzionalità descritte in questa sezione e delle API nel file air.swf, è necessario che nel browser Web dell'utente finale, in Windows o Mac OS, sia installato Adobe® Flash® Player 9 update 3. In Linux, la funzione di installazione invisibile richiede Flash Player 10 (versione 10,0,12,36 o successiva). È possibile scrivere il codice per verificare la versione installata di Flash Player e fornire all'utente un'interfaccia alternativa se la versione richiesta di Flash Player non è installata. Ad esempio, se è installata una versione precedente di Flash Player, è possibile fornire un collegamento alla versione di download del file AIR invece di utilizzare il file badge.swf o l'API air.swf per installare un'applicazione. Utilizzo del file badge.swf per l'installazione di un'applicazione AIR AIR SDK include un file badge.swf che consente di utilizzare facilmente la funzionalità di installazione invisibile. Tale file consente di installare il runtime e un'applicazione AIR da un collegamento in una pagina Web. Il file badge.swf file e il relativo codice sorgente vengono forniti per la distribuzione sul vostro sito Web. Le istruzioni incluse in questa sezione forniscono informazioni sull'impostazione dei parametri del file badge.swf fornito da Adobe. Viene inoltre fornito il codice sorgente per il file badge.swf, che l'utente può personalizzare. Incorporare il file badge.swf in una pagina Web 1 Individuate i seguenti file forniti nella directory samples/badge di AIR SDK, quindi aggiungeteli al server Web. • badge.swf • default_badge.html • AC_RunActiveContent.js 2 Aprite la pagina default_badge.html in un editor di testo. 3 Nella funzione AC_FL_RunContent() JavaScript della pagina default_badge.html, regolate le definizioni dei parametri FlashVars per i seguenti elementi: Parametro Descrizione appname Il nome dell'applicazione,visualizzato dal file SWF quando il runtime non è installato. appurl (Obbligatorio). L'URL del file AIR da scaricare. Utilizzate un URL assoluto, non relativo. airversion (Obbligatorio). Per la versione 1.0 del runtime, impostare il valore su 1.0. imageurl L'URL dell'immagine (facoltativo) da visualizzare nel badge. buttoncolor Il colore del pulsante di download, specificato come valore esadecimale, ad esempio FFCC00. messagecolor Il colore del messaggio di testo visualizzato sotto il pulsante quando il runtime non è installato (specificato come valore esadecimale, ad esempio FFCC00). 4 La dimensione minima del file badge.swf è 217 pixel di larghezza per 180 pixel di altezza. Regolate i valori dei parametri width e height della funzione AC_FL_RunContent() in modo da adattarli alle proprie esigenze. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 319 Distribuzione, installazione ed esecuzione di applicazioni AIR 5 Ridenominate il file default_badge.html e regolatene il codice (oppure includetelo in un'altra pagina HTML) per adattarlo alle vostre esigenze. È anche possibile modificare e ricompilare il file badge.swf. Per dettagli, consultate “Modifica del file badge.swf” a pagina 319. Installazione dell'applicazione AIR da un collegamento di installazione invisibile in una pagina Web Dopo aver aggiunto il collegamento di installazione invisibile in una pagina, l'utente può installare l'applicazione AIR facendo clic sul collegamento nel file SWF. 1 Accedete alla pagina HTML tramite un browser Web con installato Flash Player (versione 9 update 3 o successiva in Windows e Mac OS o versione 10 in Linux). 2 Nella pagina Web, fate clic sul collegamento nel file badge.swf. • Se è stato installato il runtime, passate alla fase successiva. • In caso contrario, viene visualizzata una finestra di dialogo che chiede se si desidera installare il runtime. Procedete all'installazione (consultate “Installazione di Adobe AIR” a pagina 1), quindi procedete con il passaggio successivo. 3 Nella finestra Installazione, lasciate selezionate le impostazioni predefinite, quindi fate clic su Continua. In un computer con sistema operativo Windows, AIR effettua automaticamente le seguenti operazioni: • Installa l'applicazione nella directory c:\Programmi\ • Crea un collegamento al desktop per l'applicazione • Crea un collegamento al menu Start • Aggiunge una voce per l'applicazione in Installazione applicazioni di Pannello di controllo In Mac OS, il programma di installazione aggiunge l'applicazione alla directory Applicazioni (ad esempio, nella directory /Applicazioni di Mac OS). In un computer con sistema operativo Linux, AIR effettua automaticamente le seguenti operazioni: • Installa l'applicazione in /opt. • Crea un collegamento al desktop per l'applicazione • Crea un collegamento al menu Start • Aggiunge una voce relativa all'applicazione nello strumento di gestione pacchetti di sistema 4 Selezionate le opzioni desiderate, quindi fate clic sul pulsante Installa. 5 Al termine dell'installazione, scegliete Fine. Modifica del file badge.swf AIR SDK fornisce i file di origine per il file badge.swf. Tali file sono inclusi nella cartella samples/badge di SDK. File di origine Descrizione badge.fla Il file di origine di Flash utilizzato per la compilazione di badge.swf. Il file badge.fla viene compilato in un file SWF 9, che è possibile caricare in Flash Player. AIRBadge.as Classe di ActionScript 3.0 che definisce la classe di base utilizzata nel file badge.fla. Potete utilizzare Flash CS3 o Flash CS4 per riprogettare l'interfaccia grafica del file badge.fla. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 320 Distribuzione, installazione ed esecuzione di applicazioni AIR La funzione di costruzione AIRBadge(), definita nella classe AIRBadge, carica il file air.swf ospitato in http://airdownload.adobe.com/air/browserapi/air.swf. Il file air.swf include il codice per l'utilizzo della funzionalità di installazione invisibile. Il metodo onInit() nella classe AIRBadge viene chiamato dopo che il file air.swf è stato caricato: private function onInit(e:Event):void { _air = e.target.content; switch (_air.getStatus()) { case "installed" : root.statusMessage.text = ""; break; case "available" : if (_appName && _appName.length > 0) { root.statusMessage.htmlText = "<p align='center'><font color='#" + _messageColor + "'>In order to run " + _appName + ", this installer will also set up Adobe® AIR™.</font></p>"; } else { root.statusMessage.htmlText = "<p align='center'><font color='#" + _messageColor + "'>In order to run this application, " + "this installer will also set up Adobe® AIR™.</font></p>"; } break; case "unavailable" : root.statusMessage.htmlText = "<p align='center'><font color='#" + _messageColor + "'>Adobe® AIR™ is not available for your system.</font></p>"; root.buttonBg_mc.enabled = false; break; } } Il codice imposta la variabile globale _air sulla classe principale del file air.swf caricato. Tale classe include i seguenti metodi public a cui accede il file badge.swf per chiamare la funzionalità di installazione invisibile: Metodo Descrizione getStatus() Determina se il runtime è installato sul computer o se può essere installato. Per dettagli, consultate “Verificare se il runtime è installato” a pagina 321. installApplication() Installa l'applicazione specificata sul computer dell'utente. Per dettagli, consultate “Installazione di un'applicazione AIR dal browser” a pagina 323. • url: una stringa che definisce l'URL. Utilizzare un percorso di URL assoluto, non relativo. • runtimeVersion: una stringa che indica la versione del runtime (ad esempio, "1.0.M6") richiesta dall'applicazione da installare. • arguments: argomenti da trasmettere all'applicazione se viene avviata all'installazione. L'applicazione viene avviata all'installazione se l'elemento allowBrowserInvocation viene impostato su true nel file descrittore dell'applicazione. (Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46.) Se l'applicazione viene avviata come risultato di un'installazione invisibile dal browser (con l'utente che sceglie di effettuare l'avvio all'installazione), l'oggetto NativeApplication dell'installazione invia un evento BrowserInvokeEvent solo se vengono trasmessi gli argomenti. Si considerino le implicazioni di sicurezza dei dati che vengono trasmessi all'applicazione. Per dettagli, consultate “Avvio dal browser di un'applicazione AIR installata” a pagina 323. Le impostazioni per url e runtimeVersion vengono trasmesse nel file SWF tramite le impostazioni di FlashVars nella pagina contenitore HTML. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 321 Distribuzione, installazione ed esecuzione di applicazioni AIR Se l'applicazione viene avviata automaticamente all'installazione, è possibile utilizzare la comunicazione LocalConnection per fare in modo che l'applicazione installata contatti il file badge.swf alla chiamata. Per dettagli, consultate “Comunicazione tra le applicazioni” a pagina 315. È anche possibile chiamare il metodo getApplicationVersion() del file air.swf per verificare se un'applicazione è installata. La chiamata al metodo può essere effettuata prima del processo di installazione o dopo che tale processo è stato avviato. Per dettagli, consultate “Verificare da una pagina Web se un'applicazione AIR è installata” a pagina 322. Caricamento del file air.swf È possibile creare un file SWF personalizzato che utilizza le API nel file air.swf per interagire con il runtime e le applicazioni AIR da una pagina Web in un browser. Il file air.swf è ospitato in http://airdownload.adobe.com/air/browserapi/air.swf. Per fare riferimento alle API di air.swf API dal file SWF personalizzato, caricate air.swf nello stesso dominio dell'applicazione del file SWF. Nel codice seguente viene mostrato un esempio di caricamento del file air.swf nel dominio dell'applicazione del file SWF: var airSWF:Object; // This is the reference to the main class of air.swf var airSWFLoader:Loader = new Loader(); // Used to load the SWF var loaderContext:LoaderContext = new LoaderContext(); // Used to set the application domain loaderContext.applicationDomain = ApplicationDomain.currentDomain; airSWFLoader.contentLoaderInfo.addEventListener(Event.INIT, onInit); airSWFLoader.load(new URLRequest("http://airdownload.adobe.com/air/browserapi/air.swf"), loaderContext); function onInit(e:Event):void { airSWF = e.target.content; } Dopo che il file air.swf è stato caricato, quando l'oggetto contentLoaderInfo dell'oggetto Loader invia l'evento init, è possibile chiamare le API di air.swf. Le API sono descritte nelle sezioni che seguono: • “Verificare se il runtime è installato” a pagina 321 • “Verificare da una pagina Web se un'applicazione AIR è installata” a pagina 322 • “Installazione di un'applicazione AIR dal browser” a pagina 323 • “Avvio dal browser di un'applicazione AIR installata” a pagina 323 Nota: il file badge.swf fornito con AIR SDK carica automaticamente il file air.swf. Consultate “Utilizzo del file badge.swf per l'installazione di un'applicazione AIR” a pagina 318 . Le istruzioni fornite in questa sezione si applicano alla creazione del file SWF personalizzato che carica il file air.swf. Verificare se il runtime è installato Un file SWF può verificare se il runtime è installato effettuando la chiamata al metodo getStatus() nel file air.swf caricato da http://airdownload.adobe.com/air/browserapi/air.swf. Per dettagli, consultate “Caricamento del file air.swf” a pagina 321. Dopo che il file air.swf è stato caricato, il file SWF può effettuare la chiamata al metodo getStatus() del file air.swf, come nell'esempio seguente: var status:String = airSWF.getStatus(); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 322 Distribuzione, installazione ed esecuzione di applicazioni AIR Il metodo getStatus() restituisce uno dei seguenti valori di stringa. in base allo stato del runtime sul computer: Valore stringa Descrizione "available" Il runtime può essere installato ma attualmente non è installato in questo computer. "unavailable" Il runtime non può essere installato in questo computer. "installed" Il runtime è installato su questo computer. Il metodo getStatus() genera un errore se la versione richiesta di Flash Player (versione 9 update 3 o successiva in Windows e Mac OS o versione 10 in Linux) non è installata nel browser. Verificare da una pagina Web se un'applicazione AIR è installata Un file SWF può verificare se un'applicazione AIR (con un ID editore e un ID applicazione corrispondente) è installata effettuando una chiamata al metodo getApplicationVersion() nel file air.swf file caricato da http://airdownload.adobe.com/air/browserapi/air.swf. Per dettagli, consultate “Caricamento del file air.swf” a pagina 321. Dopo che il file air.swf è stato caricato, il file SWF può effettuare la chiamata al metodo getApplicationVersion() del file air.swf, come nell'esempio seguente: var appID:String = "com.example.air.myTestApplication"; var pubID:String = "02D88EEED35F84C264A183921344EEA353A629FD.1"; airSWF.getApplicationVersion(appID, pubID, versionDetectCallback); function versionDetectCallback(version:String):void { if (version == null) { trace("Not installed."); // Take appropriate actions. For instance, present the user with // an option to install the application. } else { trace("Version", version, "installed."); // Take appropriate actions. For instance, enable the // user interface to launch the application. } } Il metodo getApplicationVersiom() presenta i seguenti parametri: Parametri Descrizione appID L'ID applicazione dell'applicazione. Per dettagli, consultate “Definizione dell'identità dell'applicazione” a pagina 49. pubID L'ID editore dell'applicazione. Per dettagli, consultate “Informazioni sugli identificatori di editori AIR” a pagina 326 callback Una funzione callback che serva da funzione di gestore. Il metodo getApplicationVersion() funziona in modo asincrono e al rilevamento della versione installata (o della mancanza di una versione installata) viene chiamato questo metodo di callback. La definizione del metodo di callback deve includere un solo parametro, una stringa, impostata sulla stringa di versione dell'applicazione installata. Se l'applicazione non è installata, alla funzione viene trasmesso un valore null, come illustrato nel precedente esempio di codice. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 323 Distribuzione, installazione ed esecuzione di applicazioni AIR Il metodo getApplicationVersion() genera un errore se la versione richiesta di Flash Player (versione 9 update 3 o successiva in Windows e Mac OS o versione 10 in Linux) non è installata nel browser. Installazione di un'applicazione AIR dal browser Un file SWF può installare un'applicazione AIR effettuando una chiamata al metodo installApplication() nel file air.swf caricato da http://airdownload.adobe.com/air/browserapi/air.swf. Per dettagli, consultate “Caricamento del file air.swf” a pagina 321. Dopo che il file air.swf è stato caricato, il file SWF può effettuare la chiamata al metodo installApplication() del file air.swf, come nel codice seguente: var url:String = "http://www.example.com/myApplication.air"; var runtimeVersion:String = "1.0"; var arguments:Array = ["launchFromBrowser"]; // Optional airSWF.installApplication(url, runtimeVersion, arguments); Il metodo installApplication() installa l'applicazione specificata sul computer dell'utente. Il metodo dispone dei parametri seguenti: Parametro Descrizione url Stringa che definisce l'URL del file AIR da installare. Utilizzare un percorso di URL assoluto, non relativo. runtimeVersion Stringa che indica la versione del runtime (ad esempio, "1.0") richiesta dall'applicazione da installare. arguments Array di argomenti da trasmettere all'applicazione se viene avviata all'installazione. Negli argomenti vengono riconosciuti solo i caratteri alfanumerici. Per passare valori diversi, è possibile utilizzare uno schema di codifica. L'applicazione viene avviata all'installazione se l'elemento allowBrowserInvocation viene impostato su true nel file descrittore dell'applicazione. (Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46.) Se l'applicazione viene avviata come risultato di un'installazione invisibile dal browser (con l'utente che sceglie di effettuare l'avvio all'installazione), l'oggetto NativeApplication dell'installazione invia un evento BrowserInvokeEvent solo se sono stati trasmessi gli argomenti. Per dettagli, consultate “Avvio dal browser di un'applicazione AIR installata” a pagina 323. Il metodo installApplication() può funzionare solo quando viene chiamato nel gestore di eventi per un evento utente (ad esempio, un clic del mouse). Il metodo installApplication() genera un errore se la versione richiesta di Flash Player (versione 9 update 3 o successiva in Windows e Mac OS o versione 10 in Linux) non è installata nel browser. In Mac OS, per installare una versione aggiornata di un'applicazione sono necessari privilegi di sistema adeguati per effettuare l'installazione nella directory delle applicazioni, nonché privilegi di amministratore se l'applicazione aggiorna il runtime. In Windows, sono richiesti privilegi di amministratore. È anche possibile chiamare il metodo getApplicationVersion() del file air.swf per verificare se un'applicazione è già installata. La chiamata al metodo può essere effettuata prima del processo di installazione o dopo che tale processo è stato avviato. Per dettagli, consultate “Verificare da una pagina Web se un'applicazione AIR è installata” a pagina 322. Quando l'applicazione è stata posta in esecuzione è in grado di comunicare con il contenuto SWF del browser mediante la classe LocalConnection. Per dettagli, consultate “Comunicazione tra le applicazioni” a pagina 315. Avvio dal browser di un'applicazione AIR installata Per utilizzare la funzionalità di chiamata browser, che consente l'avvio dal browser, il file descrittore dell'applicazione di destinazione deve includere la seguente impostazione: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 324 Distribuzione, installazione ed esecuzione di applicazioni AIR <allowBrowserInvocation>true</allowBrowserInvocation> Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. Un file SWF può avviare un'applicazione AIR nel browser effettuando una chiamata al metodo launchApplication() nel file air.swf caricato da http://airdownload.adobe.com/air/browserapi/air.swf. Per dettagli, consultate “Caricamento del file air.swf” a pagina 321. Dopo che il file air.swf è stato caricato, il file SWF può effettuare la chiamata al metodo launchApplication() del file air.swf, come nel codice seguente: var appID:String = "com.example.air.myTestApplication"; var pubID:String = "02D88EEED35F84C264A183921344EEA353A629FD.1"; var arguments:Array = ["launchFromBrowser"]; // Optional airSWF.launchApplication(appID, pubID, arguments); Il metodo launchApplication() è definito al primo livello del file air.swf, caricato nel dominio dell'applicazione del file SWF dell'interfaccia utente. La chiamata a questo metodo determina l'avvio dell'applicazione specificata (se è installata e se è consentita la chiamata browser tramite l'impostazione allowBrowserInvocation nel file descrittore dell'applicazione). Il metodo dispone dei parametri seguenti: Parametro Descrizione appID L'ID applicazione dell'applicazione da avviare. Per dettagli, consultate “Definizione dell'identità dell'applicazione” a pagina 49. pubID L'ID editore dell'applicazione da avviare. Per dettagli, consultate “Informazioni sugli identificatori di editori AIR” a pagina 326 arguments Un array di argomenti da passare all'applicazione. L'oggetto NativeApplication dell'applicazione invia un evento BrowserInvokeEvent con una proprietà arguments impostata su questo array. Negli argomenti vengono riconosciuti solo i caratteri alfanumerici. Per passare valori diversi, è possibile utilizzare uno schema di codifica. Il metodo launchApplication() può funzionare solo quando viene chiamato nel gestore di eventi per un evento utente (ad esempio, un clic del mouse). Il metodo launchApplication() genera un errore se la versione richiesta di Flash Player (versione 9 update 3 o successiva in Windows e Mac OS o versione 10 in Linux) non è installata nel browser. Se l'elemento allowBrowserInvocation è impostato su false nel file descrittore dell'applicazione, la chiamata al metodo launchApplication() non ha alcun effetto. Prima di presentare l'interfaccia utente per l'avvio dell'applicazione, è possibile chiamare il metodo getApplicationVersion() nel file air.swf. Per dettagli, consultate “Verificare da una pagina Web se un'applicazione AIR è installata” a pagina 322. Quando l'applicazione viene chiamata tramite la funzionalità di chiamata browser, l'oggetto NativeApplication dell'applicazione invia un oggetto BrowserInvokeEvent. Per informazioni dettagliate, consultate “Chiamata del browser” a pagina 297. Se utilizzate la funzionalità di chiamata browser, valutate le implicazioni relative alla sicurezza, descritte in “Chiamata del browser” a pagina 297. Quando l'applicazione è stata posta in esecuzione è in grado di comunicare con il contenuto SWF del browser mediante la classe LocalConnection. Per dettagli, consultate “Comunicazione tra le applicazioni” a pagina 315. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 325 Distribuzione, installazione ed esecuzione di applicazioni AIR Distribuzione aziendale Gli amministratori IT possono installare il runtime di Adobe AIR e le applicazioni AIR in modo invisibile all'utente utilizzando gli strumenti standard di distribuzione desktop. Gli amministratori IT possono effettuare le seguenti operazioni: • Installare in modo invisibile all'utente il runtime di Adobe utilizzando strumenti quali Microsoft SMS, IBM Tivoli o qualsiasi altro strumento di distribuzione che consente l'utilizzo di bootstrap per questo tipo di installazioni. • Installare in modo invisibile all'utente l'applicazione AIR utilizzando gli stessi strumenti impiegati per la distribuzione del runtime. Per ulteriori informazioni, consultate il manuale Adobe AIR Administrator's Guide (Guida per l'amministratore di Adobe AIR) (http://www.adobe.com/go/learn_air_admin_guide_it). Firma digitale di un file AIR L'apposizione di firma digitale ai file di installazione AIR mediante un certificato rilasciato da un'autorità di certificazione (CA) riconosciuta offre una garanzia significativa che l'applicazione in fase di installazione non sia stata alterata in modo casuale o intenzionalmente dannoso e identifica lo sviluppatore come firmatario (editore). Il nome dell'editore viene visualizzato durante l'installazione quando l'applicazione AIR è stata firmata con un certificato attendibile o che risulta concatenato a un certificato attendibile sul computer di installazione. Altrimenti, il nome dell'editore viene visualizzato come "Sconosciuto". Importante: un'entità dannosa che abbia in qualche modo ottenuto il file di archivio chiavi per la firma dell'utente o che ne abbia scoperto la chiave privata può creare un file AIR con la vostra identità. Informazioni sui certificati per la firma del codice Le garanzie di sicurezza, i limiti e gli obblighi legali relativi all'utilizzo dei certificati per la firma del codice sono definiti nel CPS (Certificate Practice Statements) e negli accordi di sottoscrizione pubblicati dall'autorità di certificazione emittente. Per ulteriori informazioni sugli accordi per le autorità di certificazione che rilasciano certificati per la firma di codice AIR, consultate: ChosenSecurity (http://www.chosensecurity.com/products/tc_publisher_id_adobe_air.htm) http://www.chosensecurity.com/resource_center/repository.htm (http://www.chosensecurity.com/resource_center/repository.htm) GlobalSign (http://www.globalsign.com/developer/code-signing-certificate/index.htm) GlobalSign CPS (http://www.globalsign.com/repository/index.htm) Thawte CPS (CPS Thawte) (http://www.thawte.com/cps/index.html) Thawte Code Signing Developer's Agreement (Contratto dello sviluppatore per la firma del codice) (http://www.thawte.com/ssl-digital-certificates/free-guides-whitepapers/pdf/develcertsign.pdf) VeriSign CPS (http://www.verisign.com/repository/CPS/) Verisign Subscriber’s Agreement (Contratto di abbonamento a Verisign) (https://www.verisign.com/repository/subscriber/SUBAGR.html) SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 326 Distribuzione, installazione ed esecuzione di applicazioni AIR Informazioni sulla firma del codice AIR Quando un file AIR viene firmato, nel file di installazione viene inclusa una firma digitale. Tale firma comprende un digest del pacchetto, usato per verificare che il file AIR non sia stato alterato dal momento della firma, e informazioni sulla firma del certificato, che consentono di verificare l'identità dell'editore. Per stabilire se un certificato può essere ritenuto attendibile, AIR utilizza l'infrastruttura PKI (public key infrastructure, infrastruttura a chiave pubblica) supportata nell'archivio certificati del sistema operativo per stabilire l'attendibilità di un certificato. Il computer su cui l'applicazione AIR è installata deve ritenere direttamente attendibile il certificato utilizzato per la firma dell'applicazione AIR oppure deve considerare attendibile una catena di certificati che collegano il certificato stesso a un'autorità CA che verifichi le informazioni dell'editore. Se un file AIR è firmato mediante un certificato non concatenato a uno dei certificati principali affidabili (e normalmente in questa categoria sono inclusi tutti i certificati autofirmati), le informazioni sull'editore non possono essere verificate. Anche se AIR può determinare che il pacchetto AIR non è stato alterato dal momento della firma, non c'è modo di sapere chi abbia effettivamente creato e firmato il file. Nota: un utente può scegliere di ritenere affidabile un certificato autofirmato e quindi in qualsiasi applicazione AIR firmata con quel certificato viene visualizzato il valore del campo del nome comune come nome dell'editore. In AIR non viene fornito alcun sistema per consentire a un utente di designare un certificato come attendibile. Il certificato (che non include la chiave privata) deve essere fornito all'utente separatamente, e quest'ultimo deve utilizzare uno dei meccanismi forniti dal sistema operativo oppure uno strumento appropriato per importare il certificato nella posizione adatta all'interno dell'archivio certificati del sistema. Informazioni sugli identificatori di editori AIR Come parte del processo di creazione di un file AIR, ADT (AIR Developer Tool) genera un ID editore, vale a dire un identificatore univoco per il certificato utilizzato per la creazione del file AIR. Se si riutilizza lo stesso certificato per più applicazioni AIR, esse avranno tutte lo stesso ID editore. L'ID editore viene utilizzato per identificare l'applicazione AIR nella comunicazione LocalConnection (consultate “Comunicazione tra le applicazioni” a pagina 315). È possibile identificare l'ID editore di un'applicazione installata leggendone la proprietà NativeApplication.nativeApplication.publisherID. Per calcolare l'ID editore vengono utilizzati i seguenti campi: Name, CommonName, Surname, GivenName, Initials, GenerationQualifier, DNQualifier, CountryName, localityName, StateOrProvinceName, OrganizationName, OrganizationalUnitName, Title, Email, SerialNumber, DomainComponent, Pseudonym, BusinessCategory, StreetAddress, PostalCode, PostalAddress, DateOfBirth, PlaceOfBirth, Gender, CountryOfCitizenship, CountryOfResidence e NameAtBirth. Se si rinnova un certificato rilasciato da un'autorità di certificazione o si rigenera un certificato autofirmato, perché l'ID editore resti lo stesso i campi devono rimanere gli stessi. Inoltre, il certificato principale di un certificato rilasciato da un'autorità di certificazione e la chiave pubblica di un certificato autofirmato devono essere gli stessi. Informazioni sui formati dei certificati Gli strumenti di firma di AIR accettano qualsiasi archivio di chiavi accessibile mediante Java Cryptography Architecture (JCA). Sono quindi inclusi gli archivi di chiavi basati su file quali i file in formato PKCS12 (che di solito hanno un'estensione pfx o p12), i file Java keystore, gli archivi di chiavi hardware PKCS11 e gli archivi di chiavi di sistema. Il formati degli archivi di chiavi a cui può accedere ADT variano in base alla versione e configurazione del runtime Java utilizzato per l'esecuzione di ADT. L'accesso ad alcuni tipi di archivi di chiavi, come ad esempio i token hardware PKCS1, possono richiedere l'installazione e la configurazione di plug-in JCA e di driver software aggiuntivi. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 327 Distribuzione, installazione ed esecuzione di applicazioni AIR Per firmare i file AIR, potete utilizzare la maggior parte dei certificati esistenti per la firma di codice oppure ottenerne uno nuovo rilasciato appositamente per la firma di applicazioni AIR. Potete ad esempio utilizzare uno dei tipi di certificati seguenti di VeriSign, Thawte, GlobalSign o ChosenSecurity: • ChosenSecurity • TC Publisher ID per Adobe AIR • GlobalSign • Certificato per la firma del codice di ObjectSign • Thawte: • Certificato per sviluppatori AIR • Certificato per sviluppatori Apple • Certificato per sviluppatori JavaSoft • Cerificato Microsoft Authenticode • VeriSign: • ID digitale di Adobe AIR • ID digitale Microsoft Authenticode • ID digitale Sun Java Signing Nota: il certificato deve essere creato per la firma di codice. Non potete utilizzare un certificato SSL o di altro tipo per firmare file AIR. Indicatori di data e ora Quando si appone la firma a un file AIR, lo strumento di creazione dei pacchetti interroga il server di un'autorità di indicazione di data e ora per ottenere una data e ora della firma verificabile a livello indipendente. L'indicatore di data e ora ottenuto viene incorporato nel file AIR. Fino a quando il certificato è valido per l'ora della firma, il file AIR può essere installato, anche se tale certificato è scaduto. D'altro canto, se non viene ottenuto alcun indicatore di data e ora, il file AIR non può più essere installato dopo la scadenza o la revoca del certificato. Per impostazione predefinita, gli strumenti di creazione pacchetti di AIR ottengono un indicatore di data e ora. Tuttavia, per consentire la creazione di pacchetti delle applicazioni anche quando il servizio di indicazione di data e ora non è disponibile, è possibile disattivare la richiesta del servizio. Adobe raccomanda la presenza di indicatori di data e ora su tutti i file AIR distribuiti a livello pubblico. L'autorità predefinita per l'ottenimento di indicatori di data e ora per gli strumenti di creazione pacchetti AIR è Geotrust. Ottenimento di un certificato Per ottenere un certificato, normalmente si visita il sito Web dell'autorità di certificazione per completare il processo di approvvigionamento della società. Gli strumenti utilizzati per produrre l'archivio di chiavi richiesto dagli strumenti AIR varia in base al certificato acquistato, alla modalità di memorizzazione del certificato sul computer dell'utente e, in alcuni casi, al browser impiegato per ottenere il certificato. Per ottenere ed esportare, ad esempio, un certificato di Adobe Developer da Thawte, è necessario utilizzare Mozilla Firefox. Il certificato può quindi essere esportato come file .p12 o .pfx direttamente dall'interfaccia di Firefox. È possibile generare un certificato autofirmato mediante ADT (Air Development Tool), lo strumento utilizzato per creare pacchetti di file di installazione di AIR. È possibile utilizzare anche alcuni strumenti di terzi. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 328 Distribuzione, installazione ed esecuzione di applicazioni AIR Per istruzioni su come generare un certificato autofirmato e sulla firma di un file AIR, consultate “Creazione di un pacchetto di un file di installazione AIR mediante ADT (AIR Developer Tool)” a pagina 362. È anche possibile esportare e firmare file AIR mediante Flex Builder, Dreamweaver e l'aggiornamento di AIR per Flash. Nell'esempio seguente viene illustrato come ottenere un certificato per sviluppatori AIR dall'autorità di certificazione Thawte e prepararlo all'utilizzo in ADT. Esempio: ottenimento di un certificato per sviluppatori AIR da Thawte Nota: nell'esempio viene illustrato solo uno dei vari sistemi per ottenere e preparare all'uso un certificato per la firma del codice. Ogni autorità di certificazione dispone di politiche e procedure distinte. Per acquistare un certificato per sviluppatori AIR sul sito Web di Thawte, è necessario utilizzare Mozilla Firefox. La chiave privata per il certificato è memorizzata nell'archivio di chiavi del browser. Accertarsi che l'archivio di chiavi di Firefox sia protetto con una password master e che il computer stesso sia fisicamente sicuro. Una volta terminato il processo di approvvigionamento, è possibile esportare e rimuovere il certificato e la chiave privata dall'archivio di chiavi del browser. Come parte del processo di registrazione del certificato, viene generata una coppia di chiavi pubblica/privata. La chiave privata viene memorizzata automaticamente nell'archivio di chiavi di Firefox. Per richiedere e quindi recuperare il certificato dal sito Web di Thawte, è necessario utilizzare lo stesso computer. 1 Visitate il sito Web di Thawte e passate alla Product page for Code Signing Certificates (Pagina del prodotto per i certificati per la firma del codice). 2 Dall'elenco dei certificati per firma del codice, selezionate il certificato per sviluppatori AIR (Adobe AIR Developer Certificate). 3 Completate il processo di registrazione in tre fasi. Sarà necessario fornire informazioni di contatto e relative all'azienda. A questo punto, Thawte esegue il proprio processo di identificazione e potrebbe richiedere ulteriori informazioni. Al termine della verifica, poi, Thawte vi invierà un messaggio di posta elettronica con istruzioni su come recuperare il certificato. Nota: ulteriori informazioni sul tipo di documentazione richiesta sono disponibili qui: https://www.thawte.com/ssldigital-certificates/free-guides-whitepapers/pdf/enroll_codesign_eng.pdf. 4 Recuperate il certificato rilasciato dal sito Thawte. Esso viene salvato automaticamente nell'archivio di chiavi di Firefox. 5 Esportate un file dell'archivio di chiavi contenente la chiave privata e il certificato dall'archivio di chiavi di Firefox effettuando la seguente procedura: Nota: la chiave privata e il certificato in Firefox vengono esportati in un formato p12 (pfx) che anche ADT, Flex, Flash e Dreamweaver sono in grado di utilizzare. a Aprite la finestra di dialogo Gestione certificati di Firefox: b In Windows: aprite Strumenti -> Opzioni -> Avanzate-> Crittografia -> Mostra certificati c In Mac OS: aprite Firefox -> Preferenze -> Avanzate -> Crittografia -> Mostra certificati d In Linux: aprite Modifica -> Preferenze -> Avanzate -> Crittografia -> Mostra certificati e Selezionate il certificato per la firma del codice di AIR (Adobe AIR Code Signing Certificate) dall'elenco dei certificati, quindi fate clic sul pulsante Backup. f Immettete un nome file e il percorso in cui esportare il file dell'archivio di certificati, quindi fate clic su Salva. g Se utilizzate la password master di Firefox, per l'esportazione del file vi verrà richiesto di immettere la password per il dispositivo di sicurezza del software. Questa password è utilizzata solo da Firefox. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 329 Distribuzione, installazione ed esecuzione di applicazioni AIR h Nella finestra di dialogo di scelta di una password di backup per il certificato create una password per la protezione del file dell'archivio di chiavi. Importante: questa password protegge il file dell'archivio di chiavi ed è necessaria quando il file deve essere utilizzato per la firma di applicazioni AIR. Cercate di utilizzare una password sicura. i Fate clic su OK. Verrà visualizzato un messaggio di riuscita della creazione della password di backup. Il file dell'archivio di chiavi contente la chiave privata e il certificato viene salvato con un'estensione p12 (in formato PKCS12). 6 Il file dell'archivio di chiavi esportato può essere utilizzato con ADT, Flex Builder, Flash o Dreamweaver. La password creata per il file è necessaria ogniqualvolta viene apposta la firma a un'applicazione AIR. Importante: la chiave privata e il certificato vengono memorizzati nell'archivio di chiavi di Firefox. Ciò consente di esportare copie aggiuntive del file di certificato, ma implica anche la creazione di un ulteriore punto di accesso da proteggere per garantire la sicurezza di certificato e chiave privata. Modifica dei certificati In alcune circostanze può essere necessario modificare il certificato utilizzato per la firma dell'applicazione AIR. Ciò può avvenire, ad esempio, nei seguenti casi: • Aggiornamento da un certificato autofirmato a un certificato rilasciato da un'autorità di certificazione • Passaggio da un certificato autofirmato sul punto di scadere a un altro • Passaggio da un certificato commerciale a un altro, ad esempio in caso di modifica della ragione sociale Dal momento che la firma del certificato è uno degli elementi che determinano l'identità di un'applicazione AIR, non è sufficiente firmare un aggiornamento dell'applicazione con un certificato diverso. Per consentire a AIR di riconoscere un file come aggiornamento, occorre firmare sia l'originale che qualsiasi altro file di aggiornamento AIR con lo stesso certificato. In caso contrario, il nuovo file AIR verrà installato come applicazione separata invece che come aggiornamento dell'installazione esistente. Con AIR 1.1 è possibile modificare il certificato di firma di un'applicazione mediante una firma di migrazione. Per firma di migrazione si intende una seconda firma apposta al file di aggiornamento di AIR. La firma di migrazione utilizza il certificato originale, che stabilisce che il firmatario è l'editore originale dell'applicazione. Importante: è necessario cambiare il certificato prima che il certificato originale scada o venga revocato. Se non viene creato un aggiornamento a cui è apposta una firma di migrazione prima della scadenza del certificato in uso, gli utenti dovranno disinstallare la versione esistente della vostra applicazione prima di installare qualsiasi aggiornamento. I certificati rilasciati a livello commerciale, di solito, possono essere rinnovati per evitare la scadenza, a differenza dei certificati autofirmati. Per cambiare i certificati: 1 Create un aggiornamento dell'applicazione 2 Create un pacchetto e firmate il file di aggiornamento di AIR con il nuovo certificato. 3 Firmate nuovamente il file AIR con il certificato originale, mediante il comando -migrate di ADT. La procedura per l'apposizione di una firma di migrazione è descritta in “Firma di un file AIR per la modifica del certificato dell'applicazione” a pagina 371 Quando il file AIR aggiornato viene installato, l'identità dell'applicazione cambia. Il cambiamento di identità ha le seguenti ripercussioni: • L'ID editore dell'applicazione cambia in modo da corrispondere al nuovo certificato. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 330 Distribuzione, installazione ed esecuzione di applicazioni AIR • La nuova versione dell'applicazione non è in grado di accedere ai dati nell'archivio locale crittografato esistente. • Il percorso della directory di memorizzazione dell'applicazione cambia. I dati nel vecchio percorso non vengono copiati nella nuova directory (la nuova applicazione, tuttavia, è in grado di individuare la directory originale in base al vecchio ID editore). • L'applicazione non è più in grado di aprire le connessioni locali mediante il vecchio ID editore. • Se un utente reinstalla un file AIR nella versione precedente alla migrazione, esso viene installato come applicazione separata mediante l'ID editore originale. L'applicazione è responsabile della migrazione dei dati tra l'originale e le nuove versioni dell'applicazione stessa. Per migrare i dati nell'archivio locale crittografato (ELS, encrypted local store) È impossibile per la nuova versione dell'applicazione leggere l'ELS della vecchia versione: spesso è addirittura più semplice ricreare i dati anziché migrarli. È importante che continuiate ad apporre la firma di migrazione sul maggior numero di aggiornamenti successivi possibile, per evitare che utenti che non hanno ancora effettuato l'aggiornamento dell'originale siano costretti a installare una versione di migrazione intermedia o a disinstallare la versione corrente per poter installare l'aggiornamento più recente. Alla lunga, infine, il certificato originale scadrà e a quel punto non sarà più possibile apporre la firma di migrazione (tuttavia, a meno che non venga disattivata l'indicazione di data e ora, i file AIR già firmati con una firma di migrazione restano validi. La firma di migrazione contiene un'indicazione di data e ora per consentire l'accettazione della firma anche dopo la scadenza del certificato). Per altri aspetti, un file con firma di migrazione è un normale file di AIR. Se l'applicazione è installata su un sistema senza la versione originale, la nuova versione viene installata nella maniera consueta. Nota: di solito, quando si rinnova un certificato rilasciato a livello commerciale, non è necessario migrarlo. Un certificato rinnovato conserva la stessa identità dell'editore dell'originale, a meno che il nome distinto non sia stato modificato. Per un elenco completo degli attributi dei certificati utilizzati per determinare il nome distinto, consultate “Informazioni sugli identificatori di editori AIR” a pagina 326. Terminologia In questa sezione viene fornito un glossario della terminologia chiave, che è fondamentale conoscere per prendere decisioni in merito alla firma delle applicazioni per la pubblica distribuzione. Termine Descrizione Autorità di certificazione (CA, Certification Authority) Entità di una rete di infrastrutture di chiavi pubbliche che funge da terza parte attendibile e che certifica l'identità del proprietario di una chiave pubblica. Di norma, una CA rilascia certificati digitali firmati mediante la propria chiave privata per attestare l'avvenuta verifica dell'identità del possessore del certificato. CPS (Certificate Practice Statement) Documento che stabilisce le pratiche e le politiche dell'autorità di certificazione adottate in merito al rilascio e alla verifica dei certificati. Il CPS fa parte del contratto tra CA e le parti coinvolte. Definisce inoltre le politiche per la verifica dell'identità e il livello di garanzia offerto dai certificati forniti. CRL (Certificate Revocation List) Elenco di certificati rilasciati e successivamente revocati, che non possono più essere ritenuti affidabili. Nel momento in cui un'applicazione AIR viene firmata, AIR controlla l'elenco CRL. Se non è presente un indicatore di data e ora, il controllo viene ripetuto al momento dell'installazione dell'applicazione. Catena di certificati Per catena di certificati si intende una sequenza di certificati in cui ciascun certificato presente è stato firmato dal certificato successivo. Certificato digitale Documento digitale che contiene informazioni sull'identità del proprietario, la sua chiave pubblica e l'identità del certificato stesso. Un certificato rilasciato da un'autorità di certificazione è firmato a sua volta da un certificato appartenente alla CA che lo ha rilasciato. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 331 Distribuzione, installazione ed esecuzione di applicazioni AIR Termine Descrizione Firma digitale Messaggio o digest crittografato che è possibile decrittare solo mediante la chiave pubblica che costituisce metà della coppia di chiavi pubblica-privata. In un PKI, una firma digitale contiene uno o più certificati digitali di cui è possibile tenere traccia e che è possibile attribuire all'autorità di certificazione. Una firma digitale consente di convalidare la dichiarazione che un messaggio o un file non è stato alterato dal momento della firma (entro i limiti di garanzia forniti dall'algoritmo di crittografia utilizzato), nonché, presupponendo che l'autorità di certificazione sia considerata attendibile, l'identità del firmatario. Archivio di chiavi Database contenente certificati digitali nonché, in alcuni casi, le chiavi private correlate. JCA (Java Cryptography Architecture) Architettura estensibile per la gestione e l'accesso degli archivi di chiavi. Per ulteriori informazioni, consultate il documento Java Cryptography Architecture Reference Guide (Guida di riferimento per la Java Cryptography Architecture). PKCS #11 Standard per l'interfaccia di token di crittografia creato da RSA Laboratories. Un archivio di chiavi basato su token hardware. PKCS #12 Standard per la sintassi di scambio di informazioni personali creato da RSA Laboratories. Un archivio di chiavi basato su file che di solito contiene una chiave privata e il certificato digitale associato. Chiave privata La metà privata di una coppia di chiavi pubblica-privata a crittografia asimmetrica. La chiave privata deve essere tenuta segreta e non deve mai essere trasmessa su una rete. I messaggi con firma digitale vengono crittografati mediante chiave privata dal firmatario. Chiave pubblica La metà pubblica di una coppia di chiavi pubblica-privata a crittografia asimmetrica. La chiave pubblica è disponibile a tutti e viene usata per decrittare i messaggi crittografati mediante la chiave privata. PKI (Public Key Infrastructure) Sistema di attendibilità nel quale le autorità di certificazione attestano l'identità dei proprietari delle chiavi pubbliche. I client sulla rete si affidano ai certificati digitali rilasciati da una CA attendibile per verificare l'identità del firmatario di un messaggio digitale o file. Indicatore di data e ora Dato di riferimento a firma digitale contenente l'ora e il giorno in cui si è verificato un evento. ADT può includere un indicatore di data e ora proveniente da server temporale conforme alle specifiche RFC 3161 in un pacchetto AIR. Quando è presente, AIR utilizza l'indicatore di data e ora per stabilire la validità di un certificato al momento della firma, consentendo in tal modo l'installazione di un'applicazione AIR anche dopo che il certificato di firma è scaduto. Autorità di rilascio degli indicatori di data e ora Autorità che rilascia indicatori di data e ora. Per essere riconosciuto da AIR, l'indicatore di data e ora deve essere conforme alle specifiche RFC 3161, mentre la firma dell'indicatore di data e ora deve concatenarsi a un certificato principale attendibile presente sul computer di installazione. 332 Capitolo 33: Aggiornamento delle applicazioni AIR Gli utenti possono installare o aggiornare un'applicazione AIR facendo doppio clic su un file AIR sul computer o dal browser (utilizzando la funzione di installazione continua). Il programma di installazione di Adobe® AIR™ gestisce l'installazione, avvisando l'utente se sta tentando di aggiornare un'applicazione esistente (consultate “Distribuzione, installazione ed esecuzione di applicazioni AIR” a pagina 316). Tuttavia, è anche possibile che un'applicazione installata esegua l'aggiornamento automatico a una nuova versione utilizzando la classe Updater (un'applicazione installata può rilevare che una nuova versione è disponibile per essere scaricata e installata). La classe Updater include un metodo update() che consente di selezionare un file AIR sul computer dell'utente e di eseguire l'aggiornamento a quella versione. L'ID dell'applicazione e l'ID dell'editore di un file AIR aggiornato devono corrispondere all'applicazione da aggiornare. L'ID dell'editore è derivato dal certificato di firma. Questo significa che l'aggiornamento e l'applicazione da aggiornare devono essere firmate con lo stesso certificato. A partire da AIR 1.1 e versioni successive, potete migrare un'applicazione per utilizzare un nuovo certificato per la firma del codice. La migrazione di un'applicazione per utilizzare una nuova firma implica la firma del file AIR aggiornato con i certificati nuovo e originale. La migrazione del certificato è un processo unidirezionale. Dopo la migrazione, solo i file AIR firmati con il nuovo certificato (o con entrambi i certificati) verranno riconosciuti come aggiornamenti di un'installazione esistente. La gestione degli aggiornamenti delle applicazioni può essere un'operazione complessa. AIR 1.5 include il nuovo framework di aggiornamento per le applicazioni Adobe® AIR™. In questo framework sono disponibili le API che consentono agli sviluppatori di includere funzioni di aggiornamento adeguate nelle applicazioni AIR. Potete usare la migrazione del certificato per passare da un certificato autofirmato a un certificato firmato commerciale o da un certificato autofirmato o commerciale a un altro. Se non eseguite la migrazione del certificato, gli utenti esistenti devono rimuovere la versione corrente dell'applicazione prima di installare la nuova versione. Per ulteriori informazioni, consultate “Modifica dei certificati” a pagina 329. Informazioni sull'aggiornamento delle applicazioni La classe Updater (nel pacchetto flash.desktop) include un unico metodo, update(), che potete utilizzare per aggiornare l'applicazione attualmente in esecuzione a una versione diversa. Ad esempio, se l'utente dispone di una versione del file AIR ("Sample_App_v2.air") che si trova sul desktop, il codice seguente aggiorna l'applicazione: var updater:Updater = new Updater(); var airFile:File = File.desktopDirectory.resolvePath("Sample_App_v2.air"); var version:String = "2.01"; updater.update(airFile, version); Prima che un'applicazione possa utilizzare la classe Updater, l'utente o l'applicazione deve scaricare la versione aggiornata del file AIR sul computer. Per ulteriori informazioni, consultate “Scaricamento di un file AIR nel computer dell'utente” a pagina 334. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 333 Aggiornamento delle applicazioni AIR Risultati della chiamata del metodo Updater.update() Quando un'applicazione nel runtime chiama il metodo update(), il runtime chiude l'applicazione e quindi tenta di installare la nuova versione dal file AIR. Il runtime controlla che l'ID dell'applicazione e l'ID dell'editore specificati nel file AIR corrispondano a quelli dell'applicazione che chiama il metodo update(). Per informazioni sull'ID dell'applicazione e l'ID dell'editore, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. Il runtime controlla, inoltre, che la stringa della versione corrisponda alla stringa version passata al metodo update(). Se l'installazione viene effettuata correttamente, il runtime apre la nuova versione dell'applicazione. In caso contrario, viene riaperta la versione esistente (preinstallazione) dell'applicazione. In Mac OS, per installare una versione aggiornata di un'applicazione, l'utente deve disporre di privilegi di sistema adeguati per eseguire installazioni nella directory dell'applicazione. In Windows e Linux, sono richiesti privilegi di amministratore. Se la versione aggiornata dell'applicazione richiede una versione aggiornata del runtime, viene installata la nuova versione runtime. Per aggiornare il runtime, l'utente deve disporre di privilegi amministrativi per il computer Durante il test di un'applicazione mediante ADL, una chiamata al metodo update() determina un'eccezione di runtime. Informazioni sulla stringa della versione La stringa specificata come parametro version del metodo update() deve corrispondere alla stringa nell'attributo version dell'elemento application principale del file descrittore dell'applicazione per il file AIR da installare. La specifica del parametro version è richiesta per motivi di sicurezza. Richiedendo all'applicazione di verificare il numero di versione nel file AIR, si evita che vengano inavvertitamente installate vecchie versioni che potrebbero contenere vulnerabilità di sicurezza successivamente risolte. L'applicazione deve anche confrontare la stringa della versione nel file AIR con quella nell'applicazione installata per evitare attacchi di downgrade. La stringa della versione è disponibile in qualsiasi formato. Può essere, ad esempio, "2.01" o "versione 2". Il formato della stringa è a discrezione dello sviluppatore dell'applicazione. Il runtime non convalida la stringa della versione; la convalida della stringa deve essere eseguita dal codice dell'applicazione prima che venga eseguito l'aggiornamento. Se un'applicazione Adobe AIR scarica un file AIR tramite il Web, è opportuno disporre di un meccanismo che consente al servizio Web di inviare una notifica riguardo la versione scaricata. L'applicazione può quindi utilizzare questa stringa come parametro version del metodo update(). Se il file AIR file è ottenuto in modo diverso e la versione del file AIR non è nota, l'applicazione AIR può esaminare il file AIR per determinare la versione (un file AIR è un archivio compresso in formato ZIP e il file descrittore dell'applicazione è il secondo record nell'archivio). Per ulteriori informazioni sul file descrittore dell'applicazione, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 334 Aggiornamento delle applicazioni AIR Presentazione di un'interfaccia utente di aggiornamento dell'applicazione personalizzata AIR include un'interfaccia di aggiornamento predefinita: Questa interfaccia è sempre utilizzata la prima volta che un utente installa una versione dell'applicazione su una macchina. Tuttavia, potete definire un'interfaccia personalizzata da utilizzare per istanze successive. Se nell'applicazione è definita un'interfaccia di aggiornamento personalizzata, specificate un elemento customUpdateUI nel file descrittore dell'applicazione per l'applicazione attualmente installata: <customUpdateUI>true</customUpdateUI> Quando l'applicazione è installata e l'utente apre un file AIR con un ID applicazione e un ID editore che corrispondono all'applicazione installata, il runtime apre l'applicazione, anziché il programma di installazione dell'applicazione AIR predefinita. Per ulteriori informazioni, consultate “Realizzazione di un'interfaccia utente personalizzata per gli aggiornamenti dell'applicazione” a pagina 54. L'applicazione può decidere, quando viene eseguita (quando l'oggetto NativeApplication.nativeApplication invia un evento load), se aggiornare l'applicazione (utilizzando la classe Updater). Se decide di eseguire l'aggiornamento, può presentare all'utente la propria interfaccia di installazione (che è diversa dall'interfaccia di esecuzione standard). Scaricamento di un file AIR nel computer dell'utente Per utilizzare la classe Updater, l'utente o l'applicazione deve prima salvare un file AIR localmente sul computer dell'utente. Nota: in AIR 1.5 è incluso un framework di aggiornamento che consente agli sviluppatori di includere funzioni di aggiornamento adeguate nelle applicazioni AIR. L'uso di questo framework può risultare molto più facile rispetto all'uso diretto del metodo update() della classe Update. Per ulteriori dettagli, consultate “Uso del framework di aggiornamento” a pagina 336. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 335 Aggiornamento delle applicazioni AIR Il codice seguente legge un file AIR da un URL (http://example.com/air/updates/Sample_App_v2.air) e salva il file AIR nella directory di memorizzazione dell'applicazione: var urlString:String = "http://example.com/air/updates/Sample_App_v2.air"; var urlReq:URLRequest = new URLRequest(urlString); var urlStream:URLStream = new URLStream(); var fileData:ByteArray = new ByteArray(); urlStream.addEventListener(Event.COMPLETE, loaded); urlStream.load(urlReq); function loaded(event:Event):void { urlStream.readBytes(fileData, 0, urlStream.bytesAvailable); writeAirFile(); } function writeAirFile():void { var file:File = File.applicationStorageDirectory.resolvePath("My App v2.air"); var fileStream:FileStream = new FileStream(); fileStream.open(file, FileMode.WRITE); fileStream.writeBytes(fileData, 0, fileData.length); fileStream.close(); trace("The AIR file is written."); } Per ulteriori informazioni, consultate “Flusso di lavoro per lettura e scrittura di file” a pagina 123. Controllo per verificare se un'applicazione viene eseguita per la prima volta Dopo aver completato l'aggiornamento di un'applicazione, potete inviare all'utente un messaggio "operazioni preliminari" o "benvenuto". All'avvio, l'applicazione esegue un controllo per verificare se è la prima volta che viene eseguita, in modo da poter determinare se visualizzare il messaggio. Nota: in AIR 1.5 è incluso un framework di aggiornamento che consente agli sviluppatori di includere funzioni di aggiornamento adeguate nelle applicazioni AIR. Questo framework fornisce dei metodi semplici per controllare se una versione di un'applicazione viene eseguita per la prima volta. Per ulteriori dettagli, consultate “Uso del framework di aggiornamento” a pagina 336. Un modo per eseguire questa operazione è salvare un file nella directory di memorizzazione dell'applicazione durante l'inizializzazione dell'applicazione. A ogni avvio dell'applicazione, è necessario verificare l'esistenza di questo file. Se il file non esiste, allora è la prima volta che l'applicazione è in esecuzione per l'utente corrente. Se il file esiste, l'applicazione è stata già eseguita almeno una volta. Se il file esiste e contiene un numero di versione precedente a quello corrente, allora è la prima volta che l'utente esegue la nuova versione. Se l'applicazione salva i dati localmente (ad esempio, nella directory di memorizzazione dell'applicazione), è opportuno verificare la presenza di eventuali dati salvati (dalle versioni precedenti) al momento del primo avvio. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 336 Aggiornamento delle applicazioni AIR Uso del framework di aggiornamento La gestione degli aggiornamenti delle applicazioni può essere un'operazione complessa. Il framework di aggiornamento per le applicazioni AdobeAIRinclude le API che consentono agli sviluppatori di includere funzioni di aggiornamento adeguate nelle applicazioni AIR. La funzionalità presente nel framework di aggiornamento di AIR assiste gli sviluppatori nell'esecuzione delle seguenti operazioni: • controllo periodico degli aggiornamenti in base a un intervallo o su richiesta dell'utente; • download di file AIR (aggiornamenti) da un'origine Web; • avviso all'utente alla prima esecuzione di una nuova versione installata; • conferma che l'utente desidera controllare la disponibilità di aggiornamenti; • visualizzazione di informazioni relative alla nuova versione di aggiornamento; • visualizzazione dell'avanzamento del download e di informazioni relative a eventuali errori. Nel framework di aggiornamento di AIR è disponibile un'interfaccia utente di esempio che potete usare per la vostra applicazione. Fornisce all'utente le informazioni di base e le opzioni relative agli aggiornamenti dell'applicazione. Nell'applicazione potete anche definire un'interfaccia utente personalizzata da usare con il framework di aggiornamento. Il framework di aggiornamento di AIR consente di archiviare le informazioni relative alla versione di aggiornamento di un'applicazione AIR in semplici file di configurazione XML. Per la maggior parte delle applicazioni, l'impostazione di questi file di configurazione e l'inclusione di codice di base consentono di fornire una buona funzionalità di aggiornamento per l'utente finale. Anche senza utilizzare il framework di aggiornamento, Adobe AIR include una classe Updater che può essere usata dalle applicazioni AIR per l'aggiornamento alle nuove versioni. Questa classe consente l'aggiornamento di un'applicazione a una versione contenuta in un file AIR sul computer dell'utente. La gestione degli aggiornamenti può tuttavia comportare operazioni più complesse del semplice aggiornamento di un'applicazione basato su un file AIR archiviato localmente. File nel framework di aggiornamento di AIR Il framework di aggiornamento di AIR include le seguenti directory: • doc - La documentazione (che state leggendo) relativa al framework di aggiornamento di AIR. • frameworks - In questa directory sono inclusi i file SWC per lo sviluppo in Flex, e i file SWF per lo sviluppo in HTML. Per ulteriori informazioni vedere le sezioni immediatamente seguenti: • “Impostazione dell'ambiente di sviluppo Flex” a pagina 337 • “Inclusione dei file del framework in un'applicazione AIR basata su HTML” a pagina 337 • samples - In questa directory sono inclusi esempi basati su Flex e HTML che mostrano come utilizzare il framework di aggiornamento delle applicazioni. Compilate e verificate questi file, come per qualsiasi applicazione AIR. • templates - In questa directory sono inclusi i file del descrittore dell'aggiornamento di esempio (semplici e localizzati) e i file di configurazione (consultate Impostazione dell'ambiente di sviluppo Flex e and “Esempio di base: Uso della versione ApplicationUpdaterUI” a pagina 337 per ulteriori informazioni su questi file). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 337 Aggiornamento delle applicazioni AIR Impostazione dell'ambiente di sviluppo Flex Nella directory frameworks/flex del framework di aggiornamento sono inclusi i seguenti file: • ApplicationUpdater.swc - Definisce la funzionalità di base della libreria di aggiornamenti, senza interfaccia utente • ApplicationUpdater_UI.swc - Definisce la funzionalità di base della libreria di aggiornamenti, includendo un'interfaccia utente che può essere usata dall'applicazione per visualizzare le opzioni di aggiornamento I file SWC definiscono le classi che potete usare nello sviluppo in Flex. Per usare il framework di aggiornamento quando effettuate la compilazione con Flex SDK, includete il file ApplicationUpdater.swc o ApplicationUpdater_UI.swc nella chiamata al compilatore amxmlc. Nell'esempio riportato di seguito, il compilatore carica il file ApplicationUpdater.swc nella sottodirectory lib della directory Flex SDK: amxmlc -library-path+=lib/ApplicationUpdater.swc -- myApp.mxml Nell'esempio riportato di seguito, il compilatore carica il file ApplicationUpdater_UI.swc nella sottodirectory lib della directory Flex SDK: amxmlc -library-path+=lib/ApplicationUpdater_UI.swc -- myApp.mxml Quando sviluppate un'applicazione usando Flex Builder, aggiungete il file SWC nella scheda relativa al percorso della libreria nelle impostazioni del percorso di Flex Builder nella finestra di dialogo delle proprietà. Assicuratevi di copiare i file SWC nella directory a cui farete riferimento nel compilatore amxmlc (usando Flex SDK) o in Flex Builder. Inclusione dei file del framework in un'applicazione AIR basata su HTML Nella directory frameworks/html del framework di aggiornamento sono inclusi i seguenti file SWF: • ApplicationUpdater.swf - Definisce la funzionalità di base della libreria di aggiornamenti, senza interfaccia utente • ApplicationUpdater_UI.swf - Definisce la funzionalità di base della libreria di aggiornamenti, includendo un'interfaccia utente che può essere usata dall'applicazione per visualizzare le opzioni di aggiornamento Il codice JavaScript nelle applicazioni AIR può usare le classi definite nei file SWF. Per usare il framework di aggiornamento, includete il file ApplicationUpdater.swf o ApplicationUpdater_UI.swf nella directory (o in una sottodirectory) dell'applicazione. Quindi, nel file HTML che userà il framework (nel codice JavaScript), includete un tag script che carica il file: <script src="applicationUpdater.swf" type="application/x-shockwave-flash"/> In alternativa, usate questo tag script per caricare il file ApplicationUpdater_UI.swf: <script src="ApplicationUpdater_UI.swf" type="application/x-shockwave-flash"/> L'API definita in questi due file viene descritta nella parte rimanente di questo documento. Esempio di base: Uso della versione ApplicationUpdaterUI La versione ApplicationUpdaterUI del framework di aggiornamento fornisce un'interfaccia di base che potete usare facilmente nella vostra applicazione. Di seguito è riportato un esempio di base. Create innanzitutto un'applicazione AIR che chiama il framework di aggiornamento: 1 Se la vostra applicazione è un'applicazione AIR basata su HTML, caricate il file ApplicationUpdaterUI.js: <script src="ApplicationUpdater_UI.swf" type="application/x-shockwave-flash"/> 2 Nella logica della vostra applicazione AIR, create un'istanza dell'oggetto ApplicationUpdaterUI. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 338 Aggiornamento delle applicazioni AIR In ActionScript, usate il seguente codice: var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI(); In JavaScript, usate il seguente codice: var appUpdater = new runtime.air.update.ApplicationUpdaterUI(); Potete aggiungere questo codice a una funziona di inizializzazione che viene eseguita dopo il caricamento dell'applicazione. 3 Create un file di testo denominato updateConfig.xml e aggiungetevi quanto riportato di seguito: <?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://ns.adobe.com/air/framework/update/configuration/1.0"> <url>http://example.com/updates/update.xml</url> <delay>1</delay> </configuration> Modificate l'elemento URL del file updateConfig.xml in modo che corrisponda alla posizione finale del file descrittore dell'aggiornamento sul server Web (consultate la procedura successiva). Il valore delay è il numero di giorni che l'applicazione attende prima di controllare se sono presenti aggiornamenti. 4 Aggiungete il file updateConfig.xml alla directory project dell'applicazione AIR. 5 Impostate l'oggetto updater in modo che faccia riferimento al file updateConfig.xml e chiamate il metodo initialize() dell'oggetto. In ActionScript, usate il seguente codice: appUpdater.configurationFile = new File("app:/updateConfig.xml"); appUpdater.initialize(); In JavaScript, usate il seguente codice: appUpdater.configurationFile = new air.File("app:/updateConfig.xml"); appUpdater.initialize(); 6 Create una seconda versione dell'applicazione AIR con una versione diversa rispetto alla prima applicazione. (La versione è specificata nel file descrittore dell'applicazione, nell'elemento version). Aggiungete quindi la versione di aggiornamento dell'applicazione AIR al server Web: 1 Copiate la versione di aggiornamento del file AIR sul server Web. 2 Create un file di testo denominato updateDescriptor.xml e aggiungetevi il contenuto riportato di seguito: <?xml version="1.0" encoding="utf-8"?> <update xmlns="http://ns.adobe.com/air/framework/update/description/1.0"> <version>1.1</version> <url>http://example.com/updates/sample_1.1.air</url> <description>This is the latest version of the Sample application.</description> </update> Modificate gli elementi version, URL e description del file updateDescriptor.xml in modo che corrispondano al file AIR di aggiornamento. 3 Aggiungete il file updateDescriptor.xml alla stessa directory sul server Web che contiene il file AIR di aggiornamento. Questo è un esempio di base che tuttavia fornisce una funzionalità di aggiornamento sufficiente per molte applicazioni. Nella parte restante di questo documento viene descritto come utilizzare il framework di aggiornamento per soddisfare le vostre esigenze specifiche. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 339 Aggiornamento delle applicazioni AIR Per un altro esempio dell'uso del framework di aggiornamento, consultate l'applicazione di esempio seguente nel Centro per sviluppatori di Adobe AIR: Update Framework in a Flash-based Application (Framework di aggiornamento in un'applicazione basata su Flash)(http://www.adobe.com/go/learn_air_qs_update_framework_flash_it). Definizione del file descrittore dell'aggiornamento e aggiunta del file AIR al server Web Quando usate il framework di aggiornamento di AIR, definite le informazioni di base sull'aggiornamento disponibile in un file descrittore dell'aggiornamento archiviato sul server Web. Il file descrittore dell'aggiornamento è un semplice file XML. Il framework di aggiornamento incluso nell'applicazione controlla questo file per verificare se è stata caricata una nuova versione. Il file descrittore dell'aggiornamento contiene i seguenti dati: • version - La nuova versione dell'applicazione AIR. Deve essere la stessa stringa usata come versione nel file descrittore della nuova applicazione AIR. Se la versione nel file descrittore dell'applicazione non corrisponde alla versione del file AIR di aggiornamento, il framework di aggiornamento genera un'eccezione. • url - La posizione del file AIR di aggiornamento. Si tratta del file che contiene la versione di aggiornamento dell'applicazione AIR. • description - Dettagli relativi alla nuova versione. Queste informazioni possono essere visualizzate all'utente durante il processo di aggiornamento. Gli elementi version e url sono obbligatori. L'elemento description è opzionale. Di seguito è riportato un esempio di file descrittore dell'aggiornamento: <?xml version="1.0" encoding="utf-8"?> <update xmlns="http://ns.adobe.com/air/framework/update/description/1.0"> <version>1.1a1</version> <url>http://example.com/updates/sample_1.1a1.air</url> <description>This is the latest version of the Sample application.</description> </update> Se desiderate definire il tag description in più lingue, usate più elementi text che definiscono un attributo lang: <?xml version="1.0" encoding="utf-8"?> <update xmlns="http://ns.adobe.com/air/framework/update/description/1.0"> <version>1.1a1</version> <url>http://example.com/updates/sample_1.1a1.air</url> <description> <text xml:lang="en">English description</text> <text xml:lang="fr">French description</text> <text xml:lang="ro">Romanian description</text> </description> </update> Copiate il file descrittore dell'aggiornamento, insieme al file AIR di aggiornamento, sul server Web. Nella directory templates inclusa nel descrittore dell'aggiornamento sono disponibili esempi di file descrittori dell'aggiornamento. Sono incluse versioni sia monolingua che multilingua. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 340 Aggiornamento delle applicazioni AIR Creazione di un'istanza di un oggetto updater Dopo avere caricato il framework di aggiornamento di AIR nel codice (consultate “Impostazione dell'ambiente di sviluppo Flex” a pagina 337 e “Inclusione dei file del framework in un'applicazione AIR basata su HTML” a pagina 337), dovete creare un'istanza di un oggetto updater, come nell'esempio seguente: var appUpdater:ApplicationUpdater = new ApplicationUpdater(); Nel codice precedente viene usata la classe ApplicationUpdater (che non fornisce un'interfaccia utente). Se desiderate usare la classe ApplicationUpdaterUI (che fornisce un'interfaccia utente), usate quanto segue: var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI(); Negli altri esempi di codice presenti in questo documento si presuppone che abbiate creato un'istanza di un oggetto updater denominato appUpdater. Configurazione delle impostazioni di aggiornamento Potete configurare sia ApplicationUpdater che ApplicationUpdaterUI tramite un file di configurazione fornito con l'applicazione oppure tramite ActionScript o JavaScript nell'applicazione. Definizione delle impostazioni di aggiornamento in un file di configurazione XML Il file di configurazione dell'aggiornamento è un file in formato XML che può contenere i seguenti elementi: • updateURL - Un oggetto String, che rappresenta la posizione del descrittore dell'aggiornamento sul server remoto. È consentita qualsiasi posizione URLRequest valida. Dovete definire la proprietà updateURL tramite il file di configurazione oppure tramite uno script (consultate “Definizione del file descrittore dell'aggiornamento e aggiunta del file AIR al server Web” a pagina 339). Questa proprietà deve essere definita prima di usare l'oggetto updater (prima di chiamare il metodo initialize() dell'oggetto updater, descritto in“Inizializzazione del framework di aggiornamento” a pagina 343). • delay - Un numero che rappresenta un intervallo di tempo espresso in giorni (sono consentiti valori come 0.25) per il controllo degli aggiornamenti. Un valore 0 (che corrisponde al valore predefinito) specifica che l'oggetto updater non esegue automaticamente un controllo periodico. Il file di configurazione per ApplicationUpdaterUI può contenere il seguente elemento, oltre agli elementi updateURL e delay: • defaultUI: un elenco di elementi dialog. Ogni elemento dialog ha un attributo name che corrisponde alla finestra di dialogo nell'interfaccia utente. Ogni elemento dialog ha un attributo visible che definisce se la finestra di dialogo è visibile. Il valore predefinito è true. di seguito sono riportati i possibili valori per l'attributo name: • "checkForUpdate" - Corrisponde alle finestre di dialogo Check for Update, No Update e Update Error (Verifica disponibilità aggiornamenti, Nessun aggiornamento ed Errore durante l'aggiornamento) • "downloadUpdate" - Corrisponde alla finestra di dialogo Download Update (Scarica aggiornamento) • "downloadProgress" - Corrisponde alle finestre di dialogo Download Progress e Download Error (Stato scaricamento ed Errore durante lo scaricamento) • • "installUpdate" - Corrisponde alla finestra di dialogo Install Update (Installa aggiornamento) • "fileUpdate" - Corrisponde alle finestre di dialogo File Update, File No Update e File Error (Aggiornamento file, Nessun aggiornamento del file ed Errore del file) "unexpectedError" - Corrisponde alla finestra di dialogo Unexpected Error (Errore imprevisto) Quando è impostato su false, la finestra di dialogo corrispondente non viene visualizzata durante la procedura di aggiornamento. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 341 Aggiornamento delle applicazioni AIR Di seguito è riportato un esempio del file di configurazione per il framework ApplicationUpdater: <?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://ns.adobe.com/air/framework/update/configuration/1.0"> <url>http://example.com/updates/update.xml</url> <delay>1</delay> </configuration> Di seguito è riportato un esempio del file di configurazione per il framework ApplicationUpdaterUI, che include una definizione per l'elemento defaultUI: <?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://ns.adobe.com/air/framework/update/configuration/1.0"> <url>http://example.com/updates/update.xml</url> <delay>1</delay> <defaultUI> <dialog name="checkForUpdate" visible="false" /> <dialog name="downloadUpdate" visible="false" /> <dialog name="downloadProgress" visible="false" /> </defaultUI> </configuration> La proprietà configurationFile deve puntare alla posizione di tale file, come nell'esempio seguente: • ActionScript: appUpdater.configurationFile = new File("app:/cfg/updateConfig.xml"); • JavaScript: appUpdater.configurationFile = new air.File("app:/cfg/updateConfig.xml"); Nella directory templates del framework di aggiornamento è incluso il file di configurazione di esempio configtemplate.xml. Definizione delle impostazioni di aggiornamento nel codice ActionScript o JavaScript Questi parametri di configurazione possono essere impostati anche usando il codice nell'applicazione, come nell'esempio seguente: appUpdater.updateURL = " http://example.com/updates/update.xml"; appUpdater.delay = 1; Le proprietà dell'oggetto updater sono updateURL e delay. Queste proprietà definiscono le stesse impostazioni degli elementi updateURL e delay nel file di configurazione: l'URL del file descrittore dell'aggiornamento e l'intervallo per il controllo degli aggiornamenti. Se specificate un file di configurazione e le impostazioni nel codice, le proprietà impostate usando il codice hanno la precedenza sulle impostazioni corrispondenti nel file di configurazione. Dovete definire la proprietà updateURL tramite il file di configurazione oppure tramite uno script (consultate “Definizione del file descrittore dell'aggiornamento e aggiunta del file AIR al server Web” a pagina 339), prima di utilizzare l'oggetto updater (prima di chiamare il metodo initialize() dell'oggetto updater, descritto in “Inizializzazione del framework di aggiornamento” a pagina 343). Il framework ApplicationUpdaterUI definisce queste proprietà aggiuntive dell'oggetto updater: • isCheckForUpdateVisible - Corrisponde alle finestre di dialogo Check for Update, No Update e Update Error (Verifica disponibilità aggiornamenti, Nessun aggiornamento ed Errore durante l'aggiornamento) • isDownloadUpdateVisible - Corrisponde alla finestra di dialogo Download Update (Scarica aggiornamento) SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 342 Aggiornamento delle applicazioni AIR • isDownloadProgressVisible - Corrisponde alle finestre di dialogo Download Progress e Download Error (Stato scaricamento ed Errore durante lo scaricamento) • isInstallUpdateVisible - Corrisponde alla finestra di dialogo Install Update (Installa aggiornamento) • isFileUpdateVisible - Corrisponde alle finestre di dialogo File Update, File No Update e File Error (Aggiornamento file, Nessun aggiornamento del file ed Errore del file) • isUnexpectedErrorVisible - Corrisponde alla finestra di dialogo Unexpected Error (Errore imprevisto) Ogni proprietà corrisponde a una o più finestre di dialogo nell'interfaccia utente ApplicationUpdaterUI. Ogni proprietà è un valore booleano, con un valore predefinito true. Quando è impostato su false, le finestre di dialogo corrispondenti non vengono visualizzate durante la procedura di aggiornamento. Queste proprietà delle finestre di dialogo hanno la precedenza sulle impostazioni nel file di configurazione dell'aggiornamento. Processo di aggiornamento Il framework di aggiornamento di AIR completa il processo di aggiornamento nei seguenti passaggi: 1 L'inizializzazione dell'oggetto updater verifica se è stato effettuato un controllo per rilevare la presenza di un aggiornamento entro l'intervallo di tempo definito (consultate “Configurazione delle impostazioni di aggiornamento” a pagina 340). Se è previsto un controllo dell'aggiornamento, il processo continua. 2 L'oggetto updater scarica e interpreta il file descrittore dell'aggiornamento. 3 L'oggetto updater scarica il file AIR di aggiornamento. 4 L'oggetto updater installa la versione aggiornata dell'applicazione. L'oggetto updater invia degli eventi al completamento di ognuno di questi passaggi. Nella versione ApplicationUpdater, potete annullare gli eventi che indicano l'avvenuto completamento di un passaggio del processo. Se annullate uno di questi eventi, il passaggio successivo del processo viene annullato. Nella versione ApplicationUpdaterUI, l'oggetto updater presenta una finestra di dialogo che consente all'utente di annullare ogni singolo passaggio del processo o di procedere. Se annullate l'evento, potete chiamare i metodi dell'oggetto updater per riprendere il processo. Mentre la versione ApplicationUpdater procede nel processo di aggiornamento, registra il relativo stato corrente nella proprietà currentState. Questa proprietà è impostata su una stringa con i seguenti valori possibili: • "UNINITIALIZED" - L'oggetto updater non è stato inizializzato. • "INITIALIZING" - L'oggetto updater è in corso di inizializzazione. • "READY" - L'oggetto updater è stato inizializzato. • "BEFORE_CHECKING" - L'oggetto updater non ha ancora effettuato la verifica del file descrittore dell'aggiornamento. • "CHECKING" - L'oggetto updater sta effettuando la verifica del file descrittore dell'applicazione. • "AVAILABLE" - Il file descrittore di updater è disponibile. • "DOWNLOADING" - L'oggetto updater sta scaricando il file AIR. • "DOWNLOADED" - L'oggetto updater ha scaricato il file AIR. • "INSTALLING" - L'oggetto updater sta installando il file AIR. • "PENDING_INSTALLING" - L'oggetto updater ha effettuato l'inizializzazione e vi sono aggiornamenti in sospeso. Alcuni metodi dell'oggetto updater vengono eseguiti solo in presenza di un determinato stato dell'oggetto stesso. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 343 Aggiornamento delle applicazioni AIR Inizializzazione del framework di aggiornamento Dopo l'impostazione delle proprietà di configurazione (consultate“Esempio di base: Uso della versione ApplicationUpdaterUI” a pagina 337), chiamate il metodo initialize() per inizializzare l'aggiornamento: appUpdater.initialize(); Questo metodo esegue le seguenti operazioni: • Inizializza il framework di aggiornamento, installa automaticamente in modo sincrono gli aggiornamenti in sospeso. È necessario chiamare questo metodo durante l'avvio dell'applicazione, in quanto potrebbe riavviare l'applicazione quando viene chiamato. • Controlla se è presente un aggiornamento posticipato e lo installa. • Se durante il processo di aggiornamento si verifica un errore, cancella il file di aggiornamento e le informazioni sulla versione dall'area di memorizzazione dell'applicazione. • Se l'intervallo è scaduto, avvia il processo di aggiornamento. In caso contrario riavvia il timer. La chiamata a questo metodo può attivare l'invio dei seguenti eventi da parte dell'oggetto updater: • UpdateEvent.INITIALIZED - Inviato quando l'inizializzazione è completa. • ErrorEvent.ERROR - Inviato quando si verifica un errore durante l'inizializzazione. All'invio dell'evento UpdateEvent.INITIALIZED, il processo di aggiornamento viene completato. Quando chiamate il metodo initialize(), l'oggetto updater avvia il processo di aggiornamento e completa tutti i passaggi in base all'impostazione del ritardo specificato per il timer. Potete comunque avviare il processo di aggiornamento in qualsiasi momento, chiamando il metodo checkNow() dell'oggetto updater: appUpdater.checkNow(); Questo metodo non attiva alcuna operazione se il processo di aggiornamento è già in esecuzione. Altrimenti, avvia il processo di aggiornamento. L'oggetto updater può inviare il seguente evento a seguito della chiamata del metodo checkNow(): • UpdateEvent.CHECK_FOR_UPDATE, subito prima del tentativo di scaricare il file descrittore dell'aggiornamento. Se annullate l'evento checkForUpdate, potete chiamare il metodo checkForUpdate() dell'oggetto updater. (Consultate la sezione successiva). Se non annullate l'evento, il processo di aggiornamento continua con la verifica del file descrittore dell'aggiornamento. Gestione del processo di aggiornamento nella versione ApplicationUpdaterUI Nella versione ApplicationUpdaterUI, l'utente può annullare il processo tramite i pulsanti Annulla presenti nelle finestre di dialogo dell'interfaccia utente. Potete inoltre annullare il processo di aggiornamento a livello di codice, chiamando il metodo cancelUpdate() dell'oggetto ApplicationUpdaterUI. Potete impostare le proprietà dell'oggetto ApplicationUpdaterUI o definire gli elementi nel file di configurazione dell'aggiornamento per specificare quali conferme vengono visualizzate nelle finestre di dialogo dall'oggetto updater. Per ulteriori dettagli, consultate “Configurazione delle impostazioni di aggiornamento” a pagina 340. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 344 Aggiornamento delle applicazioni AIR Gestione del processo di aggiornamento nella versione ApplicationUpdater Potete chiamare il metodo preventDefault() degli oggetti evento inviati dall'oggetto the ApplicationUpdater per annullare i passaggi del processo di aggiornamento (consultate “Processo di aggiornamento” a pagina 342). L'annullamento del comportamento predefinito consente all'applicazione di visualizzare un messaggio per chiedere all'utente se desidera continuare. Nelle seguenti sezioni viene descritto come continuare il processo di aggiornamento quando viene annullato un passaggio del processo. Scaricamento e interpretazione del file descrittore dell'aggiornamento L'oggetto ApplicationUpdater invia l'evento checkForUpdate prima dell'inizio del processo di aggiornamento, subito prima che l'oggetto updater tenti di scaricare il file descrittore dell'aggiornamento. Se annullate il comportamento predefinito dell'evento checkForUpdate, l'oggetto updater non scarica il file descrittore dell'aggiornamento. Per riprendere il processo di aggiornamento, potete chiamare il metodo checkForUpdate(): appUpdater.checkForUpdate(); Se viene chiamato il metodo checkForUpdate(), l'oggetto updater scarica in modo asincrono e interpreta il file descrittore dell'aggiornamento. A seguito della chiamata del metodo checkForUpdate(), l'oggetto updater può inviare i seguenti eventi: • StatusUpdateEvent.UPDATE_STATUS - L'oggetto updater ha scaricato e interpretato correttamente il file descrittore dell'aggiornamento. Questo evento presenta le seguenti proprietà: • available- Un valore booleano. Impostato su true se è disponibile una versione diversa rispetto a quella dell'applicazione corrente; in caso contrario false (la versione è la stessa). • version - Un oggetto String. La versione rilevata dal file descrittore dell'aggiornamento del file di aggiornamento. • details - Un oggetto Array. Se non sono presenti versioni localizzate della descrizione, questo oggetto array restituisce una stringa vuota ("") come primo elemento e la descrizione come secondo elemento. Se sono presenti più versioni della descrizione (nel file descrittore dell'aggiornamento), l'array contiene più array secondari. Ogni array presenta due elementi: il primo è un codice di lingua (ad esempio "en"), mentre il secondo è la descrizione corrispondente (una stringa) per quella lingua. Consultate “Definizione del file descrittore dell'aggiornamento e aggiunta del file AIR al server Web” a pagina 339. • StatusUpdateErrorEvent.UPDATE_ERROR - Si è verificato un errore e l'oggetto updater non ha potuto scaricare o interpretare il file descrittore dell'aggiornamento. Scaricamento del file AIR di aggiornamento L'oggetto ApplicationUpdater invia l'evento updateStatus dopo che il file descrittore dell'aggiornamento è stato scaricato e interpretato correttamente. Il comportamento predefinito prevede di avviare lo scaricamento del file di aggiornamento, se è disponibile. Se annullate il comportamento predefinito, potete chiamare il metodo downloadUpdate() per riprendere il processo di aggiornamento: appUpdater.downloadUpdate(); Se viene chiamato questo metodo, l'oggetto updater scarica in modo asincrono la versione di aggiornamento del file AIR. Il metodo downloadUpdate() può inviare i seguenti eventi: • UpdateEvent.DOWNLOAD_START - La connessione al server è stata stabilita. Quando usate la libreria di ApplicationUpdaterUI, questo evento visualizza una finestra di dialogo con una barra di avanzamento che traccia lo stato dello scaricamento. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 345 Aggiornamento delle applicazioni AIR • ProgressEvent.PROGRESS - Inviato periodicamente mentre avanza lo scaricamento del file. • DownloadErrorEvent.DOWNLOAD_ERROR - Inviato se si verifica un errore durante la connessione o lo scaricamento del file di aggiornamento. Viene inviato anche in caso di stati HTTP non validi (ad esempio “404 - File non trovato”). Questo evento presenta una proprietà errorID, un valore integer che definisce le informazioni aggiuntive sull'errore. Una proprietà subErrorID aggiuntiva può contenere ulteriori informazioni sull'errore. • UpdateEvent.DOWNLOAD_COMPLETE - L'oggetto updater ha scaricato e interpretato correttamente il file descrittore dell'aggiornamento. Se non annullate questo evento, la versione ApplicationUpdater continua con l'installazione della versione di aggiornamento. Nella versione ApplicationUpdaterUI, viene visualizzata all'utente una finestra di dialogo con l'opzione per continuare. Aggiornamento dell'applicazione L'oggetto ApplicationUpdater invia l'evento downloadComplete dopo avere completato lo scaricamento del file di aggiornamento. Se annullate il comportamento predefinito, potete chiamare il metodo installUpdate() per riprendere il processo di aggiornamento: appUpdater.installUpdate(file); Se viene chiamato questo metodo, l'oggetto updater installa una versione di aggiornamento del file AIR. Il metodo include il parametro file; un oggetto File che fa riferimento al file AIR da utilizzare come aggiornamento. L'oggetto ApplicationUpdater può inviare l'evento beforeInstall a seguito della chiamata al metodo installUpdate(): • UpdateEvent.BEFORE_INSTALL - Inviato subito prima dell'installazione dell'aggiornamento. A volte, può essere utile impedire l'installazione dell'aggiornamento a questo punto, in modo che l'utente possa completare il lavoro in corso prima di procedere all'aggiornamento. la chiamata al metodo preventDefault() dell'oggetto Event posticipa l'installazione fino al riavvio successivo; non possono essere avviati altri processi di aggiornamento. (Sono inclusi gli aggiornamenti che dovessero risultare della chiamata al metodo checkNow() o dal controllo periodico). Installazione da un file AIR arbitrario Potete chiamare il metodo installFromAIRFile() per installare la versione di aggiornamento da un file AIR sul computer dell'utente: appUpdater.installFromAIRFile(); Con questo metodo, l'oggetto updater installa una versione di aggiornamento dell'applicazione dal file AIR. Il metodo installFromAIRFile() può inviare i seguenti eventi: • StatusFileUpdateEvent.FILE_UPDATE_STATUS - Inviato dopo che ApplicationUpdater ha completato la convalida del file inviato usando il metodo installFromAIRFile(). Questo evento presenta le seguenti proprietà: • available - Impostato su true se è disponibile una versione diversa rispetto a quella dell'applicazione corrente; in caso contrario false (le versione sono le stesse). • version - La stringa che rappresenta la nuova versione disponibile. • path - Rappresenta il percorso nativo del file di aggiornamento. Potete annullare questo evento se la proprietà available dell'oggetto StatusFileUpdateEvent è impostata su true. L'annullamento dell'evento comporta l'interruzione dell'aggiornamento. Per continuare l'aggiornamento annullato, chiamate il metodo installUpdate(). SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 346 Aggiornamento delle applicazioni AIR • StatusFileUpdateErrorEvent.FILE_UPDATE_ERROR - Si è verificato un errore e l'oggetto updater non ha potuto installare l'applicazione AIR. Annullamento del processo di aggiornamento Per annullare il processo di aggiornamento, potete chiamare il metodo cancelUpdate(): appUpdater.cancelUpdate(); Questo metodo annulla le eventuali operazioni di scaricamento in sospeso, eliminando i file scaricati incompleti, e riavvia il timer di controllo periodico. Questo metodo non attiva alcuna operazione se l'oggetto updater è in corso di inizializzazione. Localizzazione dell'interfaccia ApplicationUpdaterUI La classe ApplicationUpdaterUI fornisce un'interfaccia utente predefinita per il processo di aggiornamento. Sono incluse le finestre di dialogo che consentono all'utente di avviare o annullare il processo e di eseguire altre azioni correlate. L'elemento description del file descrittore dell'aggiornamento consente di definire la descrizione dell'applicazione in più lingue. Potete usare più elementi text che definiscono gli attributi lang, come nel seguente esempio: <?xml version="1.0" encoding="utf-8"?> <update xmlns="http://ns.adobe.com/air/framework/update/description/1.0"> <version>1.1a1</version> <url>http://example.com/updates/sample_1.1a1.air</url> <description> <text xml:lang="en">English description</text> <text xml:lang="fr">French description</text> <text xml:lang="ro">Romanian description</text> </description> </update> Il framework di aggiornamento utilizza la descrizione che meglio si adatta alla sequenza di localizzazione dell'utente finale. Per ulteriori informazioni, consultate Definizione del file descrittore dell'aggiornamento e aggiunta del file AIR al server Web. Gli sviluppatori in Flex possono aggiungere direttamente una nuova lingua al pacchetto "ApplicationUpdaterDialogs". Gli sviluppatori in JavaScript possono chiamare il metodo addResources() dell'oggetto updater. Questo metodo aggiunge dinamicamente un nuovo pacchetto di risorse per una lingua. Nel pacchetto di risorse sono definite le stringhe localizzate per una lingua. Queste stringhe vengono usate in diversi campi di testo delle finestre di dialogo. Gli sviluppatori in JavaScript possono usare la proprietà localeChain della classe ApplicationUpdaterUI per definire la sequenza di versioni locali usate dall'interfaccia utente. In genere, questa proprietà viene usata solo dagli sviluppatori in JavaScript (HTML). Gli sviluppatori in Flex possono usare ResourceManager per gestire la sequenza di versioni locali. Il seguente codice JavaScript definisce, ad esempio, pacchetti di risorse per le lingue rumeno e ungherese: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 347 Aggiornamento delle applicazioni AIR appUpdater.addResources("ro_RO", {titleCheck: "Titlu", msgCheck: "Mesaj", btnCheck: "Buton"}); appUpdater.addResources("hu", {titleCheck: "Cím", msgCheck: "Üzenet"}); var languages = ["ro", "hu"]; languages = languages.concat(air.Capabilities.languages); var sortedLanguages = air.Localizer.sortLanguagesByPreference(languages, air.Capabilities.language, "en-US"); sortedLanguages.push("en-US"); appUpdater.localeChain = sortedLanguages; Per ulteriori dettagli, consultate la descrizione del metodo addResources() della classe nella Guida di riferimento. 348 Capitolo 34: Localizzazione di applicazioni AIR Adobe® AIR™ 1.1 dispone di supporto multilingue. Introduzione alla localizzazione La localizzazione è il processo di inclusione di risorse con lo scopo di supportare più versioni linguistiche. Un'impostazione locale è la combinazione di una lingua e un codice di paese. Ad esempio, en_US fa riferimento alla lingua inglese parlata negli Stati Uniti, mentre fr-FR fa riferimento alla lingua francese parlata in Francia. Per localizzare un'applicazione per queste impostazioni locali, è necessario fornire due gruppi di risorse: uno per l'impostazione locale en_US e uno per quella fr_FR. Impostazioni locali diverse possono avere in comune la stessa lingua. Ad esempio, en-US ed en_GB (Gran Bretagna) sono impostazioni locali diverse. In questo caso, entrambe le impostazioni locali utilizzano la lingua inglese, ma il codice del paese indica che si tratta di impostazioni locali diverse che pertanto potrebbero utilizzare risorse differenti. Ad esempio, il correttore ortografico di un'applicazione con impostazioni locali en-US potrebbe prevedere la parola "color", mentre la stessa parola in un'applicazione con impostazioni locali en_GB sarebbe scritta "colour". Inoltre, le unità di misura della valuta sarebbero rappresentate dal dollaro o dalla sterlina, a seconda dell'impostazione locale, e anche il formato di data e ora potrebbe essere diverso. È inoltre possibile fornire un gruppo di risorse per una lingua senza specificare un codice di paese. Potete ad esempio fornire risorse en per la lingua inglese e ulteriori risorse per l'impostazione locale en-US, specifiche dell'inglese americano. AIR SDK comprende un framework per la localizzazione HTML (contenuto in un file AIRLocalizer.js). Tale framework include API che agevolano le operazioni con più impostazioni locali. Per informazioni dettagliate, consultate “Localizzazione di contenuto HTML” a pagina 350. La localizzazione va oltre la semplice traduzione delle stringhe utilizzate nell'applicazione. Può comprendere anche qualsiasi tipo di risorsa, come file audio, immagini e video. Localizzazione del nome e della descrizione dell'applicazione nel programma di installazione dell'applicazione È possibile specificare più lingue per gli elementi name e description nel file descrittore dell'applicazione. Ad esempio, l'elemento seguente specifica il nome dell'applicazione in tre lingue (inglese, francese e tedesco). <name> <text xml:lang="en">Sample 1.0</text> <text xml:lang="fr">Échantillon 1.0</text> <text xml:lang="de">Stichprobe 1.0</text> </name> SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 349 Localizzazione di applicazioni AIR L'attributo xml:lang di ogni elemento di testo specifica un codice lingua, definito dallo standard RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). L'elemento name definisce il nome dell'applicazione visualizzato dal programma di installazione dell'applicazione AIR che utilizza il valore localizzato più prossimo alle lingue dell'interfaccia utente definite nelle impostazioni del sistema operativo. Anche in questo caso, potete specificare più lingue per l'elemento description nel file descrittore dell'applicazione. Tale elemento definisce il testo descrittivo visualizzato nel programma di installazione dell'applicazione AIR. Queste impostazioni si applicano solo alle lingue disponibili nel programma di installazione dell'applicazione AIR. Non definiscono le impostazioni locali disponibili per l'applicazione installata in esecuzione. Le applicazioni AIR possono disporre di interfacce utente in grado di supportare più lingue, comprese e in aggiunta a quelle disponibili per il programma di installazione dell'applicazione AIR. Per ulteriori informazioni, consultate “Definizione delle proprietà nel file descrittore dell'applicazione” a pagina 47. Selezione delle impostazioni locali Per determinare le impostazioni locali utilizzate dall'applicazione, è possibile adottare uno dei metodi seguenti: • Richiesta all'utente - È possibile avviare l'applicazione con impostazioni locali predefinite e quindi chiedere all'utente di scegliere le impostazioni locali preferite. • Capabilities.languages — La proprietà Capabilities.languages elenca un array di lingue disponibili per le lingue preferite dall'utente, in base all'impostazione del sistema operativo. Le stringhe contengono tag language (e informazioni script e region, ove applicabili) definite dallo standard RFC4646 (http://www.ietf.org/rfc/rfc4646.txt) e utilizzano il trattino come delimitatore (ad esempio, "en-US" o "ja-JP"). La prima voce dell'array restituito presenta lo stesso ID lingua primario della proprietà language. Se ad esempio languages[0] è impostata su "enUS", la proprietà language è impostata su "en". Se invece la proprietà language è impostata su "xu" (a indicare una lingua sconosciuta), il primo elemento dell'array languages è diverso. • Capabilities.language — La proprietà Capabilities.language fornisce il codice della lingua per l'interfaccia utente del sistema operativo. Questa proprietà è tuttavia limitata a 20 lingue conosciute. Nei sistemi in lingua inglese, restituisce solo il codice della lingua e non il codice del paese. Per questi motivi, è consigliabile utilizzare il primo elemento dell'array Capabilities.languages. Localizzazione di contenuto Flash Flash CS3 e Flash CS4 includono una classe Locale nei componenti ActionScript 3.0 che consente di controllare la modalità di visualizzazione di un testo multilingua da parte di un file SWF. Il pannello Stringhe di Flash consente di utilizzare identificatori di stringa anziché valori letterali nei campi di testo dinamici, pertanto potete creare un file SWF che visualizzi testo caricato da un file XML specifico di una lingua. Per informazioni sull'utilizzo della classe Locale, consultate il manuale di Flash Guida di riferimento del linguaggio e dei componenti ActionScript 3.0. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 350 Localizzazione di applicazioni AIR Localizzazione di contenuto HTML L'AIR 1.1 SDK contiene un framework per la localizzazione HTML. Il file AIRLocalizer.js di JavaScript definisce il framework. La directory frameworks dell'AIR SDK contiene il file AIRLocalizer.js, il quale comprende una classe air.Localizer con le funzionalità che supportano l'utente nella creazione di applicazioni che supportano più versioni localizzate. Caricamento del codice del framework per la localizzazione HTML in AIR Per utilizzare il framework di localizzazione, copiate il file AIRLocalizer.js nel progetto. Inseritelo quindi nel file HTML principale dell'applicazione utilizzando un tag script: <script src="AIRLocalizer.js" type="text/javascript" charset="utf-8"></script> Il codice JavaScript successivo può chiamare l'oggetto air.Localizer.localizer: <script> var localizer = air.Localizer.localizer; </script> L'oggetto air.Localizer.localizer è un oggetto singleton che definisce metodi e proprietà per l'utilizzo e la gestione di risorse localizzate. La classe Localizer comprende i seguenti metodi: Metodo Descrizione getFile() Ottiene il testo di un pacchetto di risorse specificato per impostazioni locali specificate. Consultate “Ottenimento di risorse per impostazioni locali specifiche” a pagina 356. getLocaleChain() Restituisce le lingue nella catena di impostazioni locali. Consultate “Definizione della catena di impostazioni locali” a pagina 355. getResourceBundle() Restituisce le chiavi del pacchetto e i valori corrispondenti come un oggetto. Consultate “Ottenimento di risorse per impostazioni locali specifiche” a pagina 356. getString() Ottiene la stringa definita per una risorsa. Consultate “Ottenimento di risorse per impostazioni locali specifiche” a pagina 356. setBundlesDirectory( ) Imposta il percorso della directory dei pacchetti. Consultate “Personalizzazione delle impostazioni di AIR HTML Localizer” a pagina 354. setLocalAttributePre fix() Imposta il prefisso utilizzato dagli attributi del localizer impiegati negli elementi HTML DOM. Consultate “Personalizzazione delle impostazioni di AIR HTML Localizer” a pagina 354 setLocaleChain() Imposta l'ordine delle lingue nella catena delle impostazioni locali. Consultate “Definizione della catena di impostazioni locali” a pagina 355. sortLanguagesByPrefe rence() Ordina le impostazioni locali nella catena in base al relativo ordine nelle impostazioni del sistema operativo. Consultate “Definizione della catena di impostazioni locali” a pagina 355. update() Aggiorna l'HTML DOM (o un elemento DOM) con le stringhe localizzate dalla catena di impostazioni locali corrente. Per informazioni sulle catene di impostazioni locali, consultate “Gestione di catene di impostazioni locali” a pagina 352. Per ulteriori informazioni sul metodo update(), consultate “Aggiornamento degli elementi DOM per l'uso dell'impostazione locale corrente” a pagina 353. La classe Localizer comprende le seguenti proprietà statiche: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 351 Localizzazione di applicazioni AIR Proprietà Descrizione localizer Restituisce un riferimento all'oggetto Localizer singleton per l'applicazione. ultimateFallbackLocale Le impostazioni locali utilizzate se l'applicazione non supporta le preferenze dell'utente. Consultate “Definizione della catena di impostazioni locali” a pagina 355. Definizione di pacchetti di risorse Il framework di localizzazione HTML legge le versioni localizzate delle stringhe dai file di localizzazione. Un file di localizzazione è una raccolta di valori basati su chiave, serializzati in un file di testo. Un file di localizzazione viene anche detto pacchetto. Create una sottodirectory della directory di progetto dell'applicazione, denominata "locale". Potete anche utilizzare un nome diverso: consultate “Personalizzazione delle impostazioni di AIR HTML Localizer” a pagina 354. Questa directory comprenderà i file di localizzazione ed è detta anche directory dei pacchetti. Create una sottodirectory della directory dei pacchetti per ogni impostazione locale supportata dall'applicazione. Denominate ogni sottodirectory in base al codice delle impostazioni locali, ad esempio assegnate alla directory del francese il codice "fr" e a quella dell'inglese il codice "en". Potete utilizzare un carattere di sottolineatura (_) per definire un'impostazione locale che comprenda una lingua e un codice di paese. Assegnate ad esempio alla directory dell'inglese americano il codice "en_us". In alternativa, potete utilizzare il trattino al posto del carattere di sottolineatura, come in "en-us". Il framework di localizzazione HTML supporta entrambi. Potete aggiungere alla sottodirectory di un'impostazione locale il numero di file di risorse che desiderate. In genere si crea un file di localizzazione per ogni lingua (e lo si inserisce nella directory relativa alla lingua). Il framework di localizzazione HTML comprende un metodo getFile() che consente di leggere il contenuto di un file (consultate “Ottenimento di risorse per impostazioni locali specifiche” a pagina 356. I file che hanno l'estensione .properties sono detti file di proprietà della localizzazione. Potete utilizzarli per specificare coppie chiave-valore per un'impostazione locale. Un file properties definisce un valore stringa per ogni riga. L'esempio seguente definisce un valore stringa "Hello in English." per una chiave denominata greeting: greeting=Hello in English. Un file properties contenente il testo seguente definisce sei coppie chiave-valore: title=Sample Application greeting=Hello in English. exitMessage=Thank you for using the application. color1=Red color2=Green color3=Blue L'esempio mostra una versione inglese del file properties da inserire nella directory en. La versione francese di questo file properties si trova nella directory fr: title=Application Example greeting=Bonjour en français. exitMessage=Merci d'avoir utilisé cette application. color1=Rouge color2=Vert color3=Bleu SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 352 Localizzazione di applicazioni AIR Potete definire più file di risorse per diversi tipi di informazioni. Un file legal.properties può ad esempio contenere testo legale standard (come le informazioni di copyright). Potete riutilizzare tale risorsa in più applicazioni. Analogamente, potete definire file distinti che specifichino contenuto localizzato per parti differenti dell'interfaccia utente. Per supportare più lingue, utilizzate la codifica UTF-8 per questi file. Gestione di catene di impostazioni locali Quando l'applicazione carica il file AIRLocalizer.js, esegue l'esame delle impostazioni locali specificate nell'applicazione. Queste impostazioni locali corrispondono alle sottodirectory della directory dei pacchetti (consultate “Definizione di pacchetti di risorse” a pagina 351). Questo elenco di impostazioni locali disponibili è detto anche catena di impostazioni locali. Il file AIRLocalizer.js ordina automaticamente la catena di impostazioni locali in base all'ordine preferito definito nelle impostazioni del sistema operativo. La proprietà Capabilities.languages elenca le lingue dell'interfaccia utente del sistema operativo nell'ordine preferito. In tal modo, se un'applicazione definisce risorse per le impostazioni locali "en", "en_US" ed "en_UK", il framework di AIR HTML Localizer ordina la catena di impostazioni locali in modo corretto. Quando viene avviata un'applicazione in un sistema in cui "en" rappresenta l'impostazione locale principale, la catena delle impostazioni locali viene così ordinata: ["en", "en_US", "en_UK"]. In tal caso, l'applicazione cerca le risorse prima nel pacchetto "en", poi in quello "en_US". Se invece in un sistema "en_US" rappresenta l'impostazione locale principale, l'ordinamento corrisponde a ["en_US", "en", en_UK"]. In tal caso, l'applicazione cerca le risorse prima nel pacchetto "en_US" e poi in quello "en". Per impostazione predefinita, l'applicazione definisce le prime impostazioni locali della catena come impostazioni locali predefinite da utilizzare. Potete chiedere all'utente di selezionare le impostazioni locali alla prima esecuzione dell'applicazione e quindi memorizzare la selezione in un file di preferenze e utilizzare tali impostazioni locali al successivo avvio dell'applicazione. L'applicazione può utilizzare stringhe delle risorse di qualunque impostazione locale della catena. Se per un'impostazione locale non è definita alcuna stringa di risorse, l'applicazione utilizzerà la successiva stringa di risorse corrispondente per altre impostazioni locali definite nella catena. Potete personalizzare la catena di impostazioni locali chiamando il metodo setLocaleChain() dell'oggetto Localizer. Consultate “Definizione della catena di impostazioni locali” a pagina 355. Aggiornamento di elementi DOM con contenuto localizzato Un elemento dell'applicazione può fare riferimento al valore di una chiave di un file di proprietà di localizzazione. Ad esempio, l'elemento title dell'esempio seguente specifica un attributo local_innerHTML. Il framework di localizzazione utilizza questo attributo per cercare un valore localizzato. Per impostazione predefinita, il framework cerca i nomi degli attributi che iniziano con "local_". Il framework aggiorna gli attributi con nomi che corrispondono al testo successivo a "local_". In tal caso, il framework imposta l'attributo innerHTML dell'elemento title. L'attributo innerHTML utilizza il valore definito per la chiave mainWindowTitle nel file delle proprietà predefinite (default.properties): <title local_innerHTML="default.mainWindowTitle"/> Se per l'impostazione locale corrente non è definito alcun valore corrispondente, il framework di localizer cerca nel resto della catena di impostazioni locali. Utilizza l'impostazione locale successiva nella catena di impostazioni locali per cui è definito un valore. Nell'esempio seguente, il testo (attributo innerHTML) dell'elemento p utilizza il valore della chiave greeting definito nel file delle proprietà predefinite: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 353 Localizzazione di applicazioni AIR <p local_innerHTML="default.greeting" /> Nell'esempio seguente, l'attributo value (e il testo visualizzato) dell'elemento input utilizza il valore della chiave btnBlue definita nel file delle proprietà predefinite: <input type="button" local_value="default.btnBlue" /> Per aggiornare l'HTML DOM affinché vengano utilizzate le stringhe definite nella catena di impostazioni locali corrente, chiamate il metodo update() dell'oggetto Localizer. Se chiamate il metodo update(), l'oggetto Localizer analizza il DOM e applica modifiche se trova attributi di localizzazione ("local_..."): air.Localizer.localizer.update(); Potete definire valori sia per un attributo (come "innerHTML") che per il corrispondente attributo di localizzazione (come "local_innerHTML"). In tal caso, il framework di localizzazione sovrascrive solo il valore dell'attributo se trova un valore corrispondente nella catena di localizzazione. Ad esempio, l'elemento seguente definisce gli attributi value e local_value: <input type="text" value="Blue" local_value="default.btnBlue"/> Potete anche aggiornare solamente un elemento DOM specifico. Consultate la sezione successiva, “Aggiornamento degli elementi DOM per l'uso dell'impostazione locale corrente” a pagina 353. Per impostazione predefinita, AIR HTML Localizer utilizza "local_" come prefisso degli attributi che definiscono le impostazioni di localizzazione di un elemento. Ad esempio, per impostazione predefinita un attributo local_innerHTML definisce il pacchetto e il nome della risorsa utilizzati per il valore innerHTML di un elemento. Inoltre, per impostazione predefinita un attributo local_value definisce il pacchetto e il nome della risorsa utilizzati per l'attributo value di un elemento. È possibile configurare Localizer per utilizzare un prefisso di attributo diverso da "local_". Consultate “Personalizzazione delle impostazioni di AIR HTML Localizer” a pagina 354. Aggiornamento degli elementi DOM per l'uso dell'impostazione locale corrente Quando l'oggetto Localizer aggiorna l'HTML DOM, gli elementi contrassegnati utilizzano i valori degli attributi in base a stringhe definite nella catena corrente delle impostazioni locali. Affinché il localizer HTML aggiorni l'HTML DOM, chiamate il metodo update() dell'oggetto Localizer: air.Localizer.localizer.update(); Per aggiornare solamente un elemento DOM specificato, passatelo come parametro al metodo update(). Il metodo update() dispone di un solo parametro, parentNode, che è opzionale. Se specificato, il parametro parentNode definisce l'elemento DOM da localizzare. Quando chiamate il metodo update() e specificate un parametro parentNode, vengono impostati i valori localizzati per tutti gli elementi secondari che specificano attributi di localizzazione. Ad esempio, considerate il seguente elemento div: <div id="colorsDiv"> <h1 local_innerHTML="default.lblColors" ></h1> <p><input type="button" local_value="default.btnBlue" /></p> <p><input type="button" local_value="default.btnRed" /></p> <p><input type="button" local_value="default.btnGreen" /></p> </div> Per aggiornare questo elemento affinché vengano utilizzate le stringhe localizzate specificate nella catena corrente di impostazioni locali, utilizzate il codice JavaScript seguente: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 354 Localizzazione di applicazioni AIR var divElement = window.document.getElementById("colorsDiv"); air.Localizer.localizer.update(divElement); Se nella catena delle impostazioni locali non viene trovato alcun valore chiave, il framework di localizzazione imposta il valore dell'attributo sul valore dell'attributo "local_". Ad esempio, nell'esempio precedente, supponete che il framework di localizzazione non riesca a trovare un valore per la chiave lblColors (in qualsiasi file default.properties della catena di impostazioni locali). In tal caso, utilizza "default.lblColors" come valore innerHTML. L'uso di questo valore consente di indicare (allo sviluppatore) risorse mancanti. Il metodo update() invia un evento resourceNotFound quando non riesce a trovare una risorsa nella catena di impostazioni locali. La costante air.Localizer.RESOURCE_NOT_FOUND definisce la stringa "resourceNotFound". L'evento dispone di tre proprietà: bundleName, resourceName e locale. La proprietà bundleName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà resourceName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà locale corrisponde al nome dell'impostazione locale in cui non si trova la risorsa. Il metodo update() invia un evento bundleNotFound quando non riesce a trovare un pacchetto specificato. La costante air.Localizer.BUNDLE_NOT_FOUND definisce la stringa "bundleNotFound". L'evento dispone di due proprietà: bundleName e locale. La proprietà bundleName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà locale corrisponde al nome dell'impostazione locale in cui non si trova la risorsa. Il metodo update() opera in modo asincrono (e invia gli eventi resourceNotFound e bundleNotFound in modo asincrono). Il codice seguente imposta i listener di eventi per gli eventi resourceNotFound e bundleNotFound: air.Localizer.localizer.addEventListener(air.Localizer.RESOURCE_NOT_FOUND, rnfHandler); air.Localizer.localizer.addEventListener(air.Localizer.BUNDLE_NOT_FOUND, rnfHandler); air.Localizer.localizer.update(); function rnfHandler(event) { alert(event.bundleName + ": " + event.resourceName + ":." + event.locale); } function bnfHandler(event) { alert(event.bundleName + ":." + event.locale); } Personalizzazione delle impostazioni di AIR HTML Localizer Il metodo setBundlesDirectory() dell'oggetto Localizer consente di personalizzare il percorso della directory dei pacchetti. Il metodo setLocalAttributePrefix() dell'oggetto Localizer consente di personalizzare il percorso della directory dei pacchetti e il valore dell'attributo utilizzato da Localizer. La directory dei pacchetti predefinita corrisponde alla sottodirectory delle impostazioni locali della directory dell'applicazione. Potete specificare un'altra directory chiamando il metodo setBundlesDirectory() dell'oggetto Localizer. Questo metodo accetta un parametro, path, che corrisponde al percorso della directory dei pacchetti predefinita in formato stringa. Il valore del parametro path può corrispondere a uno dei seguenti: • Una stringa che definisce un percorso relativo alla directory dell'applicazione, ad esempio "locales" • Una stringa che definisce un URL valido che utilizza gli schemi URL app, app-storage o file, ad esempio "app://languages" (non utilizzare lo schema URL http) • Un oggetto File Per informazioni sugli URL e i percorsi di directory, consultate “Percorsi degli oggetti File” a pagina 109. Ad esempio, il codice seguente imposta la directory dei pacchetti su una sottodirectory di lingue della directory di memorizzazione dell'applicazione (non della directory dell'applicazione): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 355 Localizzazione di applicazioni AIR air.Localizer.localizer.setBundlesDirectory("languages"); Se per il parametro path non viene passato un percorso valido, il metodo genera un'eccezione BundlePathNotFoundError. Questo errore ha "BundlePathNotFoundError" come proprietà name e la relativa proprietà message specifica il percorso non valido. Per impostazione predefinita, AIR HTML Localizer utilizza "local_" come prefisso per gli attributi che definiscono le impostazioni di localizzazione di un elemento. Ad esempio, l'attributo local_innerHTML definisce il pacchetto e il nome della risorsa utilizzati per il valore innerHTML del seguente elemento input: <p local_innerHTML="default.greeting" /> Il metodo setLocalAttributePrefix() dell'oggetto Localizer consente di utilizzare un prefisso dell'attributo diverso da "local_". Questo metodo statico accetta un parametro, ovvero la stringa che desiderate utilizzare come prefisso dell'attributo. Ad esempio, il codice seguente imposta il framework di localizzazione affinché venga utilizzato "loc_" come prefisso dell'attributo: air.Localizer.localizer.setLocalAttributePrefix("loc_"); Potete personalizzare il prefisso dell'attributo utilizzato dal framework di localizzazione. Questa operazione può essere utile se il valore predefinito ("local_") entra in conflitto con il nome di un altro attributo che avete utilizzato nel codice. Assicuratevi di utilizzare caratteri validi per gli attributi HTML quando chiamate questo metodo (ad esempio, il valore non può contenere un carattere di spazio vuoto). Per ulteriori informazioni sull'uso degli attributi di localizzazione negli elementi HTML, consultate “Aggiornamento di elementi DOM con contenuto localizzato” a pagina 352. Le impostazioni relative alla directory dei pacchetti e al prefisso degli attributi non persistono tra le diverse sessioni dell'applicazione. Se utilizzate impostazioni personalizzate per la directory dei pacchetti o il prefisso degli attributi, assicuratevi di configurarle a ogni inizializzazione dell'applicazione. Definizione della catena di impostazioni locali Per impostazione predefinita, quando caricate il codice di AIRLocalizer.js, viene impostata la catena di impostazioni locali predefinita. Le impostazioni locali disponibili nella directory dei pacchetti e nelle impostazioni della lingua del sistema operativo definiscono questa catena di impostazioni locali. Per informazioni dettagliate, consultate “Gestione di catene di impostazioni locali” a pagina 352. È possibile modificare la catena delle impostazioni locali chiamando il metodo statico setLocaleChain() dell'oggetto Localizer. Ad esempio, potete chiamare questo metodo se l'utente indica una preferenza per una lingua specifica. Il metodo setLocaleChain() accetta un parametro, chain, che è un array di impostazioni locali, ad esempio ["fr_FR","fr","fr_CA"]. L'ordine delle impostazioni locali nell'array imposta l'ordine in cui il framework cerca le risorse (nelle operazioni successive). Se non si trova una risorsa per la prima impostazione locale della catena, si continua a cercare nelle risorse di un'altra impostazione locale. Se l'argomento chain non è presente, non è un array oppure è un array vuoto, la funzione non viene eseguita e viene generata un'eccezione IllegalArgumentsError. Il metodo statico getLocaleChain() dell'oggetto Localizer restituisce un array che elenca le impostazioni locali della catena di impostazioni locali corrente. Il codice seguente legge la catena di impostazioni locali corrente e aggiunge due impostazioni locali per il francese all'inizio della catena: var currentChain = air.Localizer.localizer.getLocaleChain(); newLocales = ["fr_FR", "fr"]; air.Localizer.localizer.setLocaleChain(newLocales.concat(currentChain)); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 356 Localizzazione di applicazioni AIR Il metodo setLocaleChain() invia un evento "change" quando aggiorna la catena di impostazioni locali. La costante air.Localizer.LOCALE_CHANGE definisce la stringa "change". L'evento dispone di una proprietà, localeChain, un array di codici di impostazioni locali nella nuova catena di impostazioni locali. Il codice seguente imposta un listener di eventi per questo evento: var currentChain = air.Localizer.localizer.getLocaleChain(); newLocales = ["fr_FR", "fr"]; localizer.addEventListener(air.Localizer.LOCALE_CHANGE, changeHandler); air.Localizer.localizer.setLocaleChain(newLocales.concat(currentChain)); function changeHandler(event) { alert(event.localeChain); } La proprietà statica air.Localizer.ultimateFallbackLocale rappresenta l'impostazione locale utilizzata quando l'applicazione non supporta alcuna preferenza dell'utente. Il valore predefinito è "en". Potete impostarlo su un'altra impostazione locale, come illustrato nel codice seguente: air.Localizer.ultimateFallbackLocale = "fr"; Ottenimento di risorse per impostazioni locali specifiche Il metodo getString() dell'oggetto Localizer restituisce la stringa definita per una risorsa in un'impostazione locale specifica. Non è necessario specificare un valore locale quando si chiama il metodo. In tal caso, il metodo analizza l'intera catena delle impostazioni locali e restituisce la stringa nella prima impostazione locale che include il nome della risorsa specificato. Il metodo dispone dei parametri seguenti: Parametro Descrizione bundleName Il pacchetto che contiene la risorsa. È il nome file del file delle proprietà senza l'estensione .properties. Ad esempio, se questo parametro è impostato su "alerts", il codice di Localizer cerca nei file di localizzazione denominati alerts.properties. resourceName Il nome della risorsa. templateArgs Opzionale. Un array di stringhe per sostituire i tag numerati nella stringa di sostituzione. Considerate ad esempio una chiamata a una funzione con parametro templateArgs impostato su ["Raúl", "4"] e dove la stringa di risorsa corrispondente è "Hello, {0}. You have {1} new messages.". In tal caso, la funzione restituisce "Hello, Raúl. You have 4 new messages.". Per ignorare questa impostazione, passate un valore null. locale Opzionale. Il codice dell'impostazione locale (ad esempio "en", "en_us" o "fr") da utilizzare. Se viene specificata un'impostazione locale ma non viene trovato un valore corrispondente, il metodo non continua a cercare i valori in altre impostazioni locali della catena. Se non è specificato alcun codice di impostazione locale, la funzione restituisce la stringa nella prima impostazione locale della catena che include un valore per il nome della risorsa specificata. Il framework di localizzazione può aggiornare attributi HTML DOM contrassegnati. Tuttavia, è possibile utilizzare le stringhe localizzate in altri modi. Ad esempio, è possibile utilizzare una stringa in codice HTML generato dinamicamente o come valore di parametro in una chiamata di funzione. Ad esempio, il codice seguente chiama la funzione alert() con la stringa definita nella risorsa error114 del file delle proprietà predefinito dell'impostazione locale fr_FR: alert(air.Localizer.localizer.getString("default", "error114", null, "fr_FR")); SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 357 Localizzazione di applicazioni AIR Il metodo getString() invia un evento resourceNotFound quando non riesce a trovare una risorsa nel pacchetto specificato. La costante air.Localizer.RESOURCE_NOT_FOUND definisce la stringa "resourceNotFound". L'evento dispone di tre proprietà: bundleName, resourceName e locale. La proprietà bundleName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà resourceName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà locale corrisponde al nome dell'impostazione locale in cui non si trova la risorsa. Il metodo getString() invia un evento bundleNotFound quando non riesce a trovare il pacchetto specificato. La costante air.Localizer.BUNDLE_NOT_FOUND definisce la stringa "bundleNotFound". L'evento dispone di due proprietà: bundleName e locale. La proprietà bundleName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà locale corrisponde al nome dell'impostazione locale in cui non si trova la risorsa. Il metodo getString() opera in modo asincrono (e invia gli eventi resourceNotFound e resourceNotFound in modo asincrono). Il codice seguente imposta listener di eventi per gli eventi resourceNotFound e bundleNotFound: air.Localizerlocalizer.addEventListener(air.Localizer.RESOURCE_NOT_FOUND, rnfHandler); air.Localizerlocalizer.addEventListener(air.Localizer.BUNDLE_NOT_FOUND, bnfHandler); var str = air.Localizer.localizer.getString("default", "error114", null, "fr_FR"); function rnfHandler(event) { alert(event.bundleName + ": " + event.resourceName + ":." + event.locale); } function bnfHandler(event) { alert(event.bundleName + ":." + event.locale); } Il metodo getResourceBundle() dell'oggetto Localizer restituisce un pacchetto specifico per una determinata impostazione locale. Il valore restituito del metodo è un oggetto le cui proprietà corrispondono alle chiavi nel pacchetto. Se l'applicazione non è in grado di trovare il pacchetto specificato, il metodo restituisce null. Il metodo accetta due parametri: locale e bundleName. Parametro Descrizione locale L'impostazione locale (ad esempio "fr"). bundleName Il nome del pacchetto. Il codice riportato di seguito, ad esempio, chiama il metodo document.write() per caricare il pacchetto predefinito per l'impostazione locale fr. Chiama quindi il metodo document.write() per scrivere i valori delle chiavi str1 e str2 in tale pacchetto: var aboutWin = window.open(); var bundle = localizer.getResourceBundle("fr", "default"); aboutWin.document.write(bundle.str1); aboutWin.document.write("<br/>"); aboutWin.document.write(bundle.str2); aboutWin.document.write("<br/>"); Il metodo getResourceBundle() invia un evento bundleNotFound quando non riesce a trovare il pacchetto specificato. La costante air.Localizer.BUNDLE_NOT_FOUND definisce la stringa "bundleNotFound". L'evento dispone di due proprietà: bundleName e locale. La proprietà bundleName corrisponde al nome del pacchetto in cui non si trova la risorsa. La proprietà locale corrisponde al nome dell'impostazione locale in cui non si trova la risorsa. Il metodo getFile() dell'oggetto Localizer restituisce il contenuto di un pacchetto, come una stringa, per un'impostazione locale specifica. Il file di pacchetto viene letto come file UTF-8. Il metodo comprende i parametri seguenti: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 358 Localizzazione di applicazioni AIR Parametro Descrizione resourceFileName Il nome del file della risorsa (come "about.html"). templateArgs Opzionale. Un array di stringhe per sostituire i tag numerati nella stringa sostitutiva. Ad esempio, considerate di richiamare la funzione in cui il parametro templateArgs è ["Raúl", "4"]e la stringa di risorsa corrispondente contengano due righe: <html> <body>Hello, {0}. You have {1} new messages.</body> </html> In tal caso, la funzione restituisce una stringa con due righe: <html> <body>Hello, Raúl. You have 4 new messages. </body> </html> locale Il codice dell'impostazione locale, ad esempio "en_GB" da utilizzare. Se viene specificata un'impostazione locale ma non viene trovato un file corrispondente, il metodo non continua a cercare in altre impostazioni locali della catena. Se non viene specificato alcun codice di impostazione locale, la funzione restituisce il testo nella prima impostazione locale della catena che presenta un file corrispondente a resourceFileName. Ad esempio, il codice seguente chiama il metodo document.write() utilizzando il contenuto del file about.html dell'impostazione locale fr: var aboutWin = window.open(); var aboutHtml = localizer.getFile("about.html", null, "fr"); aboutWin.document.close(); aboutWin.document.write(aboutHtml); Il metodo getFile() invia un evento fileNotFound se non riesce a trovare una risorsa nella catena di impostazioni locali. La costante air.Localizer.FILE_NOT_FOUND definisce la stringa "resourceNotFound". Il metodo getFile() opera in modo asincrono (e invia l'evento fileNotFound in modo asincrono). L'evento ha due proprietà: fileName e locale. La proprietà fileName corrisponde al nome del file non trovato. La proprietà locale corrisponde al nome dell'impostazione locale in cui non si trova la risorsa. Il codice seguente imposta i listener di eventi per questo evento: air.Localizer.localizer.addEventListener(air.Localizer.FILE_NOT_FOUND, fnfHandler); air.Localizer.localizer.getFile("missing.html", null, "fr"); function fnfHandler(event) { alert(event.fileName + ": " + event.locale); } Localizzazione di date, ore e valute Il modo con cui le applicazioni presentano date, ore e valute varia notevolmente per ogni impostazione locale. Ad esempio, lo standard statunitense per indicare le date è mese/giorno/anno, mentre quello europeo è giorno/mese/anno. È possibile scrivere codice per formattare date, ore e valute. Ad esempio, il codice seguente converte un oggetto Date nel formato mese/giorno/anno o giorno/mese/anno. Se la variabile locale (che rappresenta l'impostazione locale) è impostata su "en_US", la funzione restituisce il formato mese/giorno/anno. L'esempio converte un oggetto Date nel formato giorno/mese/anno per tutte le altre impostazioni locali: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 359 Localizzazione di applicazioni AIR function convertDate(date) { if (locale == "en_US") { return (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear(); } else { return date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear(); } } 360 Capitolo 35: Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Gli strumenti della riga di comando di Adobe® AIR™ consentono di testare e di creare pacchetti di applicazioni Adobe AIR. È inoltre possibile utilizzare questi strumenti in processi di creazione automatici. Gli strumenti della riga di comando di AIR sono inclusi in AIR SDK (http://www.adobe.com/go/learn_air_download_AIRSDK_it). Utilizzo di ADL (AIR Debug Launcher) Con ADL (AIR Debug Launcher) potete eseguire nel corso dello sviluppo applicazioni basate sia su SWF che su HTML. Mediante ADL potrete eseguire un'applicazione senza prima effettuare la creazione del pacchetto e installarla. Per impostazione predefinita in ADL viene utilizzato un runtime incluso con SDK, pertanto per utilizzare ADL non occorrerà installare separatamente il runtime. ADL stampa istruzioni trace ed errori di runtime nell'output standard, ma non supporta punti di interruzione o altre funzionalità di debug. Se state sviluppando un'applicazione basata su SWF, per problemi di debug complessi utilizzate Flash Debugger (o Flash CS). Per connettervi a Flash Debugger, potete avviare il programma di debug prima di eseguire la vostra applicazione tramite ADL. Avvio di un'applicazione mediante ADL Utilizzate la sintassi seguente: adl [-runtime runtime-directory] [-pubid publisher-id] [-nodebug] application.xml [rootdirectory] [-- arguments] -runtime runtime-directory Specifica la directory contenente il runtime da utilizzare. Se non è specificata, viene utilizzata la directory di runtime nello stesso SDK in cui viene utilizzato il programma ADL. Se si sposta ADL fuori dalla relativa cartella SDK, sarà necessario specificare la directory di runtime. In Windows e Linux, specificate la directory contenente la directory Adobe AIR . In Mac OS X, specificate la directory contenente Adobe AIR.framework. -pubid publisher-id Assegna il valore specificato come ID editore dell'applicazione AIR per questa esecuzione. Specificando un ID editore temporaneo è possibile testare le funzionalità di un'applicazione AIR, ad esempio la comunicazione su una connessione locale, che utilizzano l'ID editore per l'identificazione univoca dell'applicazione. L'ID editore finale è determinato dal certificato digitale utilizzato per la firma del file di installazione di AIR. -nodebug Disattiva il supporto per il debug. Se utilizzata, il processo dell'applicazione non consente la connessione al debugger Flash e le finestre di dialogo per le eccezioni non gestite vengono eliminate. (Le istruzioni trace vengono comunque stampate nella finestra della console.) La disattivazione del debug consente di eseguire l'applicazione più rapidamente e di emulare più fedelmente la modalità di esecuzione di un'applicazione installata. application.xml Il file descrittore dell'applicazione. Consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 361 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando root-directory Specifica la directory principale dell'applicazione da eseguire. Se il valore non viene specificato, si utilizza la directory contenente il file descrittore dell'applicazione. -- arguments Qualsiasi stringa di caratteri che appare dopo "--" viene trasmessa all'applicazione come argomento della riga di comando. Nota: quando si avvia un'applicazione AIR già in esecuzione, non viene avviata una nuova istanza dell'applicazione, ma viene inviato un evento invoke all'istanza in esecuzione. Stampa di istruzioni trace Per stampare istruzioni trace nella console utilizzata per l'esecuzione di ADL, aggiungete le istruzioni trace al codice mediante la funzione trace(): trace("debug message"); air.trace("debug message"); Esempi ADL Eseguire un'applicazione nella directory corrente: adl myApp-app.xml Eseguire un'applicazione nella sottodirectory della directory corrente: adl source/myApp-app.xml release Eseguire un'applicazione e trasmettere due argomenti della riga di comando, "tick" e "tock": adl myApp-app.xml -- tick tock Eseguire un'applicazione utilizzando un runtime specifico: adl -runtime /AIRSDK/runtime myApp-app.xml Eseguire un'applicazione senza il supporto del debug: adl myApp-app.xml -nodebug Connessione a FDB (Flash Debugger) Per eseguire il debug di un'applicazione AIR basata su SWF mediante Flash Debugger, avviate una sessione FDB e quindi una versione di debug dell'applicazione. Un'applicazione AIR contenente una versione di debug di un file SWF si connette automaticamente a una sessione FDB in ascolto. Nota: in una versione di debug di un'applicazione AIR, il file SWF principale viene compilato con il flag -debug. 1 Avviate FDB. Il programma FDB si trova nella directory bin di Flex SDK. Nella console viene visualizzato il prompt FDB: <fdb> 2 Eseguite il comando run: <fdb>run [Invio] 3 In un diverso comando o console della shell, avviate una versione di debug dell'applicazione: adl myApp.xml 4 Utilizzando i comandi FDB, impostate i punti di interruzione come desiderato. 5 Digitate: continue [Invio] Se un'applicazione AIR è basata su SWF, il debugger controlla solamente l'esecuzione del codice ActionScript. Se l'applicazione AIR è basata su HTML, il debugger controlla solamente l'esecuzione del codice JavaScript. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 362 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Per eseguire ADL senza connettersi al debugger, includete l'opzione -nodebug: adl myApp.xml -nodebug Per informazioni di base sui comandi FDB, eseguite il comando help: <fdb>help [Enter] Per informazioni dettagliate sui comandi FDB, consultate Using the command-line debugger commands (Uso dei comandi del debugger della riga di comando) nella documentazione di Flex. Codici di errore e di uscita di ADL Nella tabella seguente vengono descritti i codici di uscita stampati da ADL: Codice di uscita Descrizione 0 Avvio riuscito. Viene effettuata l'uscita da ADL dopo l'uscita dall'applicazione AIR. 1 Chiamata riuscita di un'applicazione AIR già in esecuzione. Uscita immediata da ADL. 2 Errore di utilizzo. Gli argomenti forniti ad ADL non sono corretti. 3 Impossibile trovare il runtime. 4 Impossibile avviare il runtime. Spesso ciò accade perché il livello della patch o della versione specificati nell'applicazione non corrisponde al livello della patch o della versione del runtime. 5 Si è verificato un errore. Motivo sconosciuto. 6 Impossibile trovare il file descrittore dell'applicazione. 7 Il contenuto del descrittore dell'applicazione non è valido. Di solito quest'errore indica che il file XML non è stato formato correttamente. 8 Impossibile trovare il file del contenuto dell'applicazione principale (specificato nell'elemento <content> del file descrittore dell'applicazione). 9 Il file del contento dell'applicazione principale non è un file SWF o HTML valido. Creazione di un pacchetto di un file di installazione AIR mediante ADT (AIR Developer Tool) ADT (AIR Developer Tool) consente di creare un file di installazione AIR sia per le applicazioni basate su SWF che su quelle basate su HTML. Se per la creazione dell'applicazione si utilizza Flash CS3, per creare il pacchetto AIR è anche possibile utilizzare il comando per la creazione del file AIR nel menu Comandi. Per ulteriori informazioni, consultate “Aggiornamento Adobe AIR per Flash CS3 Professional” a pagina 14. Per informazioni sull'uso di Flash CS4 per creare applicazioni AIR, consultate Pubblicazione in Adobe AIR in Uso di Flash. ADT è un programma Java che è possibile eseguire dalla riga di comando o da uno strumento di creazione come ad esempio Ant. Gli SDK AIR e Flex includono gli script della riga di comando che eseguono il programma Java in vostra vece. Creazione del pacchetto di un file di installazione Per ciascuna applicazione AIR devono essere presenti, quanto meno, un file descrittore dell'applicazione e un file principale SWF o HTML. Qualsiasi altra risorsa dell'applicazione installata deve essere inclusa nel pacchetto del file AIR. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 363 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Tutti i file di installazione di AIR devono essere firmati mediante un certificato digitale. Il programma di installazione di AIR utilizza la firma per verificare che il file dell'applicazione non sia stato alterato dal momento in cui è stato firmato. Potete usare un certificato per la firma del codice rilasciato da un'autorità di certificazione oppure un certificato autofirmato. Un certificato rilasciato da un'autorità di certificazione attendibile offre agli utenti dell'applicazione una qualche garanzia dell'identità dell'editore. Non è possibile utilizzare un certificato autofirmato per verificare l'identità del firmatario. Questo svantaggio è anche un limite alla garanzia che il pacchetto non sia stato alterato, in quanto un file di installazione legittimo potrebbe essere sostituito da un falso prima che raggiunga l'utente. Per creare un pacchetto e firmare un file AIR in un unico passaggio, è possibile utilizzare il comando -package di ADT. È inoltre possibile creare un pacchetto intermedio, non firmato, mediante il comando -prepare, quindi firmarlo mediante il comando -sign in un passaggio separato. Quando si appone la firma sul pacchetto di installazione, ADT contatta automaticamente il server di un'autorità di indicazione di data e ora per la verifica dell'ora. Le informazioni di indicazione di data e ora vengono incluse nel file AIR. Un file AIR che include un'indicazione di data e ora verificata può essere installato in qualsiasi momento. Se ADT non è in grado di connettersi al server di indicazione di data e ora, la creazione del pacchetto viene annullata. È possibile ignorare l'opzione di indicazione di data e ora, ma senza un indicatore di data e ora un'applicazione AIR non è più installabile dopo che il certificato utilizzato per la firma del file di installazione è scaduto. Se si sta creando un pacchetto per aggiornare un'applicazione AIR esistente, il pacchetto deve essere firmato con lo stesso certificato dell'applicazione originale oppure con un certificato con la stessa identità. Per avere la stessa identità, due certificati devono disporre dello stesso nome distinto (tutti i campi di informazioni corrispondono) e la stessa catena di certificati al certificato principale. Pertanto, è possibile utilizzare un certificato rinnovato da un'autorità di certificazione purché non si modifichi alcuna informazione di identificazione. In AIR 1.1 è possibile migrare un'applicazione in modo che utilizzi un nuovo certificato mediante il comando migrate. La migrazione del certificato richiede la firma del file AIR mediante il nuovo e il vecchio certificato e consente di passare da un certificato autofirmato a un certificato commerciale per la firma del codice oppure da un certificato autofirmato o commerciale a un altro. Quando si effettua la migrazione di un certificato, non occorre che gli utenti disinstallino l'applicazione esistente prima di installare la nuova versione. Per impostazione predefinita le firme di migrazione presentano indicazioni di data e ora. Nota: le impostazioni nel file descrittore dell'applicazione determinano l'identità di un'applicazione AIR e il relativo percorso di installazione predefinito. Consultate “Struttura del file descrittore dell'applicazione” a pagina 46. Creazione di pacchetti e firma di un file AIR in un unico passaggio ❖ Utilizzate il comando -package con la sintassi seguente su un'unica riga di comando: adt -package SIGNING_OPTIONS air_file app_xml [file_or_dir | -C dir file_or_dir | -e file dir ...] ... SIGNING_OPTIONS: le opzioni di firma identificano l'archivio di chiavi contenente la chiave privata e il certificato utilizzato per firmare il file AIR. Per firmare un'applicazione AIR con un certificato autofirmato generato da ADT, le opzioni da utilizzare sono: SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 364 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando -storetype pkcs12 -keystore certificate.p12 Nel presente esempio, certificate.p12 è il nome del file archivio di chiavi. (ADT richiede la password dal momento che non viene fornita nella riga di comando). Le opzioni di firma sono descritte in maniera completa in “Opzioni di firma della riga di comando ADT” a pagina 368. air_file: il nome del file AIR creato. app_xml: il percorso al file descrittore dell'applicazione, specificato come percorso assoluto o come percorso relativo alla directory corrente. Il file descrittore dell'applicazione viene rinominato come “application.xml” nel file AIR. file_or_dir: i file e le directory da includere nel pacchetto del file AIR. È possibile specificare un numero qualsiasi di file e directory, delimitati da spazi vuoti. Se si elenca una directory, tutti i file e le sottodirectory inclusi, ad eccezione dei file nascosti, vengono aggiunti al pacchetto. Inoltre, se il file descrittore dell'applicazione viene specificato direttamente o attraverso l'espansione di directory o caratteri jolly, esso viene ignorato e non viene aggiunto al pacchetto una seconda volta. File e directory specificati devono trovarsi nella directory corrente o in una delle relative sottodirectory. Utilizzate l'opzione -C per cambiare la directory corrente. Importante: non è possibile utilizzare caratteri jolly negli argomenti file_or_dir che seguono l'opzione –C. Le shell comandi, infatti, espandono i caratteri jolly prima della trasmissione degli argomenti ad ADT, che pertanto cerca i file nella posizione sbagliata. È tuttavia possibile utilizzare il carattere punto, vale a dire ".", per indicare la directory corrente. Ad esempio, "-C assets ." copia tutto nella directory assets, incluse tutte le sottodirectory, nel livello principale del pacchetto dell'applicazione. -C dir Cambia la directory di lavoro nel valore di dir prima dell'elaborazione di directory e file successivi aggiunti al pacchetto dell'applicazione. File o directory vengono aggiunti alla radice del pacchetto dell'applicazione. L'opzione –C può essere utilizzata ogniqualvolta si desideri includere file da più punti nel file system. Se per dir viene specificato un percorso relativo, esso viene risolto dalla directory di lavoro originale. Quando ADT elabora i file e le directory incluse nel pacchetto, i percorsi relativi tra la directory corrente e i file di destinazione vengono archiviati. Questi percorsi vengono espansi nella directory dell'applicazione quando il pacchetto viene installato. Pertanto, se si specifica -C release/bin lib/feature.swf, il file release/bin/lib/feature.swf viene collocato nella sottodirectory lib della cartella principale dell'applicazione. -e file dir Colloca il file specificato nella directory del pacchetto specificata. Nota: l'elemento <content> del file descrittore dell'applicazione deve specificare la posizione finale del file principale dell'applicazione nella struttura di directory del pacchetto dell'applicazione. Esempi ADT Creare pacchetti di specifici file dell'applicazione nella directory corrente: adt –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf components.swc Creare pacchetti di tutti i file e sottodirectory nella directory di lavoro corrente: adt –package -storetype pkcs12 -keystore ../cert.p12 myApp.air myApp.xml . Nota: il file archivio di chiavi contiene la chiave privata impiegata per firmare l'applicazione. Non includete mai il certificato per la firma nel pacchetto AIR! Se sono stati utilizzati caratteri jolly nel comando ADT, collocate il file archivio di chiavi in una posizione differente, in modo che non venga incluso nel pacchetto. In questo esempio il file archivio di chiavi, cert.p12, risiede nella directory principale. Creare pacchetti solo dei file principali e di una sottodirectory images: adt –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf images SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 365 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Creare un pacchetto del file application.xml e del file SWF principale situato in una directory di lavoro (release/bin): adt –package -storetype pkcs12 -keystore cert.p12 myApp.air release/bin/myApp.xml –C release/bin myApp.swf Creare un pacchetto di risorse da più di una posizione del file system di creazione. In questo esempio, prima della creazione del pacchetto le risorse dell'applicazione sono situate nelle seguenti cartelle: /devRoot /myApp /release /bin myApp.xml myApp.swf /artwork /myApp /images image-1.png ... image-n.png /libraries /release /libs lib-1.swf ... lib-n.swf AIRAliases.js L'esecuzione del seguente comando ADT dalla directory /devRoot/myApp: adt –package -storetype pkcs12 -keystore cert.p12 myApp.air release/bin/myApp.xml –C release/bin myApp.swf –C ../artwork/myApp images –C ../libraries/release libs determina la seguente struttura di pacchetti: /myAppRoot /META-INF /AIR application.xml hash myApp.swf mimetype /images image-1.png ... image-n.png /libs lib-1.swf ... lib-n.swf AIRAliases.js Eseguire ADT come programma Java (senza impostare il percorso di classe): java –jar {AIRSDK}/lib/ADT.jar –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf Eseguire ADT come programma Java (con il percorso di classe Java impostato per includere il pacchetto ADT.jar): SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 366 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando java com.adobe.air.ADT –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf Messaggi di errore di ADT Nelle seguenti tabelle sono elencati i possibili errori segnalati dal programma ADT e le probabili cause: Errori di convalida del descrittore dell'applicazione Codice di errore Descrizione Note 100 Application descriptor cannot be parsed (Impossibile analizzare il descrittore dell'applicazione) Verificate che il file descrittore dell'applicazione non contenga errori di sintassi XML, ad esempio tag non chiusi. 101 Namespace is missing (Spazio dei nomi mancante) Aggiungete lo spazio dei nomi mancante. 102 Invalid namespace (Spazio dei nomi non valido) Verificate l'ortografia dello spazio dei nomi. 103 Unexpected element or attribute (Elemento o attributo imprevisto) Rimuovete gli elementi e gli attributi errati. Nel file descrittore non sono consentiti valori personalizzati. Verificate l'ortografia dei nomi di elementi e di attributi. Assicuratevi che gli elementi siano inseriti nell'elemento principale corretto e che gli attributi siano usati con gli elementi corretti. 104 Missing element or attribute (Elemento o attributo mancante) Aggiungete l'elemento o l'attributo richiesto. 105 Element or attribute contains an invalid Correggete il valore errato. value (L'elemento o l'attributo contiene un valore non valido) 106 Illegal window attribute combination (Combinazione di attributi della finestra non valida) Alcune impostazioni delle finestra, ad esempio transparency = true e systemChrome = standard non possono essere usate insieme. Modificate una delle impostazioni incompatibili. 107 Window minimum size is larger than the window maximum size (Le dimensioni minime della finestra sono maggiori delle dimensioni massime) Modificate l'impostazione delle dimensioni minime o massime. Per informazioni su spazi dei nomi, elementi, attributi e relativi valori validi, consultate “Impostazione delle proprietà dell'applicazione AIR” a pagina 46. Errori relativi all'icona dell'applicazione SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 367 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Codice di errore Descrizione Note 200 Verificate che il file sia presente nel percorso specificato. Icon file cannot be opened (Impossibile aprire il file di icona) Usate un'altra applicazione per accertarvi che il file possa essere aperto. 201 Icon is the wrong size (Dimensioni dell'icona errate) Le dimensioni in pixel dell'icona devono corrispondere al tag XML. Dato, ad esempio l'elemento del descrittore dell'applicazione: <image32x32>icon.png</image32x3 2> Le dimensioni dell'immagine in icon.png devono essere esattamente 32x32 pixel. 202 Icon file contains an unsupported image format (Il file di icona contiene un formato di immagine non supportato) È supportato solo il formato PNG. Convertite le immagini in altri formati prima di creare il pacchetto dell'applicazione. Errori relativi al file dell'applicazione Codice di errore Descrizione Note 300 Missing file, or file cannot be opened (File mancante o impossibile aprirlo) Non è possibile individuare o aprire un file specificato nella riga di comando. 301 Application descriptor file missing or cannot be opened (File del descrittore dell'applicazione mancante o impossibile aprirlo) Non è possibile individuare il file del descrittore dell'applicazione nel percorso specificato oppure non è possibile aprirlo. 302 Root content file missing from package Il file SWF o HTML a cui fa riferimento (File del contenuto principale mancante dal l'elemento <content> del descrittore dell'applicazione deve essere aggiunto al pacchetto) pacchetto, includendolo nei file elencati nella riga di comando di ADT. 303 Icon file missing from package (File di icona Il file di icona specificati nel descrittore mancante dal pacchetto) dell'applicazione devono essere aggiunto al pacchetto, includendoli nei file elencati nella riga di comando di ADT. I file di icona non vengono aggiunti automaticamente. 304 Initial window content is invalid (Il contenuto della finestra iniziale non è valido) Il file a cui fa riferimento l'elemento <content> del descrittore dell'applicazione non viene riconosciuto come file HTML o SWF valido. 305 Initial window content SWF version exceeds namespace version (La versione SWF del contenuto della finestra iniziale è maggiore della versione dello spazio dei nomi) La versione SWF del file a cui fa riferimento l'elemento <content> del descrittore dell'applicazione non è supportata dalla versione di AIR specificata nello spazio dei nomi del descrittore. Questo errore viene generato, ad esempio, se tentate di includere in un pacchetto un file SWF10 (Flash Player 10) come contenuto iniziale di un'applicazione AIR 1.1. Codici di uscita per altri errori SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 368 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Codice di uscita Descrizione Note 2 Usage error (Errore di utilizzo) Verificate se gli argomenti della riga di comando contengono errori. 5 Unknown error (Errore sconosciuto) Questo errore indica una situazione che non può essere spiegata con le comuni condizioni di errore. Le possibili cause principali di questo errore comprendono: incompatibilità tra ADT e Java Runtime Environment, installazioni di ADT o JRE danneggiate ed errori di programmazione all'interno di ADT. 6 Could not write to output directory (Impossibile scrivere nella directory di output) Accertatevi che la directory di output specificata (o implicita) sia accessibile e che sull'unità che la contiene sia disponibile spazio su disco sufficiente. 7 Could not access certificate (Impossibile accedere al certificato) Accertatevi che il percorso dell'archivio di chiavi sia specificato correttamente. Controllate che il certificato nell'archivio di chiavi sia accessibile. Per facilitare la risoluzione dei problemi di accesso ai certificati, potete usare l'utilità Java 1.6 Keytool. 8 Invalid certificate (Certificato non valido) Il file di certificato non è strutturato correttamente, è scaduto o è stato modificato o revocato. 9 Could not sign AIR file (Impossibile firmare il file AIR) Verificate le opzioni di firma passate ad ADT. 10 Could not create time stamp (Impossibile creare l'indicatore di data e ora) ADT non è stato in grado di stabilire una connessione al server degli indicatori di data e ora. Se vi connettete a Internet tramite un server proxy, potreste dover configurare le impostazioni del proxy JRE. 11 Certificate creation error (Errore durante la creazione del certificato) Verificate gli argomenti della riga di comando usati per creare le firme. 12 Invalid input (Input non valido) Verificate i percorsi dei file e gli altri argomenti passati ad ADT nella riga di comando. Opzioni di firma della riga di comando ADT ADT utilizza JCA (Java Cryptography Architecture) per accedere alle chiavi private e ai certificati per la firma di applicazioni AIR. Le opzioni di firma identificano l'archivio di chiavi nonché il certificato e la chiave privata all'interno di quell'archivio. L'archivio di chiavi deve includere sia la chiave privata che la catena di certificati associata. Quest'ultima viene utilizzata per stabilire l'ID editore per l'applicazione. Se il certificato per la firma è concatenato a un certificato attendibile presente su un computer, il nome comune del certificato viene visualizzato come nome editore della finestra di dialogo di installazione di AIR. ADT richiede che il certificato sia conforme allo standard x509v3 (RFC3280) e includa l'estensione Extended Key Usage con valori appropriati per la firma del codice. I limiti all'interno del certificato vengono rispettati e possono precludere l'utilizzo di alcuni certificati per la firma di applicazioni AIR. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 369 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Nota: se appropriate, ADT utilizza le impostazioni proxy dell'ambiente di runtime Java per connettersi alle risorse Internet e verificare gli elenchi di revoca dei certificati e ottenere indicatori di data e ora. Se si incontrano problemi nella connessione a risorse Internet quando si utilizza ADT e la rete richiede impostazioni proxy specifiche, può essere necessario configurare le impostazioni proxy JRE. Specifica di opzioni di firma AIR ❖ Per specificare le opzioni di firma ADT per i comandi -package e -prepare, utilizzate la sintassi seguente: [-alias aliasName] [-storetype type] [-keystore path] [-storepass password1] [-keypass password2] [-providerName className] [-tsa url] -alias aliasName: l'alias di una chiave nell'archivio di chiavi. Se un archivio di chiavi contiene un solo certificato, non è necessario specificare un alias. Quando non è specificato alcun alias, ADT utilizza la prima chiave dell'archivio. Non tutte le applicazioni di gestione dell'archivio di chiavi consentono l'assegnazione di un alias ai certificati. Quando si utilizza l'archivio di chiavi di sistema di Windows, ad esempio, utilizzate come alias il nome distinto del certificato. L'utilità Java Keytool consente di elencare i certificati disponibili in modo che sia possibile determinare l'alias. Ad esempio, l'esecuzione del comando: keytool -list -storetype Windows-MY genera un output analogo al seguente per un certificato: CN=TestingCert,OU=QE,O=Adobe,C=US, PrivateKeyEntry, Certificate fingerprint (MD5): 73:D5:21:E9:8A:28:0A:AB:FD:1D:11:EA:BB:A7:55:88 Per fare riferimento a questo certificato sulla riga di comando di ADT, impostate l'alias su: CN=TestingCert,OU=QE,O=Adobe,C=US In Mac OS X, l'alias di un certificato nel portachiavi corrisponde al nome visualizzato nell'applicazione Accesso portachiavi. -storetype type: il tipo di archivio di chiavi, determinato dall'implementazione dell'archivio di chiavi. L'implementazione dell'archivio di chiavi predefinita inclusa con la maggior parte delle installazioni di Java supporta i tipi JKS e PKCS12. Java 5.0 include il supporto per il tipo PKCS11 per l'accesso agli archivi di chiavi sui token hardware, e il tipo Keychain, per l'accesso al portachiavi di Mac OS X. Java 6.0 include il supporto per il tipo MSCAPI (in Windows). Se sono stati installati e configurati altri provider JCA, potrebbero essere disponibili ulteriori tipi di archivi di chiavi. Se non è stato specificato alcun tipo di archivio di chiavi, viene utilizzato il tipo predefinito per il provider JCA predefinito. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 370 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Tipo di archivio Formato dell'archivio di chiavi Versione minima di Java JKS File dell'archivio di chiavi Java (keystore) 1.2 PKCS12 File PKCS12 (.p12 o .pfx) 1.4 PKCS11 Token hardware 1.5 KeychainStore Portachiavi Mac OS X 1.5 Windows-MY o Windows-ROOT MSCAPI 1.6 -keystore path: il percorso al file dell'archivio di chiavi per tipi di archivi basati su file. -storepass password1: la password necessaria per accedere all'archivio di chiavi. Se non viene specificata, ADT richiede la password. -keypass password2: la password necessaria per accedere alla chiave privata utilizzata per firmare l'applicazione AIR. Se non viene specificata, ADT richiede la password. -providerName className: il provider JCA per il tipo di archivio di chiavi specificato. Se il valore non viene specificato, ADT utilizza il provider predefinito per quel tipo di archivio di chiavi. -tsa url: specifica l'URL di un server di indicatori di data e ora conforme a RFC3161 per applicare l'indicazione di data e ora alla firma digitale. Se non viene specificato alcun URL, viene utilizzato un server di indicatori data e ora fornito da Geotrust. Quando alla firma di un'applicazione AIR vengono aggiunte indicazioni di data e ora, è possibile installare l'applicazione anche dopo che il certificato è scaduto, in quanto l'indicatore di data e ora verifica che il certificato era valido al momento della firma. Se ADT non è in grado di connettersi al server di indicazione di data e ora, la firma viene annullata e non è possibile produrre alcun pacchetto. Per disattivare l'aggiunta di indicatori di date e ora, specificate -tsa none. Un'applicazione AIR inserita in un pacchetto senza un indicatore di data e ora, tuttavia, non è più installabile dopo la scadenza del certificato per la firma. Nota: le opzioni di firma sono come le opzioni equivalenti dell'utilità Java Keytool. È possibile utilizzare l'utilità Keytool per esaminare e gestire archivi di chiavi su Windows. Allo stesso scopo, su Mac OS X può utilizzare l'utilità di sicurezza Apple®. Esempi di opzioni di firma Firma mediante un file p12: -storetype pkcs12 -keystore cert.p12 Firma mediante l'archivio di chiavi Java predefinito: -alias AIRcert -storetype jks Firma mediante uno specifico archivio di chiavi Java: -alias AIRcert -storetype jks -keystore certStore.keystore Firma mediante il portachiavi Mac OS X: -alias AIRcert -storetype KeychainStore -providerName Apple Firma mediante l'archivio di chiavi di sistema di Windows: -alias cn=AIRCert -storeype Windows-MY SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 371 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Firma mediante un token hardware (consultate le istruzioni del produttore del token sulla configurazione di Java per l'utilizzo del token e per il valore corretto di providerName): -alias AIRCert -storetype pkcs11 -providerName tokenProviderName Firma senza incorporare un indicatore di data e ora: -storetype pkcs12 -keystore cert.p12 -tsa none Creazione di un file AIR intermedio non firmato mediante ADT Il comando -prepare consente di creare un file AIR intermedio non firmato, che è necessario firmare mediante il comando -sign ADT per produrre un file di installazione AIR valido. Il comando -prepare utilizza gli stessi flag e parametri del comando -package, ad eccezione delle opzioni di firma. L'unica differenza è che il file di output non è firmato. Il file intermedio è generato mediante l'estensione del nome file: airi. Per firmare un file AIR intermedio, utilizzate il comando -sign di ADT (consultate Firma di un file AIR intermedio mediante ADT). Esempio di ADT adt –prepare unsignedMyApp.airi myApp.xml myApp.swf components.swc Firma di un file AIR intermedio mediante ADT Per firmare un file AIR intermedio mediante ADT, utilizzate il comando -sign. Il comando di firma funziona solo con file AIR intermedi (estensione airi). Non è possibile firmare un file AIR una seconda volta. Per creare un file AIR intermedio, utilizzate il comando adt -prepare (consultate “Creazione di un file AIR intermedio non firmato mediante ADT” a pagina 371). Firmare un file AIRI ❖ Utilizzate il comando ADT -sign con la seguente sintassi: adt -sign SIGNING_OPTIONSairi_fileair_file SIGNING_OPTIONS: le opzioni di firma identificano la chiave privata e il certificato da utilizzare per firmare il file AIR. Queste opzioni sono descritte in “Opzioni di firma della riga di comando ADT” a pagina 368. airi_file: il percorso al file AIR intermedio non firmato da firmare. air_file: il nome del file AIR da creare. Esempio di ADT adt –sign -storetype pkcs12 -keystore cert.p12 unsignedMyApp.airi myApp.air Per ulteriori informazioni, consultate “Firma digitale di un file AIR” a pagina 325. Firma di un file AIR per la modifica del certificato dell'applicazione Per aggiornare un'applicazione AIR esistente in modo che utilizzi un nuovo certificato per la firma, utilizzate il comando -migrate ADT. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 372 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando La migrazione dei certificati può essere utile nelle seguenti situazioni: • Aggiornamento da un certificato autofirmato a un certificato rilasciato da un'autorità di certificazione • Passaggio da un certificato autofirmato sul punto di scadere a un nuovo certificato autofirmato • Passaggio da un certificato commerciale a un altro, ad esempio in caso di modifica della ragione sociale Per poter applicare una firma di migrazione, il certificato originale deve essere comunque valido. Dopo che il certificato è scaduto, non è possibile applicare una firma di migrazione. Gli utenti dell'applicazione dovranno disinstallare la versione esistente prima di poter installare quella aggiornata. Va notato che per impostazione predefinita la firma di migrazione è provvista di indicazione di data e ora, pertanto gli aggiornamenti AIR firmati mediante una firma di migrazione restano validi anche dopo che il certificato è scaduto. Nota: in genere, quando si rinnova un certificato rilasciato per uso commerciale, non è necessario eseguirne la migrazione. Un certificato rinnovato conserva la stessa identità dell'editore dell'originale, a meno che il nome distinto non sia stato modificato. Per un elenco completo degli attributi dei certificati utilizzati per determinare il nome distinto, consultate “Informazioni sugli identificatori di editori AIR” a pagina 326. Per migrare l'applicazione per utilizzare un nuovo certificato: 1 Create un aggiornamento dell'applicazione 2 Create un pacchetto e firmate il file di aggiornamento di AIR con il nuovo certificato. 3 Firmate nuovamente il file AIR con il certificato originale, mediante il comando -migrate. Un file AIR firmato mediante il comando -migrate può essere utilizzato sia per installare una nuova versione dell'applicazione che per aggiornare le versioni precedenti, incluse quelle firmate con il vecchio certificato. Migrare un'applicazione AIR per utilizzare un nuovo certificato ❖ Utilizzate il comando ADT -migrate con la seguente sintassi: adt -migrate SIGNING_OPTIONS air_file_in air_file_out SIGNING_OPTIONS: le opzioni di firma identificano la chiave privata e il certificato da utilizzare per firmare il file AIR. Queste opzioni devono identificare il certificato per la firma originale e sono descritte in “Opzioni di firma della riga di comando ADT” a pagina 368. air_file_in: il file AIR per l'aggiornamento, firmato mediante il nuovo certificato. air_file_out: il file AIR da creare. Esempio ADT adt –migrate -storetype pkcs12 -keystore cert.p12 myApp.air myApp.air Per ulteriori informazioni, consultate “Firma digitale di un file AIR” a pagina 325. Nota: il comando -migrate è stato aggiunto a ADT nella versione AIR 1.1. Creazione di un certificato autofirmato mediante ADT I certificati autofirmati consentono di produrre un file di installazione AIR valido, ma forniscono solo garanzie di sicurezza limitate dal momento che l'autenticità dei certificati autofirmati non può essere verificata. Quando viene installato un file AIR autofirmato, le informazioni sull'editore vengono visualizzate dall'utente come Sconosciuto. Un certificato generato da ADT è valido per cinque anni. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 373 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Se si crea un aggiornamento per un'applicazione AIR che era stata firmata mediante un certificato autofirmato, è necessario utilizzare lo stesso certificato per firmare entrambi i file AIR, originale e aggiornamento. I certificati prodotti da ADT sono sempre unici, anche se vengono utilizzati gli stessi parametri. Pertanto, se desiderate autofirmare gli aggiornamenti con un certificato generato da ADT, conservate il certificato originale in una posizione sicura. Inoltre, dopo che il certificato originale generato ADT è scaduto, non sarà possibile produrre un file AIR aggiornato, quindi potrete pubblicare nuove applicazioni con un certificato diverso, ma non nuove versioni della stessa applicazione. Importante: a causa delle limitazioni dei certificati autofirmati, per la firma di applicazioni AIR rilasciate pubblicamente Adobe consiglia di utilizzare un certificato commerciale rilasciato da un'autorità di certificazione considerata attendibile. Il certificato e la chiave privata associata generata da ADT sono memorizzati in un file archivio di chiavi di tipo PKCS12. La password specificata è impostata sulla chiave stessa, non sull'archivio di chiavi. Generazione di un certificato di ID digitale per la firma automatica di file AIR ❖ Utilizzate il comando -certificate su un'unica riga di comando: adt -certificate -cn name [-ou org_unit][-o org_name][-c country] key_type pfx_file password -cn name: la stringa assegnata al nome comune del nuovo certificato. -ou org_unit: una stringa assegnata come unità organizzativa che rilascia il certificato. (Opzionale). -o org_name: una stringa assegnata come organizzazione che rilascia il certificato. (Opzionale). -c country: un codice Paese di due lettere, in base allo standard ISO-3166. Se viene fornito un codice non valido, il certificato non viene generato. (Opzionale). key_type: il tipo di chiave da utilizzare per un certificato, “1024-RSA” o “2048-RSA”. pfx_file: il percorso per il file di certificato da generare. password: la password per il nuovo certificato. La password è obbligatoria per firmare i file AIR mediante questo certificato. Esempi di creazione di certificati adt -certificate -cn SelfSign -ou QE -o "Example, Co" -c US 2048-RSA newcert.p12 39#wnetx3tl adt -certificate -cn ADigitalID 1024-RSA SigningCert.p12 39#wnetx3tl Per firmare i file AIR mediante questi certificati, si utilizzano le seguenti opzioni di firma mediante i comandi package o -prepare di ADT: -storetype pkcs12 -keystore newcert.p12 -keypass 39#wnetx3tl -storetype pkcs12 -keystore SigningCert.p12 -keypass 39#wnetx3tl Utilizzo di Apache Ant con gli strumenti SDK Nel presente argomento vengono forniti esempi di utilizzo dello strumento Apache Ant per il testing e la creazione di pacchetti di applicazioni AIR. Nota: questa trattazione non intende tuttavia fornire una descrizione completa di Apache Ant. Per una documentazione su Ant, consultate il sito http://Ant.Apache.org. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 374 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Utilizzo di Ant per progetti semplici In questo esempio viene illustrata la generazione di un'applicazione AIR mediante Ant e gli strumenti della riga di comando. Viene utilizzata una struttura di progetto semplice, con tutti i file archiviati in un'unica directory. Per semplificare il riutilizzo dello script di generazione, in questi esempi vengono impiegate diverse proprietà definite. Un insieme di proprietà identifica le posizioni di installazione degli strumenti della riga di comando. <property name="SDK_HOME" value="C:/Flex3SDK"/> <property name="ADL" value="${SDK_HOME}/bin/adl.exe"/> <property name="ADT.JAR" value="${SDK_HOME}/lib/adt.jar"/> Il secondo insieme di proprietà è invece specifico del progetto. Per le proprietà si presuppone una convenzione di denominazione in cui i file AIR e il descrittore dell'applicazione sono denominati in base al file d'origine principale. Altre convenzioni sono supportate senza difficoltà. <property <property <property <property <property <property name="APP_NAME" value="ExampleApplication"/> name="APP_ROOT" value="."/> name="APP_DESCRIPTOR" value="${APP_ROOT}/${APP_NAME}-app.xml"/> name="AIR_NAME" value="${APP_NAME}.air"/> name="STORETYPE" value="pkcs12"/> name="KEYSTORE" value="ExampleCert.p12"/> Chiamata ad ADL per il test di un'applicazione Per eseguire l'applicazione con ADL, utilizzate un'attività exec: <target name="test" depends="compile"> <target name="test"> <exec executable="${ADL}"> <arg value="${APP_DESCRIPTOR}"/> </exec> </target> Chiamata ad ADL per la creazione di un pacchetto di un'applicazione Per creare un pacchetto dell'applicazione, utilizzate un'attività Java per eseguire lo strumento adt.jar: <target name="package"> <java jar="${ADT.JAR}" fork="true" failonerror="true"> <arg value="-package"/> <arg value="-storetype"/> <arg value="${STORETYPE}"/> <arg value="-keystore"/> <arg value="${KEYSTORE}"/> <arg value="${AIR_NAME}"/> <arg value="${APP_DESCRIPTOR}"/> <arg value="${APP_NAME}.swf"/> <arg value="*.png"/> </java> </target> Se l'applicazione dispone di più file da includere nel pacchetto, è possibile aggiungere elementi <arg> aggiuntivi. Utilizzo di Ant per progetti più complessi La struttura di directory di un'applicazione tipica è più complessa di una directory unica. Nell'esempio seguente viene illustrato un file di generazione utilizzato per la compilazione, il testing e la creazione di pacchetti di un'applicazione AIR con una struttura di directory del progetto più pratica. SVILUPPO DI APPLICAZIONI ADOBE AIR 1.5 CON ADOBE FLASH CS4 PROFESSIONAL 375 Creazione di un'applicazione AIR mediante gli strumenti della riga di comando Per questo progetto campione i file di origine dell'applicazione e altre risorse come i file di icona vengono archiviati in una directory src. Lo script di generazione crea le seguenti directory di lavoro: build Archivia le versioni di release (non di debug) dei file SWF compilati. debug Archivia una versione di debug non inclusa nel pacchetto dell'applicazione, che comprende tutti i file di risorse ed SWF compilati. L'utilità ADL esegue l'applicazione da questa directory. release Archivia il pacchetto AIR finale Gli strumenti AIR richiedono l'impiego di alcune opzioni aggiuntive quando si lavora con file esterni alla directory di lavoro corrente: Testing Il secondo argomento trasmesso ad ADL specifica la directory principale dell'applicazione AIR. Per specificare la directory principale dell'applicazione, all'attività di testing viene aggiunta la seguente riga: <arg value="${debug}"/> Creazione di pacchetti Per la creazione di pacchetti file da sottodirectory che non dovrebbero appartenere alla struttura del pacchetto finale occorre utilizzare la direttiva -C per cambiare la directory di lavoro ADT. Quando si utilizza la direttiva -C, i file e le directory della nuova directory di lavoro vengono copiati nel livello principale del file di pacchetto AIR. Pertanto, -C build file.png copia file.png nella directory principale dell'applicazione. Analogamente, -C assets icons copia la cartella delle icone nel livello principale, quindi copia anche tutti i file e le directory in essa contenuti. La sequenza seguente di righe nell'attività del pacchetto, ad esempio, aggiunge la directory icons direttamente nel livello principale del file del pacchetto dell'applicazione: <arg value="-C"/> <arg value="${assets}"/> <arg value="icons"/> Nota: se è necessario spostare molte risorse in diversi percorsi relativi, solitamente è più facile smistarle in una directory temporanea mediante attività Ant anziché generare un elenco complesso di argomenti per ADT. Dopo che le ris