Télécharger le PDF de l`aide
Transcription
Télécharger le PDF de l`aide
Développement d’applications ADOBE AIR 1.5 avec ADOBE FLASH CS4 PROFESSIONAL ® ® ® ™ © 2008 Adobe Systems Incorporated. Tous droits réservés. Copyright Développement d'applications Adobe® AIR™ 1.5 avec Adobe® Flash® CS4 Si le présent guide est fourni avec un logiciel régi par un contrat d'utilisateur final, ce guide ainsi que le logiciel qui y est décrit, sont fournis sous licence et peuvent être utilisés ou copiés uniquement en conformité avec les conditions de cette licence. Sauf indication expresse dans le contrat de licence, aucune partie de ce guide ne peut être reproduite, stockée dans un système d'extraction ni transmise de quelque manière que soit, électronique, mécanique, par enregistrement ou autre, sans l'accord écrit préalable d'Adobe Systems Incorporated. Il est important de noter que le contenu du présent guide est protégé par la loi sur les droits d'auteur, même s'il n'est pas distribué avec un logiciel régi par un contrat de licence d'utilisateur final. Le contenu de ce guide est fourni à titre d'information uniquement ; il peut faire l'objet de modifications sans préavis et ne saurait être considéré comme un engagement quelconque de la part d'Adobe Systems Incorporated. Adobe Systems Incorporated décline toute responsabilité quant aux erreurs ou imprécisions susceptibles d'apparaître dans les informations que présente ce guide. Il est important de rappeler que certaines illustrations ou images que vous souhaitez inclure dans votre projet peuvent être protégées par les lois de copyright. L'inclusion sans autorisation de tels éléments dans vos propres travaux peut porter atteinte aux droits du détenteur de ce copyright. Veillez à obtenir toutes les autorisations nécessaires auprès de ce dernier. Toute référence à des noms de sociétés ou de personnes dans les modèles types n'est utilisée qu'à titre d'exemple et ne fait référence à aucune société ou personne réelle. 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 Sommaire Chapitre 1 : Installation d'Adobe AIR Installation d'Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Désinstallation d'Adobe AIR ........................................................................................... 2 Installation et exécution des exemples d'application AIR ................................................................ 2 Chapitre 2 : Configuration de Flash CS3 pour Adobe AIR Configuration requise pour la mise à jour Adobe AIR pour Flash CS3 Installation de la mise à jour Adobe Air pour Flash CS3 Retrait de la mise à jour Adobe Air pour Flash CS3 Ajouts AIR à Flash CS3 .................................................... 3 .................................................................. 3 ...................................................................... 4 ................................................................................................. 4 Chapitre 3 : Présentation d'Adobe AIR Nouveautés d'AIR 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Nouveautés d'AIR 1.5 .................................................................................................. 8 Chapitre 4 : Recherche des ressources AIR Chapitre 5 : Création de votre première application AIR avec Flash CS3 ou CS4 Création de l'application Hello World dans Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Test de l'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Conversion d'un fichier FLA en application Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Chapitre 6 : Mise à jour Adobe AIR pour Flash CS3 Professional Création d'un fichier Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Définition des paramètres de publication d'Adobe AIR Aperçu d'une application Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Débogage d'une application Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Création d'une application AIR et de ses fichiers d'installation Création d'un fichier descripteur d'application personnalisé Signature de votre application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Chapitre 7 : Sécurité AIR Principes de sécurité AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Installation et mises à jour Sandbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Sécurité HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Programmation entre contenus de différents domaines Ecriture sur les disques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Utilisation sécurisée d'un contenu non approuvé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Recommandations destinées aux développeurs en matière de sécurité Signature du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Chapitre 8 : Définition des propriétés d'une application AIR Structure du fichier descripteur d'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Définition des propriétés dans le fichier descripteur d'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL iv Sommaire Chapitre 9 : Fonctionnalités propres à Adobe AIR Classes propres à AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Classes d'exécution dotées de fonctionnalités propres à AIR Classes de structure pour la surveillance de services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Chapitre 10 : Utilisation des fenêtres natives Informations complémentaires en ligne sur les fenêtres natives Principes de base des fenêtres dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Création de fenêtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Gestion des fenêtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Ecoute des événements d'une fenêtre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Affichage des fenêtres en mode plein écran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Chapitre 11 : Ecrans Informations complémentaires en ligne sur les écrans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Principes de base des écrans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Dénombrement des écrans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Chapitre 12 : Utilisation de menus natifs Informations complémentaires en ligne sur les menus natifs Principes de base des menus AIR Création de menus natifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Présentation des menus contextuels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Présentation des menus contextuels dans HTML Définition des menus natifs par déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Affichage de menus en incrustation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Gestion des événements de menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Exemple : menu de fenêtre et d'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Chapitre 13 : Icônes de la barre des tâches Informations complémentaires en ligne sur les icônes de la barre des tâches A propos des icônes de la barre des tâches Icônes du Dock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Icônes de la barre d'état système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Icônes et boutons de la barre des tâches de la fenêtre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Chapitre 14 : Utilisation du système de fichiers Informations complémentaires en ligne sur l'API de fichiers d'AIR Principes de base des classes File d'AIR Utilisation des objets File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Obtention d'informations sur le système de fichiers Utilisation de répertoires Utilisation des fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Lecture et écriture de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Chapitre 15 : Opération glisser-déposer Informations complémentaires en ligne sur l'opération glisser-déposer Principes de base de l'opération glisser-déposer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL v Sommaire Prise en charge du mouvement de glissement vers l'extérieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Prise en charge du mouvement de glissement vers l'intérieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Evénements glisser-déposer HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Chapitre 16 : Opération copier-coller Informations complémentaires en ligne sur l'opération copier-coller Opération copier-coller dans l'environnement HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Commandes de menu et frappes pour l'opération copier-coller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Chapitre 17 : Utilisation de tableaux d'octets Lecture et écriture d'un objet ByteArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Exemple ByteArray : lecture d'un fichier .zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Chapitre 18 : Utilisation des bases de données SQL locales Informations complémentaires en ligne sur les bases de données SQL locales A propos des bases de données SQL locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Création et modification d'une base de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Manipulation des données de bases de données SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Utilisation des opérations de base de données synchrones et asynchrones Utilisation du chiffrement avec les bases de données SQL Stratégies d'utilisation des bases de données SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Chapitre 19 : Stockage des données chiffrées Chapitre 20 : A propos de l'environnement HTML Présentation de l'environnement HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 AIR et extensions Webkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Chapitre 21 : Programmation en HTML et JavaScript A propos de la classe HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Contournement des erreurs JavaScript liées à la sécurité Accès aux classes de l'API AIR à partir de JavaScript A propos des URL dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Mise des objets ActionScript à disposition de JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Accès au DOM HTML et aux objets JavaScript à partir d'ActionScript Intégration d'un contenu SWF en HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Utilisation des bibliothèques ActionScript au sein d'une page HTML Conversion des objets Date et RegExp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Manipulation d'une feuille de style HTML à partir d'ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Programmation croisée du contenu dans des sandbox de sécurité distincts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 Chapitre 22 : Gestion des événements HTML Evénements HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Gestion des événements DOM avec ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Réponse aux exceptions JavaScript non interceptées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Gestion des événements d'exécution avec JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL vi Sommaire Chapitre 23 : Programmation du conteneur HTML Affichage des propriétés des objets HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Défilement du contenu HTML Accès à l'historique de HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Paramétrage de l'agent d'utilisateur employé lors du chargement du contenu HTML Paramétrage du codage des caractères à utiliser pour le contenu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Paramétrage des interfaces utilisateur de type navigateur pour un contenu HTML Création de sous-classes de la classe HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Chapitre 24 : Ajout de contenu PDF Détection des capacités PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Chargement du contenu PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Programmation du contenu PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Limites connues pour du contenu PDF dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 Chapitre 25 : Utilisation de la gestion des droits d'auteur numériques (DRM) Informations complémentaires en ligne sur la gestion des droits numériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Présentation du flux de travail associé aux fichiers FLV chiffrés Membres et événements DRM de la classe NetStream Utilisation de la classe DRMStatusEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 Utilisation de la classe DRMAuthenticateEvent Utilisation de la classe DRMErrorEvent Utilisation de la classe DRMManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 Utilisation de la classe DRMContentData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 Chapitre 26 : Lancement d'applications et options de fermeture Appel d'une application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Capture des arguments de ligne de commande Lancement lors de la connexion Appel du navigateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 Fermeture d'une application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Chapitre 27 : Lecture des paramètres de l'application Lecture du fichier descripteur d'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Lecture des identifiants d'application et d'éditeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Chapitre 28 : Utilisation des informations sur le moteur d'exécution et les systèmes d'exploitation Gestion des associations de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Lecture de la version du moteur d'exécution et du correctif Détection des capacités d'AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Suivi de la présence des utilisateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Chapitre 29 : Surveillance de la connectivité réseau Détection des changements apportés à la connectivité réseau Principes de base de la surveillance des services Détection de la connectivité HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Détection de la connectivité des sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL vii Sommaire Chapitre 30 : Requêtes d'URL et mise en réseau Utilisation de la classe URLRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 Modifications de la classe URLStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Ouverture d'une URL dans le navigateur Web par défaut du système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Chapitre 31 : Communication inter-applications Chapitre 32 : Distribution, installation et exécution d'applications AIR Installation et exécution d'une application AIR à partir du Bureau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Installation et exécution d'applications AIR à partir d'une page Web Déploiement dans l'entreprise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 Signature numérique d'un fichier AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 Chapitre 33 : Mise à jour des applications AIR A propos de la mise à jour des applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 Présentation d'une interface utilisateur personnalisée pour la mise à jour d'applications Téléchargement d'un fichier AIR sur l'ordinateur de l'utilisateur Vérifications permettant de savoir si l'application est exécutée pour la première fois Utilisation de la structure de mise à jour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Chapitre 34 : Localisation d'applications AIR Introduction à la localisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 Localisation du nom et de la description de l'application dans son programme d'installation Choix d'un jeu de paramètres régionaux . . . . . . . . . . . . . . . . . . . . . . . . . . 351 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 Localisation du contenu Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 Localisation de contenu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Localisation des dates, heures et devises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 Chapitre 35 : Création d'une application AIR à l'aide des outils de ligne de commande Utilisation de l'application de débogage du lanceur AIR (ADL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Création d'un package de fichier d'installation AIR à l'aide de l'outil ADT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Modification du certificat d'une application à l'aide d'une signature de fichier AIR Création d'un certificat auto-signé à l'aide de l'outil ADT Utilisation d'Apache Ant avec les outils du kit SDK Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 1 Chapitre 1 : Installation d'Adobe AIR Adobe® AIR™ vous permet d'exécuter les applications AIR dans le poste de travail. Pour installer le moteur d'exécution, procédez comme suit, au choix : • Installez le moteur d'exécution séparément (sans installer d'application AIR). • Installez une application AIR pour la première fois, auquel cas vous êtes invité(e) à installer le moteur d'exécution. • Configurez un environnement de développement AIR tel que le SDK d'AIR, Adobe® Flex™ Builder™ 3 ou le SDK d'Adobe Flex™ 3 (qui contient les outils de développement de ligne de commande AIR). Le moteur d'exécution ne doit être installé qu'une seule fois sur chaque ordinateur. La configuration requise pour l'installation d'AIR et l'exécution d'applications AIR est détaillée à l'adresse : Adobe AIR : Configuration requise (http://www.adobe.com/fr/products/air/systemreqs/). Installation d'Adobe AIR Les instructions suivantes permettent de télécharger et d'installer les versions Windows®, Mac OS X et Linux d'AIR. Pour mettre à jour le moteur d'exécution, l'utilisateur doit disposer des droits d'administrateur sur l'ordinateur. Installation du moteur d'exécution sur un ordinateur Windows 1 Téléchargez le fichier d'installation du moteur d'exécution. 2 Double-cliquez sur le fichier d'installation du moteur d'exécution. 3 Dans la fenêtre d'installation, suivez les invites pour achever l'installation. Installation du moteur d'exécution sur un ordinateur Mac 1 Téléchargez le fichier d'installation du moteur d'exécution. 2 Double-cliquez sur le fichier d'installation du moteur d'exécution. 3 Dans la fenêtre d'installation, suivez les invites pour achever l'installation. 4 Si le programme d'installation affiche une fenêtre d'authentification, entrez votre nom d'utilisateur et votre mot de passe Mac OS. Installation du moteur d'exécution sur un ordinateur Linux 1 Téléchargez le fichier d'installation du moteur d'exécution. 2 Définissez les autorisations du fichier de sorte que le programme d'installation puisse être exécuté : A partir d'une ligne de commande, vous pouvez définir les autorisations du fichier avec la commande chmod +x installer.bin. Certaines versions de Linux vous permettent de définir les autorisations des fichiers dans la boîte de dialogue Propriétés, ouverte par l'intermédiaire d'un menu contextuel. 3 Exécutez le programme d'installation à partir de la ligne de commande ou en double-cliquant sur le fichier d'installation du moteur d'exécution. 4 Dans la fenêtre d'installation, suivez les invites pour achever l'installation. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 2 Installation d'Adobe AIR AIR est installé en tant que package rpm ou dpkg, avec les noms : adobeairv.n et adobecerts. L'installation requiert un serveur X en exécution. AIR enregistre le type mime : application/vnd.adobe.air-application-installerpackage+zip. Désinstallation d'Adobe AIR Après l'installation du moteur d'exécution, les procédures suivantes permettent de le désinstaller. Désinstallation du moteur d'exécution sur un ordinateur Windows 1 Dans le menu Démarrer de Windows, sélectionnez Paramètres > Panneau de configuration. 2 Sélectionnez le panneau de configuration Ajout ou suppression de programmes. 3 Pour désinstaller le moteur d'exécution, sélectionnez « Adobe AIR ». 4 Cliquez sur le bouton Modifier/Supprimer. Désinstallation du moteur d'exécution sur un ordinateur Mac • Double-cliquez sur le programme de désinstallation d'Adobe AIR, situé dans le dossier /Applications/Utilities. Désinstallation du moteur d'exécution sur un ordinateur Linux Effectuez l'une des opérations suivantes : • Sélectionnez la commande « Programme de désinstallation d'Adobe AIR » dans le menu Applications. • Exécutez le programme d'installation binaire d'AIR avec l'option -uninstall. • Supprimez les packages AIR (adobeairv.n et adobecerts) avec votre gestionnaire de package. Installation et exécution des exemples d'application AIR Certains exemples d'application illustrent des fonctionnalités AIR. Procédez comme suit pour y accéder et les installer : 1 Téléchargez et exécutez les exemples d'application AIR. Les applications compilées et le code source sont disponibles. 2 Pour télécharger et exécuter un exemple d'application, cliquez sur le bouton Installer maintenant proposé. Vous êtes invité à installer et exécuter l'application. 3 Si vous décidez de télécharger des exemples d'application et de les exécuter ultérieurement, sélectionnez les liens de téléchargement. Vous pouvez à tout moment exécuter une application AIR en procédant comme suit : • Sous Windows, double-cliquez sur l'icône de l'application sur le bureau ou sélectionnez-la dans le menu Démarrer de Windows. • Sous Mac OS, double-cliquez sur l'icône de l'application, qui est installée par défaut dans le dossier Applications de votre répertoire utilisateur (tel que Macintosh HD/Users/Jean/Applications/). • Sous Linux, double-cliquez sur l'icône de l'application sur le bureau ou sélectionnez-la dans le menu Applications. Les applications AIR sont installées dans leur propre dossier sous le répertoire /opt. Remarque : pour vérifier si ces instructions ont été mises à jour, consultez les Notes de parution d'AIR, qui résident à l'adresse suivante : http://www.adobe.com/go/learn_air_relnotes_fr. 3 Chapitre 2 : Configuration de Flash CS3 pour Adobe AIR La mise à jour Adobe® AIR™ pour Adobe® Flash® CS3 Professional étend l'environnement de développement de Flash avec des éléments qui vous permettent de créer des applications AIR avec Flash. Vous pouvez ainsi créer, tester et déboguer des fichiers d'application AIR dans Flash. Adobe® Flash® CS4 Professional comporte une prise en charge intégrée pour la création d'applications AIR. Pour plus d'informations, consultez Publication pour Adobe AIR dans Utilisation de Flash. La mise à jour Adobe AIR pour Flash CS3 prend en charge AIR 1.0 et 1.1 et Flash Player 9.x. Flash CS4 est requis pour développer des applications avec AIR 1.5 et Flash Player 10. Configuration requise pour la mise à jour Adobe AIR pour Flash CS3 Pour utiliser Flash CS3 afin de développer et exécuter des applications AIR, les logiciels suivants doivent être installés sur votre ordinateur : • Flash CS3 Professional Si vous n'avez pas de copie de Flash CS3 Professional, vous pouvez en acquérir une sur le site Web d'Adobe : http://www.adobe.com/fr/products/flash/. • Adobe AIR Pour plus d'informations sur l'installation d'Adobe AIR, consultez la section « Installation d'Adobe AIR » à la page 1. • Mise à jour Adobe Air pour Flash CS3 Si vous avez déjà installé une version de la mise à jour Adobe AIR pour Flash CS3, commencez par la retirer selon les instructions de la section Désinstallation de la mise à jour Adobe AIR pour Flash CS3. Si vous n'avez pas encore installé la mise à jour Adobe AIR pour Flash CS3, passez à la section « Installation de la mise à jour Adobe Air pour Flash CS3 » à la page 3. Installation de la mise à jour Adobe Air pour Flash CS3 Avant d'installer la mise à jour Adobe AIR pour Flash CS3, fermez Flash et les navigateurs éventuellement ouverts. • Téléchargez la mise à jour Adobe AIR pour Flash CS3. • Après avoir téléchargé la mise à jour, double-cliquez sur son fichier pour l'installer. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 4 Configuration de Flash CS3 pour Adobe AIR Retrait de la mise à jour Adobe Air pour Flash CS3 Si vous avez déjà installé la mise à jour Adobe AIR pour Flash CS3, suivez les instructions suivantes pour la retirer avant d'installer une nouvelle mise à jour Adobe AIR pour Flash CS3. 1 Supprimez le dossier suivant : (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\AIK (Mac) DD:/Applications/Adobe Flash CS3/AIK 2 Localisez l'emplacement suivant : (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\<lang>\First Run\Commands\ (Mac) DD:/Applications/Adobe Flash CS3/First Run/Commands et supprimer les fichiers/dossiers suivants : • Dossier AIR • AIR - Application and Installer Settings.jsfl • AIR - Create AIR File.jsfl 3 Supprimez le fichier suivant : (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\<lang>\Configuration\External Libraries\FLAir.dll (Mac) DD:/Applications/Adobe Flash CS3/Configuration/External Libraries/FLAir.bundle. 4 Supprimez le fichier suivant : (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\<lang>\Configuration\Players\AdobeAIR1_0.xml (Mac) DD:/Applications/Adobe Flash CS3/Configuration/Players/ AdobeAIR1_0.xml 5 Localisez l'emplacement suivant : (Windows) DD:\Document and Settings\<nom d'utilisateur>\Local Settings\Application Data\Adobe\Flash CS3\<lang>\Configuration\Commands\ (Mac) DD:/Utilisateurs/<nom d'utilisateur>/Bibliothèque/Application Support/Adobe/Flash CS3/<lang>/Configuration/Commands/ et supprimez les fichiers/dossiers suivants : • Dossier AIR • AIR - Application and Installer Settings.jsfl • AIR - Create AIR File.jsfl Remarque : si l'emplacement spécifié n'apparaît pas sous Windows, activez l'option « Afficher les fichiers et les dossiers masqués » dans les options des dossiers. Ajouts AIR à Flash CS3 Une fois la mise à jour Adobe AIR installée, Flash présente les modifications suivantes : • Dans l'onglet Flash de la boîte de dialogue Paramètres de publication (Fichier > Paramètres de publication), le menu Version affiche une nouvelle entrée pour Adobe AIR 1.0. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 5 Configuration de Flash CS3 pour Adobe AIR • L'écran de bienvenue mis à jour propose une nouvelle entrée pour la création d'un fichier Flash (Adobe AIR). (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\fr\FirstRun\StartPage (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\fr\FirstRun\StartPage\resources Remarque : sur un ordinateur Macintosh, si l'option Fichier Flash (Adobe AIR) ne s'affiche pas dans l'écran de bienvenue, supprimez le dossier suivant et redémarrez Flash : DD:/Utilisateurs/<nom d'utilisateur>/Bibliothèque/Application Support/Adobe/Flash CS3/<langue>/Configuration/StartPage • Un nouveau fichier playerglobal.swc, renfermant toutes les API ActionScript 3.0 et Adobe AIR, est situé dans le dossier ActionScript 3.0/Classes. (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\fr\Configuration\ActionScript 3.0 Classes (Mac) DD:/Applications/Adobe Flash CS3/Configuration/ActionScript 3.0/Classes/ • Nouveaux fichiers jsfl (AIR - Application and Installer Settings.jsfl, AIR - Publish AIR File.jsfl) (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\fr\FirstRun\Commands (Mac) DD:/Applications/Adobe Flash CS3/First Run/Commands/ • Adobe AIR Software Development Kit (AIK) (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\AIK • Bibliothèque externe (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\fr\Configuration\External Libraries (Mac) DD:/Applications/Adobe Flash CS3/Configuration/External Libraries/ • Fichier de configuration cible (Windows) DD:\Program Files\Adobe\Adobe Flash CS3\fr\Configuration\Players\ (Mac) DD:/Applications/Adobe Flash CS3/Configuration/Players 6 Chapitre 3 : Présentation d'Adobe AIR Adobe® AIR™ est un moteur d'exécution gérant divers systèmes d'exploitation qui vous permet d'exploiter vos compétences en matière de développement Web (Adobe® Flash® CS3 Professional, Adobe® Flash® CS4 Professional, Adobe® Flex™, Adobe® ActionScript® 3.0, HTML, JavaScript®, Ajax) pour développer et déployer des Applications Internet enrichies (RIA) pour le bureau. Pour plus d'informations sur l'utilisation d'Adobe AIR, consultez le site Adobe AIR Developer Connection (http://www.adobe.com/devnet/air/). AIR vous permet de travailler dans des environnements qui vous sont familiers, d'exploiter les outils et approches que vous maîtrisez et, de par la prise en charge de Flash, Flex, HTML, JavaScript et Ajax, propose une expérience optimisée adaptée à vos besoins. Vous pouvez par exemple développer des applications qui font appel à l'une des technologies suivantes ou à une combinaison de celles-ci : • Flash / Flex / ActionScript • HTML / JavaScript / CSS / Ajax • PDF peut être exploité avec n'importe quelle application. Par conséquent, les applications AIR peuvent être basées sur : • Flash ou Flex (application dont le contenu racine est au format Flash/Flex (SWF)). • Flash ou Flex avec HTML ou PDF (applications dont le contenu racine est au format Flash/Flex (SWF) et intègre un contenu HTML (HTML, JS, CSS) ou PDF). • HTML (application dont le contenu racine est au format HTML, JS, CSS). • HTML avec Flash/Flex ou PDF (applications dont le contenu racine est au format HTML et intègre un contenu Flash/Flex (SWF) ou PDF). Les utilisateurs manipulent les applications AIR comme toute application de bureau native. Le moteur d'exécution est installé une seule fois sur l'ordinateur de l'utilisateur. Il est alors possible d'installer et d'exécuter les applications AIR à l'instar de toute autre application de bureau. Quel que soit le système d'exploitation utilisé, le moteur d'exécution propose une plate-forme et une structure uniformes de déploiement d'applications. La cohérence des fonctionnalités et interactions rend ainsi superflus les tests dans plusieurs navigateurs. Au lieu de développer une application pour un système d'exploitation déterminé, vous ciblez le moteur d'exécution. Cette approche offre les avantages suivants : • Les applications développées pour AIR s'exécutent sur divers systèmes d'exploitation sans nécessiter d'intervention supplémentaire de votre part. Le moteur d'exécution assure une présentation et des interactions cohérentes et prévisibles sur tous les systèmes d'exploitation pris en charge par AIR. • En vous permettant d'exploiter les technologies et modèles de conception Web existants et d'assurer la migration de vos applications Web vers le poste de travail sans nécessiter l'apprentissage de technologies traditionnelles de développement d'applications de bureau ou d'un code natif complexe, vous réduisez les délais de création d'applications. • Parce qu'il ne fait pas appel à des langages de niveau inférieur tels que C et C++, le développement d'applications s'en trouve simplifié. Il est ainsi inutile de gérer les API complexes de bas niveau propres à chaque système d'exploitation. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 7 Présentation d'Adobe AIR Développer des applications pour AIR vous permet d'exploiter un riche ensemble de structures et d'API : • Les API propres à AIR proposées par le moteur d'exécution et la structure AIR • Les API d'ActionScript utilisées par les fichiers SWF et la structure Flex (ainsi que qu'autres bibliothèques et structures basées sur ActionScript) • HTML, CSS et JavaScript • La plupart des structures Ajax AIR a un impact considérable sur la création, le déploiement et l'utilisation des applications. Il vous assure un contrôle créatif accru et permet la migration de vos applications Flash, Flex, HTML et Ajax dans le poste de travail, sans s'appuyer sur les technologies de développement pour poste de travail traditionnelles. Nouveautés d'AIR 1.1 Adobe AIR 1.1 a introduit les fonctionnalités suivantes : • Les boîtes de dialogue d'installation et du moteur d'exécution ont été traduites dans les langues suivantes : • Portugais (Brésil) • Chinois (traditionnel et simplifié) • Français • Allemand • Italien • Japonais • Coréen • Russe • Français • Espagnol • Prise en charge du développement d'applications internationalisées, y compris la saisie au clavier des langues à deux octets. Voir « Localisation d'applications AIR » à la page 351. • Prise en charge de la localisation des attributs de nom et de description dans le fichier descripteur de l'application. • Prise en charge de la localisation des messages d'erreur, tels que SQLError.detailID et SQLError.detailArguments, dans la base de données SQLite. • Ajout de la propriété Capabilities.languages pour obtenir un tableau des langues d'interface utilisateur favorites définies par le système d'exploitation. • Les intitulés des boutons HTML et des menus par défaut, par exemple les menus contextuels et la barre de menus Mac, ont été localisés dans toutes les langues prises en charge. • Prise en charge de la migration des certificats depuis une application auto-signée vers une application liée à une autorité de certification (CA). • Prise en charge de Microsoft Windows XP Tablet PC Edition et des éditions 64 bits de Windows Vista® Home Premium, Business, Ultimate ou Enterprise. • Ajout de l'API File.spaceAvailable pour connaître la quantité d'espace disponible sur un disque. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 8 Présentation d'Adobe AIR • Ajout de la propriété NativeWindow.supportsTransparency pour déterminer si une fenêtre peut être tracée en transparence par le système d'exploitation actuel. Pour plus d'informations sur la version AIR 1.1, consultez les notes de parution d'Adobe AIR 1.1 (http://www.adobe.com/go/learn_air_relnotes_fr). Nouveautés d'AIR 1.5 Adobe AIR 1.5 introduit les nouvelles fonctionnalités suivantes : • Prise en charge des fonctionnalités suivantes de Flash Player 10. • Filtres et effets personnalisés • API de dessin améliorée • Génération de son dynamique • Type de données vectorielles • API améliorées de chargement et de téléchargement des fichiers • Protocole RTMFP (Real Time Media Flow Protocol) • Effets 3D • Prise en charge avancée du texte • Gestion des couleurs • Moteur de texte • Flux continu (streaming) dynamique • Codec audio Speex Pour plus d'informations sur ces fonctionnalités, consultez http://www.adobe.com/fr/products/flashplayer/features/. • Autres langues prises en charge dans le programme d'installation AIR 1.5 et d'autres boîtes de dialogue du moteur d'exécution : tchèque, néerlandais, suédois, turc, polonais. • Chiffrement de base de données. Dans AIR 1.5, les fichiers de base de données peuvent être chiffrés. Tout le contenu d'une base de données, y compris ses métadonnées, peut être chiffré de sorte que les données ne puissent pas être lues hors de l'application AIR qui les a chiffrées. Grâce à cette fonctionnalité, un développeur peut chiffrer, déchiffrer et rechiffrer les fichiers de base de données. Voir « Stockage des données chiffrées » à la page 219. • Cette version du WebKit utilisé par Adobe AIR a été mise à jour et prend maintenant en charge l'interpréteur JavaScript SquirrelFish. • De nouvelles API de validation des signatures XML peuvent être utilisées pour vérifier l'intégrité et l'identité du signataire des données ou des informations. Voir Validation des signatures XML. Pour plus d'informations sur la version AIR 1.5, consultez les notes de parution d'Adobe AIR 1.5 (http://www.adobe.com/go/learn_air_relnotes_fr). 9 Chapitre 4 : Recherche des ressources AIR Pour plus d'informations sur le développement des applications Adobe® AIR™, consultez les ressources suivantes : Source Emplacement Programmation avec ActionScript 3.0 http://www.adobe.com/go/learn_fl_cs4_programmingAS3_fr Guide de référence du langage et des composants ActionScript 3.0 (avec AIR) http://www.adobe.com/go/learn_flashcs4_langref_fr Démarrages rapides d'Adobe AIR pour Flash http://www.adobe.com/go/learn_air_flash_qs_fr Utilisation de Flash http://www.adobe.com/go/learn_fl_cs4_using_fr Utilisation des composants ActionScript 3.0 http://www.adobe.com/go/learn_fl_cs4_as3components_fr Vous pouvez trouver des articles, des exemples et des présentations par des experts d'Adobe et de la communauté sur Adobe AIR Developer Connection à l'adresse http://www.adobe.com/devnet/air/. Il est également possible de télécharger Adobe AIR et des logiciels apparentés à partir de ce site. Vous pouvez trouver une section consacrée aux développeurs Flash à l'adresse http://www.adobe.com/devnet/air/flex/. Visitez le site Web du support Adobe à l'adresse http://www.adobe.com/fr/support/ pour trouver des informations de dépannage sur votre produit et pour vous renseigner sur les options d'assistance technique gratuite ou payante. Suivez le lien Formation pour accéder à la collection Adobe Press, à un grand nombre de ressources pour la formation, à des programmes de certification pour les logiciels Adobe et davantage encore. 10 Chapitre 5 : Création de votre première application AIR avec Flash CS3 ou CS4 Les instructions de cette rubrique proposent une brève démonstration pratique du fonctionnement d'Adobe® AIR™ en vous aidant à créer et à mettre en package une application AIR simple nommée « Hello World » avec Adobe® Flash® CS3 Professional. Si vous ne l'avez pas encore fait, téléchargez et installez la mise à jour d'Adobe AIR pour Flash CS3. Pour plus d'informations sur l'installation d'Adobe AIR pour Flash CS3, consultez la section « Configuration de Flash CS3 pour Adobe AIR » à la page 3. Si vous utilisez Adobe® Flash® CS4 Professional, la prise en charge d'Adobe AIR y est intégrée. Vous n'avez donc rien à installer pour démarrer. Création de l'application Hello World dans Flash La création d'une application Adobe AIR dans Flash ressemble beaucoup à la création d'un autre fichier FLA. La différence est que vous commencez par créer un fichier Flash (Adobe AIR) dans l'écran de bienvenue et que vous terminez par créer les paramètres de l'application et du programme d'installation et par installer votre application AIR. La procédure suivante vous guide tout au long de la procédure de création d'une application Hello World simple avec Flash CS3 ou CS4. Pour créer l'application Hello World 1 Démarrez Flash. 2 Dans l'écran de bienvenue, cliquez sur Fichier Flash (Adobe AIR) pour créer un fichier FLA vide avec les paramètres de publication d'Adobe AIR. 3 Cliquez sur OK en réponse à la boîte de dialogue de résumé, Programmation Adobe AIR avec Flash CS3. Lors de sa première ouverture, cette boîte de dialogue met quelques secondes à apparaître. (Cette boîte de dialogue n'apparaît pas dans Flash CS4.) 4 Sélectionnez l'outil Texte dans le panneau Outils et créez un champ de texte statique (par défaut) au centre de la scène. Choisissez une largeur pouvant contenir 15 à 20 caractères. 5 Entrez le texte « Hello World » dans le champ. 6 Enregistrez le fichier, en lui donnant un nom (par exemple, helloAIR). Test de l'application 1 Appuyez sur Ctrl + Entrée ou sélectionnez Contrôle > Tester l'animation pour tester l'application dans Adobe AIR. 2 Pour utiliser la fonction Déboguer l'animation, ajoutez d'abord du code ActionScript à l'application. Vous pouvez le faire rapidement en ajoutant une instruction trace telle que : trace("Running AIR application using Debug Movie"); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 11 Création de votre première application AIR avec Flash CS3 ou CS4 3 Appuyez sur Ctrl + Maj + Entrée ou sélectionnez Déboguer > Déboguer l'animation pour exécuter l'application avec Déboguer l'animation. 4 Sélectionnez Commandes > AIR - Paramètres de l'application et du programme d'installation pour ouvrir la boîte de dialogue du même nom. Dans Flash CS4, sélectionnez Fichier > Paramètres AIR pour ouvrir cette boîte de dialogue. 5 Signez le package Adobe AIR avec un certificat numérique auto-signé : a Cliquez sur le bouton Définir… pour ouvrir la boîte de dialogue Signature numérique. b Cliquez sur le bouton Créer... pour ouvrir la boîte de dialogue Créer un certificat numérique auto-signé. c Renseignez les entrées Nom de l'éditeur, Unité d'organisation, Nom de l'organisation, E-mail, Pays, Mot de passe et Confirmer le mot de passe. d Spécifiez le type de certificat. L'option Type du certificat fait référence au niveau de sécurité : 1024-RSA utilise une clé 1 024 bits (moins sécurisée) et 2048-RSA une clé 2 048 bits (plus sécurisée). e Enregistrez les informations dans un fichier de certificat en renseignant l'entrée Enregistrer sous ou en cliquant sur le bouton Parcourir... pour localiser un dossier. (Par exemple, C:/Temp/mycert.pfx). Lorsque vous avez terminé, cliquez sur OK. f Flash vous renvoie à la boîte de dialogue Signature numérique. Le chemin et le nom de fichier du certificat autosigné s'affichent dans le champ de texte Certificat. Si ce n'est pas le cas, entrez le chemin et le nom du fichier ou cliquez sur le bouton Parcourir pour le localiser et le sélectionner. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 12 Création de votre première application AIR avec Flash CS3 ou CS4 g Dans le champ Mot de passe de la boîte de dialogue Signature numérique, entrez le mot de passe que vous avez choisi à l'étape C, puis cliquez sur OK. Pour plus d'informations sur la signature de vos applications Adobe AIR, consultez la section « Signature de votre application » à la page 21. 6 Pour créer le fichier de l'application et du programme d'installation, cliquez sur le bouton Publier le fichier AIR. Pour créer les fichiers SWF et application.xml, vous devez tester ou déboguer l'animation avant de créer le fichier AIR. 7 Pour installer l'application, double-cliquez sur le fichier AIR (application.air) dans le dossier où vous avez enregistré votre application. 8 Dans la boîte de dialogue Installation de l'application, cliquez sur le bouton Installer. 9 Vérifiez les paramètres d'emplacement et de préférences d'installation et assurez-vous que la case à cocher ‘Démarrer l'application à la fin de l'installation’ est activée. Cliquez sur Continuer. 10 Lorsque le message Installation terminée apparaît, cliquez sur Terminer. L'application Hello World ressemble à l'illustration suivante : Conversion d'un fichier FLA en application Adobe AIR Vous pouvez également convertir un fichier FLA existant en application AIR. Pour plus d'informations, consultez la section « Définition des paramètres de publication d'Adobe AIR » à la page 13. Si vous utilisez Flash CS4, consultez Publication pour Adobe AIR dans Utilisation de Flash. 13 Chapitre 6 : Mise à jour Adobe AIR pour Flash CS3 Professional La mise à jour Adobe® AIR™ pour Adobe® Flash® CS3 Professional étend l'environnement de programmation pour vous permettre de créer, déboguer et mettre en package les applications Adobe AIR avec Flash. Le processus de création d'une application Adobe AIR recouvre la création d'un fichier FLA pour Adobe AIR, la définition de paramètres de publication, le développement et la création de l'application Adobe AIR et des fichiers d'installation pour la déployer et l'exécuter. Si vous utilisez Adobe® Flash® CS4 Professional, consultez Publication dans Adobe AIR du guide Utilisation de Flash pour plus d'informations sur la création d'applications AIR. Pour plus d'informations sur les API d'Adobe AIR ActionScript® 3.0 utilisables dans votre application, consultez le Guide de référence du langage et des composants ActionScript 3.0. Pour obtenir la liste des API d'Adobe AIR ActionScript, consultez la section « Fonctionnalités propres à Adobe AIR » à la page 56. Remarque : pour utiliser les classes du package air.net, commencez par faire glisser le composant ServiceMonitorShim du panneau Composants vers le panneau Bibliothèque, puis ajoutez l'instruction import suivante à votre code ActionScript 3.0 : import air.net.*; Création d'un fichier Adobe AIR Vous pouvez créer des documents Fichier Flash (Adobe AIR) à l'aide de l'écran de bienvenue de Flash ou créer un fichier Flash (ActionScript 3.0) et le convertir en fichier Adobe AIR via la boîte de dialogue Paramètres de publication. Vous ne pouvez cependant pas créer de fichier Adobe AIR à l'aide de la boîte de dialogue Nouveau document (Fichier > Nouveau). Pour plus d'informations sur la conversion d'un fichier FLA en fichier Adobe AIR, consultez la section « Définition des paramètres de publication d'Adobe AIR » à la page 13. 1 Démarrez Flash ou, si Flash est déjà actif, fermez les documents ouverts pour revenir à l'écran de bienvenue. Remarque : si vous avez désactivé l'écran de bienvenue de Flash, vous pouvez l'afficher de nouveau en sélectionnant Modifier > Préférences et en choisissant Ecran de bienvenue dans le menu déroulant Au démarrage, dans la catégorie Général. 2 Dans l'écran de bienvenue, cliquez sur Fichier Flash (Adobe AIR). Un message d'alerte apparaît et vous indique comment accéder aux paramètres de l'application Adobe AIR et à la documentation d'aide. Pour éviter l'affichage de ce message à l'avenir, activez l'option Ne plus afficher ce message, mais il sera alors impossible de l'afficher de nouveau. Définition des paramètres de publication d'Adobe AIR Les paramètres de publication de Flash permettent d'examiner ou de modifier les paramètres d'un fichier AIR et de convertir un document Flash (ActionScript 3.0) en document Fichier Flash (Adobe AIR). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 14 Mise à jour Adobe AIR pour Flash CS3 Professional Affichage des paramètres de publication d'Adobe AIR 1 Dans l'écran de bienvenue de Flash, ouvrez un document de type Fichier Flash (Adobe AIR). 2 Sélectionnez Fichier > Paramètres de publication, puis cliquez sur l'onglet Flash pour afficher les paramètres de publication Adobe AIR. Adobe AIR 1.0 est automatiquement sélectionné dans le menu Version lorsque vous ouvrez un document Adobe AIR. La version ActionScript est automatiquement définie sur ActionScript 3.0. Le paramètre de sécurité de lecture locale est grisé car il ne concerne pas les fichiers AIR SWF. Si vous avez ouvert un fichier FLA de Flash, vous pouvez le convertir en fichier AIR en modifiant ses paramètres de publication. Conversion d'un fichier Flash FLA au format Flash AIR à l'aide de la boîte de dialogue Paramètres de publication 1 Effectuez l'une des opérations suivantes : • Ouvrez un fichier FLA existant. • Utilisez l'écran de bienvenue ou sélectionnez Fichier > Nouveau pour créer un nouveau fichier FLA. 2 Choisissez Fichier > Paramètres de publication. 3 Dans l'onglet Flash, sélectionnez Adobe AIR 1.0 dans le menu déroulant Version. L'entrée de la version ActionScript est désactivée dans la mesure où ActionScript 3.0 est la seule option possible pour un fichier AIR. Les autres options par défaut sont identiques pour les fichiers FLA et Adobe AIR. 4 Cliquez sur le bouton Publier, puis sur le bouton OK pour fermer la boîte de dialogue Paramètres de publication. L'inspecteur des propriétés indique à présent que la cible du lecteur est Adobe AIR 1 lorsque l'outil Sélection est sélectionné. Remarque : lorsque vous sélectionnez le profil Adobe AIR 1.0, Flash ajoute automatiquement l'emplacement du fichier AIR playerglobal.swc à la variable d'environnement Classpath. Le fichier playerglobal.swc d'AIR permet d'exploiter les API AIR d'ActionScript. Toutefois, si vous passez d'Adobe AIR 1 à Adobe® Flash® Player 9, Flash ne réinitialise pas automatiquement le profil par défaut, ni ne modifie le paramètre Classpath pour utiliser playerglobal.swc pour Flash Player 9. Si vous modifiez le paramètre de publication d'Adobe AIR 1 vers Flash Player 9, vous devez sélectionner le profil de publication Par défaut. Pour plus d'informations sur la boîte de dialogue Paramètres de publication, consultez Utilisation de Flash à l'adresse www.adobe.com/go/learn_fl_using_fr. Conversion d'un fichier Flash FLA en application Flash AIR à l'aide du menu Commandes 1 Ouvrez votre fichier FLA. 2 Si vous ouvrez un nouveau Fichier Flash (ActionScript 3.0), enregistrez-le. Si vous ne l'enregistrez pas, un avertissement apparaît à l'étape suivante. 3 Sélectionnez Commandes > AIR - Paramètres de l'application et du programme d'installation. Un message d'alerte apparaît et vous demande si vous souhaitez convertir le fichier en paramètres de publication Adobe AIR. 4 Cliquez sur OK pour convertir le fichier FLA en paramètres de publication d'Adobe AIR. La boîte de dialogue AIR - Paramètres de l'application et du programme d'installation apparaît. Pour plus d'informations sur la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation, consultez la section « Création d'une application AIR et de ses fichiers d'installation » à la page 16. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 15 Mise à jour Adobe AIR pour Flash CS3 Professional Vous pouvez appliquer les commandes Tester l'animation, Déboguer l'animation et Créer un fichier AIR au fichier FLA AIR converti. Aperçu d'une application Adobe AIR Vous pouvez obtenir un aperçu du fichier Flash AIR SWF tel qu'il apparaît dans l'application AIR. Cet aperçu permet de visualiser les différents aspects de l'application sans avoir à l'installer ni à créer de package. 1 Assurez-vous que les paramètres de publication ont bien été définis pour une application Adobe AIR. Pour plus d'informations, consultez la section « Définition des paramètres de publication d'Adobe AIR » à la page 13. 2 Sélectionnez Contrôle > Tester l'animation ou appuyez sur Ctrl + Entrée. Si vous n'avez pas défini les paramètres de l'application dans la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation, Flash génère un fichier descripteur d'application par défaut (swfname-app.xml) dans le dossier contenant le fichier SWF. Si vous avez configuré l'application à l'aide de cette boîte de dialogue, le fichier du descripteur d'application reflète ces paramètres. Débogage d'une application Adobe AIR Le fichier SWF d'Adobe AIR peut être débogué de la même façon qu'un fichier SWF ActionScript 3.0 pour Flash Player 9, à l'exception du débogage à distance. 1 Assurez-vous de bien avoir défini les paramètres de publication Adobe AIR. 2 Ajoutez du code ActionScript dans le panneau Actions (Fenêtre > Actions). Dans le cadre du test, vous pouvez ajouter une instruction trace() comme indiqué ci-dessous dans le panneau Actions, sur la première image du Scénario : trace("My application is running"); 3 Sélectionnez Déboguer > Déboguer l'animation ou appuyez sur Ctrl + Maj + Entrée. Flash démarre le débogueur ActionScript et exporte le fichier SWF avec les informations de débogage. Si vous n'avez pas défini les paramètres de l'application dans la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation, Flash génère un descripteur d'application par défaut (swfname-app.xml) dans le dossier contenant le fichier SWF. Si vous avez configuré l'application à l'aide de cette boîte de dialogue, le fichier du descripteur d'application reflète ces paramètres. Lorsque vous sélectionnez Déboguer > Déboguer l'animation ou appuyez sur Ctrl + Maj + Entrée pour déboguer l'application, Flash renvoie un avertissement si l'application ne contient pas de code ActionScript. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 16 Mise à jour Adobe AIR pour Flash CS3 Professional Création d'une application AIR et de ses fichiers d'installation Lorsque votre application est terminée, créez l'application AIR et les fichiers d'installation pour la déployer. Adobe AIR ajoute deux éléments dans le menu Commandes de Flash : AIR - Paramètres de l'application et du programme d'installation et AIR - Créer un fichier AIR. Après avoir créé les paramètres de l'application et du programme d'installation AIR, vous pouvez utiliser l'élément AIR - Créer un fichier AIR pour recréer le fichier AIR (.air) avec les paramètres existants. Création de l'application Adobe AIR et de ses fichiers d'installation 1 Dans Flash, ouvrez la page ou l'ensemble des pages composant votre application Adobe AIR. 2 Enregistrez le fichier FLA Adobe AIR avant d'ouvrir la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation. 3 Sélectionnez Commandes > AIR - Paramètres de l'application et du programme d'installation. 4 Complétez la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation, puis cliquez sur Publier le fichier AIR. Lorsque vous cliquez sur le bouton Publier le fichier AIR, les fichiers suivants sont mis en package : le fichier FLA, le fichier SWF, le fichier descripteur d'application, les fichiers des icônes de l'application et les fichiers énumérés dans le champ de texte Fichiers inclus. Si vous n'avez pas encore créé de certificat numérique, Flash affiche la boîte de dialogue Signature numérique lorsque vous cliquez sur le bouton Publier un fichier AIR. La boîte de dialogue AIR - Paramètres de l'application et du programme d'installation comprend deux sections : Paramètres d'application et Paramètres d'installation. Pour plus d'informations sur ces paramètres, consultez les sections suivantes. Paramètres d'application La section Paramètres d'application de la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation comprend les options suivantes : Nom de fichier Nom du fichier principal de l'application. Par défaut, il s'agit du nom du fichier SWF. Nom Nom utilisé par le programme d'installation pour générer le nom du fichier d'application et le dossier de l'application. Ce nom ne doit contenir que les caractères autorisés pour les noms de fichier ou de dossier. Par défaut, il s'agit du nom du fichier SWF. Version Facultatif. Spécifie le numéro de version de votre application. Par défaut, ce champ reste vide. ID Identifie l'application par un ID unique. Vous pouvez modifier l'ID par défaut si vous le souhaitez. N'incluez pas d'espaces ni de caractères spéciaux dans l'ID. Les seuls caractères valides sont 0-9, a-z, A-Z, . (point) et - (tiret), de 1 à 212 caractères de long. L'ID par défaut est com.adobe.example.nom_application. Description Facultatif. Permet d'entrer une description de l'application à afficher lorsque l'utilisateur installe celle-ci. Par défaut, ce champ reste vide. Copyright Facultatif. Permet d'inclure la mention de copyright devant s'afficher lorsque l'utilisateur installe l'application. Style de fenêtre Spécifie le style de fenêtre (ou arrière-plan) à utiliser pour l'interface utilisateur lorsque l'utilisateur exécute l'application sur son ordinateur. Vous pouvez spécifier Arrière-plan système, qui se rapporte au style visuel utilisé par le système d'exploitation. Vous pouvez également spécifier Arrière-plan personnalisé (opaque) ou Arrièreplan personnalisé (transparent). Pour afficher l'application sans arrière-plan personnalisé, sélectionnez Aucun. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 17 Mise à jour Adobe AIR pour Flash CS3 Professional Arrière-plan système entoure l'application avec le contrôle de fenêtre standard du système d'exploitation. Arrière-plan personnalisé (opaque) supprime l'arrière-plan standard du système et vous permet de créer votre propre arrière-plan pour l'application. (L'arrière-plan personnalisé se définit directement dans le fichier FLA.) Arrière-plan personnalisé (transparent) correspond à Arrière-plan personnalisé (opaque), mais ajoute de la transparence à la bordure de la page. Cette fonctionnalité permet d'obtenir des fenêtres d'application qui n'ont pas nécessairement la forme d'un carré ou d'un rectangle. Icône Facultatif. Permet d'associer une icône à l'application. L'icône s'affiche après l'installation de l'application et son exécution dans Adobe AIR. Vous pouvez spécifier quatre tailles différentes d'icône (128, 48, 32 et 16 pixels) en fonction des différents affichages de cette dernière. Par exemple, l'icône peut apparaître dans le navigateur de fichiers dans les vues miniatures, détails et mosaïque. Elle peut également apparaître sous forme d'icône de bureau et dans le titre de la fenêtre de l'application AIR, ainsi qu'à d'autres endroits. Si aucun fichier d'icône n'est spécifié, l'icône exemple de l'application AIR est définie par défaut. Pour spécifier une icône, cliquez sur le bouton Sélectionner les images pour icônes dans la boîte de dialogue AIR Paramètres de l'application et du programme d'installation. Dans la boîte de dialogue Images d'icône qui apparaît, cliquez sur le dossier de chaque taille d'icône, puis sélectionnez le fichier d'icône désiré. Les fichiers doivent être au format PNG (Portable Network Graphics). L'illustration suivante présente la boîte de dialogue Images d'icône avec les icônes d'application par défaut d'Adobe AIR. Spécification de différentes tailles d'icônes d'application Si vous spécifiez une image, sa taille doit correspondre à celle que vous avez définie (128x128, 48x48, 32x32 ou 16x16). Si vous ne spécifiez pas d'image pour une taille particulière, Adobe AIR redimensionne l'une des images fournies pour créer l'icône manquante. Paramètres avancés Le bouton Paramètres de la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation permet de définir des paramètres avancés pour le fichier descripteur d'application. Lorsque vous cliquez sur ce bouton, la boîte de dialogue Paramètres avancés apparaît. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 18 Mise à jour Adobe AIR pour Flash CS3 Professional Cette boîte de dialogue permet de spécifier les types de fichier associés que l'application doit traiter. Par exemple, si vous souhaitez que votre application devienne l'application principale de traitement des fichiers HTML, vous devez le spécifier dans le champ de texte Types de fichier associés. Vous pouvez également spécifier des paramètres pour les aspects suivants de l'application : • Taille et position de la fenêtre initiale • Dossier dans lequel l'application est installée • Dossier du menu Programmes devant accueillir l'application La boîte de dialogue présente les options suivantes : Types de fichier associés Permet de spécifier les types de fichier associés que l'application AIR doit traiter. Cliquez sur le bouton Plus (+) pour ajouter un nouveau type de fichier dans le champ de texte. Si vous cliquez sur le bouton Plus, la boîte de dialogue Paramètres du type de fichier apparaît. Un clic sur le bouton Moins (-) permet de supprimer un élément sélectionné dans le champ de texte. Un clic sur le bouton Crayon permet d'afficher la boîte de dialogue Paramètres du type de fichier et de modifier un élément sélectionné dans le champ de texte. Par défaut, les boutons Moins (-) et Crayon sont grisés. La sélection d'un élément dans le champ de texte active ces boutons et permet de supprimer ou modifier cet élément. La valeur par défaut du champ de texte est Aucune. Pour plus d'informations sur les paramètres de type des fichiers associés, consultez la section « Paramètres du type de fichier » à la page 19. Paramètres initiaux de la fenêtre Permet de spécifier les paramètres de taille et de positionnement de la fenêtre initiale de l'application. • Largeur : spécifie la largeur initiale de la fenêtre, en pixels. Cette valeur est vide par défaut. • Hauteur : spécifie la hauteur initiale de la fenêtre, en pixels. Cette valeur est vide par défaut. • X : spécifie la position horizontale de la fenêtre, en pixels. Cette valeur est vide par défaut. • Y : spécifie la position verticale de la fenêtre, en pixels. Cette valeur est vide par défaut. • Largeur maximale et Hauteur maximale : spécifie la taille maximale de la fenêtre, en pixels. Ces valeurs sont vides par défaut. • Largeur minimale et Hauteur minimale : spécifie la taille minimale de la fenêtre, en pixels. Ces valeurs sont vides par défaut. • Agrandissement possible : permet de spécifier si l'utilisateur peut agrandir la fenêtre. Cette option est sélectionnée par défaut. • Réduction possible : permet de spécifier si l'utilisateur peut réduire la fenêtre. Cette option est sélectionnée par défaut. • Redimensionnable : permet de spécifier si l'utilisateur peut changer la taille de la fenêtre. Si cette option n'est pas sélectionnée, les options Largeur maximale, Hauteur maximale, Largeur minimale et Hauteur minimale ne sont pas disponibles. Cette option est sélectionnée par défaut. • Visible : permet de spécifier si la fenêtre d'application est visible dès le début. Cette option est sélectionnée par défaut. Autres paramètres Permet de spécifier les informations supplémentaires suivantes concernant l'installation : • Dossier d'installation : spécifie le dossier dans lequel l'application est installée. • Dossier du menu Programmes : spécifie le nom du dossier du menu de programmes de l'application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 19 Mise à jour Adobe AIR pour Flash CS3 Professional • Utiliser l'interface utilisateur personnalisée pour les mises à jour : précise ce qui doit se passer lorsqu'un utilisateur ouvre le fichier AIR d'une application déjà installée. Par défaut, AIR affiche une boîte de dialogue qui permet à l'utilisateur de mettre à jour la version installée avec la version du fichier AIR. Si vous préférez ne pas offrir cette possibilité à l'utilisateur et laisser l'application contrôler ses mises à jour, activez cette option. L'activation de cette option remplace le comportement par défaut et permet à l'application de contrôler ses propres mises à jour. Pour plus d'informations sur la mise à jour d'une application AIR par programmation, consultez la section « Mise à jour des applications AIR » à la page 335. Paramètres du type de fichier Flash affiche la boîte de dialogue Paramètres de type de fichier si vous cliquez sur le bouton Plus (+) ou sur le bouton Crayon de la boîte de dialogue Paramètres avancés pour ajouter ou modifier les types de fichier associés à l'application. Les seuls champs obligatoires de cette boîte de dialogue sont les champs Nom et Extension. Si vous cliquez sur OK alors que l'un de ces champs est vide, Flash affiche un message d'erreur. Vous pouvez spécifier les paramètres suivants pour un type de fichier associé : Nom Nom du type de fichier (par exemple, HTML, Fichier texte ou Exemple). Extension Extension du nom de fichier (par exemple, html, txt ou xmpl) comportant jusqu'à 39 caractères alphanumériques de base (A-Za-z0-9) et ne commençant pas par un point. Description Facultatif. Description du type de fichier (par exemple, Fichier vidéo Adobe). Type de contenu Facultatif. Spécifie le type MIME pour le fichier. Paramètres de l'icône de type de fichier Facultatif. Permet de spécifier l'icône associée au type de fichier. Vous pouvez spécifier quatre tailles différentes d'icône (128x128, 48x48, 32x32 et 16x16 pixels) en fonction des différents affichages de cette dernière. Par exemple, l'icône peut apparaître dans le navigateur de fichiers dans les vues miniatures, détails et mosaïque. Si vous spécifiez une image, elle doit être de la taille indiquée. Si vous ne spécifiez pas de fichier pour une taille particulière, AIR utilise l'image de la taille la plus proche et la redimensionne en fonction de l'occurrence donnée. Pour spécifier une icône, cliquez sur le dossier correspondant à la taille de l'icône et sélectionnez le fichier d'icône à utiliser ou entrez le chemin et le nom du fichier de l'icône dans le champ de texte accolé à l'invite. Le fichier de l'icône doit être au format PNG. Après la création d'un nouveau type de fichier, celui-ci s'affiche dans la zone de liste Type de fichier de la boîte de dialogue Paramètres avancés. Paramètres du fichier descripteur d'application Les paramètres d'application que vous spécifiez sont enregistrés dans le fichier nom_application-app.xml. Vous avez cependant la possibilité d'indiquer à Flash que vous souhaitez utiliser un fichier descripteur d'application personnalisé. Utiliser le fichier du descripteur d'application personnalisé Permet de localiser un fichier de descripteur d'application personnalisé. Si vous sélectionnez Utiliser un fichier descripteur d'application personnalisé, la section Paramètres d'application de la boîte de dialogue est grisée. Pour spécifier l'emplacement du fichier descripteur d'application personnalisé, entrez ce dernier dans le champ de texte situé au-dessous de l'option Utiliser le fichier du descripteur d'application personnalisé ou cliquez sur l'icône du dossier et localisez cet emplacement. Pour plus d'informations sur le fichier descripteur d'application, consultez la section « Création d'un fichier descripteur d'application personnalisé » à la page 20. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 20 Mise à jour Adobe AIR pour Flash CS3 Professional Paramètres d'installation La deuxième section de la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation présente les paramètres relatifs à l'installation de l'application. Signature numérique Toutes les applications Adobe AIR doivent être signées avant d'être installées sur un autre système. Pour plus d'informations sur l'affectation d'une signature numérique à une application Flash Adobe AIR, consultez la section « Signature de votre application » à la page 21. Destination Indique l'emplacement du fichier AIR. L'emplacement par défaut est le répertoire dans lequel vous avez enregistré le fichier FLA. Pour sélectionner un autre emplacement, cliquez sur l'icône de dossier. Le nom du package par défaut est le nom de l'application avec l'extension .air. Fichiers/Dossiers inclus Spécifie les fichiers et les dossiers supplémentaires à inclure dans votre application. Cliquez sur le bouton Plus (+) pour ajouter des fichiers et sur le bouton Dossier pour ajouter des dossiers. Pour supprimer un fichier ou un dossier de la liste, sélectionnez ce fichier ou ce dossier et cliquez sur le bouton Moins (-). Par défaut, le fichier du descripteur d'application et le fichier SWF principal sont automatiquement ajoutés dans la liste du package. La liste du package contient ces fichiers, même si vous n'avez pas encore publié le fichier FLA Adobe AIR. La liste du package donne la liste des fichiers et des dossiers sous forme de structure plate. Les fichiers des dossiers n'apparaissent pas dans la liste et les noms de chemin complet des fichiers sont fournis, mais peuvent être tronqués si nécessaire. Les fichiers d'icône ne sont pas inclus dans la liste. Lorsque Flash met les fichiers en package, il copie les fichiers d'icône dans un dossier temporaire dont l'emplacement est relatif à celui du fichier SWF. Flash supprime ensuite le dossier lorsque la mise en package est terminée. Echec de création des fichiers de l'application et du programme d'installation La création des fichiers de l'application et du programme d'installation échoue dans les cas suivants : • La chaîne de l'identifiant de l'application est de longueur incorrecte ou contient des caractères non valides. Cette chaîne doit comprendre entre 0 et 212 caractères et peut inclure les caractères suivants : 0-9, a-z, A-Z, . (point), (tiret). • Les fichiers spécifiés dans la liste de l'installateur n'existent pas. • Les tailles des fichiers d'icône personnalisés sont incorrectes. • Le dossier de destination AIR ne dispose pas de droits d'accès en écriture. • Vous n'avez pas signé l'application ou n'avez pas spécifié qu'il s'agit d'une application Adobe AIRI à signer ultérieurement. Création d'un fichier descripteur d'application personnalisé Le fichier descripteur d'application personnalisé est un fichier XML modifiable dans un éditeur de texte. Pour créer un fichier descripteur d'application personnalisé, modifiez les valeurs en fonction de vos besoins. Les valeurs par défaut sont les suivantes : • id = com.adobe.example.swfname • fileName = swfname • name = swfname DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 21 Mise à jour Adobe AIR pour Flash CS3 Professional • version = 1.0 • description = vide • copyright = vide • initialWindow • title = name • 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 Pour plus d'informations sur le fichier descripteur d'application, consultez la section « Définition des propriétés d'une application AIR » à la page 46. Signature de votre application Toutes les applications Adobe AIR doivent être signées avant d'être installées sur un autre système. Flash autorise toutefois la création de fichiers de programme d'installation Adobe AIR non signés pour que l'application puisse être signée ultérieurement. Ces fichiers de programme d'installation Adobe AIR non signés sont appelés package AIRI. Cette capacité se révèle particulièrement utile lorsque le certificat est enregistré sur un autre ordinateur ou lorsque la signature et le développement de l'application sont traités séparément. Signature d'une application Adobe AIR avec un certificat numérique acquis auprès d'une autorité de certification racine 1 Dans la boîte de dialogue AIR - Paramètres de l'application et du programme d'installation, cliquez sur le bouton Définir. La boîte de dialogue Signature numérique apparaît. Cette boîte de dialogue comporte deux boutons radio qui vous permettent de signer l'application Adobe AIR avec un certificat numérique ou de préparer un package AIRI. Si vous signez votre application AIR, vous pouvez utiliser un certificat numérique accordé par une autorité de certification racine ou créer un certificat auto-signé. Il est très simple de créer un certificat auto-signé, mais celui-ci est moins fiable qu'un certificat accordé par une autorité de certification racine. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 22 Mise à jour Adobe AIR pour Flash CS3 Professional Boîte de dialogue Signature numérique permettant de signer une application AIR 2 Sélectionnez un fichier de certificat dans le menu déroulant ou cliquez sur le bouton Parcourir pour en localiser un. 3 Sélectionnez le certificat. 4 Entrez un mot de passe. 5 Cliquez sur OK. Pour plus d'informations sur la signature de votre application AIR, consultez la section « Signature numérique d'un fichier AIR » à la page 328. Création d'un certificat numérique auto-signé 1 Cliquez sur le bouton Créer. La boîte de dialogue Créer un certificat numérique auto-signé apparaît. 2 Renseignez les entrées Nom de l'éditeur, Unité d'organisation, Nom de l'organisation, Pays, Mot de passe et Confirmer le mot de passe. 3 Spécifiez le type de certificat. L'option Type fait référence au niveau de sécurité du certificat : 1024-RSA utilise une clé 1 024 bits (moins sécurisée) et 2048-RSA une clé 2 048 bits (plus sécurisée). 4 Enregistrez les informations dans un fichier de certificat en renseignant l'entrée Enregistrer sous ou en cliquant sur le bouton Parcourir pour localiser un dossier. 5 Cliquez sur OK. 6 Dans la boîte de dialogue Signature numérique, entrez le mot de passe défini à la seconde étape de cette procédure, puis cliquez sur OK. Lorsqu'un certificat numérique a été défini, le bouton Définir est remplacé par le bouton Modifier. Pour que Flash retienne le mot de passe utilisé dans cette session, cliquez sur Mémoriser le mot de passe pour cette session. Si l'option Horodatage est désactivée lorsque vous cliquez sur OK, une boîte de dialogue vous signale que l'application ne pourra pas s'installer après l'expiration du certificat numérique. Si vous cliquez sur Oui en réponse à l'avertissement, l'horodatage est désactivé. Si vous cliquez sur Non, l'option Horodatage est automatiquement sélectionnée et l'horodatage est activé. Pour plus d'informations sur la création d'un certificat numérique auto-signé, consultez la section « Signature numérique d'un fichier AIR » à la page 328. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 23 Mise à jour Adobe AIR pour Flash CS3 Professional Vous pouvez également créer une application AIRI (AIR Intermediate) sans signature numérique. L'utilisateur ne pourra cependant pas installer l'application dans son ordinateur tant que vous n'aurez pas ajouté la signature numérique. Préparation d'un fichier intermédiaire (AIRI) qui sera signé par la suite ❖ Dans la boîte de dialogue Signature numérique, sélectionnez Préparer un fichier AIR intermédiaire (AIRI) qui sera signé par la suite, puis cliquez sur OK. L'état de la signature numérique change pour signaler que vous avez choisi de préparer un package AIRI qui sera signé ultérieurement, et le bouton Définir se transforme en bouton Modifier. 24 Chapitre 7 : Sécurité AIR Cette rubrique aborde les questions de sécurité dont il faut tenir compte lors du développement d'une application AIR. Principes de sécurité AIR Les applications AIR s'exécutent avec les mêmes privilèges utilisateur que les applications natives. En règle générale, ces privilèges prévoient un large accès aux capacités du système d'exploitation, telles que la lecture et l'écriture des fichiers, le démarrage des applications, les dessins sur l'écran et la communication avec le réseau. Les restrictions du système d'exploitation qui se rapportent aux applications natives, tels que les privilèges spécifiques aux utilisateurs, se rapportent également aux applications AIR. Quoique le modèle de sécurité d'Adobe® AIR™ constitue une évolution par rapport à celui d'Adobe® Flash® Player, le contrat de sécurité est différent de celui appliqué au contenu d'un navigateur. Ce contrat offre aux développeurs des moyens sûrs pour accéder à des fonctions beaucoup plus importantes et se lancer dans des expériences beaucoup plus enrichissantes et variées qui ne conviendraient pas à une application basée sur un navigateur. Les applications AIR sont rédigées à l'aide de pseudo-code binaire compilé (contenu SWF) ou de script interprété (JavaScript, HTML) de sorte que le moteur d'exécution fournisse la gestion de la mémoire. Ceci minimise les risques que les applications AIR soient affectées par des vulnérabilités liées à la gestion de la mémoire, comme une surcharge de mémoire tampon ou une détérioration de mémoire. Voilà quelques-unes des vulnérabilités les plus courantes qui affectent les applications d'ordinateur de bureau rédigées en code natif. Installation et mises à jour Les applications AIR sont distribuées par des fichiers d'installation AIR qui utilisent l'extension air. Lorsque Adobe AIR est installé et qu'un fichier d'installation AIR est ouvert, le moteur d'exécution gère le processus d'installation. Remarque : les développeurs peuvent spécifier une version, un nom d'application et une source d'éditeur, mais le flux initial de l'installation de l'application lui-même ne peut pas être modifié. Cette restriction est tout à l'avantage des utilisateurs car toutes les applications AIR partagent une procédure d'installation sûre, continue et stable, gérée par le moteur d'exécution. Si une personnalisation de l'application s'avère nécessaire, cela peut se faire lors de sa première exécution. Emplacement d'installation du moteur d'exécution Les applications AIR demandent que le moteur d'exécution soit installé sur l'ordinateur d'un utilisateur, de même que les fichiers SWF demandent tout d'abord que le module externe du navigateur Flash Player le soit. Le moteur d'exécution est installé à l'emplacement suivant sur l'ordinateur d'un utilisateur : • Mac OS : /Bibliothèque/Frameworks/ • Windows : C:\Program • Linux : /opt/Adobe Files\Common Files\Adobe AIR AIR/ DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 25 Sécurité AIR Sous Mac OS, pour installer une version mise à jour d'une application, l'utilisateur doit disposer de privilèges système appropriés pour accéder au répertoire de l'application. S'il utilise Windows ou Linux, l'utilisateur doit disposer de privilèges d'administrateur. Le moteur d'exécution peut être installé de deux façons : l'utilisation de la fonction d'installation transparente (une installation directe à partir d'un navigateur Web) ou une installation manuelle. Pour plus d'informations, consultez la section « Distribution, installation et exécution d'applications AIR » à la page 318. Installation transparente (moteur d'exécution et application) La fonction d'installation transparente fournit aux développeurs une expérience d'installation continue pour les utilisateurs qui n'ont pas encore Adobe AIR sur leur ordinateur. Dans la méthode d'installation transparente, le développeur crée un fichier SWF qui présente l'application à installer. Lorsqu'un utilisateur clique sur le fichier, celuici tente de détecter le moteur d'exécution. S'il n'est pas détecté, il est installé et immédiatement activé avec le processus d'installation pour l'application du développeur. Installation manuelle D'un autre côté, l'utilisateur peut manuellement télécharger et installer le moteur d'exécution avant d'ouvrir un fichier AIR. Le développeur peut alors distribuer un fichier AIR de différentes façons : par exemple, par e-mail ou un lien HTML sur un site Web. Lorsque le fichier AIR est ouvert, le moteur d'exécution se lance dans l'installation de l'application. Pour plus d'informations sur ce processus, consultez la section « Distribution, installation et exécution d'applications AIR » à la page 318. Flux d'installation de l'application Le modèle de sécurité AIR permet aux utilisateurs de décider s'il y a lieu d'installer une application AIR. L'expérience dans l'installation d'AIR a permis d'apporter plusieurs améliorations par rapport aux technologies d'installation des applications natives, ce qui rend cette décision de confiance plus facile à prendre pour les utilisateurs : • Le moteur d'exécution fournit une expérience d'installation stable sur tous les systèmes d'exploitation, même lorsqu'une application AIR est installée à partir d'un lien dans un navigateur Web. La plupart des expériences d'installation des applications dépendent d'un navigateur ou d'une autre application pour fournir des informations sur la sécurité, si encore elles existent. • L'expérience d'installation de l'application AIR identifie la source de l'application et les informations sur la nature des privilèges disponibles pour l'application, à condition que l'utilisateur permette à l'installation de se poursuivre. • Le moteur d'exécution gère le processus d'installation d'une application AIR. Une application AIR n'est pas en mesure d'intervenir dans le processus d'installation que le moteur d'exécution utilise. En règle générale, les utilisateurs ne devraient pas installer d'application d'ordinateur de bureau qui provient d'une source à laquelle ils ne font pas confiance ou qui ne peut pas être authentifiée. Le fardeau de la preuve sur la sécurité pour les applications natives est également valable pour les applications AIR comme elle l'est pour d'autres applications à installer. Destination de l'application Le répertoire d'installation peut être défini à l'aide de l'une des deux options suivantes : 1 L'utilisateur personnalise la destination au cours de l'installation. L'application s'installe à l'emplacement que lui indique l'utilisateur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 26 Sécurité AIR 2 Si celui-ci ne modifie pas la destination de l'installation, l'application s'installe suivant le chemin par défaut fourni par le moteur d'exécution : • Mac OS : ~/Applications/ • Windows XP (et versions antérieures) : C:\Program Files\ • Windows Vista : ~/Apps/ • Linux : /opt/ Si le développeur spécifie un paramètre installFolder dans le fichier descripteur d'application, l'application s'installe dans un sous-répertoire de ce dossier. Système de fichiers AIR Le processus d'installation pour les applications AIR copie tous les fichiers que le développeur a inclus au sein du fichier d'installation d'AIR dans l'ordinateur local de l'utilisateur. L'application installée est composée des éléments suivants : • Windows : un répertoire qui contient tous les fichiers inclus dans le fichier d'installation d'AIR. Le moteur d'exécution crée aussi un fichier exe au cours de l'installation de l'application AIR. • Linux : un répertoire qui contient tous les fichiers inclus dans le fichier d'installation d'AIR. Le moteur d'exécution crée également un fichier bin au cours de l'installation de l'application AIR. • Mac OS : un fichier app qui reprend tout le contenu du fichier d'installation d'AIR. Il peut être inspecté à l'aide de l'option « Afficher le contenu du package » dans Finder. Le moteur d'exécution crée ce fichier app dans le cadre de l'installation de l'application AIR. Une application AIR est exécutée par : • Windows : l'exécution du fichier .exe dans le dossier install ou un raccourci qui correspond à ce fichier (comme un raccourci dans le menu Démarrer ou sur le Bureau). • Linux : l'exécution du fichier .bin dans le dossier install, la sélection de l'application dans le menu Applications ou l'exécution d'un alias ou d'un raccourci. • Mac OS : l'exécution du fichier .app ou un alias qui pointe dessus. Le système des fichiers d'application contient aussi des sous-répertoires liés à la fonction de l'application. Par exemple, les informations envoyées à la mémoire locale chiffrée sont enregistrées dans un sous-répertoire qui porte le même nom que l'identifiant d'application de l'application. Mémoire de l'application AIR Les applications AIR disposent de privilèges pour écrire dans n'importe quel emplacement du disque dur de l'utilisateur ; toutefois, il est recommandé aux développeurs d'utiliser le chemin app-storage:/ pour le stockage local lié à leur application. Les fichiers écrits dans app-storage:/ à partir d'une application se trouvent à un emplacement standard qui dépend de leur système d'exploitation : • Sous Mac OS : le répertoire de stockage d'une application se nomme <appData>/<appId>/Local Store/, où <appData> correspond au « dossier des préférences » de l'utilisateur, le plus souvent /Utilisateurs/<utilisateur>/Bibliothèque/Preferences • Sous Windows : le répertoire de stockage d'une application se nomme <appData>\<appId>\Local Store\ , où <appData> correspond au « dossier spécial » CSIDL_APPDATA de l'utilisateur, le plus souvent C:\Documents and Settings\<nom d'utilisateur>\Application Data DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 27 Sécurité AIR • Sous Linux : <appData>/<appID>/Local Store/, où <appData> correspond à /home/<utilisateur>/.appdata Vous pouvez accéder au répertoire de stockage de l'application via la propriété air.File.applicationStorageDirectory. Vous pouvez accéder à son contenu à l'aide la méthode resolvePath() de la classe Fichier. Pour plus d'informations, consultez la section « Utilisation du système de fichiers » à la page 108. Mise à jour d'Adobe AIR Lorsque l'utilisateur installe une application AIR qui nécessite une version mise à jour du moteur d'exécution, celui-ci installe automatiquement la version appropriée. Pour mettre à jour le moteur d'exécution, un utilisateur doit disposer des privilèges administrateur pour l'ordinateur. Mise à jour des applications AIR Le développement et le déploiement des mises à jour des logiciels constituent l'un des défis les plus importants dans le domaine de la sécurité auxquels sont confrontées les applications rédigées en code natif. L'interface de programmation AIR fournit un mécanisme pour améliorer cette situation : la méthode Updater.update() peut être appelée lors du lancement afin de vérifier un emplacement distant pour un fichier AIR. Si une mise à jour s'impose, le fichier AIR est téléchargé, installé et l'application redémarre. Les développeurs peuvent utiliser cette classe, non seulement pour obtenir de nouvelles fonctions, mais également pour réagir à des risques de sécurité potentiels. Remarque : les développeurs peuvent spécifier la version d'une application en paramétrant la propriété version du fichier descripteur d'application. AIR n'interprète pas la chaîne de version de quelque façon que ce soit. Par conséquent, la version « 3.0 » n'est pas nécessairement plus récente que la version « 2.0 ». C'est au développeur de maintenir un versionnage significatif. Pour plus d'informations, consultez la section « Définition des propriétés dans le fichier descripteur d'application » à la page 47. Désinstallation d'une application AIR Un utilisateur peut désinstaller une application AIR : • Sous Windows : utilisation du panneau Ajout/Suppression de programmes pour supprimer l'application. • Sous Mac OS : suppression du fichier app de l'emplacement install. La suppression d'une application AIR entraîne celle de tous les fichiers de son répertoire. Toutefois, elle ne supprime pas les fichiers que l'application peut avoir placé hors de ce répertoire. Les changements apportés à des fichiers par l'application AIR hors du répertoire de l'application ne sont pas affectés par une suppression des applications AIR. Désinstallation d'Adobe AIR Pour désinstaller AIR : • Sous Windows : ouvrez la boîte de dialogue Ajout/Suppression de programmes dans le Panneau de configuration, sélectionnez Adobe AIR, puis cliquez sur « Supprimer ». • Sous Mac OS : exécutez l'application Uninstaller d'Adobe AIR dans le répertoire Applications. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 28 Sécurité AIR Paramètres du Registre Windows pour les administrateurs Sous Windows, les administrateurs peuvent configurer une machine pour empêcher (ou permettre) les mises à jour de l'installation de l'application AIR et du moteur d'exécution. Ces paramètres se trouvent dans le Registre Windows sous la clé suivante : HKLM\Software\Policies\Adobe\AIR. Parmi eux figurent : Paramètre du Registre Description AppInstallDisabled Indique que l'installation et la désinstallation de l'application AIR sont autorisées. Définissez sur 0 pour « autorisé » et 1 pour « interdit ». UntrustedAppInstallDisabled Indique que l'installation des applications AIR non approuvées (applications qui ne sont pas dotées d'un certificat approuvé) est autorisée. Consultez la section « Signature numérique d'un fichier AIR » à la page 328. Définissez sur 0 pour « autorisé » et 1 pour « interdit ». UpdateDisabled Indique que la mise à jour du moteur d'exécution est autorisée, soit comme tâche de fond, soit comme faisant partie d'une installation explicite. Définissez sur 0 pour « autorisé » et 1 pour « interdit ». Sandbox AIR fournit une architecture de sécurité qui définit les autorisations en conséquence pour chaque fichier dans une application AIR, interne ou externe. Les autorisations sont accordées aux fichiers suivant leur origine ; ceux-ci sont affectés à des groupements de sécurité logiques appelés sandbox. A propos des sandbox des applications AIR Le modèle de sécurité d'exécution des sandbox est formé du modèle de sécurité de Flash Player et du sandbox de l'application. Les fichiers qui ne se trouvent pas dans le sandbox de l'application sont soumis à des restrictions relatives à la sécurité similaires à celles spécifiées par le modèle de sécurité de Flash Player. Le moteur d'exécution utilise ces sandbox de sécurité pour définir la plage de données à laquelle le code peut accéder et les opérations qu'il peut exécuter. Pour maintenir une sécurité locale, les fichiers de chaque sandbox sont isolés de ceux des autres sandbox. Par exemple, un fichier SWF chargé dans une application AIR à partir d'une URL Internet externe est placée dans un sandbox distant. Il n'a pas l'autorisation par défaut de s'introduire dans les fichiers qui se trouvent dans le répertoire de l'application et qui sont affectés au sandbox de l'application. Le tableau ci-dessous décrit chaque type de sandbox : Sandbox Description application Le fichier se trouve dans le répertoire de l'application et il est doté de la gamme complète des privilèges AIR. distant Le fichier provient d'une URL d'Internet et il fonctionne suivant les règles d'un sandbox basées sur le domaine qui sont analogues à celles qui s'appliquent à des fichiers distants de Flash Player. Il existe des sandbox distants, distincts pour chaque domaine de réseau, comme http://www.example.com et https://foo.example.org. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 29 Sécurité AIR Sandbox Description approuvé localement Le fichier est local et l'utilisateur l'a désigné comme approuvé à l'aide du Gestionnaire des paramètres ou d'un fichier de configuration approuvé de Flash Player. Le fichier peut à la fois lire à partir de sources de données locales et communiquer avec Internet, mais il n'est pas doté de la gamme complète de privilèges AIR. local avec réseau Le fichier est un fichier SWF local publié avec une désignation de réseau, mais il n'a pas été explicitement approuvé par l'utilisateur. Le fichier peut communiquer avec Internet mais il ne peut pas lire les sources de données locales. Ce sandbox n'est disponible que pour un contenu SWF. local avec système de fichiers Le fichier est un fichier local de Programmation qui n'a pas été publié avec une désignation de mise en réseau et il n'a pas été explicitement approuvé par l'utilisateur. Ceci inclut les fichiers JavaScript qui n'ont pas été approuvés. Le fichier peut lire les sources de données locales mais il ne peut pas communiquer avec Internet. Cette rubrique est axée essentiellement sur le sandbox de l'application et ses rapports avec les autres sandbox de l'application AIR. Les développeurs qui utilisent un contenu affecté à un autre sandbox devraient lire la documentation consacrée au modèle de sécurité de Flash Player. Consultez le chapitre Sécurité de Flash Player de la documentation Programmation avec ActionScript 3.0 (http://www.adobe.com/go/flashcs4_prog_as3_security_fr) et le Livre blanc sur la sécurité de Flash Player 9 (http://www.adobe.com/go/fp9_0_security_fr) ou le Livre blanc sur la sécurité de Flash Player 10 (http://www.adobe.com/go/fp10_0_security_fr). Sandbox de l'application Lorsqu'une application est installée, tous les fichiers qui se trouvent dans un fichier d'installation AIR sont installés sur l'ordinateur de l'utilisateur dans le répertoire de l'application. Les développeurs peuvent se référer à ce répertoire dans le code par le modèle d'URL app:/. Consultez la section « Utilisation des modèles d'URL AIR dans les URL » à la page 312. Tous les fichiers qui se trouvent dans l'arborescence du répertoire de l'application sont affectés au sandbox de l'application lorsque celle-ci est exécutée. Le contenu du sandbox de l'application est doté de tous les privilèges disponibles pour une application AIR, y compris l'interaction avec le système des fichiers locaux. De nombreuses applications AIR n'utilisent que ces fichiers installés localement pour exécuter l'application. Toutefois, les applications AIR ne se limitent pas uniquement aux fichiers contenus dans le répertoire de l'application ; elles peuvent charger tout type de fichier à partir de n'importe quelle source. Ceci inclut aussi bien les fichiers locaux par rapport à l'ordinateur de l'utilisateur que ceux accessibles à partir des sources externes, comme ceux sur un réseau local ou sur Internet. Le type de fichier n'a pas d'impact sur les restrictions relatives à la sécurité ; les fichiers HTML chargés sont dotés des mêmes privilèges de sécurité que les fichiers SWF chargés à partir de la même source. Le contenu du sandbox de sécurité de l'application a accès aux interfaces de programmation d'AIR que le contenu des autres sandbox n'est pas autorisé à utiliser. Par exemple, la propriété air.NativeApplication.nativeApplication.applicationDescriptor, qui renvoie les contenus du fichier descripteur d'application pour l'application, est limitée au contenu du sandbox de sécurité de l'application. Un autre exemple d'interface de programmation limitée : la classe FileStream qui contient des méthodes pour la lecture et l'écriture dans le système de fichiers local. Les interfaces de programmation ActionScript qui ne sont disponibles qu'au contenu du sandbox de sécurité de l'application sont signalées par le logo AIR dans leGuide de référence du langage ActionScript 3.0 pour Adobe AIR. L'utilisation de ces interfaces de programmation dans d'autres sandbox provoque le renvoi d'une exception SecurityError. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 30 Sécurité AIR Pour un contenu HTML, dans un objet HTMLLoader, toutes les interfaces de programmation JavaScript d'AIR (celles qui sont disponibles via la propriété window.runtime ou l'objet air lors de l'utilisation du fichier AIRAliases.js), sont mises à la disposition du contenu dans le sandbox de sécurité de l'application. Le contenu HTML dans un autre sandbox n'a pas accès à la propriété window.runtime de sorte que ce contenu ne peut pas avoir accès aux interfaces de programmation AIR. Restrictions relatives à JavaScript et à HTML Pour un contenu HTML dans le sandbox de sécurité de l'application, il existe des limitations dans l'utilisation des interfaces de programmation qui peuvent transformer dynamiquement des chaînes en code exécutable après le chargement du code. Ceci empêche l'application d'injecter (et d'exécuter) du code par inadvertance à partir de sources non-applicatives, comme des domaines du réseau potentiellement non sécurisés. L'utilisation de la fonction eval() en est un exemple. Pour plus de détails, consultez la section « Restrictions relatives au code pour un contenu dans des sandbox différents » à la page 33. Restrictions relatives aux balises img dans le contenu du champ de texte ActionScript Pour prévenir les attaques éventuelles d'hameçonnage, les balises img du contenu HTML des objets TextField d'ActionScript sont ignorées dans un contenu SWF au sein du sandbox de sécurité de l'application. Restrictions relatives au protocole asfunction Le contenu du sandbox de l'application ne peut pas utiliser le protocole asfunction du contenu HTML dans les champs de texte ActionScript 2.0. Aucun accès à la mémoire cache persistante interdomaines Le contenu SWF du sandbox de l'application ne peut pas utiliser la mémoire cache interdomaines, une fonction qui a été ajoutée à Flash Player 9 Mise à jour 3. Cette fonction permet à Flash Player de mettre constamment en mémoire cache le contenu du composant de la plate-forme Adobe et de le réutiliser à la demande dans du contenu SWF chargé. Cela lui évite de recharger le contenu plusieurs fois. Privilèges du contenu dans des sandbox hors application Les fichiers chargés à partir d'un réseau ou d'un site Internet sont affectés au sandbox distant. Ceux chargés à partit d'emplacements hors du répertoire de l'application sont affectés au sandbox local avec système de fichiers, local avec réseau ou approuvé localement ; ceci dépend de la façon dont a été créé le fichier et si l'utilisateur l'a explicitement approuvé par le Gestionnaire de paramètres global de Flash Player. Pour plus d'informations, consultez le site http://www.macromedia.com/support/documentation/fr/flashplayer/help/settings_manager.html. Restrictions relatives à JavaScript et à HTML Contrairement au contenu du sandbox de sécurité de l'application, celui de JavaScript dans un sandbox de sécurité hors application peut à tout moment appeler la fonction eval() pour exécuter dynamiquement le code généré. Toutefois, il existe des restrictions relatives à JavaScript dans un sandbox de sécurité hors application. Ces restrictions sont les suivantes : • Le code JavaScript dans un sandbox hors application n'a pas accès à l'objet window.runtime et, de ce fait, il ne peut pas exécuter d'interfaces de programmation AIR. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 31 Sécurité AIR • Par défaut, le contenu dans un sandbox de sécurité hors application ne peut pas utiliser d'appels XMLHttpRequest pour charger des données à partir d'autres domaines ; il est limité au domaine d'où l'appel est lancé. Toutefois, le code de l'application peut autoriser le contenu hors application de le faire en paramétrant l'attribut allowCrossdomainXHR dans l'image conteneur ou l'iframe. Pour plus d'informations, consultez la section « Programmation entre contenus de différents domaines » à la page 37. • Il existe des restrictions relatives aux appels de la méthode window.open de JavaScript. Pour plus de détails, consultez la section « Restrictions relatives à l'appel de la méthode window.open() de JavaScript » à la page 36. Pour plus de détails, consultez la section « Restrictions relatives au code pour un contenu dans des sandbox différents » à la page 33. Restrictions relatives au chargement d'éléments de CSS, d'image, d'iframe et d'img Un contenu HTML dans un sandbox de sécurité distant (réseau) ne peut charger que du contenu CSS, image, iframe et img à partir d'un domaine distant (à partir d'URL du réseau). Un contenu HTML dans un sandbox local avec système de fichiers, local avec réseau ou approuvé localement ne peut charger que du contenu CSS, image, iframe et img à partir de sandbox locaux (mais pas à partir d'URL d'application ou de réseau). Sécurité HTML Le moteur d'exécution applique des règles et fournit des mécanismes pour compenser des vulnérabilités de sécurité possibles dans HTML et JavaScript. Les mêmes règles s'appliquent que votre application soit rédigée principalement en JavaScript ou que vous chargiez le contenu HTML et JavaScript dans une application basée sur SWF. Un contenu dans le sandbox de l'application et un autre dans un sandbox de sécurité hors application (consultez la section « Sandbox » à la page 28) possèdent des privilèges différents. Lorsque vous chargez un contenu dans une iframe ou une image, le moteur d'exécution fournit un mécanisme pont de sandbox sécurisé qui permet au contenu de l'image ou de l'iframe de communiquer de façon sûre avec le contenu du sandbox de sécurité de l'application. La présente rubrique décrit l'architecture de sécurité de HTML AIR et la façon d'utiliser les iframes, les images et le pont de sandbox pour paramétrer votre application. Pour plus d'informations, consultez la section « Contournement des erreurs JavaScript liées à la sécurité » à la page 239. Aperçu de la configuration de vos applications à base d'HTML Les images et iframes fournissent une structure adéquate pour l'organisation du contenu HTML dans AIR. Les images fournissent des moyens qui permettent à la fois de maintenir la persistance des données et pour travailler de façon sécurisée avec du contenu distant. Comme HTML dans AIR conserve son organisation normale, basée sur des pages, l'environnement HTML est intégralement actualisé si l'image supérieure de votre contenu HTML « navigue » dans une page différente. Vous pouvez utiliser des images et des iframes pour maintenir la persistance des données dans AIR pratiquement de la même façon que vous le feriez pour une application Web qui s'exécuterait dans un navigateur. Définissez les principaux objets de votre application dans l'image supérieure et ils persisteront aussi longtemps que vous n'autoriserez pas l'image à naviguer dans une nouvelle page. Utilisez des images ou des iframes enfant pour charger et afficher des parties transitoires de l'application. Il existe plusieurs façons de maintenir la persistance des données, en plus des images ou bien à leur place. Par exemple, des cookies, des objets locaux partagés, l'emplacement de stockage des fichiers locaux, celui des fichiers chiffrés et celui des bases de données locales. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 32 Sécurité AIR Comme HTML dans AIR conserve sa frontière normale et imprécise entre le code exécutable et les données, AIR place le contenu de l'image supérieure de l'environnement HTML dans le sandbox de l'application. Après l'événement load de la page, AIR restreint toutes les opérations, telles que eval(), susceptibles de convertir une chaîne de texte en un objet exécutable. Cette restriction est imposée même lorsqu'une application ne charge pas du contenu distant. Pour que du contenu HTML distant puissent exécuter ces opérations restreintes, vous devez utiliser des images ou des iframes pour placer le contenu dans un sandbox hors application. (L'exécution de contenu dans une image enfant affectée à un sandbox peut s'avérer nécessaire lorsque vous utilisez des structures d'application JavaScript qui reposent sur la fonction eval().) Pour un répertoire complet des restrictions relatives à JavaScript dans le sandbox de l'application, consultez la section « Restrictions relatives au code pour un contenu dans des sandbox différents » à la page 33. Comme HTML dans AIR conserve sa capacité à charger du contenu distant et possiblement non sécurisé, AIR applique une politique de « même origine » qui empêche le contenu d'un domaine d'interagir avec celui de l'autre. Pour permettre une interaction entre contenu de l'application et contenu d'un autre domaine, vous pouvez configurer un pont qui servira d'interface entre une image parent et une image enfant. Configuration d'un rapport de sandbox parent-enfant AIR ajoute les attributs sandboxRoot et documentRoot aux éléments image et iframe de HTML. Ces attributs vous permettent de traiter le contenu de l'application comme s'il provenait d'un autre domaine : Attribut Description sandboxRoot L'URL à utiliser pour déterminer le sandbox et le domaine dans lesquels placer le contenu de l'image. Les modèles d'URL file:, http: ou https: doivent être utilisés. documentRoot L'URL à partir de laquelle il faut charger le contenu de l'image. Les modèles d'URL app:, http: ou app-storage: doivent être utilisés. L'exemple ci-dessous mappe le contenu installé dans le sous-répertoire du sandbox de l'application qui doit s'exécuter dans le sandbox distant et le domaine www.example.com : <iframe src="ui.html" sandboxRoot="http://www.example.com/local/" documentRoot="app:/sandbox/"> </iframe> Configuration d'un pont entre images parent et enfant dans des sandbox ou des domaines différents AIR ajoute les propriétés childSandboxBridge et parentSandboxBridge à l'objet window de toute image enfant. Ces propriétés vous permettent de définir des ponts qui serviront d'interfaces entre une image parent et une image enfant. Chaque pont ne va que dans une seule direction : childSandboxBridge : la propriété childSandboxBridge permet à l'image enfant de présenter une interface au contenu dans l'image parent. Pour présenter une interface, vous définissez la propriété childSandbox sur une fonction ou un objet dans l'image enfant. Vous pouvez alors accéder à l'objet ou à la fonction à partir du contenu dans l'image parent. L'exemple ci-dessous montre comment un script qui s'exécute dans une image enfant peut présenter un objet contenant une fonction ou une propriété à son parent : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 33 Sécurité AIR var interface = {}; interface.calculatePrice = function(){ return .45 + 1.20; } interface.storeID = "abc" window.childSandboxBridge = interface; Si ce contenu enfant est dans une iframe affectée d'une id child, vous pouvez accéder à l'interface à partir du contenu parent en lisant la propriété childSandboxBridge de l'image : var childInterface = document.getElementById("child").childSandboxBridge; air.trace(childInterface.calculatePrice()); //traces "1.65" air.trace(childInterface.storeID)); //traces "abc" parentSandboxBridge : la propriété parentSandboxBridge permet à l'image parent de présenter une interface au contenu dans l'image enfant. Pour présenter une interface, vous définissez la propriété parentSandbox de l'image enfant sur une fonction ou un object dans l'image parent. Vous pouvez alors accéder à l'objet ou à la fonction à partir du contenu dans l'image enfant. L'exemple ci-dessous montre comment un script qui s'exécute dans l'image parent peut présenter un objet contenant une fonction save à un enfant : var interface = {}; interface.save = function(text){ var saveFile = air.File("app-storage:/save.txt"); //write text to file } document.getElementById("child").parentSandboxBridge = interface; Avec cette interface, le contenu de l'image enfant pourrait enregistrer du texte dans un fichier appelé save.txt. Toutefois, il ne pourrait avoir aucun autre accès au système de fichiers. En règle générale, le contenu de l'application devrait présenter l'interface la plus étroite possible aux autres sandbox. Le contenu enfant pourrait appeler la fonction save comme suit : var textToSave = "A string."; window.parentSandboxBridge.save(textToSave); Si le contenu enfant tente de définir une propriété de l'objetparentSandboxBridge, le moteur d'exécution renvoie une exception SecurityError. Si le contenu parent tente de définir une propriété de l'objetchildSandboxBridge, le moteur d'exécution renvoie une exception SecurityError. Restrictions relatives au code pour un contenu dans des sandbox différents Comme nous l'avons vu dans l'introduction à cette rubrique, « Sécurité HTML » à la page 31, le moteur d'exécution applique les règles et fournit des mécanismes pour compenser les vulnérabilités de sécurité possibles dans HTML et JavaScript. La présente rubrique répertorie ces restrictions. Si le code tente d'appeler ces interfaces de programmation réservées, le moteur d'exécution renvoie une erreur accompagnée du message « Violation des règles de sécurité dans le sandbox de sécurité de l'application par le moteur d'exécution d'Adobe AIR sur du code JavaScript ». Pour plus d'informations, consultez la section « Contournement des erreurs JavaScript liées à la sécurité » à la page 239. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 34 Sécurité AIR Restrictions relatives à l'utilisation de la fonction eval() de JavaScript et de techniques similaires Pour le contenu HTML dans le sandbox de sécurité de l'application, il existe des limites dans l'utilisation des interfaces de programmation susceptibles de transformer dynamiquement les chaînes en code exécutable après le chargement de ce code (après que l'événement onload de l'élément body a été distribué et que l'exécution de la fonction du gestionnaire onload est terminée). Ceci empêche l'application d'injecter (et d'exécuter) du code par inadvertance à partir de sources non-applicatives, comme des domaines du réseau potentiellement non sécurisés. Par exemple, si votre application utilise des données de chaîne à partir d'une source distante pour écrire dans la propriété innerHTML d'un élément DOM, la chaîne pourrait inclure du code exécutable (JavaScript) et susceptible d'exécuter des opérations non sécurisées. Toutefois, tant que le contenu est en cours de chargement, il n'y a pas de risque que des chaînes distantes soient insérées dans le DOM. L'utilisation de la fonction eval() de JavaScript constitue une restriction. Dès que le code du sandbox de l'application est chargé et après le traitement du gestionnaire d'événement onload, vous ne pouvez utiliser la fonction eval() que dans certaines conditions. Les règles suivantes s'appliquent dans l'utilisation de la fonction eval() après le chargement du code à partir du sandbox de sécurité de l'application : • Les expressions contenant des littéraux sont autorisées. Par exemple : eval("null"); eval("3 + .14"); eval("'foo'"); • Les littéraux d'objet sont autorisés, comme dans les cas décrits ci-dessous : { prop1: val1, prop2: val2 } • Les littéraux d'objet de lecture et de définition (getter/setter) sont interdits comme dans les exemples ci-dessous : { get prop1() { ... }, set prop1(v) { ... } } • Les littéraux de tableau sont autorisés, comme dans les cas décrits ci-dessous : [ val1, val2, val3 ] • Les expressions impliquant des lectures de propriété sont interdites comme dans ce qui suit : a.b.c • Le lancement de fonctions est interdit. • Les définitions de fonctions sont interdites. • Le paramétrage de toute propriété est interdit. • Les littéraux de fonctions sont interdits. Toutefois, au cours du chargement du code, avant l'événement onload et au cours de l'exécution de la fonction du gestionnaire d'événement onload, ces restrictions ne s'appliquent pas au contenu du sandbox de sécurité de l'application. Par exemple, après le chargement du code, l'exécution du code ci-dessous dans le moteur d'exécution renvoie une exception. eval("alert(44)"); eval("myFunction(44)"); eval("NativeApplication.applicationID"); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 35 Sécurité AIR Un code généré dynamiquement, comme celui qui est produit par l'appel de la fonction eval(), présenterait un risque pour la sécurité s'il était autorisé au sein du sandbox de l'application. Par exemple, une application peut exécuter par inadvertance une chaîne chargée à partir d'un domaine de réseau et celle-ci peut contenir du code malveillant. Par exemple, il peut s'agir de code conçu pour la suppression ou la modification de fichiers dans l'ordinateur de l'utilisateur. Ou bien encore de code qui renvoie à un domaine de réseau non approuvé une copie du contenu d'un fichier local. Vous trouverez ci-dessous des façons de générer du code dynamique : • Appel de la fonction eval(). • Utilisation des propriétés innerHTML ou des fonctions DOM pour insérer des balises de script qui chargent un script hors du répertoire de l'application. • Utilisation des propriétés innerHTML ou des fonctions DOM pour insérer des balises de script qui possèdent du code incorporé (plutôt que de charger un script au moyen de l'attribut src). • Paramétrage de l'attribut src pour qu'une balise script charge un fichier JavaScript qui est hors du répertoire de l'application. • Utilisation du modèle d'URL de JavaScript comme dans (href="javascript:alert('Test')"). • Utilisation de la fonction setInterval() ou setTimout(), où le premier paramètre (qui définit la fonction pour qu'elle s'exécute de façon asynchrone) est une chaîne (à évaluer) plutôt qu'un nom de fonction (comme dans setTimeout('x = 4', 1000)). • Appel de document.write() ou de document.writeln(). Le code dans le sandbox de sécurité de l'application ne peut utiliser ces méthodes au cours du chargement du contenu. Ces restrictions n'empêchent pas l'utilisation d'eval() avec des littéraux d'objet JSON. Ceci permet au contenu de votre application de travailler avec la bibliothèque JavaScript de JSON. Il vous est néanmoins interdit d'utiliser du code JSON surchargé (avec des gestionnaires d'événement). Pour d'autres structures Ajax et bibliothèques de code JavaScript, assurez-vous que le code de la structure ou de la bibliothèque fonctionne sur du code généré dynamiquement, dans le cadre de ces restrictions. Si ce n'est pas le cas, placez tout contenu qui utilise la structure ou la bibliothèque dans un sandbox de sécurité hors application. Pour plus de détails, consultez la section « Privilèges du contenu dans des sandbox hors application » à la page 30 et « Programmation entre contenu d'application et contenu hors application » à la page 42. Adobe maintient un répertoire de structures Ajax, reconnues pour leur prise en charge du sandbox de sécurité de l'application, à l'adresse http://www.adobe.com/products/air/develop/ajax/features/. Contrairement au contenu du sandbox de sécurité de l'application, celui de JavaScript dans un sandbox de sécurité hors application peut à tout moment appeler la fonction eval() pour exécuter dynamiquement le code généré. Restrictions relatives à l'accès aux interfaces de programmation AIR (pour des sandbox hors application) Le code JavaScript dans un sandbox hors application n'a pas accès à l'objet window.runtime et, de ce fait, il ne peut pas exécuter d'interfaces de programmation AIR. Si un contenu, dans un sandbox de sécurité hors application, appelle le code ci-dessous, l'application renvoie une exception TypeError. try { window.runtime.flash.system.NativeApplication.nativeApplication.exit(); } catch (e) { alert(e); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 36 Sécurité AIR Le type d'exception est TypeError (valeur non définie) parce que le contenu du sandbox hors application ne reconnaît pas l'objet window.runtime de sorte qu'il est considéré comme une valeur non définie. Vous pouvez présenter les fonctionnalités du moteur d'exécution dans un sandbox hors application à l'aide d'un pont de script. Pour plus de détails, consultez la section « Programmation entre contenu d'application et contenu hors application » à la page 42. Restrictions relatives à l'utilisation des appels XMLHttpRequest Le contenu HTML du sandbox de sécurité de l'application utilise des méthodes XMLHttpRequest pour charger des données à partir d'emplacements hors du sandbox de l'application au cours du chargement du contenu HTML et de l'exécution de l'événement onLoad. Par défaut, un contenu HTML dans des sandbox de sécurité hors application n'est pas autorisé à utiliser l'objet XMLHttpRequest de JavaScript pour charger des données à partir des domaines autres que le domaine qui appelle la requête. Une balise image ou iframe peut contenir un attribut allowcrosscomainxhr. La définition de cet attribut sur toute valeur non-nulle permet au contenu de l'image ou de l'iframe d'utiliser l'objet XMLHttpRequest de JavaScript pour charger les données à partir des domaines autres que celui du code qui appelle la requête. <iframe id="UI" src="http://example.com/ui.html" sandboxRoot="http://example.com/" allowcrossDomainxhr="true" documentRoot="app:/"> </iframe> Pour plus d'informations, consultez la section « Programmation entre contenus de différents domaines » à la page 37. Restrictions relatives au chargement d'éléments de CSS, d'image, d'iframe et d'img (pour un contenu dans des sandbox hors application) Un contenu HTML dans un sandbox de sécurité distant (réseau) ne peut charger que du contenu CSS, image, iframe et img à partir de sandbox distants (à partir d'URL du réseau). Un contenu HTML dans un sandbox local avec système de fichiers, local avec réseau ou approuvé localement ne peut charger que du contenu CSS, image, iframe et img à partir de sandbox locaux (mais pas à partir de sandbox d'application ou distants). Restrictions relatives à l'appel de la méthode window.open() de JavaScript Si une fenêtre créée par un appel à la méthode window.open() de JavaScript affiche un contenu à partir d'un sandbox de sécurité hors application, le titre de la fenêtre commence par celui de la fenêtre principale (de lancement), suivi du caractère deux points (:). Il n'est pas possible d'utiliser du code pour retirer cette partie du titre de l'écran. Le contenu d'un sandbox de sécurité hors application ne peut réussir un appel à la méthode window.open() de JavaScript que s'il répond à un événement déclenché par la souris ou le clavier de l'utilisateur. Cette condition permet d'éviter qu'un contenu hors application ne crée des fenêtres qui pourraient être utilisées de façon trompeuse, par exemple pour des attaques d'hameçonnage. En outre, le gestionnaire d'événement pour l'événement de la souris ou du clavier ne peut pas paramétrer la méthode window.open() pour qu'elle s'exécute au bout d'un certain temps, par exemple en appelant la fonction setTimeout(). Le contenu d'un sandbox distant (réseau) ne peut utiliser la méthode window.open() que pour ouvrir le contenu dans un sandbox de réseau distant. Il ne peut pas utiliser cette méthode pour ouvrir du contenu à partir de l'application ou d'un sandbox local. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 37 Sécurité AIR Un contenu dans un sandbox local avec système de fichiers, local avec réseau ou approuvé localement (consultez la section « Sandbox » à la page 28) ne peut utiliser la méthode window.open() que pour ouvrir un contenu dans un sandbox local. Il ne peut pas utiliser cette méthode pour ouvrir du contenu à partir de l'application ou d'un sandbox distant. Erreurs lors de l'appel de code interdit Si vous appelez du code interdit d'exécution dans un sandbox en raison de ces restrictions liées à la sécurité, le moteur d'exécution distribue une erreur JavaScript : « Violation des règles de sécurité dans le sandbox de sécurité de l'application par le moteur d'exécution d'Adobe AIR sur du code JavaScript ». Pour plus d'informations, consultez la section « Contournement des erreurs JavaScript liées à la sécurité » à la page 239. Protection du sandbox lors du chargement de contenu HTML depuis une chaîne La méthode loadString() de la classe HTMLLoader vous permet de créer du contenu HTML au moment de l'exécution. Toutefois, les données utilisées comme contenu HTML peuvent être corrompues lorsqu'elles sont chargées à partir d'une source Internet non sécurisée. De ce fait, par défaut, le contenu HTML créé à l'aide de la méthode loadString() n'est pas placé dans le sandbox de l'application et n'a pas accès aux API AIR. Vous pouvez cependant définir la propriété placeLoadStringContentInApplicationSandbox d'un objet HTMLLoader sur true pour placer le contenu HTML créé avec la méthode loadString() dans le sandbox de l'application. Pour plus d'informations, consultez la section « Chargement de contenu HTML depuis une chaîne » à la page 237. Programmation entre contenus de différents domaines Les applications AIR disposent de privilèges spéciaux lorsqu'elles sont installées. Il est essentiel que les mêmes privilèges ne soient pas dévoilés à un autre contenu, y compris les fichiers distants et les fichiers locaux qui ne font pas partie de l'application. A propos du pont de sandbox AIR Généralement, le contenu d'un autre domaine ne peut pas appeler de scripts d'autres domaines. Pour protéger les applications AIR d'une divulgation accidentelle d'informations ou de contrôles privilégiés, les restrictions suivantes sont placées dans le contenu du sandbox de sécurité de l'application (contenu installé avec l'application) : • Le code dans le sandbox de sécurité de l'application ne peut pas autoriser l'accès aux autres sandbox par un appel à la méthode Security.allowDomain(). L'appel à cette méthode depuis le sandbox de sécurité de l'application renvoie une erreur. • Il est impossible d'importer un contenu hors application dans un sandbox de l'application en paramétrant la propriété LoaderContext.securityDomain ou LoaderContext.applicationDomain. Il subsiste encore des situations où l'application AIR principale demande un contenu à partir du domaine distant pour avoir un accès contrôlé à des scripts de celle-ci, ou vice-versa. Pour ce faire, le moteur d'exécution fournit un mécanisme de pont de sandbox qui sert de passerelle entre deux sandbox. Un pont de sandbox peut fournir une interaction explicite entre sandbox de sécurité distant et d'application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 38 Sécurité AIR Le pont de sandbox présente deux objets auxquels les scripts chargés et en cours de chargement peuvent tous deux accéder : • L'objet parentSandboxBridge permet au contenu en cours de chargement de présenter des propriétés et des fonctions à des scripts du contenu chargé. • L'objet childSandboxBridge permet au contenu chargé de présenter des propriétés et des fonctions à des scripts dans le contenu en cours de chargement. Ce sont les valeurs et non les références qui sont transmises par le pont de sandbox. Toutes les données sont sérialisées. Ce qui signifie que les objets présentés par l'un des côtés du pont ne peuvent pas être définis par l'autre et qu'aucun des objets présentés n'est typé. De plus, vous ne pouvez présenter que des objets et des fonctions simples (pas complexes). Si le contenu enfant tente de définir une propriété de l'objetparentSandboxBridge, le moteur d'exécution renvoie une exception SecurityError. De même, si le contenu parent tente de définir une propriété de l'objetchildSandboxBridge, le moteur d'exécution renvoie une exception SecurityError. Exemple de pont de sandbox (SWF) Supposez qu'une application de disquaire AIR souhaite autoriser des fichiers distants à diffuser le prix des albums, mais qu'il ne souhaite pas que le fichier SWF distant dévoile s'il s'agit d'un prix de vente. Pour ce faire, une classe StoreAPI fournit une méthode d'acquisition de prix tout en masquant le prix de vente. Une occurrence de cette classe StoreAPI est alors affectée à la propriété parentSandboxBridge de l'objet LoaderInfo dont l'objet Loader charge le fichier SWF distant. Voici le code pour le disquaire AIR : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 39 Sécurité 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'objet StoreAPI appelle l'application principale pour récupérer le prix courant de l'album mais renvoie « Non disponible » lorsque la méthode getSaleAlbumPrice() est appelée. Le code ci-dessous définit la classe StoreAPI : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 40 Sécurité 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(); } } Le code suivant représente un exemple d'un fichier SWF PriceQuoter qui rend compte du prix du disquaire mais pas de celui de la vente. 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()); } } } Exemple de pont de sandbox (HTML) Dans un contenu HTML, les propriétés parentSandboxBridge et childSandboxBridge sont ajoutées à l'objet Window de JavaScript d'un document enfant. Pour un exemple sur la façon de configurer des fonctions de pont dans un contenu HTML, consultez la section « Configuration d'une interface de pont de sandbox » à la page 254. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 41 Sécurité AIR Limitation de l'exposition de l'interface de programmation Lorsque vous présentez des ponts de sandbox, il est important de présenter des interfaces de programmation de haut niveau qui limitent le degré d'exposition à des abus. Nous vous rappelons que le contenu qui appelle votre implémentation de pont peut être en danger (par exemple, par une injection de code). Ainsi, par exemple, la présentation de la méthode readFile(path:String) (qui lit le contenu d'un fichier arbitraire) par un pont est exposé à un risque. Il serait préférable de présenter une interface de programmation readApplicationSetting() qui ne suit pas un chemin mais qui lit un fichier spécifique. L'approche plus sémantique limite les dommages qu'une application peut causer dès qu'une de ses parties est affectée. Voir aussi « Programmation croisée du contenu dans des sandbox de sécurité distincts » à la page 252 « Sandbox de l'application » à la page 29 « Privilèges du contenu dans des sandbox hors application » à la page 30 Ecriture sur les disques Les applications qui s'exécutent dans un navigateur Web n'ont qu'une interaction limitée avec le système de fichiers local de l'utilisateur. Les navigateurs Web implémentent des stratégies de sécurité qui garantissent que l'ordinateur de l'utilisateur ne peut pas être mis en danger à la suite du chargement d'un contenu du Web. Par exemple, les fichiers SWF qui passent par Flash Player dans un navigateur ne peuvent pas interagir directement avec des fichiers qui se trouvent déjà sur l'ordinateur d'un utilisateur. Les objets partagés et les cookies peuvent être écrits dans l'ordinateur d'un utilisateur dans le but de maintenir les préférences et les données de l'utilisateur, mais il s'agit là de la limite de l'interaction avec le système de fichiers. Comme les applications AIR sont installées en mode natif, ils possèdent un contrat de sécurité différent, celui qui inclut la possibilité de lire et d'écrire dans tout le système de fichiers local. Cette liberté s'accompagne d'une grande responsabilité de la part des développeurs. Les insécurités accidentelles de l'application compromettent non seulement la fonctionnalité de l'application, mais aussi l'intégrité de l'ordinateur de l'utilisateur. C'est pourquoi les développeurs devraient lire la section « Recommandations destinées aux développeurs en matière de sécurité » à la page 43. Les développeurs AIR peuvent accéder à des fichiers du système de fichiers local et en placer dans ce système à l'aide de plusieurs conventions de modèles d'URL : Modèle d'URL Description app:/ Un alias du répertoire de l'application. Les fichiers auxquels on accède à partir de ce chemin sont affectés au sandbox de l'application et sont dotés du maximum de privilèges par le moteur d'exécution. app-storage:/ Un alias du répertoire de stockage local de l'application, standardisé par le moteur d'exécution. Les fichiers auxquels on accède à partir de ce chemin sont affectés au sandbox hors application. file:/// Un alias qui représente la racine du disque dur de l'utilisateur. Un fichier auquel on accède à partir de ce chemin est affecté à un sandbox de l'application si le fichier existe dans le répertoire de l'application et à un sandbox hors application dans les autres cas. Remarque : les applications AIR ne peuvent pas modifier le contenu à l'aide du modèle d'URL app:. De plus, le répertoire de l'application peut être lu uniquement en raison des paramètres de l'administrateur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 42 Sécurité AIR A moins qu'il n'existe des restrictions de l'administrateur à propos de l'ordinateur de l'utilisateur, les applications AIR détiennent le privilège d'écrire sur tout emplacement du disque dur de l'utilisateur. Les développeurs sont informés d'utiliser le chemin app-storage:/ pour le stockage local lié à leur application. Les fichiers écrits sur app-storage:/ à partir d'une application sont placés dans un emplacement standard : • Sous Mac OS : le répertoire de stockage d'une application se nomme <appData>/<appId>/Local Store/, où <appData> représente le dossier des préférences de l'utilisateur. Il s'agit le plus souvent de /Utilisateurs/<utilisateur>/Bibliothèque/Preferences • Sous Windows : le répertoire de stockage d'une application se nomme <appData>/<appId>/Local Store/, où <appData> représente le dossier spécial CSIDL_APPDATA de l'utilisateur. Il s'agit le plus souvent de C:\Documents and Settings\<nom d'utilisateur>\Application Data • Sous Linux : <appData>/<appID>/Local Store/, où <appData> correspond à /home/<utilisateur>/.appdata Si une application est conçue pour interagir avec des fichiers existants dans le système de fichiers de l'utilisateur, prenez soin de lire les « Recommandations destinées aux développeurs en matière de sécurité » à la page 43. Utilisation sécurisée d'un contenu non approuvé Un contenu qui n'est pas affecté au sandbox de l'application peut fournir des fonctionnalités supplémentaires à votre application, mais uniquement s'il respecte les critères de sécurité du moteur d'exécution. La présente rubrique décrit le contrat de sécurité AIR avec un contenu hors application. Security.allowDomain() Les applications AIR limitent la programmation de l'accès au contenu hors application de façon plus rigoureuse que le module externe du navigateur de Flash Player ne le fait pour du contenu non approuvé. Par exemple, dans le Flash Player du navigateur, lorsqu'un fichier SWF affecté au sandbox approuvé localement appelle la méthode System.allowDomain(), la programmation de l'accès est autorisée à tout SWF chargé à partir du domaine spécifié. L'approche analogue à partir du contenu de l'application dans les applications AIR n'est pas permise, car cela consisterait à autoriser un accès déraisonnable au fichier hors application dans le système de fichiers de l'utilisateur. Les fichiers distants ne peuvent pas accéder directement au sandbox de l'application, quels que soient les appels à la méthode Security.allowDomain(). Programmation entre contenu d'application et contenu hors application Les applications AIR qui programment entre contenu d'application et contenu hors application disposent de mécanismes de sécurité plus complexes. Les fichiers qui ne sont pas dans le sandbox de l'application ne sont autorisés à accéder aux propriétés et méthodes des fichiers dans le sandbox de l'application que par l'utilisation d'un pont de sandbox. Un pont de sandbox agit en tant que passerelle entre contenu de l'application et contenu hors application. Il fournit ainsi une interaction explicite entre les deux fichiers. Lorsqu'ils sont utilisés correctement, les ponts de sandbox procurent une couche supplémentaire de sécurité pour empêcher un contenu hors application d'accéder à des références d'objets qui font partie du contenu de l'application. L'avantage que peut présenter un pont de sandbox est très bien décrit par un exemple. Supposez qu'une application de disquaire AIR souhaite fournir une interface de programmation à des publicitaires voulant créer leurs propres fichiers SWF qui leur permettront de communiquer avec l'application du disquaire. Celui-ci veut fournir aux publicitaires des méthodes pour rechercher des artistes et des CD du magasin. Mais il veut aussi isoler quelques méthodes et propriétés du fichier SWF tiers, pour des raisons de sécurité. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 43 Sécurité AIR Cette possibilité existe avec un pont de sandbox. Par défaut, un contenu chargé de l'extérieur dans une application AIR à l'exécution n'a accès à aucune méthode ou propriété de l'application principale. Avec une implémentation de pont de sandbox personnalisé, un développeur peut fournir des services au contenu distant sans exposer ces méthodes et propriétés. Considérez le pont de sandbox comme une voie entre contenu approuvé et non approuvé qui fournit une communication entre le contenu chargé et le contenu récepteur sans présenter de références d'objet. Pour plus d'informations sur la façon d'utiliser les ponts de sandbox en toute sécurité, consultez la section « Programmation entre contenus de différents domaines » à la page 37. Protection contre la génération dynamique de contenu SWF à risque La méthode Loader.loadBytes() fournit un moyen pour une application de générer un contenu SWF à partir d'un tableau d'octets. Cependant, des attaques par injection sur des données chargées à partir de sources distantes pourraient causer des dommages sérieux lors du chargement du contenu. Ceci est particulièrement valable lors du chargement des données dans le sandbox de l'application où le contenu SWF généré peut accéder à l'ensemble des interfaces de programmation d'AIR au complet. Il existe des conditions légitimes pour utiliser la méthode loadBytes() sans générer de code SWF exécutable. Vous pouvez utiliser cette méthode pour générer des données d'image afin de contrôler le délai d'affichage de celle-ci, par exemple. Il y a aussi des situations légitimes qui dépendent effectivement de l'exécution du code, comme la création dynamique de contenu SWF pour de la lecture audio. Dans AIR, par défaut, la méthode loadBytes() ne vous permet pas de charger un contenu SWF ; il ne vous permet que de charger un contenu d'image. Dans AIR, la propriété loaderContext de la méthode loadBytes() possède une propriété allowLoadBytesCodeExecution que vous pouvez définir sur true afin d'autoriser explicitement l'application à utiliser loadBytes() pour charger un contenu SWF exécutable. Le code ci-dessous montre comment utiliser cette fonction : var loader:Loader = new Loader(); var loaderContext:LoaderContext = new LoaderContext(); loaderContext.allowLoadBytesCodeExecution = true; loader.loadBytes(bytes, loaderContext); Si vous appelez loadBytes() pour charger un contenu SWF et que la propriété allowLoadBytesCodeExecution de l'objet LoaderContext est définie sur false (valeur par défaut), l'objet Loader renvoie une exception SecurityError. Remarque : dans une version ultérieure d'Adobe AIR, cette interface de programmation pourrait changer. Lorsque cela se produira, il vous sera peut-être nécessaire de recompiler le contenu qui utilise la propriété allowLoadBytesCodeExecution de la classe LoaderContext. Recommandations destinées aux développeurs en matière de sécurité Bien que les applications AIR soient créées à l'aide des technologies du Web, il est important pour les développeurs de noter qu'ils ne travaillent pas au sein du sandbox de sécurité du navigateur. Ceci signifie qu'il est possible de créer des applications qui n'endommagent pas le système local, intentionnellement ou non. AIR tente de minimiser ce risque, mais il y a toujours moyen d'introduire des vulnérabilités. La présente rubrique décrit les risques potentiels en matière de sécurité. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 44 Sécurité AIR Risque lors de l'importation de fichiers dans un sandbox de sécurité de l'application Les fichiers qui existent dans le répertoire de l'application sont affectés au sandbox de l'application et ils disposent des privilèges du moteur d'exécution au complet. Les applications qui écrivent dans le système de fichiers local devraient plutôt écrire dans app-storage:/. Ce répertoire est distinct des fichiers d'application puisqu'il se trouve sur l'ordinateur de l'utilisateur. De ce fait, les fichiers n'étant pas affectés au sandbox de l'application, ils présentent un risque réduit en matière de sécurité. Il est recommandé aux développeurs de tenir compte des éléments suivants : • N'incluez un fichier dans un fichier AIR (de l'application installée) que si c'est absolument nécessaire. • N'incluez un fichier de programmation dans un fichier AIR (de l'application installée) que si son comportement est bien compris et approuvé. • Il ne faut pas écrire ou modifier de contenu dans le répertoire de l'application. Le moteur d'exécution empêche les applications d'écrire ou de modifier des fichiers et des répertoires à l'aide du modèle d'URL app:/ en renvoyant une exception SecurityError. • N'utilisez pas de données, provenant d'une source de réseau, comme paramètres pour les méthodes de l'interface de programmation AIR qui pourraient conduire à une exécution du code. Ce point est également valable pour la méthode Loader.loadBytes() et la fonction eval() de JavaScript. Risque lors de l'utilisation d'une source externe pour déterminer des chemins Une application AIR court un risque lors de l'utilisation de données ou de contenu externes. C'est pourquoi il faut prendre grand soin lors de l'utilisation de données qui proviennent du réseau ou du système de fichiers. C'est au développeur en fin de compte qu'incombe la charge de confiance et les communications du réseau qui sont utilisées ; mais le chargement de données étrangères est risqué par nature et ne devrait pas se faire dans le cadre d'opérations critiques. Les mises en garde suivantes s'adressent aux développeurs : • Utilisation de données provenant d'une source du réseau pour déterminer un nom de fichier • Utilisation de données provenant d'une source du réseau pour créer une URL à laquelle l'application fait appel pour envoyer des informations de nature privée Risques lors de l'utilisation, du stockage ou de la transmission d'informations d'identification non sécurisées Le stockage des informations d'identification de l'utilisateur sur son système de fichiers local introduit par nature un grand risque. Il est recommandé aux développeurs de tenir compte des éléments suivants : • Si les informations d'identification doivent être stockées localement, chiffrez-les lorsque vous écrivez dans le système de fichiers local. Le moteur d'exécution fournit, par la classe EncryptedLocalStore, un emplacement de stockage unique pour chaque application installée Pour plus de détails, consultez la section « Stockage des données chiffrées » à la page 219. • Ne transmettez pas d'informations d'identification non chiffrées à une source du réseau à moins que celle-ci ne soit approuvée. • Ne spécifiez jamais un mot de passe par défaut lors de la création d'informations d'identification ; laissez l'utilisateur créer les siennes. Les utilisateurs qui ne modifient pas les éléments par défaut exposent leurs informations d'identification à un attaquant qui connaît déjà le mot de passe par défaut. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 45 Sécurité AIR Risque d'attaque par rétrogradation de version Au cours de l'installation de l'application, le moteur d'exécution s'assure qu'une version de l'application n'est pas actuellement installée. Si elle l'est déjà, le moteur d'exécution compare la chaîne de la version à la version en cours d'installation. S'il y a une différence, l'utilisateur peut choisir de mettre à niveau son installation. Le moteur d'exécution ne peut pas garantir que la version nouvellement installée soit plus récente que la précédente, seulement qu'elle est différente. Un attaquant peut distribuer une version antérieure à l'utilisateur pour contourner une faiblesse dans la sécurité. C'est pourquoi il est recommandé au développeur de vérifier la version lorsque l'application est exécutée. Il est également utile que les applications vérifient le réseau pour des mises à jour. Ainsi, même si un attaquant parvient à faire exécuter une version antérieure à un utilisateur, celle-ci se rendra compte qu'elle a besoin d'une mise à jour. De plus, la mise en place d'un modèle de contrôle de version pour l'application rend plus difficile l'utilisation d'une ruse pour pousser un utilisateur à installer une version antérieure. Pour plus de détails sur la fourniture de versions d'application, consultez la section « Définition des propriétés dans le fichier descripteur d'application » à la page 47. Signature du code Tous les fichiers du programme d'installation AIR sont tenus de contenir du code signé. La signature du code est un processus cryptographique qui confirme que l'origine spécifiée du logiciel est exacte. Les applications AIR peuvent être signées soit par une liaison à un certificat provenant d'une Autorité de certification (AC), soit par la création de votre propre certificat. Un certificat commercial délivré par une AC bien connue est fortement recommandé. Il garantit à vos utilisateurs qu'ils installent votre application et non pas une contrefaçon. Cependant, des certificats auto-signés peuvent être créés à l'aide d'adt à partir du SDK ou à l'aide de Flash, Flash Builder ou toute autre application qui utilise adt pour la génération de certificats. Les certificats auto-signés ne garantissent pas que l'application en cours d'installation soit authentique. Pour plus d'informations sur les applications AIR signées numériquement, consultez les sections « Signature numérique d'un fichier AIR » à la page 328 et « Création d'une application AIR à l'aide des outils de ligne de commande » à la page 363. 46 Chapitre 8 : Définition des propriétés d'une application AIR Outre tous les fichiers et autres ressources qui composent une application AIR, chaque application AIR requiert un fichier descripteur. Le fichier descripteur d'une application est un fichier XML qui définit les propriétés de base de cette dernière. Lors du développement d'applications AIR avec la mise à jour Adobe® AIR™ pour Adobe® Flash® CS3 Professional ou Adobe® Flash® CS4 Professional, le fichier descripteur d'application est automatiquement généré à la création du projet AIR. Pour modifier les paramètres du descripteur d'application, vous utilisez un panneau auquel vous accédez via le menu Commandes > AIR - Paramètres de l'application et du programme d'installation. Vous pouvez également modifier manuellement le fichier descripteur d'application. Structure du fichier descripteur d'application Le fichier descripteur d'application contient des propriétés qui affectent l'application entière, telles que son nom, sa version, son copyright, etc. Vous pouvez attribuer n'importe quel nom à un fichier descripteur d'application. Lorsque vous créez un fichier AIR en utilisant les paramètres par défaut de Flash CS3 ou CS4, le nom du fichier descripteur d'application est remplacé par application.xml. Il est ensuite placé dans un répertoire spécial au sein du package AIR. Exemple de fichier descripteur d'application : <?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> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 47 Définition des propriétés d'une application AIR <maxSize>1280 960</maxSize> </initialWindow> <installFolder>Example Co/Hello World</installFolder> <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> Définition des propriétés dans le fichier descripteur d'application Utilisez les éléments XML et les attributs du fichier descripteur d'application pour définir les types de propriétés suivants de votre application AIR : • Version du moteur d'exécution AIR requise • Identité de l'application • Dossiers d'installation et de menus du programme • Propriétés initiales des fenêtres et du contenu • Fichiers d'icônes de l'application • Si votre application fournit une interface utilisateur personnalisée • Si votre application peut être invoquée par le contenu SWF exécuté dans le navigateur de l'utilisateur • Associations de types de fichiers Définition de la version AIR requise L'attribut de l'élément racine d'un fichier descripteur d'application, application, spécifie la version du moteur d'exécution AIR requise : <application xmlns="http://ns.adobe.com/air/application/1.5"> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 48 Définition des propriétés d'une application AIR xmlns Espace de nom AIR, que vous devez définir en tant qu'espace de nom XML par défaut. L'espace de nom est modifié pour chaque nouvelle version majeure d'AIR (mais non pour les correctifs mineurs). Le dernier segment de l'espace de nom, tel que « 1.5 », indique la version du moteur d'exécution requise par l'application. Si votre application utilise l'une des nouvelles fonctions d'AIR 1.5, assurez-vous de définir l'espace de nom sur AIR 1.5 (« http://ns.adobe.com/air/application/1.5 »). Dans le cas des applications de type SWF, la version du moteur d'exécution AIR spécifiée dans le descripteur d'application détermine la version SWF maximale pouvant être chargée en tant que contenu initial de l'application. Les applications qui spécifient AIR 1.0 ou AIR 1.1 ne peuvent utiliser que des fichiers SWF9 (Flash Player 9) en tant que contenu initial, même en cas d'exécution avec le moteur d'exécution AIR 1.5. Les applications qui spécifient AIR 1.5 peuvent utiliser des fichiers SWF9 ou SWF10 (Flash Player 10) en tant que contenu initial. La version SWF détermine la version des API AIR et Flash Player disponibles. Lorsqu'un fichier SWF9 est utilisé en tant que contenu initial d'une application AIR 1.5, cette application n'a accès qu'aux API AIR 1.1 et Flash Player 9. De plus, les modifications de comportement apportées aux API existantes dans AIR 1.5 ou Flash Player 10 n'ont aucun effet. (Les modifications de sécurité importantes apportées aux API sont une exception à ce principe et peuvent être appliquées de façon rétroactive aux correctifs présents ou futurs du moteur d'exécution.) Pour les applications de type HTML, la version du moteur d'exécution spécifiée dans le descripteur d'application luimême détermine la version des API AIR et Flash Player disponibles pour l'application. Les comportements HTML, CSS et JavaScript sont toujours déterminés par la version du WebKit utilisée dans le moteur d'exécution AIR installé et non par le descripteur d'application. Lorsqu'une application AIR charge du contenu SWF, la version des API AIR et Flash Player disponibles pour ce contenu dépend de la manière dont le contenu est chargé. Le tableau suivant montre comment la version de l'API est déterminée en fonction de la méthode de chargement : Méthode de chargement du contenu Méthode de détermination de la version de l'API Contenu initial, application de type SWF Version SWF du fichier loaded Contenu initial, application de type HTML Espace de nom du descripteur d'application SWF chargé par le contenu SWF Version du contenu loading Bibliothèque SWF chargée par le contenu HTML via la balise <script> Espace de nom du descripteur d'application SWF chargé par le contenu HTML , via les API AIR Espace de nom du descripteur d'application ou Flash Player (par exemple flash.display.Loader) SWF chargé par le contenu HTML via les balises <object> ou <embed> (ou les API JavaScript équivalentes) Version SWF du fichier loaded Lors du chargement d'un fichier SWF d'une version différente de celle du contenu en cours de chargement, deux problèmes peuvent survenir : • Chargement de contenu SWF10 par SWF9 (ou antérieur) (Les références aux API AIR 1.5 et Flash Player 10 du contenu chargé ne sont pas résolues.) • Chargement de contenu SWF9 (ou antérieur) par SWF10 (Les API modifiées dans AIR 1.5 et Flash Player 10 peuvent se comporter de façon imprévue pour le contenu chargé.) minimumPatchLevel Facultatif. L'attribut minimumPatchLevel permet de définir le niveau minimal du correctif d'Adobe AIR requis par l'application. Les applications AIR indiquent généralement la version d'AIR requise en définissant simplement l'espace de nom dans le fichier descripteur d'application. L'espace de nom est modifié pour chaque version majeure d'AIR (telle que 1.0 ou 1.5). L'espace de nom n'est pas modifié pour les correctifs. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 49 Définition des propriétés d'une application AIR Les correctifs ne contiennent qu'un nombre limité de corrections et aucune modification de l'API. En règle générale, les applications n'indiquent pas la version du correctif requise. Toutefois, une correction intégrée à un correctif règle parfois un problème affectant une application. Dans ce cas de figure, une application peut indiquer la valeur de l'attribut minimumPatchLevel pour s'assurer que le correctif correspondant est appliqué avant l'installation de l'application. Le programme d'installation de l'application AIR invite l'utilisateur à télécharger et installer la version ou le correctif requis, le cas échéant. L'exemple suivant illustre un élément d'application qui définit la valeur de l'attribut minimumPatchLevel : <application xmlns="http://ns.adobe.com/air/application/1.1" minimumPatchLevel="5331"> Définition de l'identité de l'application Les éléments suivants définissent l'ID, la version, le nom, le nom de fichier, la description et le copyright d'une application : <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 Chaîne d'identifiant propre à l'application, appelée l'ID d'application. La valeur de l'attribut ne contient que les caractères suivants : • 0–9 • a–z • A–Z • . (point) • - (tiret) La valeur doit comporter entre 1 et 212 caractères. Cet élément est obligatoire. La chaîne id utilise généralement une arborescence séparée par un point, à l'instar d'une adresse de nom de domaine DNS inversée, un nom de classe ou de package Java™ ou un identifiant de type universel Mac OS® X. Le format de type DNS n'est pas imposé et AIR ne crée pas d'association entre le nom et les domaines DNS en tant que tels. version Identifie la version de l'application, qui ne se réfère pas à la version du moteur d'exécution. La chaîne version est un indicateur défini par l'application. AIR n'interprète pas la chaîne de version. De ce fait, la version « 3.0 » n'est pas considérée comme étant plus récente que la version « 2.0 ». Exemples : « 1.0 », « .4 », « 0.5 », « 4.9 », « 1.3.4a ». Cet élément est obligatoire. filename Chaîne à utiliser en tant que nom de fichier de l'application (sans extension) lors de l'installation de cette dernière. Le fichier d'application démarre l'application AIR dans le moteur d'exécution. Si aucune valeur name n'est définie, l'élément filename fait également office de nom du dossier d'installation. Cet élément est obligatoire. La propriété filename peut contenir tout caractère Unicode (UTF-8), à l'exception des caractères suivants, dont l'utilisation est interdite dans les noms de fichier dans divers systèmes de fichiers : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 50 Définition des propriétés d'une application AIR Caractère Code hexadécimal divers 0x00 – x1F * x2A " x22 : x3A > x3C < x3E ? x3F \ x5C | x7C Le dernier caractère de la valeur filename ne doit pas correspondre à un point. name (facultatif, mais recommandé) Titre affiché par le programme d'installation de l'application AIR. Si vous indiquez un nœud texte unique (au lieu de plusieurs éléments text), le programme d'installation de l'application AIR utilise ce nom, quelle que soit la langue système activée : <name>Test Application</name> Le modèle de descripteur d'application AIR 1.0 ne permet de définir qu'un seul nœud texte simple en tant que nom (plutôt que plusieurs éléments text). Dans AIR 1.1 (ou version ultérieure), il est possible de spécifier plusieurs langues dans l'élément name. Ainsi, l'exemple suivant stipule le nom en trois langues (anglais, français et espagnol) : <name> <text xml:lang="en">Hello AIR</text> <text xml:lang="fr">Bonjour AIR</text> <text xml:lang="es">Hola AIR</text> </name> L'attribut xml:lang de chaque élément text définit un code de langue, comme indiqué à l'adresse suivante RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Le programme d'installation d'une application AIR utilise le nom le plus proche de la langue de l'interface utilisateur du système d'exploitation de l'utilisateur. Prenons l'exemple d'une installation dans laquelle l'élément name du fichier descripteur d'application comprend une valeur pour le jeu de paramètres régionaux en (anglais). Le programme d'installation d'une application AIR utilise le nom en si le système d'exploitation identifie en (anglais) en tant que langue de l'interface utilisateur. Il utilise également le nom en si la langue de l'interface utilisateur système correspond à en-US (anglais américain). Toutefois, si la langue de l'interface utilisateur correspond à en-US et que le fichier descripteur d'application définit à la fois les noms en-US et en-GB, le programme d'installation d'AIR utilise la valeur en-US. Si l'application ne définit pas de nom qui corresponde aux langues prises en charge par le système d'exploitation, le programme d'installation d'une application AIR utilise la première valeur name stipulée dans le fichier descripteur d'application. Si aucun élément name n'est indiqué, le programme d'installation d'une application AIR utilise l'élément filename à titre de nom d'application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 51 Définition des propriétés d'une application AIR L'élément name ne définit que le titre d'application utilisé par le programme d'installation d'une application AIR. Le programme d'installation d'une application AIR prend en charge plusieurs langues : chinois traditionnel, chinois simplifié, tchèque, néerlandais, anglais, français, allemand, italien, japonais, coréen, polonais, portugais brésilien, russe, espagnol, suédois et turc. Le programme d'installation d'une application AIR sélectionne la langue affichée (pour le texte autre que le titre et la description de l'application) en fonction de la langue de l'interface utilisateur système. La langue sélectionnée n'est pas affectée par les paramètres du fichier descripteur d'application. L'élément name ne définit pas les jeux de paramètres régionaux disponibles pour l'application installée en cours d'exécution. Pour plus d'informations sur le développement d'applications multilingues, consultez le chapitre « Localisation d'applications AIR » à la page 351. description (facultatif) Description de l'application, affichée dans le programme d'installation d'une application AIR. Si vous indiquez un nœud texte unique (au lieu de plusieurs éléments text), le programme d'installation de l'application AIR utilise cette description, quelle que soit la langue système activée : <description>This is a sample AIR application.</description> Le modèle de descripteur d'application AIR 1.0 ne permet de définir qu'un seul nœud texte simple en tant que nom (plutôt que plusieurs éléments text). Dans AIR 1.1 (ou version ultérieure), il est possible de spécifier plusieurs langues dans l'élément description. Ainsi, l'exemple suivant stipule une description en trois langues (anglais, français et espagnol) : <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'attribut xml:lang de chaque élément text définit un code de langue, comme indiqué à l'adresse suivante RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Le programme d'installation d'une application AIR utilise la description la plus proche de la langue de l'interface utilisateur du système d'exploitation de l'utilisateur. Prenons l'exemple d'une installation dans laquelle l'élément description du fichier descripteur d'application comprend une valeur pour le jeu de paramètres régionaux en (anglais). Le programme d'installation d'une application AIR utilise le nom en si le système de l'utilisateur identifie en (anglais) en tant que langue de l'interface utilisateur. Il utilise également le nom en si la langue de l'interface utilisateur système correspond à en-US (anglais américain). Toutefois, si la langue de l'interface utilisateur système correspond à en-US et que le fichier descripteur d'application définit à la fois les noms en-US et en-GB, le programme d'installation d'AIR utilise la valeur en-US. Si l'application ne définit pas de nom qui corresponde à la langue de l'interface utilisateur système, le programme d'installation d'une application AIR utilise la première valeur description stipulée dans le fichier descripteur d'application. Pour plus d'informations sur le développement d'applications multilingues, consultez le chapitre « Localisation d'applications AIR » à la page 351. copyright (facultatif) Informations de copyright relatives à l'application AIR. Sous Mac OS, le texte de copyright s'affiche dans la boîte de dialogue A propos de de l'application installée. Sous Mac OS, les informations de copyright sont également utilisées dans le champ NSHumanReadableCopyright du fichier Info.plist de l'application. Définition des dossiers d'installation et de menu du programme Les dossiers d'installation et de menu du programme sont définis par les paramètres de propriété suivants : <installFolder>Acme</installFolder> <programMenuFolder>Acme/Applications</programMenuFolder> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 52 Définition des propriétés d'une application AIR installFolder (facultatif) Identifie le sous-répertoire du répertoire d'installation par défaut. Sous Windows, le sous-répertoire d'installation par défaut est le répertoire Program Files. Sous Mac OS, il s'agit du répertoire /Applications. Sous Linux, il s'agit du répertoire /opt/. Par exemple, si la propriété installFolder est définie sur « Acme » et qu'une application s'appelle « ExempleApp », l'application est installée dans C:\Program Files\Acme\ExempleApp sous Windows, dans /Applications/Acme/Exemple.app sous Mac OS et dans /opt/Acme/ExampleApp sous Linux. La barre oblique (/) fait office de caractère de séparation de répertoire pour définir un sous-répertoire intégré, comme suit : <installFolder>Acme/Power Tools</installFolder> La propriété installFolder peut comporter n'importe quel caractère Unicode (UTF-8), à l'exception de ceux dont l'utilisation est interdite dans les noms de fichier dans divers systèmes de fichiers (consultez la propriété filename cidessus, qui contient la liste d'exceptions). La propriété installFolder est facultative. Si vous ne spécifiez pas la propriété installFolder, l'application est installée dans un sous-répertoire du répertoire d'installation par défaut, basé sur la propriété name. programMenuFolder (facultatif) Identifie l'emplacement de stockage des raccourcis associés à l'application dans le menu Tous les programmes du système d'exploitation Windows ou dans le menu Applications sous Linux. (Ce paramètre n'est actuellement pas pris en charge par les autres systèmes d'exploitation.) Les restrictions liées aux caractères autorisés dans la valeur de la propriété sont identiques à celles de la propriété installFolder. Le dernier caractère de cette valeur ne doit pas correspondre à une barre oblique (/). Définition des propriétés de la fenêtre d'application initiale Lorsqu'une application AIR est chargée, le moteur d'exécution utilise les valeurs de l'élément initialWindow pour créer la fenêtre initiale de l'application. Le moteur d'exécution charge ensuite le fichier SWF ou HTML indiqué par l'élément content dans la fenêtre. Exemple d'élément 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> Les éléments enfant de l'élément initialWindow définissent les propriétés de la fenêtre dans laquelle est chargé le fichier de contenu racine. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 53 Définition des propriétés d'une application AIR content La valeur indiquée de l'élément content correspond à l'URL du fichier de contenu principal de l'application. Il s'agit soit d'un fichier SWF, soit d'un fichier HTML. L'URL est définie relativement à la racine du dossier d'installation de l'application. (Si une application AIR est exécutée avec ADL, l'URL est relative au dossier contenant le fichier descripteur d'application. Vous disposez du paramètre root-dir d'ADL pour indiquer un autre répertoire racine.) Remarque : la valeur de l'élément content étant assimilée à une URL, les caractères qui composent le nom du fichier de contenu doivent respecter le codage URL, conformément aux règles définies dans RFC 1738. Les caractères espace doivent par exemple être codés sous la forme %20. title (facultatif) Titre de la fenêtre. systemChrome (facultatif) Si vous définissez cet attribut sur standard, l'arrière-plan système standard fourni par le système d'exploitation s'affiche. Si vous le définissez sur none, aucun arrière-plan système ne s'affiche. Il est impossible de modifier le paramètre systemChrome à l'exécution. transparent (facultatif) Défini sur « true » si vous souhaitez que la fenêtre de l'application gère le mélange alpha. Une fenêtre transparente risque d'être tracée plus lentement et de mobiliser plus de mémoire. Il est impossible de modifier le paramètre transparent à l'exécution. Important : vous ne pouvez définir transparent sur true que si systemChrome est défini sur none. visible (facultatif) Défini sur true si vous souhaitez que la fenêtre principale soit visible dès sa création. La valeur par défaut est false. Il peut s'avérer utile de masquer initialement la fenêtre principale, afin de ne pas afficher les modifications apportées à la position, à la taille ou à la disposition du contenu de la fenêtre. Vous pouvez alors afficher la fenêtre en appelant la méthode activate() de la fenêtre ou en définissant la propriété visible sur true. Pour plus d'informations, consultez le chapitre « Utilisation des fenêtres natives » à la page 61. x, y, width, height (facultatifs) Limite initiales de la fenêtre principale de l'application. Si vous ne définissez pas ces valeurs, la taille de la fenêtre est déterminée par les paramètres stockés dans le fichier SWF racine ou, dans le cas d'HTML, par le système d'exploitation. minSize, maxSize (facultatifs) Tailles minimale et maximale de la fenêtre. Si vous ne définissez pas ces valeurs, elles sont déterminées par le système d'exploitation. minimizable, maximizable, resizable (facultatifs) Indiquent si la fenêtre peut être réduite, agrandie et redimensionnée. Par défaut, ces paramètres sont définis sur true. Remarque : sous des systèmes d'exploitation qui assimilent l'agrandissement d'une fenêtre à une opération de redimensionnement, tel Mac OS X, les paramètres maximizable et resizable doivent être définis sur false pour interdire l'exécution d'un zoom ou d'un redimensionnement de la fenêtre. Définition de fichiers d'icône La propriété icon définit un ou plusieurs fichiers d'icône à utiliser pour l'application. L'inclusion d'une icône est facultative. Si vous ne définissez pas la propriété icon, le système d'exploitation affiche une icône par défaut. Le chemin défini est relatif au répertoire racine de l'application. Les fichiers d'icône doivent être au format PNG. Vous pouvez indiquer les tailles d'icône suivantes : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 54 Définition des propriétés d'une application AIR <icon> <image16x16>icons/smallIcon.png</image16x16> <image32x32>icons/mediumIcon.png</image32x32> <image48x48>icons/bigIcon.png</image48x48> <image128x128>icons/biggestIcon.png</image128x128> </icon> S'il existe un élément de taille donnée, l'image du fichier doit posséder exactement la taille définie. Si toutes les tailles ne sont pas disponibles, la taille la plus proche est mise à l'échelle en fonction de l'utilisation requise de l'icône par le système d'exploitation. Remarque : les icônes indiquées ne sont pas automatiquement ajoutées au package AIR. Les fichiers d'icône doivent être inclus à l'emplacement relatif correct lors de la mise en package de l'application. Pour obtenir de meilleurs résultats, fournissez une image dans chacune des tailles disponibles. Assurez-vous en outre que l'apparence des icônes est appropriée en mode de couleur 16 et 32 bits. Définition d'une interface utilisateur personnalisée pour les mises à jour d'une application AIR installe et met à jour les applications par le biais des boîtes de dialogue d'installation par défaut. Vous pouvez toutefois fournir votre propre interface utilisateur pour mettre à jour une application. Pour indiquer que votre application doit gérer elle-même le processus de mise à jour, définissez l'élément customUpdateUI sur true, comme suit : <customUpdateUI>true</customUpdateUI> Si l'élément customUpdateUI est défini sur true dans la version installée de votre application et que l'utilisateur double-clique sur le fichier AIR pour installer une nouvelle version ou procéder à la mise à jour de l'application par le biais de la fonction d'installation transparente, le moteur d'exécution ouvre la version installée de l'application, plutôt que le programme d'installation de l'application AIR par défaut. La logique de votre application peut alors déterminer la marche à suivre pour l'opération de mise à jour. (L'ID d'application et l'ID d'éditeur stockés dans le fichier AIR doivent être identiques aux identifiants de l'application installée pour que la mise à jour aboutisse.) Remarque : le mécanisme customUpdateUI n'intervient que lorsque l'application est déjà installée et que l'utilisateur double-clique sur le fichier d'installation AIR contenant une mise à jour ou qu'il installe une mise à jour de l'application par le biais de la fonction d'installation transparente. Que le paramètre customUpdateUI soit défini sur true ou non, vous pouvez télécharger et démarrer une mise à jour par le biais de la logique de votre application en affichant votre interface utilisateur personnalisée si besoin est. Pour plus d'informations, consultez le chapitre « Mise à jour des applications AIR » à la page 335. Démarrage d'une application par le biais d'un appel de navigateur Si vous définissez le paramètre suivant, il est possible de démarrer l'application AIR installée par le biais de la fonction d'appel d'un navigateur. En d'autres termes, l'utilisateur peut démarrer l'application en cliquant sur un lien de page dans un navigateur Web : <allowBrowserInvocation>true</allowBrowserInvocation> La valeur par défaut est false. Si vous définissez cette valeur sur true, tenez compte des implications liées à la sécurité, décrites à la section « Appel du navigateur » à la page 299. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 55 Définition des propriétés d'une application AIR Pour plus d'informations, consultez la section « Installation et exécution d'applications AIR à partir d'une page Web » à la page 319. Déclaration des associations de type de fichier L'élément fileTypes permet de déclarer les types de fichiers auxquels peut être associée une application AIR. Lors de l'installation d'une application AIR, tout type de fichier déclaré est enregistré dans le système d'exploitation et, sous réserve de ne pas être déjà associé à une autre application, il est associé à l'application AIR. Pour remplacer une association existante entre un type de fichier et une autre application, utilisez la méthode NativeApplication.setAsDefaultApplication() à l'exécution (de préférence avec l'accord de l'utilisateur). Remarque : les méthodes d'exécution ne gèrent que les associations de types de fichiers déclarés dans le descripteur d'application. <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'élément fileTypes est facultatif. Il peut contenir un nombre illimité d'éléments fileType. Vous devez obligatoirement définir les éléments name et extension pour chaque déclaration fileType incluse. Libre à vous d'utiliser le même nom pour diverses extensions. L'extension identifie de manière unique le type de fichier. (Notez que l'extension doit être indiquée sans le point qui la précède.) L'élément description est facultatif et est indiquée à l'utilisateur par l'interface utilisateur du système d'exploitation. La propriété contentType est obligatoire dans AIR 1.5 (il était facultatif dans AIR 1.0 et 1.1). Cette propriété aide le système d'exploitation à localiser l'application la plus adaptée pour ouvrir un fichier dans certains cas de figure. Sa valeur doit correspondre au type MIME du contenu du fichier. Notez que la valeur est ignorée sous Linux si le type de fichier est déjà enregistré et a un type MIME attribué. Vous pouvez associer des icônes aux extensions de fichiers. Utilisez dans ce cas le même format que l'élément d'icône d'application. Vous devez également inclure les fichiers d'icônes dans le fichier d'installation AIR, car ils ne sont pas automatiquement mis en package. Lorsqu'un type de fichier est associé à une application AIR, celle-ci est appelée lorsqu'un utilisateur ouvre un fichier de ce type. Si l'application est déjà ouverte, AIR distribue l'objet InvokeEvent à l'occurrence en cours d'exécution. Dans le cas contraire, AIR démarre au préalable l'application. Dans les deux cas de figure, il est possible d'extraire le chemin d'accès au fichier à partir de l'objet InvokeEvent distribué par l'objet NativeApplication. Ce chemin vous permet d'ouvrir le fichier. Pour plus d'informations, consultez les sections « Gestion des associations de fichiers » à la page 305 et « Capture des arguments de ligne de commande » à la page 297. 56 Chapitre 9 : Fonctionnalités propres à Adobe AIR Cette section présente les fonctionnalités d'Adobe® AIR™ non disponibles pour le contenu SWF s'exécutant dans Adobe® Flash® Player. Classes propres à AIR Les classes d'exécution suivantes sont spécifiques à Adobe AIR. Elles ne sont pas disponibles pour les contenus SWF exécutés dans le navigateur : Classe Package 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 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 57 Fonctionnalités propres à Adobe AIR Classe Package 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 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 58 Fonctionnalités propres à Adobe AIR Classe Package 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 De même, le package flash.security comprend l'interface IURIDereferencer, spécifique à AIR. Classes d'exécution dotées de fonctionnalités propres à AIR Les classes suivantes sont disponibles pour les contenus SWF exécutés dans le navigateur, mais AIR offre des propriétés ou des méthodes supplémentaires : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 59 Fonctionnalités propres à Adobe AIR Classe Propriété ou méthode Capabilities languages 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 événement httpResponseStatus Stage nativeWindow Security APPLICATION La plupart de ces nouvelles propriétés et méthodes sont uniquement disponibles pour le contenu situé dans le sandbox de sécurité de l'application AIR. Toutefois, les nouveaux membres des classes URLRequest sont également disponibles pour le contenu exécuté dans d'autres sandbox. Les méthodes ByteArray.compress() et ByteArray.uncompress() comprennent chacune un nouveau paramètre algorithm permettant de choisir entre les compressions deflate et zlib. Ce paramètre n'est disponible que pour le contenu s'exécutant dans AIR. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 60 Fonctionnalités propres à Adobe AIR Classes de structure pour la surveillance de services Le package air.net contient des classes destinées à la détection réseau. Il est uniquement disponible pour les contenus exécutés dans Adobe AIR. Il se trouve dans le fichier ServiceMonitor.swc. Le package comprend les classes suivantes : • ServiceMonitor • SocketMonitor • URLMonitor 61 Chapitre 10 : Utilisation des fenêtres natives Utilisez les classes fournies par l'API de la fenêtre native d'Adobe® AIR® pour créer et gérer les fenêtres du poste de travail. Informations complémentaires en ligne sur les fenêtres natives Pour plus d'informations sur l'API de fenêtre native et l'utilisation des fenêtres natives, consultez les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Interaction avec une fenêtre • Personnalisation de l'aspect d'une fenêtre native • Création de fenêtres affichées l'une derrière l'autre • Contrôle de l'ordre d'affichage des fenêtres • Création de fenêtres redimensionnables et non rectangulaires Guide de référence du langage • NativeWindow • NativeWindowInitOptions Adobe Developer Connection - Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « AIR windows ») Principes de base des fenêtres dans AIR AIR offre une API multi-plateformes facile à utiliser vous permettant de créer des fenêtres natives dans un système d'exploitation à l'aide de Flash®, Flex™ et des techniques de programmation HTML. Grâce à AIR, vous pouvez personnaliser l'aspect de votre application en toute liberté. Les fenêtres que vous créez peuvent ressembler à une application de bureau standard, en reproduisant le style Apple lors d'une exécution sous Mac, en respectant les conventions Microsoft lors d'une exécution sous Windows, et en s'harmonisant au gestionnaire de fenêtres sous Linux, sans inclure une seule ligne de code spécifique à une plate-forme. Vous pouvez par ailleurs utiliser l'arrière-plan extensible, auquel il est possible d'appliquer une enveloppe, fourni par la structure d'application Flex afin de créer votre propre style, quelle que soit la plate-forme d'exécution de votre application. Vous pouvez de surcroît concevoir votre propre arrière-plan de fenêtre avec des vecteurs et des images bitmap, et utiliser les effets de transparence, ainsi que le fondu alpha avec le poste de travail. Vous en avez assez des fenêtres rectangulaires ? Créez des fenêtres arrondies ! DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 62 Utilisation des fenêtres natives Fenêtres dans AIR AIR prend en charge trois API distinctes pour l'utilisation des fenêtres : • La classe NativeWindow, orientée ActionScript, fournit l'API de la fenêtre du niveau le plus bas. Utilisez la classe NativeWindow dans les applications programmées en ActionScript et Flash CS. Pensez à étendre la classe NativeWindow pour spécialiser les fenêtres utilisées dans votre application. • Les classes Flex framework mx:WindowedApplication et mx:Window fournissent une « enveloppe » Flex à la classe NativeWindow. Le composant WindowedApplication remplace le composant Application lorsque vous créez une application AIR avec Flex et doit toujours être utilisé comme fenêtre initiale dans votre application Flex. • Dans l'environnement HTML, vous pouvez utiliser la classe Window de JavaScript, comme dans toute application Web à base de navigateur. Les appels aux méthodes Window de JavaScript sont transmis à l'objet window natif sous-jacent. Fenêtres ActionScript Lorsque vous créez des fenêtres avec la classe NativeWindow, utilisez directement la scène et la liste d'affichage de Flash Player. Pour ajouter un objet visuel à une classe NativeWindow, ajoutez l'objet à la liste d'affichage de la scène de la fenêtre ou à un autre conteneur d'objet d'affichage sur la scène. Fenêtres de la structure d'application Flex La structure d'application Flex définit ses propres composants de fenêtre qui enveloppent l'API NativeWindow. Ces composants, mx:WindowedApplication et mx:Window, ne peuvent pas être utilisés en dehors de la structure d'application. Par conséquent, ils ne peuvent pas être utilisés dans des applications AIR développées avec Flash CS. Fenêtres HTML Lorsque vous créez des fenêtres HTML, utilisez HTML, CSS et JavaScript pour afficher du contenu. Pour ajouter un objet visuel à une fenêtre HTML, ajoutez ce contenu au DOM HTML. Les fenêtres HTML sont une catégorie spéciale de l'élément NativeWindow. L'hôte AIR définit une propriété nativeWindow dans les fenêtres HTML, qui fournit l'accès à l'occurrence de NativeWindow sous-jacente. Utilisez cette propriété pour accéder aux propriétés, méthodes et événements de l'élément NativeWindow décrits ici. Remarque : l'objet Window de JavaScript dispose également de méthodes pour la rédaction de scripts dans la fenêtre conteneur, telles que moveTo() et close(). Lorsque plusieurs méthodes sont disponibles, utilisez celle qui convient le mieux. La fenêtre initiale de l'application AIR crée pour vous la première fenêtre de l'application. AIR définit les propriétés et le contenu de la fenêtre à l'aide des paramètres spécifiés dans l'élément initialWindow du fichier descripteur d'application. Si le contenu racine est un fichier SWF, AIR crée une occurrence de NativeWindow, charge le fichier SWF et l'ajoute à la scène de la fenêtre. Si le contenu racine est un fichier HTML, AIR crée une fenêtre HTML et charge le fichier HTML. Pour plus d'informations sur les propriétés de la fenêtre spécifiées dans le fichier descripteur d'application, consultez la section « Structure du fichier descripteur d'application » à la page 46. Classes d'une fenêtre native L'API de la fenêtre native contient les classes suivantes : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 63 Utilisation des fenêtres natives Package Classes flash.display • NativeWindow • NativeWindowInitOptions • NativeWindowDisplayState • NativeWindowResize • NativeWindowSystemChrome • NativeWindowType Les constantes de chaîne de fenêtre sont définies dans les classes suivantes : flash.events • NativeWindowDisplayState • NativeWindowResize • NativeWindowSystemChrome • NativeWindowType • NativeWindowBoundsEvent • NativeWindowDisplayStateEvent Flux d'événements des fenêtres natives Les fenêtres natives distribuent des événements pour notifier les composants intéressés qu'un changement important est sur le point de se produire ou s'est déjà produit. La plupart des événements basés sur les fenêtres sont distribués par paires. Le premier événement informe qu'un changement est sur le point de se produire. Le deuxième événement annonce qu'un changement a été effectué. Vous pouvez annuler un événement d'avertissement, mais pas un événement de notification. La séquence suivante illustre le flux d'événements qui se produit lorsqu'un utilisateur clique sur le bouton d'agrandissement d'une fenêtre : 1 L'objet NativeWindow distribue un événement displayStateChanging. 2 Si aucun écouteur enregistré n'annule l'événement, la fenêtre est agrandie. 3 L'objet NativeWindow distribue un événement displayStateChange. L'objet NativeWindow distribue en outre des événements lors de modifications associées ayant trait à la taille et à la position de la fenêtre. La fenêtre ne distribue aucun événement d'avertissement pour ces modifications associées. Les événements associés sont les suivants : a Un événement move est distribué si le coin supérieur gauche de la fenêtre s'est déplacé suite à un agrandissement. b Un événement resize est distribué si la taille de la fenêtre a changé suite à un agrandissement. Un objet NativeWindow distribue une séquence d'événements similaire lors de l'agrandissement, de la restauration, de la fermeture, du déplacement et du redimensionnement d'une fenêtre. Les événements d'avertissement ne sont distribués que lorsqu'une modification est initiée via l'arrière-plan de la fenêtre ou un autre mécanisme contrôlé par le système d'exploitation. Lorsque vous appelez une méthode window pour modifier la taille, la position ou l'état d'affichage de la fenêtre, la fenêtre ne distribue qu'un seul événement pour annoncer la modification. Vous pouvez distribuer un événement d'avertissement, si vous le souhaitez, à l'aide de la méthode dispatchEvent() de la fenêtre, puis vérifier si votre événement d'avertissement a été annulé avant d'effectuer la modification. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 64 Utilisation des fenêtres natives Pour plus d'informations sur les classes, les méthodes, les propriétés et les événements de l'API de la fenêtre, consultez le Guide de référence du langage et des composants ActionScript 3.0 (http://www.adobe.com/go/learn_flash_aslr_fr). Pour obtenir des informations générales sur l'utilisation de la liste d'affichage de Flash, consultez la section « Programmation de l'affichage » du document Programmation avec Adobe ActionScript 3.0 (http://www.adobe.com/go/learn_fl_cs4_programmingAS3_fr). Propriétés de contrôle du style et du comportement d'une fenêtre native Les propriétés suivantes contrôlent l'aspect et le comportement de base d'une fenêtre : • type • systemChrome • transparent Lorsque vous créez une fenêtre, vous définissez ces propriétés sur l'objet NativeWindowInitOptions transmis au constructeur de fenêtre. AIR lit les propriétés de la fenêtre d'application initiale à partir du fichier descripteur d'application. (A l'exception de la propriété type qui ne peut pas être définie dans le fichier descripteur d'application et dont la valeur est toujours normal.) Il est impossible de modifier les propriétés une fois la fenêtre créée. Certains paramètres de ces propriétés sont mutuellement incompatibles : systemChrome ne peut pas être défini sur standard lorsque transparent est défini sur true ou type est défini sur lightweight. Types de fenêtre Les types de fenêtres d'AIR combinent les attributs d'arrière-plan et de visibilité du système d'exploitation natif pour créer trois types de fenêtre fonctionnels. Utilisez les constantes définies dans la classe NativeWindowType pour référencer les noms des types de fenêtre dans le code. AIR fournit les types de fenêtre suivants : Type Description Normale Une fenêtre classique. Les fenêtres normales utilisent l'arrière-plan plein écran et apparaissent dans la barre des tâches Windows et le menu de la fenêtre Mac OS X. Utilitaire Une palette d'outils. Les fenêtres d'utilitaire utilisent une version plus fine de l'arrière-plan système et n'apparaissent ni dans la barre des tâches Windows ni dans le menu de la fenêtre Mac OS X. Légère Les fenêtres légères n'utilisent pas d'arrière-plan et n'apparaissent ni dans la barre des tâches Windows ni dans le menu de la fenêtre Mas OS X. De plus, les fenêtres légères ne disposent pas du menu Système (Alt-Espace) sous Windows. Les fenêtres légères sont adaptées aux commandes et aux bulles de notification (listes déroulantes qui ouvrent une zone d'affichage de courte durée, par exemple). Lorsque le type légère est utilisé, la propriété systemChrome doit être définie sur none. Arrière-plan de la fenêtre L'arrière-plan d'une fenêtre est un ensemble de commandes qui permet aux utilisateurs de manipuler une fenêtre dans l'environnement de bureau. L'arrière-plan comprend les éléments suivants : barre de titre, boutons de la barre de titre, encadrement et poignées de redimensionnement. Arrière-plan système Vous pouvez définir la propriété systemChrome sur standard ou sur none. Choisissez l'arrière-plan système standard pour attribuer à votre fenêtre le jeu de commandes standard créé par le système d'exploitation de l'utilisateur. Choisissez none pour créer votre propre arrière-plan de fenêtre. Utilisez les constantes définies dans la classe NativeWindowSystemChrome pour référencer les paramètres de l'arrière-plan système dans le code. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 65 Utilisation des fenêtres natives L'arrière-plan système est géré par le système. Votre application ne bénéficie pas d'un accès direct aux commandes, mais peut réagir aux événements distribués lorsque les commandes sont utilisées. Lorsque vous utilisez l'arrière-plan standard pour une fenêtre, la propriété transparent doit être définie sur false et la propriété type doit être définie sur normal ou sur utility. Arrière-plan personnalisé Lorsque vous créez une fenêtre sans arrière-plan système, vous devez ajouter vos propres commandes d'arrière-plan afin de gérer les interactions entre un utilisateur et la fenêtre. Vous êtes également libre de créer des fenêtres transparentes et non rectangulaires. Transparence de la fenêtre Pour permettre le fondu alpha d'une fenêtre avec le bureau ou d'autres fenêtres, définissez la propriété transparent de la fenêtre sur true. La propriété transparent, qui doit être définie avant de créer la fenêtre, ne peut pas être modifiée. Une fenêtre transparente ne dispose d'aucun arrière-plan par défaut. Les zones d'une fenêtre qui ne contiennent aucun objet créé par l'application sont invisibles. Si le paramètre alpha d'un objet affiché est inférieur à un, rien en dessous de l'objet ne s'affiche : ni les objets d'affichage de la même fenêtre, ni d'autres fenêtres, ni même le bureau. Le rendu des zones sur lesquelles le fondu alpha a été appliqué peut être lent ; par conséquent, n'utilisez cet effet que lorsque cela est strictement nécessaire. Les fenêtres transparentes sont utiles lorsque vous souhaitez créer des applications avec des bordures irrégulières, qui « s'atténuent » ou semblent invisibles. Important : sous Linux, les événements de souris ne passent pas à travers des pixels entièrement transparents. Évitez de créer des fenêtres comprenant de vastes zones entièrement transparentes car vous pourriez bloquer de façon invisible l'accès de l'utilisateur aux autres fenêtres ou aux autres éléments de son bureau. Sous Mac OS X et Windows, les événements de souris passent à travers les pixels entièrement transparents. La transparence ne peut pas être utilisée avec des fenêtres disposant d'un arrière-plan système. En outre, le contenu SWF et PDF dans HTML ne s'affiche pas dans des fenêtres transparentes. Pour plus d'informations, consultez la section « Points à examiner lors du chargement d'un contenu SWF ou PDF dans une page HTML » à la page 264. Il est possible que la transparence ne soit pas prise en charge sous certains systèmes d'exploitation à cause de la configuration logicielle ou matérielle, ou des options d'affichage définies par l'utilisateur. Si la transparence n'est pas prise en charge, l'application utilise un arrière-plan noir. Dans ce cas, les zones transparentes de l'application s'affichent en noir opaque. La propriété statique NativeWindow.supportsTransparency indique si la transparence de la fenêtre est disponible. Si la propriété indique false, par exemple, vous pourriez montrer une boîte de dialogue d'avertissement à l'utilisateur ou afficher une interface utilisateur de secours rectangulaire et non transparente. Notez que la transparence est toujours prise en charge par les systèmes d'exploitation Mac et Windows. La prise en charge sur les systèmes d'exploitation Linux requiert un gestionnaire de composition de fenêtres. Cependant, même lorsqu'un tel gestionnaire est disponible, la transparence peut ne pas être disponible du fait des options d'affichage de l'utilisateur ou de sa configuration matérielle. Transparence dans une fenêtre d'application HTML Par défaut, l'arrière-plan du contenu HTML affiché dans les fenêtres HTML et les objets HTMLLoader est opaque, même si la fenêtre conteneur est transparente. Pour désactiver l'arrière-plan par défaut du contenu HTML, définissez la propriété paintsDefaultBackground sur false. L'exemple suivant crée un objet HTMLLoader et désactive l'arrière-plan par défaut : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 66 Utilisation des fenêtres natives var html:HTMLLoader = new HTMLLoader(); html.paintsDefaultBackground = false; Cet exemple utilise JavaScript pour désactiver l'arrière-plan par défaut d'une fenêtre HTML : window.htmlLoader.paintsDefaultBackground = false; Si un élément du document HTML définit une couleur d'arrière-plan, l'arrière-plan de cet élément n'est pas transparent. Il est impossible de définir une transparence (ou une opacité) partielle. Vous pouvez néanmoins utiliser une image transparente au format PNG comme arrière-plan d'une page ou d'un élément de page pour obtenir un effet visuel similaire. Catalogue des effets visuels d'une fenêtre Le tableau suivant illustre les effets visuels résultant de diverses combinaisons de paramètres de propriétés de fenêtre sous Mac OS X, Windows et Linux : Paramètres de fenêtre Type : normale SystemChrome : standard Transparent : false Type : utilitaire SystemChrome : standard Transparent : false Mac OS X Microsoft Windows Linux* DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 67 Utilisation des fenêtres natives Paramètres de fenêtre Mac OS X Microsoft Windows Linux* Type : tout type SystemChrome : aucun Transparent : false Type : tout type SystemChrome : aucun Transparent : true mxWindowedApplication ou mx:Window Type : tout type SystemChrome : aucun Transparent : true * Ubuntu avec gestionnaire de fenêtres Compiz Remarque : les éléments de l'arrière-plan système suivants ne sont pas pris en charge par AIR : barre d'outils Mac OS X, icône proxy Mac OS X, icônes de la barre de titre Windows et arrière-plan système alternatif. Création de fenêtres AIR crée automatiquement la première fenêtre d'une application, mais vous pouvez créer autant de fenêtres supplémentaires que vous le souhaitez. Pour créer une fenêtre native, utilisez la méthode constructeur NativeWindow. Pour créer une fenêtre HTML, utilisez la méthode createRootWindow() de l'objet HTMLLoader ou appelez la méthode JavaScript window.open() depuis un document HTML. Spécification des propriétés d'initialisation d'une fenêtre Une fois la fenêtre du bureau créée, il est impossible de modifier les propriétés d'initialisation d'une fenêtre. Ces propriétés immuables et leurs valeurs par défaut sont les suivantes : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 68 Utilisation des fenêtres natives Propriété Valeur par défaut systemChrome standard type normal transparent false maximizable true minimizable true resizable true Définissez les propriétés de la fenêtre initiale créée par AIR dans le fichier descripteur d'application. La fenêtre principale d'une application AIR est toujours de type normale. (Vous pouvez spécifier d'autres propriétés de fenêtre dans le fichier descripteur, telles que visible, width, et height, et les modifier à tout moment.) Définissez les propriétés des autres fenêtres natives et HTML créées par votre application à l'aide de la classe NativeWindowInitOptions. Lorsque vous créez une fenêtre, vous devez transmettre un objet NativeWindowInitOptions spécifiant les propriétés de la fenêtre à la fonction constructeur NativeWindow ou à la méthode createRootWindow() de l'objet HTMLLoader. Le code suivant crée un objet NativeWindowInitOptions pour une fenêtre d'utilitaire : var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = NativeWindowSystemChrome.STANDARD; options.type = NativeWindowType.UTILITY options.transparent = false; options.resizable = false; options.maximizable = false; Il est impossible de définir systemChrome sur standard lorsque la propriété transparent est définie sur true ou lorsque la propriété type est définie sur lightweight. Remarque : vous ne pouvez pas définir les propriétés d'initialisation d'une fenêtre créée avec la fonction window.open() de JavaScript. Vous pouvez toutefois passer outre la méthode de création de ces fenêtres en implémentant votre propre classe HTMLHost. Pour plus d'informations, consultez la section « Traitement des appels JavaScript à window.open() » à la page 273. Création de la fenêtre initiale de l'application AIR crée la fenêtre initiale de l'application en fonction des propriétés spécifiées dans le fichier descripteur d'application et charge le fichier référencé dans l'élément de contenu. L'élément de contenu doit faire référence à un fichier SWF ou HTML. La fenêtre initiale peut être la fenêtre principale de votre application, ou permettre simplement de lancer une ou plusieurs autres fenêtres. Il n'est absolument pas nécessaire de rendre cette fenêtre visible. L'outil de programmation Flash crée automatiquement le fichier SWF et ajoute la référence appropriée au fichier descripteur d'application lors du test ou de la publication d'un projet pour AIR. Le scénario principal sert de point d'entrée à votre application. A l'ouverture de votre application, AIR crée une fenêtre et charge le fichier SWF de l'application. Pour contrôler la fenêtre du bureau avec ActionScript, utilisez la propriété nativeWindow de l'objet Stage pour obtenir une référence à l'objet NativeWindow. Vous pouvez ensuite définir les propriétés de la fenêtre et appelez les méthodes de fenêtre. L'exemple suivant active la fenêtre principale à l'état maximal (à partir de la première image d'un fichier FLA Flash) : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 69 Utilisation des fenêtres natives import flash.display.NativeWindow; var mainWindow:NativeWindow = this.stage.nativeWindow; mainWindow.maximize(); mainWindow.activate(); Création d'une classe NativeWindow Pour créer une classe NativeWindow, transmettez un objet NativeWindowInitOptions au constructeur NativeWindow : var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = NativeWindowSystemChrome.STANDARD; options.transparent = false; var newWindow:NativeWindow = new NativeWindow(options); La fenêtre ne s'affiche pas tant que vous ne définissez pas la propriété visible sur true ou tant que vous n'appelez pas la méthode activate(). Une fois la fenêtre créée, vous pouvez initialiser ses propriétés et charger le contenu dans la fenêtre à l'aide de la propriété stage et des techniques de la liste d'affichage de Flash. Dans la plupart des cas, vous devez définir la propriété scaleMode de la scène d'une nouvelle fenêtre native sur noScale (utilisez la constante StageScaleMode.NO_SCALE). Les modes d'échelle de Flash sont conçus pour des situations dans lesquelles l'auteur de l'application ne connaît pas à l'avance les proportions de l'espace d'affichage de l'application. Les modes d'échelle permettent à l'auteur de faire le moins mauvais choix : découper le contenu, l'étirer ou le compresser, ou le remplir d'espace vide. Etant donné que vous contrôlez l'espace d'affichage dans AIR (le cadre de la fenêtre), vous pouvez dimensionner la fenêtre en fonction du contenu ou dimensionner le contenu en fonction de la fenêtre sans aucun compromis. Remarque : pour déterminer les tailles maximale et minimale des fenêtres disponibles sur le système d'exploitation, utilisez les propriétés NativeWindow statiques suivantes : var maxOSSize:Point = NativeWindow.systemMaxSize; var minOSSize:Point = NativeWindow.systemMinSize; Création d'une fenêtre HTML Pour créer une fenêtre HTML, vous pouvez appeler la méthode Window.open() de JavaScript ou appeler la méthode createRootWindow() de la classe HTMLLoader d'AIR. Le contenu HTML dans les sandbox de sécurité peuvent utiliser la méthode standard Window.open() de JavaScript. Si le contenu est exécuté hors du sandbox de l'application, la méthode open() ne peut être appelée qu'en réponse à l'interaction de l'utilisateur, notamment lorsque ce dernier clique sur la souris ou appuie sur une touche. Lorsque la méthode open() est appelée, une fenêtre avec un arrière-plan système est créée pour afficher le contenu à l'URL spécifiée. Exemple : newWindow = window.open("xmpl.html", "logWindow", "height=600, width=400, top=10, left=10"); Remarque : vous pouvez étendre la classe HTMLHost dans ActionScript pour personnaliser la fenêtre créée avec la fonctionnalité window.open() de JavaScript. Consultez la section « A propos de l'extension de la classe HTMLHost » à la page 268. Le contenu du sandbox de sécurité de l'application a accès à la méthode de création de fenêtres la plus performante : HTMLLoader.createRootWindow(). Cette méthode vous permet de spécifier toutes les options de création d'une nouvelle fenêtre. Par exemple, le code JavaScript suivant crée un type de fenêtre légère sans arrière-plan système, d'une taille de 300x400 pixels : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 70 Utilisation des fenêtres natives 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")); Remarque : si le contenu chargé par la nouvelle fenêtre se trouve hors du sandbox de sécurité de l'application, l'objet window ne possède aucune propriété AIR : runtime, nativeWindow ou htmlLoader. Les fenêtres créées avec la méthode createRootWindow() restent indépendantes de la fenêtre d'ouverture. Les propriétés parent et opener de l'objet Window de JavaScript sont définies sur null. La fenêtre d'ouverture peut accéder à l'objet Window de la nouvelle fenêtre à l'aide de la référence HTMLLoader renvoyée par la fonctionnalité createRootWindow(). Dans le cadre de l'exemple précédent, l'instruction newHTMLLoader.window référencerait l'objet Window de JavaScript de la fenêtre créée. Remarque : la fonctionnalité createRootWindow() peut être appelée depuis JavaScript et ActionScript. Ajout de contenu à une fenêtre La méthode d'ajout de contenu à une fenêtre AIR dépend du type de fenêtre. Vous pouvez créer un clip et utiliser le scénario pour contrôler l'état de l'application. HTML vous permet de définir d'une manière déclarative le contenu de base de la fenêtre. Vous pouvez intégrer des ressources dans le fichier SWF de l'application ou les charger à partir de fichiers d'application indépendants. Le contenu Flash et le contenu HTML peuvent être créés sur le moment et ajoutés à la fenêtre de façon dynamique. Lorsque vous chargez du contenu SWF ou du contenu HTML contenant JavaScript, vous devez tenir compte du modèle de sécurité d'AIR. Le contenu dans le sandbox de sécurité de l'application, c'est-à-dire le contenu installé avec votre application et pouvant être chargé avec le modèle d'URL app:, dispose de privilèges complets pour accéder à toutes les API d'AIR. Le contenu chargé hors de ce sandbox ne peut pas accéder aux API d'AIR. Le contenu JavaScript hors du sandbox de l'application ne peut pas utiliser les propriétés runtime, nativeWindow et htmlLoader de l'objet Window de JavaScript. Pour sécuriser la programmation croisée, vous pouvez utiliser un pont de sandbox afin de fournir une interface limitée entre le contenu applicatif et le contenu hors application. Dans le contenu HTML, vous pouvez également mapper les pages de votre application sur un sandbox hors application afin que le code sur cette page puisse intercoder le contenu externe. Consultez le chapitre « Sécurité AIR » à la page 24. Chargement d'une image ou d'un fichier SWF Vous pouvez charger des images ou des fichiers Flash SWF dans la liste d'affichage d'une fenêtre native à l'aide de la classe flash.display.Loader : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 71 Utilisation des fenêtres natives 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); } } } Vous pouvez charger un fichier SWF contenant du code de bibliothèque en vue de l'utiliser dans une application HTML. Le moyen le plus simple de charger un fichier SWF dans une fenêtre HTML consiste à utiliser la balise script, mais vous pouvez également utiliser directement l'API Loader. Remarque : les anciens fichiers SWF créés à l'aide d'ActionScript 1 ou 2 partagent les états globaux, tels que les définitions de classe, les singletons et les variables globales, si ceux-ci sont chargés dans la même fenêtre. Si ces fichiers SWF dépendent d'états globaux intacts pour fonctionner correctement, ils ne peuvent pas être chargés plus d'une fois dans la même fenêtre ; ils ne peuvent en outre pas être chargés dans la même fenêtre en tant qu'autre fichier SWF utilisant des définitions de classe et des variables qui se chevauchent. Ce contenu peut être chargé dans des fenêtres indépendantes. Chargement du contenu HTML dans une fenêtre native Pour charger du contenu HTML dans une fenêtre native, vous pouvez ajouter un objet HTMLLoader à la scène de la fenêtre, puis charger le contenu HTML dans cet objet, ou créer une fenêtre qui contient déjà un objet HTMLLoader à l'aide de la méthode HTMLLoader.createRootWindow(). L'exemple suivant affiche un contenu HTML dans une zone d'affichage de 300x500 pixels sur la scène d'une fenêtre native : //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) ); Remarque : le contenu SWF ou PDF d'un fichier HTML n'est pas affiché si la fenêtre utilise l'effet de transparence (c'està-dire si la propriété transparent de la fenêtre est définie sur true) ou si le contrôle HTMLLoader est mis à l'échelle. Incrustation du contenu SWF sur une fenêtre HTML Etant donné que les fenêtres HTML sont contenues dans une occurrence de NativeWindow, vous pouvez ajouter des objets d'affichage Flash au-dessus et en dessous du calque HTML dans la liste d'affichage. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 72 Utilisation des fenêtres natives Pour ajouter un objet d'affichage au-dessus du calque HTML, utilisez la méthode addChild() de la propriété window.nativeWindow.stage. La méthode addChild() ajoute le contenu superposé au-dessus du contenu existant dans la fenêtre. Pour ajouter un objet d'affichage en dessous du calque HTML, utilisez la méthode addChildAt() de la propriété window.nativeWindow.stage, en transmettant une valeur de zéro au paramètre index. Le fait de placer un objet à l'index zéro déplace le contenu existant (notamment l'affichage HTML) au-dessus d'un calque et insère le nouveau contenu en dessous. Afin que le contenu superposé sous la page HTML soit visible, vous devez définir la propriété paintsDefaultBackground de l'objet HTMLlLoader sur false. En outre, tout élément de la page qui définit une couleur d'arrière-plan ne sera pas transparent. Par exemple, si vous définissez une couleur d'arrière-plan pour l'élément de corps de la page, aucune page ne sera transparente. L'exemple suivant explique comment ajouter des objets d'affichage Flash en tant que sur-couches et sous-couches à une page HTML. L'exemple suivant crée deux objets de formes simples, ajoute le premier en dessous du contenu HTML et l'autre au-dessus. Cet exemple met également à jour la position de la forme en fonction de l'événement 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; } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 73 Utilisation des fenêtres natives 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> Cet exemple vous donne des notions élémentaires sur certaines techniques avancées qui utilisent JavaScript et ActionScript dans AIR. Si vous n'êtes pas familiarisé(e) avec les objets d'affichage ActionScript, consultez le chapitre Programmation de l'affichage du guideProgrammation avec Adobe ActionScript 3.0 pour plus d'informations. Exemple : création d'une fenêtre native L'exemple suivant illustre la méthode de création d'une fenêtre native : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 74 Utilisation des fenêtres natives 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(); } Gestion des fenêtres Utilisez les propriétés et les méthodes de la classe NativeWindow pour gérer l'aspect, le comportement et le cycle de vie des fenêtres du poste de travail. Obtention d'une occurrence de NativeWindow Pour manipuler une fenêtre, vous devez tout d'abord obtenir l'occurrence de la fenêtre. Vous pouvez obtenir une occurrence de fenêtre à partir de l'un des emplacements suivants : • Le constructeur de fenêtre natif utilisé pour créer la fenêtre : var win:NativeWindow = new NativeWindow(initOptions); • La propriété nativeWindow de la scène de la fenêtre : var win:NativeWindow = stage.nativeWindow; • La propriété stage d’un objet d'affichage de la fenêtre : var win:NativeWindow = displayObject.stage.nativeWindow; • La propriété target d'un événement de fenêtre native distribué par la fenêtre : private function onNativeWindowEvent(event:NativeWindowBoundsEvent):void { var win:NativeWindow = event.target as NativeWindow; } • La propriété nativeWindow d'une page HTML affichée dans la fenêtre : var win:NativeWindow = htmlLoader.window.nativeWindow; • Les propriétés activeWindow et openedWindows de l'objet NativeApplication : var nativeWin:NativeWindow = NativeApplication.nativeApplication.activeWindow; var firstWindow:NativeWindow = NativeApplication.nativeApplication.openedWindows[0]; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 75 Utilisation des fenêtres natives NativeApplication.nativeApplication.activeWindow référence la fenêtre active d'une application (mais renvoie null si la fenêtre active n'est pas une fenêtre de cette application AIR). Le tableau NativeApplication.nativeApplication.openedWindows contient toutes les fenêtres d'une application AIR n'ayant pas été fermée. Activation, affichage et masquage des fenêtres Pour activer une fenêtre, appelez la méthode NativeWindow activate(). Lorsque vous activez une fenêtre, celle-ci s'affiche au premier plan, la souris et le clavier reçoivent le focus et, le cas échéant, il est possible de rendre visible la fenêtre en la restaurant ou en définissant la propriété visible sur true. L'activation d'une fenêtre ne modifie pas l'ordre des autres fenêtres dans l'application. Lorsque vous appelez la méthode activate(), la fenêtre distribue un événement activate. Pour afficher une fenêtre masquée sans l'activer, définissez la propriété visible sur true. Cette action amène la fenêtre au premier plan, mais ne lui donne pas le focus. Pour masquer une fenêtre, définissez sa propriété visible sur false. Le masquage d'une fenêtre supprime l'affichage de la fenêtre et des icônes de la barre des tâches associées et, sous Mac OS X, l'entrée dans le menu Fenêtre. Remarque : sous Mac OS X, il n'est pas possible de masquer entièrement une fenêtre réduite qui possède une icône dans la partie de la fenêtre du Dock. Si la propriété visible est définie sur false sur une fenêtre minimisée, l'icône de la fenêtre dans le Dock est toujours affichée. Si l'utilisateur clique sur l'icône, la fenêtre est restaurée à un état visible et s'affiche. Modification de l'ordre d'affichage des fenêtres AIR propose plusieurs méthodes pour modifier directement l'ordre d'affichage des fenêtres. Vous pouvez placer une fenêtre au premier plan ou à l'arrière-plan ; vous pouvez en outre placer une fenêtre sur ou sous une autre fenêtre. L'utilisateur peut simultanément réorganiser les fenêtres en les activant. Il est possible de maintenir une fenêtre au premier plan en définissant sa propriété alwaysInFront sur true. Si ce même paramètre est défini dans plusieurs fenêtres, l'ordre d'affichage est à nouveau déterminé au sein des ces fenêtres ; toutefois, ces fenêtres sont toujours placées au-dessus des fenêtres dont la propriété alwaysInFront est définie sur false. Les fenêtres du groupe de premier niveau sont toujours affichées devant les fenêtres d'autres applications, même si l'application AIR n'est pas active. Etant donné que ce comportement peut perturber les utilisateurs, définissez la propriété alwaysInFront sur true uniquement lorsque cela est nécessaire. Exemples de cas dans lesquels cet emploi est justifié : • Fenêtres contextuelles temporaires, notamment infos-bulles, listes déroulantes, menus personnalisés ou zones déroulantes. Ces fenêtres doivent se fermer lorsqu'elles perdent le focus ; or, il est possible d'éviter qu'un utilisateur ne puisse pas afficher une autre fenêtre. • Messages et alertes extrêmement urgents. Lorsqu'une modification irrévocable risque de se produire si l'utilisateur ne répond pas à temps, il peut être justifié d'afficher au premier plan une fenêtre d'alerte. Néanmoins, la plupart des erreurs et des alertes peuvent être gérées dans l'ordre d'affichage normal des fenêtres. • Fenêtres affichées temporairement l'une derrière l'autre. Remarque : AIR n'impose pas l'utilisation correcte de la propriété alwaysInFront. Néanmoins, si votre application interrompt le flux de travail d'un utilisateur, il est probable qu'elle termine dans la corbeille de cet utilisateur. La classe NativeWindow fournit les propriétés et les méthodes suivantes pour définir l'ordre d'affichage d'une fenêtre par rapport à d'autres fenêtres : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 76 Utilisation des fenêtres natives Membre Description alwaysInFront, propriété Indique si la fenêtre est affichée dans le groupe de fenêtres de premier niveau. Dans la plupart des cas, le paramètre false est recommandé. Si vous modifiez la valeur de false à true, la fenêtre est placée devant toutes les autres fenêtres (mais elle n'est pas activée). Si vous modifiez la valeur de true à false, la fenêtre est placée derrière les fenêtres restantes du groupe de premier niveau, mais reste devant les autres fenêtres. Si vous définissez la propriété sur sa valeur actuelle pour une fenêtre, vous ne modifiez pas l'ordre d'affichage de cette dernière. orderToFront() Place la fenêtre au premier plan. orderInFrontOf() Place la fenêtre directement devant une fenêtre spécifique. orderToBack() Envoie la fenêtre derrière les autres fenêtres. orderBehind() Envoie la fenêtre directement derrière une fenêtre spécifique. activate() Place la fenêtre au premier plan (tout en la rendant visible et en lui donnant le focus). Remarque : si une fenêtre est masquée (la propriété visible est définie sur false) ou minimisée, l'appel des méthodes de l'ordre d'affichage est sans effet. Dans le système d'exploitation Linux, les différents gestionnaires de fenêtres imposent des règles différentes quant à l'ordre d'affichage des fenêtres : • Dans certains gestionnaires de fenêtres, les fenêtres d'utilitaires sont toujours affichées devant les fenêtres normales. • Dans certains gestionnaires de fenêtres, une fenêtre plein écran dont la propriété alwaysInFront est définie sur true s'affiche toujours devant les autres fenêtres dont la propriété alwaysInFront est également définie sur true. Fermeture d'une fenêtre Pour fermer une fenêtre, utilisez la méthode NativeWindow.close(). La fermeture d'une fenêtre décharge le contenu de la fenêtre, mais si les autres objets possèdent des références à ce contenu, les objets de contenu ne sont pas détruits. La méthode NativeWindow.close() s'exécute de façon asynchrone, et l'application contenue dans la fenêtre continue de fonctionner lors de la fermeture. La méthode de fermeture distribue un événement close lorsque l'opération de fermeture est terminée. Techniquement, l'objet NativeWindow est toujours valide, mais l'accès à la plupart des propriétés et des méthodes sur une fenêtre fermée génère un erreur IllegalOperationError. Vous ne pouvez pas ouvrir à nouveau une fenêtre fermée. Vérifiez la propriété closed d'une fenêtre pour vous assurer que la fenêtre a été fermée. Pour simplement masquer une fenêtre, définissez la propriété NativeWindow sur false. Si la propriété Nativeapplication.autoExit est définie sur true (valeur par défaut), l'application se ferme lors de la fermeture de sa dernière fenêtre. Autorisation d'annulation des opérations sur les fenêtres Lorsqu'une fenêtre utilise l'arrière-plan système, l'interaction de l'utilisateur avec la fenêtre peut être annulée en écoutant les événements appropriés et en annulant leur comportement par défaut. Par exemple, lorsqu'un utilisateur clique sur le bouton de fermeture de l'arrière-plan système, l'événement closing est distribué. Si l'un des écouteurs enregistrés appelle la méthode preventDefault() de l'événement, la fenêtre ne se ferme pas. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 77 Utilisation des fenêtres natives Si une fenêtre n'utilise pas l'arrière-plan système, les événements de notification des modifications désirées ne sont pas automatiquement distribués avant que la modification ait lieu. Donc, si vous appelez les méthodes qui permettent de fermer une fenêtre, d'en modifier l'état ou d'en définir les propriétés de limite, la modification ne peut pas être annulée. Pour notifier les composants dans votre application avant d'effectuer une modification, votre logique d'application peut distribuer l'événement de notification adéquat à l'aide de la méthode dispatchEvent() de la fenêtre. Par exemple, la logique suivante implémente un gestionnaire d'événement pouvant être annulé pour le bouton de fermeture d'une fenêtre : public function onCloseCommand(event:MouseEvent):void{ var closingEvent:Event = new Event(Event.CLOSING,true,true); dispatchEvent(closing); if(!closingEvent.isDefaultPrevented()){ win.close(); } } La méthode dispatchEvent() renvoie false si la méthode preventDefault() de l'événement est appelée par un écouteur. Toutefois, elle peut également renvoyer false pour d'autres raisons ; par conséquent, il convient d'utiliser explicitement la méthode isDefaultPrevented() afin de vérifier si la modification doit ou non être annulée. Agrandissement, réduction et restauration d'une fenêtre Pour agrandir la fenêtre, utilisez la méthode maximize() de la classe NativeWindow. myWindow.maximize(); Pour réduire la fenêtre, utilisez la méthode minimize() de la classe NativeWindow. myWindow.minimize(); Pour restaurer la fenêtre (c'est-à-dire rétablir la taille de la fenêtre avant l'agrandissement ou la réduction), utilisez la méthode restore() de la classe NativeWindow. myWindow.restore(); Remarque : le comportement résultant de l'agrandissement d'une fenêtre AIR est différent du comportement standard de Mac OS X. Plutôt que de basculer entre la taille « standard » définie par l'application et la dernière taille définie par l'utilisateur, les fenêtres AIR basculent entre la dernière taille définie par l'application ou l'utilisateur et la totalité de la zone utilisable de l'écran. Dans le système d'exploitation Linux, les différents gestionnaires de fenêtres imposent des règles différentes quant à la définition de l'état d'affichage des fenêtres : • Avec certains gestionnaires de fenêtres, les fenêtres d'utilitaires ne peuvent pas être agrandies. • Si une taille maximale est définie pour la fenêtre, certains gestionnaires n'autorisent pas l'agrandissement de la fenêtre. D'autres gestionnaires de fenêtres définissent l'état d'affichage sur l'état maximal, mais ne redimensionnent pas la fenêtre. Dans tous les cas, aucun événement de modification d'état d'affichage n'est distribué. • Certains gestionnaires de fenêtres ne respectent pas les paramètres maximizable ou minimizable des fenêtres. Exemple : réduction, agrandissement, restauration et fermeture d'une fenêtre L'exemple ActionScript suivant pour Flash crée quatre champs de texte cliquables qui déclenchent les méthodes minimize(), maximize(), restore() et close() de la classe NativeWindow : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 78 Utilisation des fenêtres natives 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); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 79 Utilisation des fenêtres natives 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(); } } } Redimensionnement et déplacement d'une fenêtre Lorsqu'une fenêtre utilise l'arrière-plan système, l'arrière-plan fournit des commandes de glissement pour redimensionner la fenêtre et la déplacer dans le poste de travail. Si une fenêtre n'utilise pas l'arrière-plan système, vous devez ajouter vos propres commandes pour permettre à l'utilisateur de redimensionner et de déplacer la fenêtre. Remarque : pour redimensionner ou déplacer une fenêtre, vous devez tout d'abord obtenir une référence à l'occurrence de NativeWindow. Pour plus d'informations sur la méthode d'obtention d'une référence de fenêtre, consultez la section « Obtention d'une occurrence de NativeWindow » à la page 74. Redimensionnement d'une fenêtre Pour que l'utilisateur puisse interagir avec la taille d'une fenêtre, utilisez la méthode startResize() de la classe NativeWindow. Lorsque cette méthode est appelée depuis un événement mouseDown, l'opération de redimensionnement est effectuée par la souris et se termine lorsque le système d'exploitation reçoit un événement mouseUp. Lors de l'appel de la méthode startResize(), vous transmettez un argument qui indique le bord ou le coin à partir duquel la fenêtre doit être redimensionnée. Pour définir la taille de la fenêtre par programmation, définissez les propriétés width, height ou bounds de la fenêtre sur les dimensions désirées. Lorsque vous définissez les limites, la taille et la position de la fenêtre peuvent changer simultanément. Toutefois, l'ordre de ces changements n'est pas garanti. Certains gestionnaires de fenêtres Linux ne permettent pas aux fenêtres de dépasser les limites de l'écran. Dans ce cas, la taille finale de la fenêtre peut être limitée du fait de l'ordre dans lequel les propriétés sont définies, même si l'impact des modifications aurait autrement résulté en une fenêtre valide. Par exemple, si vous modifiez à la fois la hauteur et la position y d'une fenêtre à proximité du bas de l'écran, la modification en pleine hauteur peut ne pas survenir lorsque la hauteur est modifiée avant la position y. Remarque : sous Linux, les propriétés des fenêtres sont modifiées de façon asynchrone. Si vous définissez une propriété dans une ligne de votre programme et que vous lisez la valeur dans la suivante, la valeur reflète encore l'ancien paramètre. Pour détecter le moment où la modification est appliquée, vous pouvez utiliser les événements générés par la fenêtre. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 80 Utilisation des fenêtres natives Le mode d'échelle de la scène indique le comportement de la scène de la fenêtre et de son contenu lorsqu'une fenêtre est redimensionnée. N'oubliez pas que les modes d'échelle de la scène sont conçus pour les situations où l'application ne contrôle pas la taille ou les proportions de son espace d'affichage (notamment dans le cas d'un navigateur Web). En règle générale, vous obtenez les meilleurs résultats en définissant la propriété scaleMode de la scène sur StageScaleMode.NO_SCALE. Pour mettre à l'échelle le contenu d'une fenêtre, vous pouvez toujours définir les paramètres scaleX et scaleY du contenu lors des modifications des limites de la fenêtre. Déplacement d'une fenêtre Pour déplacer une fenêtre sans la redimensionner, utilisez la méthode startMove() de la classe NativeWindow. A l'instar de la méthode startResize(), lorsque la méthode startMove() est appelée à partir d'un événement mouseDown, le déplacement est effectué avec la souris et se termine lorsque le système d'exploitation reçoit un événement mouseUp. Pour plus d'informations sur les méthodes startResize et startMove, consultez le Guide de référence du langage et des composants ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_fr). Exemple : redimensionnement et déplacement des fenêtres L'exemple suivant montre comment lancer les opérations de redimensionnement et de déplacement sur une fenêtre : 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(); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 81 Utilisation des fenêtres natives 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(); } } } Ecoute des événements d'une fenêtre Pour écouter les événements distribués par une fenêtre, enregistrez un écouteur avec l'occurrence de la fenêtre. Par exemple, pour écouter un événement closing, enregistrez un écouteur avec la fenêtre, comme suit : myWindow.addEventListener(Event.CLOSING, onClosingEvent); Lorsqu'un événement est distribué, la propriété target référence la fenêtre qui envoie l'événement. La plupart des événements de fenêtre sont associés à deux messages. Le premier message signale l'imminence d'une modification au niveau de la fenêtre (modification pouvant être annulée) ; le second message indique que la modification a été effectuée. Par exemple, lorsqu'un utilisateur clique sur le bouton de fermeture d'une fenêtre, le message de l'événement closing est distribué. Si aucun écouteur n'annule l'événement, la fenêtre se ferme et l'événement close est distribué à l'un des écouteurs. En règle générale, les événements d'avertissement, tels que closing, ne sont distribués que lorsque l'arrière-plan système a été utilisé pour déclencher un événement. L'appel de la méthode close(), par exemple, ne distribue pas automatiquement l'événement closing ; seul l'événement close est distribué. Vous pouvez toutefois créer un événement closing et le distribuer à l'aide de la méthode dispatchEvent() de la fenêtre. Les événements de fenêtre qui distribuent un objet Event sont les suivants : Evénement Description activate Distribué lorsque la fenêtre reçoit le focus. deactivate Distribué lorsque la fenêtre perd le focus. closing Distribué lorsque la fenêtre est sur le point de se fermer. Cet événement ne se produit automatiquement que lorsque l'utilisateur appuie sur le bouton de fermeture de l'arrière-plan système ou, sous OS X, lorsque la commande Quitter est invoquée. close Distribué lorsque la fenêtre a été fermée. Les événements de fenêtre qui distribuent un objet NativeWindowBoundsEvent sont les suivants : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 82 Utilisation des fenêtres natives Evénement Description moving Distribué immédiatement avant que le coin supérieur gauche de la fenêtre change de position, suite au déplacement, au redimensionnement ou à la modification de l'état d'affichage de la fenêtre. move Distribué après que le coin supérieur gauche de la fenêtre a changé de position. resizing Distribué immédiatement avant que la largeur ou la hauteur de la fenêtre change, suite au redimensionnement ou à la modification de l'état d'affichage de la fenêtre. resize Distribué après que la taille de la fenêtre a changé. Pour les événements NativeWindowBoundsEvent, vous pouvez utiliser les propriétés beforeBounds et afterBounds pour déterminer les limites de la fenêtre avant une modification imminente ou après avoir effectué une modification. Les événements de fenêtre qui distribuent un objet NativeWindowDisplayStateEvent sont les suivants : Evénement Description displayStateChanging Distribué immédiatement avant que l'état d'affichage de la fenêtre change. displayStateChange Distribué une fois l'état d'affichage de la fenêtre modifié. Pour les événements NativeWindowDisplayStateEvent, vous pouvez utiliser les propriétés beforeDisplayState et afterDisplayState pour déterminer l'état d'affichage de la fenêtre avant une modification imminente et après avoir effectué une modification. Dans certains gestionnaires de fenêtres Linux, aucun événement de modification de l'état d'affichage n'est distribué lors de l'agrandissement d'une fenêtre possédant un paramètre de taille maximale. (La fenêtre est définie sur l'état d'affichage maximal, mais n'est pas redimensionnée.) Affichage des fenêtres en mode plein écran La définition de la propriété displayState de la scène sur StageDisplayState.FULL_SCREEN_INTERACTIVE met la fenêtre en mode plein écran et la saisie clavier is est autorisée dans ce mode. (Pour le contenu SWF s'exécutant dans un navigateur, la saisie clavier n'est pas autorisée). Pour quitter le mode plein écran, l'utilisateur doit appuyer sur la touche Echap. Remarque : certains gestionnaires de fenêtres Linux ne modifient pas les dimensions de la fenêtre pour remplir l'écran si une taille maximale est définie pour celle-ci (mais suppriment l'arrière-plan système de la fenêtre). L'exemple ActionScript suivant pour Flash simule un terminal d'écran complet simple : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 83 Utilisation des fenêtres natives 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 Chapitre 11 : Ecrans Utilisez la classe Screen d'Adobe® AIR® pour accéder à des informations sur les écrans rattachés à un ordinateur de bureau. Informations complémentaires en ligne sur les écrans Vous pouvez trouver plus d'informations sur la classe Screen et l'utilisation des écrans dans les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Mesure de l'ordinateur de bureau virtuel Guide de référence du langage • Screen Articles et exemples dans Adobe Developer Connection • Adobe AIR Developer Connection pour Flash (rechercher « AIR screens ») Principes de base des écrans L'interface de programmation de l'écran contient une seule classe, Screen, qui permet à des membres statiques de lire des informations système sur les écrans et à des membres d'occurrences de décrire un écran particulier. Plusieurs écrans peuvent être reliés à un système d'ordinateurs, ce qui peut donner lieu à un espace virtuel qui contient plusieurs écrans d'ordinateur. La classe Screen d'AIR fournit des informations sur les écrans, leur organisation relative et leur espace utilisable. Si plusieurs moniteurs mappent sur le même écran, seul un écran existe. Si la taille d'un écran est plus grande que la zone d'affichage du moniteur, il n'y a pas moyen de savoir quelle partie de l'écran est actuellement visible. Un écran représente une zone d'affichage indépendante de l'ordinateur. Les écrans sont décrits comme des rectangles au sein d'un ordinateur de bureau virtuel. Le coin supérieur gauche de l'écran désigné comme zone d'affichage principale, constitue l'origine du système de coordonnées de l'ordinateur virtuel. Toutes les valeurs utilisées dans la description d'un écran sont exprimées en pixels. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 85 Ecrans Dans cette organisation d'écrans, deux écrans existent sur l'ordinateur virtuel. Les coordonnées du coin supérieur gauche de l'écran principal (nº 1) sont toujours (0,0). Si l'organisation des écrans change pour désigner l'écran nº 2 comme écran principal, les coordonnées de l'écran nº 1 deviennent négatives. Les barres de menus, les barres de tâches et les Docks sont ignorés lorsque les limites utilisables sont signalées pour un écran. Pour des informations détaillées sur la classe, les méthodes, les propriétés et les événements de l'interface de programmation des écrans, consultez le Guide de référence du langage et des composants ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_fr). Dénombrement des écrans Vous pouvez dénombrer les écrans d'un ordinateur de bureau virtuel avec les méthodes et propriétés suivantes : Méthode ou propriété Description Screen.screens Fournit un tableau d'objets Screen qui décrit les écrans disponibles. Notez que l'ordre du tableau n'a pas d'importance. Screen.mainScreen Fournit un objet Screen pour l'écran principal. Sous Mac OS X, l'écran principal est celui qui affiche la barre de menus. Sous Windows, l'écran principal est celui désigné par le système. Screen.getScreensForRectangle() Fournit un tableau d'objets Screen qui décrit les écrans qui sont coupés par le rectangle donné. Le rectangle transmis par cette méthode est défini par des coordonnées, exprimées en pixels, sur l'ordinateur virtuel. S'il n'y a aucune intersection entre écrans et rectangle, le tableau est vide. Vous pouvez utiliser cette méthode pour trouver sur quels écrans une fenêtre est affichée. Vous ne devriez pas enregistrer les valeurs renvoyées par les méthodes et propriétés de la classe Screen. L'utilisateur ou le système d'exploitation peuvent changer les écrans disponibles et leur organisation en tout temps. L'exemple suivant utilise l'interface de programmation des écrans pour déplacer une fenêtre entre plusieurs écrans en réponse à la pression sur les touches de direction. Pour déplacer la fenêtre sur l'écran suivant, l'exemple lit le tableau screens et le trie verticalement ou horizontalement, suivant la touche de direction sur laquelle on a appuyé. Le code parcourt le tableau trié en comparant chaque écran aux coordonnées de l'écran actif. Pour identifier l'écran actif de la fenêtre, l'exemple appelle Screen.getScreensForRectangle() en le transmettant dans les limites de la fenêtre. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 86 Ecrans 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 += DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 87 Ecrans 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 Chapitre 12 : Utilisation de menus natifs Les classes de l'API de menus natifs permettent de définir des menus en incrustation, contextuels, de fenêtre et d'application. Informations complémentaires en ligne sur les menus natifs Pour plus d'informations sur l'API de menus natifs et l'utilisation de ces derniers, consultez les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Ajout de menus natifs à une application AIR Guide de référence du langage • NativeMenu • NativeMenuItem Adobe Developer Connection - Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « AIR menus ») Principes de base des menus AIR Les classes de menus natifs vous permettent d'accéder aux fonctions de menu natif du système d'exploitation sur lequel s'exécute votre application. Des objets NativeMenu peuvent être utilisés pour les menus d'application (sous Mac OS X), les menus de fenêtre (sous Windows et Linux), les menus contextuels et les menus en incrustation. Classes de menu d'AIR Les classes de menu d'Adobe® AIR™ sont les suivantes : Package Classes flash.display • NativeMenu • NativeMenuItem • ContextMenu • ContextMenuItem • Event • ContextMenuEvent flash.ui flash.events DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 89 Utilisation de menus natifs Types de menus AIR prend en charge les types de menus suivants : Menus d'application Un menu d'application est un menu global qui s'applique à la totalité de l'application. Les menus d'application sont pris en charge par Mac OS X, mais pas par Windows ni Linux. Sous Mac OS x, le système d'exploitation crée automatiquement un menu d'application. Vous pouvez utiliser l'API de menus d'AIR pour ajouter des éléments et des sous-menus aux menus standard. Vous pouvez ajouter des écouteurs pour gérer les commandes de menu existantes et vous pouvez supprimer des éléments existants. Menus de fenêtre Un menu de fenêtre est associé à une fenêtre unique et s'affiche sous la barre de titre. Pour ajouter des menus à une fenêtre, vous créez un objet NativeMenu et l'affectez à la propriété menu de l'objet NativeWindow. Les menus de fenêtre sont pris en charge par les systèmes d'exploitation Windows et Linux, mais pas par Mac OS X. Les menus de fenêtre natifs ne peuvent être utilisés qu'avec les fenêtres disposant d'un arrière-plan système. Menus contextuels Un menu contextuel s'affiche lorsque l'utilisateur clique avec le bouton droit de la souris ou en maintenant la touche Commande enfoncée sur un objet interactif dans du contenu SWF ou sur un élément de document dans du contenu HTML. Vous pouvez créer un menu contextuel à l'aide de la classe NativeMenu ou ContextMenu. Dans du contenu HTML, vous pouvez utiliser les API Webkit HTML et JavaScript pour ajouter des menus contextuels aux éléments HTML. Menus d'icônes de la barre d'état système et du Dock Similaires aux menus contextuels, les menus d'icône sont affectés à l'icône d'une application dans le Dock de Mac OS X ou dans la zone de notification de la barre des tâches de Windows et Linux. Les menus d'icônes de la barre d'état système et du Dock utilisent la classe NativeMenu. Sous Mac OS X, les éléments du menu sont ajoutés au-dessus des éléments standard du système d'exploitation. Sous Windows et Linux, le menu standard n'existe pas. Menus en incrustation Un menu en incrustation AIR est similaire à un menu contextuel mais il n'est pas nécessairement associé à un objet ou composant d'application spécifique. Vous pouvez afficher des menus en incrustation n'importe où dans une fenêtre en appelant la méthode display() de tout objet NativeMenu. Menus personnalisés Les menus natifs sont dessinés entièrement par le système d'exploitation et, en tant que tels, existent en dehors des modèles de rendu Flash et HTML. Vous avez tout loisir de créer vos propres menus non natifs à l'aide de MXML, ActionScript ou JavaScript. Les classes de menu d'AIR ne permettent pas de contrôler le dessin des menus natifs. Menus par défaut Les menus par défaut suivants sont proposés par le système d'exploitation ou une classe AIR intégrée : • Menu d'application sous Mac OS X • Menu d'icône du Dock sous Mac OS X • Menu contextuel associé au texte et aux images sélectionnés dans du contenu HTML • Menu contextuel associé au texte sélectionné dans un objet TextField (ou un objet étendant TextField) Structure des menus Par nature, les menus ont des structures hiérarchiques. Les objets NativeMenu contiennent des objets enfant NativeMenuItem. Les objets NativeMenuItem qui représentent des sous-menus peuvent eux aussi contenir des objets NativeMenu. L'objet menu du niveau supérieur ou racine de la structure représente la barre de menus des menus d'application et de fenêtre. (Les menus contextuels, d'icônes et en incrustation ne possèdent pas de barre de menus.) DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 90 Utilisation de menus natifs Le schéma suivant illustre la structure d'un menu typique. Le menu racine représente la barre de menus et contient deux éléments de menu référençant les sous-menus File et Edit. Le sous-menu File de cette structure contient deux éléments de commande et un élément référençant le sous-menu Menu Ouvrir un fichier récent qui, lui-même, contient trois éléments. Le sous-menu Edit contient trois commandes et un séparateur. Pour définir un sous-menu, vous devez disposer d'un objet NativeMenu et d'un objet NativeMenuItem. L'objet NativeMenuItem définit le libellé affiché dans le menu parent et permet à l'utilisateur d'ouvrir le sous-menu. L'objet NativeMenu sert de conteneur des éléments du sous-menu. Par le biais de sa propriété submenu, l'objet NativeMenuItem référence l'objet NativeMenu. Vous trouverez un exemple de code qui crée ce menu à la section « Exemple : menu de fenêtre et d'application » à la page 100. Evénements de menu Les objets NativeMenu et NativeMenuItem distribuent des événements displaying et select : Affichage : immédiatement après son affichage, un menu et ses éléments distribuent un événement displaying à tout écouteur enregistré. L'événement displaying vous donne l'occasion de mettre à jour le contenu du menu ou l'apparence de l'élément avant son affichage à l'intention de l'utilisateur. Par exemple, dans l'écouteur de l'événement displaying d'un menu « Ouvrir un fichier récent », vous pourriez modifier les éléments de menu en fonction de la liste actuelle de documents affichés récemment. La propriété target de l'objet événement correspond systématiquement au menu sur le point d'être affiché. La propriété currentTarget représente l'objet sur lequel l'écouteur est enregistré : le menu ou un de ses éléments. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 91 Utilisation de menus natifs Remarque : l'événement displaying est également distribué à chaque accès à l'état du menu ou d'un de ses éléments. Sélection : lorsque l'utilisateur choisit une commande, l'élément distribue un événement select à tout écouteur enregistré. Les sous-menus ou les séparateurs ne distribuent jamais d'événements select car il est impossible de les sélectionner. Un événement select remonte d'un élément de menu vers son menu conteneur ou jusqu'au menu racine. Vous pouvez écouter les événements select directement sur un élément ou plus haut dans la structure de menu. Lorsque vous écoutez un événement select sur un menu, vous pouvez identifier l'élément sélectionné à l'aide de la propriété target de l'événement. Lorsque l'événement remonte dans la hiérarchie de menu, la propriété currentTarget de l'objet événement identifie l'objet menu actuel. Remarque : les objets ContextMenu et ContextMenuItem distribuent des événements menuItemSelect et menuSelect, ainsi que des événements select et displaying. Equivalents clavier des commandes de menu Vous pouvez affecter un équivalent clavier (parfois appelé accélérateur) à une commande de menu. L'élément de menu distribue un événement select à tout écouteur enregistré lorsque l'utilisateur appuie sur la touche ou la combinaison de touches. Le menu contenant l'élément doit appartenir au menu de l'application ou de la fenêtre active pour la commande à appeler. L'équivalent clavier se compose de deux parties : une chaîne représentant la touche principale et un tableau de touches de modification sur lesquelles il est également nécessaire d'appuyer. Pour affecter une touche principale, définissez la propriété keyEquivalent de l'élément de menu sur la chaîne à caractère unique correspondant à cette touche. Si vous utilisez une majuscule, la touche Maj est automatiquement ajoutée au tableau de touches de modification. Sous Mac OS X, la touche Commande (Keyboard.COMMAND) est la touche de modification par défaut. Sous Windows et Linux, il s'agit de la touche Ctrl (Keyboard.CONTROL). Ces touches par défaut sont automatiquement ajoutées au tableau de touches de modification. Pour utiliser d'autres touches de modification, affectez un nouveau tableau contenant les codes de touche souhaités à la propriété keyEquivalentModifiers. Le tableau par défaut est remplacé. Que vous utilisiez les touches de modification par défaut ou votre propre tableau de touches de modification, la touche Maj est ajoutée si la chaîne que vous affectez à la propriété keyEquivalent est une lettre majuscule. Les constantes correspondant aux codes de touche à utiliser pour les touches de modification sont définies dans la classe Keyboard. La chaîne d'équivalent clavier affectée est automatiquement affichée en regard du nom de l'élément de menu. Le format varie selon le système d'exploitation et les préférences système de l'utilisateur. Remarque : si vous affectez la valeur Keyboard.COMMAND à un tableau de touches de modification sous Windows, aucun équivalent clavier n'est affiché dans le menu. En revanche, il est impératif d'utiliser la touche Ctrl pour activer la commande de menu. L'exemple suivant affecte l'équivalent clavier Ctrl+Maj+G à un élément de menu : var item:NativeMenuItem = new NativeMenuItem("Ungroup"); item.keyEquivalent = "G"; L'exemple suivant affecte l'équivalent clavier Ctrl+Maj+G en définissant directement le tableau de modification : var item:NativeMenuItem = new NativeMenuItem("Ungroup"); item.keyEquivalent = "G"; item.keyEquivalentModifiers = [Keyboard.CONTROL]; Remarque : les équivalents clavier sont uniquement déclenchés pour les menus d'application et de fenêtre. Un équivalent clavier ajouté à un menu contextuel ou à un menu en incrustation est indiqué dans le libellé du menu, mais la commande de menu associée n'est jamais appelée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 92 Utilisation de menus natifs Mnémoniques Les mnémoniques font partie de l'interface clavier du système d'exploitation pour les menus. Linux, Mac OS X et Windows permettent d'ouvrir des menus et de sélectionner des commandes par le biais du clavier mais il existe quelques petites différences. Sous Mac OS X, l'utilisateur saisit la ou les deux premières lettres du menu ou de la commande et appuie sur Entrée. La propriété mnemonicIndex est ignorée. Sous Windows, seule une lettre est significative. Par défaut, elle correspond au premier caractère du libellé mais si vous affectez une mnémonique à un élément de menu, la lettre désignée devient le caractère significatif. Si deux éléments d'un menu possèdent le même caractère significatif (qu'une mnémonique ait été affectée ou non), l'interaction avec le menu à partir du clavier change légèrement. Plutôt que d'appuyer sur une seule lettre pour sélectionner le menu ou la commande, l'utilisateur appuie sur la lettre autant de fois que nécessaire pour mettre en évidence l'élément souhaité, puis il appuie sur la touche Entrée pour confirmer la sélection. Pour garantir un comportement cohérent, il est préférable d'affecter une seule mnémonique à chaque élément d'un menu sous Windows. Sous Linux, aucune mnémonique n'est fournie par défaut. Pour fournir une mnémonique, vous devez définir la valeur de la propriété mnemonicIndex d'un élément de menu. Spécifiez le caractère mnémonique en tant qu'index dans la chaîne de libellé. L'index du premier caractère d'un libellé est 0. Ainsi pour utiliser le « r » comme mnémonique d'un menu intitulé « Format », vous définissez la propriété mnemonicIndex sur 2. var item:NativeMenuItem = new NativeMenuItem("Format"); item.mnemonicIndex = 2; Etat d'un élément de menu Les éléments de menu possèdent deux propriétés d'état : checked (coché) et enabled (activé) : checked Définissez cette propriété sur true pour afficher une coche en regard du libellé de l'élément. var item:NativeMenuItem = new NativeMenuItem("Format"); item.checked = true; enabled Faites basculer la valeur entre true et false pour vérifier si la commande est activée. Les éléments désactivés sont affichés « en grisé » et ne distribuent pas d'événements select. var item:NativeMenuItem = new NativeMenuItem("Format"); item.enabled = false; Rattachement d'un objet à un élément de menu La propriété data de la classe NativeMenuItem vous permet de référencer un objet arbitraire dans chaque élément. Par exemple, dans un menu « Ouvrir un fichier récent », vous pourriez affecter l'objet File associé à chaque document à chaque élément de menu. var file:File = File.applicationStorageDirectory.resolvePath("GreatGatsby.pdf") var menuItem:NativeMenuItem = docMenu.addItem(new NativeMenuItem(file.name)); menuItem.data = file; Création de menus natifs Cette rubrique explique comment créer les différents types de menus natifs pris en charge par AIR. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 93 Utilisation de menus natifs Création d'un objet menu racine Pour créer un objet NativeMenu en tant que racine du menu, utilisez le constructeur NativeMenu : var root:NativeMenu = new NativeMenu(); Dans les menus d'application et de fenêtre, le menu racine représente la barre de menus et doit uniquement contenir des éléments donnant accès à des sous-menus. Les menus en incrustation et les menus contextuels ne possèdent pas de barre de menus. Le menu racine peut donc contenir des commandes et des séparateurs, ainsi que des sous-menus. Une fois le menu créé, vous pouvez lui ajouter des éléments de menu. Les éléments figurent dans le menu dans l'ordre dans lequel vous les ajoutez, à moins que vous ne les ajoutiez à un index spécifique à l'aide de la méthode addItemAt() d'un objet menu. Affectez le menu en tant que menu d'application, de fenêtre, d'icône ou contextuel ou affichez-le en tant que menu en incrustation, comme indiqué dans les sections suivantes : Définition d'un menu d'application NativeApplication.nativeApplication.menu = root; Remarque : Mac OS X définit, pour chaque application, un menu contenant des éléments standard. L'affectation d'un nouvel objet NativeMenu à la propriété menu de l'objet NativeApplication remplace le menu standard. Libre à vous de conserver ce menu standard plutôt que de le remplacer. Définition d'un menu de fenêtre nativeWindowObject.menu = root; Définition d'un menu contextuel associé à un objet interactif interactiveObject.contextMenu = root; Définition d'un menu d'icône du Dock DockIcon(NativeApplication.nativeApplication.icon).menu = root; Remarque : Mac OS X définit un menu standard pour l'icône du Dock d'une application. Lorsque vous affectez un nouvel objet NativeMenu à la propriété menu de l'objet DockIcon, les éléments de ce menu sont affichés au-dessus des éléments standard. Il est impossible de supprimer ou de modifier les éléments standard ou d'y accéder. Définition d'un menu d'icône de la barre d'état système SystemTrayIcon(NativeApplication.nativeApplication.icon).menu = root; Affichage d'un menu en incrustation root.display(stage, x, y); Création d'un sous-menu Pour créer un sous-menu, vous ajoutez un objet NativeMenuItem au menu parent, puis vous affectez l'objet NativeMenu définissant le sous-menu sur la propriété submenu de l'élément. AIR vous propose deux méthodes de création des éléments de sous-menu et de l'objet menu associé : Vous pouvez créer un élément de menu et son objet menu associé en une seule opération à l'aide de la méthode addSubmenu() : var editMenuItem:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit"); Vous pouvez aussi créer l'élément de menu et ensuite seulement affecter l'objet menu à sa propriété submenu : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 94 Utilisation de menus natifs var editMenuItem:NativeMenuItem = root.addItem("Edit", false); editMenuItem.submenu = new NativeMenu(); Création d'une commande de menu Pour créer une commande de menu, ajoutez un objet NativeMenuItem à un menu et ajoutez un écouteur d'événement référençant la fonction qui met en œuvre la commande de menu : var copy:NativeMenuItem = new NativeMenuItem("Copy", false); copy.addEventListener(Event.SELECT, onCopyCommand); editMenu.addItem(copy); Vous pouvez écouter l'événement select sur l'élément commande même (comme illustré dans l'exemple) ou sur un objet menu parent. Remarque : les éléments de menu qui représentent des sous-menus et des séparateurs ne distribuent pas d'événements select et vous ne pouvez donc pas les utiliser en tant que commandes. Création d'un séparateur de menu Pour créer un séparateur, créez un objet NativeMenuItem, en définissant le paramètre isSeparator sur true dans le constructeur. Ajoutez ensuite le séparateur au menu à l'emplacement approprié : var separatorA:NativeMenuItem = new NativeMenuItem("A", true); editMenu.addItem(separatorA); Le libellé spécifié pour le séparateur, le cas échéant, n'est pas affiché. Présentation des menus contextuels Dans du contenu SWF, il est possible d'associer un menu contextuel à tout objet qui hérite des propriétés ou méthodes de InteractiveObject en affectant un objet menu à sa propriété contextMenu. L'objet menu affecté à contextMenu peut être de type NativeMenu ou ContextMenu. Vous pouvez écouter les événements des menus natifs ou des menus contextuels lorsque vous utilisez les classes ContextMenu et ContextMenuItem ; les deux sont distribués. L'un des avantages des propriétés de l'objet ContextMenuEvent est que contextMenuOwner identifie l'objet auquel le menu est associé et mouseTarget identifie l'objet sur lequel l'utilisateur a cliqué pour ouvrir le menu. Ces informations ne sont pas disponibles avec l'objet NativeMenuEvent. L'exemple suivant crée un sprite et l'ajoute à un menu contextuel edit simple : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 95 Utilisation de menus natifs 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");} Remarque : contrairement au contenu SWF affiché dans un environnement de navigateur, dans AIR, les menus contextuels ne possèdent pas de commandes intégrées. Présentation des menus contextuels dans HTML Dans du contenu HTML, l'événement contextmenu permet d'afficher un menu contextuel. Par défaut, un menu contextuel est affiché automatiquement lorsque l'utilisateur appelle l'événement contextmenu sur le texte sélectionné (en cliquant avec le bouton droit de la souris ou en cliquant tout en appuyant sur la touche Commande). Pour empêcher l'affichage du menu par défaut, écoutez l'événement contextmenu et appelez la méthode preventDefault() de l'objet événement : function showContextMenu(event){ event.preventDefault(); } Vous pouvez ensuite ouvrir un menu contextuel personnalisé à l'aide des techniques DHTML ou en affichant un menu contextuel natif AIR. Dans l'exemple suivant, un menu contextuel natif s'affiche sur appel de la méthode display() du menu en réponse à l'événement HTML contextmenu : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 96 Utilisation de menus natifs <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> Définition des menus natifs par déclaration Il peut être laborieux de coder les propriétés d'un menu et des éléments de menu. Cependant, comme les menus ont par nature une structure hiérarchique, il est simple d'écrire une fonction qui crée un menu à l'aide d'une définition au format XML. A cet effet, la classe suivante étend NativeMenu, en intégrant un objet XML à son constructeur : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 97 Utilisation de menus natifs 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 Pour créer un menu à l'aide de cette classe, transmettez une définition de menu XML, comme suit : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 98 Utilisation de menus natifs 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); Pour rechercher les événements menu, vous pourriez écouter au niveau du menu racine et utiliser la propriété event.target.name pour déterminer quelle commande a été sélectionnée. Vous pourriez aussi rechercher des éléments du menu par nom et ajouter des écouteurs d'événement individuels. Affichage de menus en incrustation Vous pouvez afficher tout objet NativeMenu à tout moment et à tout emplacement au-dessus d'une fenêtre en appelant la méthode display() du menu. Cette méthode exigeant une référence à la scène, seul le contenu figurant dans le sandbox de l'application peut afficher un menu en incrustation. La méthode suivante affiche le menu défini par l'objet NativeMenu popupMenu en réponse à un clic de souris : private function onMouseClick(event:MouseEvent):void { popupMenu.display(event.target.stage, event.stageX, event.stageY); } Remarque : il est inutile d'afficher le menu directement en réponse à un événement. N'importe quelle méthode peut appeler la fonction display(). Gestion des événements de menu Un menu distribue des événements lorsque l'utilisateur sélectionne le menu ou l'un de ses éléments. Récapitulatif des événements associés aux classes de menu Ajoutez des écouteurs d'événement à des menus ou à des éléments individuels pour gérer les événements de menu. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 99 Utilisation de menus natifs Objet Evénements distribués NativeMenu NativeMenuEvent.DISPLAYING NativeMenuEvent.SELECT (propagé à partir des sous-menus et éléments enfant) NativeMenuItem NativeMenuEvent.SELECT NativeMenuEvent.DISPLAYING (propagé à partir du menu parent) ContextMenu ContextMenuEvent.MENU_SELECT ContextMenuItem ContextMenuEvent.MENU_ITEM_SELECT NativeMenu.SELECT Evénements de menu select Pour gérer un clic sur un élément de menu, ajoutez à l'objet NativeMenuItem un écouteur d'événement relatif à l'événement select : var menuCommandX:NativeMenuItem = new NativeMenuItem("Command X"); menuCommand.addEventListener(Event.SELECT, doCommandX) Comme les événements select remontent jusqu'aux menus conteneur, vous pouvez aussi les écouter sur un menu parent. Lorsque vous écoutez au niveau d'un menu, vous pouvez utiliser la propriété target de l'objet événement pour déterminer la commande de menu sélectionnée. L'exemple suivant suit la trace du libellé de la commande sélectionnée : 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"); } Si vous utilisez la classe ContextMenuItem, vous pouvez écouter l'événement select ou menuItemSelect. L'événement menuItemSelect donne des informations complémentaires sur l'objet auquel appartient le menu contextuel, mais ne remonte pas jusqu'aux menus conteneur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 100 Utilisation de menus natifs Evénements de menu displaying Pour gérer l'ouverture d'un menu, vous pouvez ajouter un événement displaying, qui est distribué avant l'affichage d'un menu. L'événement displaying permet de mettre à jour le menu, par exemple en ajoutant ou supprimant des éléments, ou en actualisant l'état, activé ou coché, d'éléments individuels. Exemple : menu de fenêtre et d'application L'exemple suivant crée le menu illustré à la section « Structure des menus » à la page 89. De par sa conception, ce menu fonctionne sous Windows, qui prend uniquement en charge les menus de fenêtre, et sous Mac OS X, qui prend uniquement en charge les menus d'application. Pour faire la distinction, le constructeur de la classe MenuExample vérifie les propriétés supportsMenu statiques des classes NativeWindow et NativeApplication. Si NativeWindow.supportsMenu est défini sur true, le constructeur crée un objet NativeMenu pour la fenêtre, puis crée et ajoute les sous-menus File et Edit. Si NativeApplication.supportsMenu est défini sur true, le constructeur crée les menus File et Edit, et les ajoute au menu existant que propose le système d'exploitation Mac OS X. L'exemple suivant illustre également la gestion des événements de menu. L'événement select est géré au niveau des éléments et au niveau du menu. Chaque menu du chaînage allant du menu contenant l'élément sélectionné au menu racine répond à l'événement select. L'événement displaying est utilisé avec le menu « Ouvrir un fichier récent ». Juste avant l'ouverture du menu, ses éléments sont actualisés à partir du tableau recentDocuments (qui, dans cet exemple, reste inchangé). Bien que cette procédure ne soit pas illustrée dans cet exemple, vous pouvez également écouter des événements displaying sur des éléments individuels. 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(); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 101 Utilisation de menus natifs 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); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 102 Utilisation de menus natifs 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 Chapitre 13 : Icônes de la barre des tâches La plupart des systèmes d'exploitation disposent d'une barre des tâches, comme le Dock de Mac OS X, pouvant contenir une icône en vue de représenter une application. Adobe® AIR® dispose d'une interface permettant d'interagir avec l'icône de la barre des tâches de l'application par le biais de la propriété NativeApplication.nativeApplication.icon. Informations complémentaires en ligne sur les icônes de la barre des tâches Pour obtenir de plus amples informations sur l'utilisation des barres des tâches, consultez les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Utilisation des icônes de la barre d'état système et du Dock Guide de référence du langage • DockIcon • SystemTrayIcon Adobe Developper Connection – Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « AIR taskbar icons ») A propos des icônes de la barre des tâches AIR crée l'objet NativeApplication.nativeApplication.icon automatiquement. Selon le système d'exploitation, le type d'objet est soit DockIcon soit SystemTrayIcon. Les propriétés NativeApplication.supportsDockIcon et NativeApplication.supportsSystemTrayIcon vous permettent de déterminer les sous-classes InteractiveIcon prises en charge par AIR sur le système d'exploitation actuel. La classe de base InteractiveIcon fournit les propriétés width, height et bitmaps, qui vous permettent de modifier l'image utilisée pour l'icône. En revanche, l'accès aux propriétés spécifiques à l'objet DockIcon ou SystemTrayIcon sur le mauvais système d'exploitation génère une erreur d'exécution. Pour définir ou modifier l'image utilisée pour une icône, créez un tableau contenant une ou plusieurs images, puis affectez-le à la propriété NativeApplication.nativeApplication.icon.bitmaps. La taille des icônes de la barre des tâches peut varier d'un système d'exploitation à l'autre. Pour éviter la dégradation de l'image provoquée par la mise à l'échelle, vous pouvez ajouter plusieurs tailles d'image au tableau bitmaps. Si vous fournissez plusieurs images, AIR sélectionne la taille la plus proche de la taille d'affichage actuelle de l'icône de la barre des tâches et, le cas échéant, met ces images à l'échelle. Dans l'exemple suivant, l'image d'une icône de la barre des tâches est définie à l'aide de deux images : NativeApplication.nativeApplication.icon.bitmaps = [bmp16x16.bitmapData, bmp128x128.bitmapData]; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 104 Icônes de la barre des tâches Pour modifier l'image d'une icône, affectez un tableau contenant la ou les nouvelles images à la propriété bitmaps. Vous pouvez animer l'icône en modifiant l'image en réponse à un événement enterFrame ou timer. Pour supprimer l'icône de la zone de notification sous Windows et Linux, ou pour restaurer l'apparence de l'icône par défaut sous Mac OS X, définissez bitmaps sur un tableau vide : NativeApplication.nativeApplication.icon.bitmaps = []; Icônes du Dock AIR prend en charge les icônes du Dock lorsque la propriété NativeApplication.supportsDockIcon est définie sur true. La propriété NativeApplication.nativeApplication.icon représente l'icône de l'application sur le Dock (et non l'icône de la fenêtre). Remarque : AIR ne permet pas de modifier les icônes de fenêtre sur le Dock sous Mac OS X. Par ailleurs, les modifications apportées à l'icône du Dock de l'application ne sont appliquées que lorsqu'une application est en cours d'exécution ; l'icône retrouve son aspect normal lorsque vous quittez l'application. Menus d'icônes du Dock Vous pouvez ajouter des commandes au menu du Dock standard en créant un objet NativeMenu contenant les commandes, puis en l'affectant à la propriété NativeApplication.nativeApplication.icon.menu. Les éléments du menu s'affichent au-dessus des options de menu de l'icône du Dock standard. Rebond de l'icône du Dock Vous pouvez faire rebondir l'icône du Dock en appelant la méthode NativeApplication.nativeApplication.icon.bounce(). Si vous définissez le paramètre bounce() priority sur informational, l'icône rebondit une fois. Si vous définissez ce paramètre sur critical, l'icône rebondit jusqu'à ce que l'utilisateur active l'application. Les constantes du paramètre priority sont définies dans la classe NotificationType. Remarque : l'icône ne rebondit pas si l'application est déjà active. Evénements de l'icône du Dock Lorsque vous cliquez sur l'icône du Dock, l'objet NativeApplication distribue un événement invoke. Si l'application n'est pas en cours d'exécution, le système lance l'application. Sinon, l'événement invoke est renvoyé à l'occurrence de l'application en cours d'exécution. Icônes de la barre d'état système AIR prend en charge les icônes de la barre d'état système lorsque la propriété NativeApplication.supportsSystemTrayIcon est définie sur true, ce qui n'est actuellement le cas que sous Windows et la plupart des distributions Linux. Sous Windows et Linux, les icônes de la barre d'état système s'affichent dans la zone de notification de la barre des tâches. Par défaut, aucune icône n'est affichée. Pour afficher une icône, affectez un tableau contenant des objets BitmapData à la propriété bitmaps de l'icône. Pour modifier l'image d'une icône, affectez un tableau contenant les nouvelles images à la propriété bitmaps. Pour supprimer l'icône, définissez la propriété bitmaps sur null. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 105 Icônes de la barre des tâches Menus de l'icône de la barre d'état système Vous pouvez ajouter un menu à l'icône de la barre d'état système en créant un objet NativeMenu, puis en l'affectant à la propriété NativeApplication.nativeApplication.icon.menu (le système d'exploitation ne fournit aucun menu par défaut). Pour accéder au menu de l'icône de la barre d'état système, cliquez sur l'icône avec le bouton droit de la souris. Info-bulles de l'icône de la barre d'état système Pour ajouter une info-bulle à une icône, définissez la propriété tooltip : NativeApplication.nativeApplication.icon.tooltip = "Application name"; Evénements de l'icône de la barre d'état système L'objet SystemTrayIcon référencé par la propriété NativeApplication.nativeApplication.icon distribue un événement ScreenMouseEvent pour les événements click, mouseDown, mouseUp, rightClick, rightMouseDown et rightMouseUp. Vous pouvez utiliser ces événements, ainsi que le menu d'une icône, pour autoriser les utilisateurs à interagir avec votre application lorsque celle-ci ne dispose pas de fenêtres visibles. Exemple : création d'une application ne disposant d'aucune fenêtre L'exemple suivant crée une application AIR qui dispose d'une icône de la barre d'état système, mais d'aucune fenêtre visible. L'icône de la barre d'état système dispose d'un menu avec une seule commande permettant de quitter l'application. 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")); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 106 Icônes de la barre des tâches var systray:SystemTrayIcon = NativeApplication.nativeApplication.icon as SystemTrayIcon; 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]; } } } Remarque : dans cet exemple, nous supposons qu'il existe des fichiers image nommés AIRApp_16.png et AIRApp_128.png dans un sous-répertoire icons de l'application. (Les fichiers d'icône d'exemple, que vous pouvez copier dans le dossier de votre projet, sont inclus dans le kit de développement AIR.) Icônes et boutons de la barre des tâches de la fenêtre Les icônes des fenêtres s'affichent normalement dans une zone de la fenêtre, appelée barre des tâches ou Dock, pour permettre aux utilisateurs d'accéder aisément à l'arrière-plan ou aux fenêtre minimisées. Le Dock de Mac OS X affiche l'icône correspondant à votre application, ainsi qu'une icône pour chaque fenêtre minimisée. Les barres des tâches de Microsoft Windows et Linux affichent un bouton contenant l'icône et le titre du programme de chaque fenêtre standard dans votre application. Mise en surbrillance du bouton de la fenêtre dans la barre des tâches Lorsqu'une fenêtre se trouve dans l'arrière-plan, vous pouvez informer l'utilisateur qu'un événement important ayant trait à la fenêtre s'est produit. Sous Mac OS X, vous pouvez informer l'utilisateur en faisant rebondir l'icône de l'application du Dock (comme décrit à la section « Rebond de l'icône du Dock » à la page 104). Sous Windows et Linux, vous pouvez mettre en surbrillance le bouton de la barre des tâches de la fenêtre en appelant la méthode notifyUser() de l'occurrence de NativeWindow. Le paramètre type transmis à la méthode détermine l'urgence de la notification : • NotificationType.CRITICAL : l'icône de la fenêtre clignote jusqu'à ce que l'utilisateur ramène la fenêtre au premier plan. • NotificationType.INFORMATIONAL : l'icône de la fenêtre est mise en surbrillance et change de couleur. Remarque : Sous Linux, seul le type de notification informationnel est pris en charge. La transmission de la valeur du type à la fonction notifyUser() a le même effet. L'instruction suivante met en surbrillance le bouton de la barre des tâches d'une fenêtre : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 107 Icônes de la barre des tâches stage.nativeWindow.notifyUser(NotificationType.CRITICAL); L'appel de la méthode NativeWindow.notifyUser() d'un système d'exploitation qui ne prend pas en charge la notification au niveau de la fenêtre n'a aucun effet. Utilisez la propriété NativeWindow.supportsNotification pour déterminer si la notification de fenêtres est prise en charge. Création de fenêtres sans icônes ni boutons dans la barre des tâches Sous Windows, les fenêtres de type utilitaire ou légère ne s'affichent pas dans la barre des tâches. Les fenêtres invisibles n'apparaissent pas non plus dans la barre des tâches. Etant donné que la fenêtre initiale est nécessairement de type normale, pour créer une application dont aucune fenêtre ne s'affiche dans la barre des tâches, vous devez fermer la fenêtre initiale ou la laisser invisible. Pour fermer toutes les fenêtres de votre application sans quitter l'application, définissez la propriété autoExit de l'objet NativeApplication sur false avant de fermer la dernière fenêtre. Pour simplement éviter que la fenêtre initiale soit visible, ajoutez <visible>false</visible> à l'élément <initalWindow> du fichier descripteur d'application (et ne définissez pas la propriété visible sur true, ni n'appelez la méthode activate() de la fenêtre). Dans les nouvelles fenêtres ouvertes par l'application, définissez la propriété type de l'objet NativeWindowInitOption transmis au constructeur de fenêtres sur NativeWindowType.UTILITY ou sur NativeWindowType.LIGHTWEIGHT. Sous Mac OS X, les fenêtres minimisées apparaissent sur la barre des tâches du Dock. Vous pouvez désactiver l'affichage de l'icône minimisée en masquant la fenêtre au lieu de la minimiser. L'exemple suivant écoute un événement de changement nativeWindowDisplayState et l'annule si la fenêtre est minimisée. Le gestionnaire définit la propriété visible de la fenêtre sur false : private function preventMinimize(event:NativeWindowDisplayStateEvent):void{ if(event.afterDisplayState == NativeWindowDisplayState.MINIMIZED){ event.preventDefault(); event.target.visible = false; } } Sous Mac OS X, si une fenêtre est minimisée sur le Dock lorsque vous définissez la propriété visible sur false, l'icône du Dock n'est pas supprimée. L'utilisateur peut toujours cliquer sur l'icône pour faire réapparaître la fenêtre. 108 Chapitre 14 : Utilisation du système de fichiers Pour accéder au système de fichiers de l'ordinateur hôte, utilisez les classes proposées par l'API du système de fichiers d'Adobe® AIR™. Ces classes vous permettent d'accéder aux fichiers et aux répertoires et de les gérer, de créer des fichiers et des répertoires, d'écrire des données dans les fichiers, etc. Informations complémentaires en ligne sur l'API de fichiers d'AIR Pour plus d'informations sur l'utilisation des classes File de l'interface de programmation, consultez les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Développement d'un éditeur de fichier texte Guide de référence du langage • File • FileStream • FileMode Adobe Developer Connection - Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « AIR filesystem ») Principes de base des classes File d'AIR Adobe AIR propose des classes permettant de créer et de gérer des fichiers et des dossiers, ainsi que d'y accéder. Ces classes, qui résident dans le package flash.filesystem, s'utilisent comme suit : Classes File Description File Objet File représentant le chemin d'accès à un fichier ou un répertoire. Vous utilisez un objet File pour créer un pointeur vers un fichier ou un dossier, ce qui initie une interaction avec le fichier ou le dossier. FileMode La classe FileMode définit des constantes chaîne qui sont utilisées dans le paramètre fileMode des méthodes open() et openAsync() de la classe FileStream. Le paramètre fileMode de ces méthodes détermine les fonctionnalités à la disposition de l'objet FileStream une fois le fichier ouvert, notamment l'écriture, la lecture, l'ajout en fin de fichier et la mise à jour. FileStream Objet FileStream permettant d'ouvrir des fichiers à des fins de lecture ou d'écriture. Un fois créé un objet File pointant vers un fichier nouveau ou existant, vous transmettez ce pointeur à l'objet FileStream dans le but d'ouvrir le fichier et de manipuler les données qu'il contient. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 109 Utilisation du système de fichiers Certaines méthodes de la classe File possèdent des versions synchrone et asynchrone : • File.copyTo() et File.copyToAsync() • File.deleteDirectory() et File.deleteDirectoryAsync() • File.deleteFile() et File.deleteFileAsync() • File.getDirectoryListing() et File.getDirectoryListingAsync() • File.moveTo() et File.moveToAsync() • File.moveToTrash() et File.moveToTrashAsync() En outre, les opérations FileStream s'exécutent en mode synchrone ou asynchrone selon que l'objet FileStream ouvre le fichier par appel de la méthode open() ou openAsync(). Les versions asynchrones vous permettent d'initier des processus s'exécutant en arrière-plan et de distribuer des événements lorsqu'ils sont terminés (ou lorsqu'un événement erreur se produit). Un autre code peut s'exécuter pendant que ces processus asynchrones se déroulent en arrière-plan. Lorsque vous utilisez la version asynchrone de ces opérations, vous devez configurer des fonctions d'écouteur d'événement, à l'aide de la méthode addEventListener() de l'objet File ou FileStream qui appelle la fonction. Les versions synchrones permettent d'écrire du code plus simple qui ne repose pas sur la configuration d'écouteurs d'événement. Cependant, comme aucun autre code ne peut s'exécuter pendant l'exécution d'une méthode synchrone, il est possible d'interrompre des processus importants tels que l'animation et le rendu des objets d'affichage. Utilisation des objets File Un objet File est un pointeur vers un fichier ou un répertoire du système de fichiers. La classe File étend la classe FileReference. La classe FileReference, qui est disponible dans Adobe® Flash® Player et AIR, représente un pointeur vers un fichier, mais la classe File ajoute des propriétés et des méthodes qui ne sont pas exposées dans Flash Player (dans un fichier SWF s'exécutant dans un navigateur), pour des raisons de sécurité. Présentation de la classe File La classe File permet d'effectuer les opérations suivantes : • Obtenir le chemin d'accès à des répertoires particuliers, notamment le répertoire de l'utilisateur, le répertoire de documents de l'utilisateur, le répertoire de lancement de l'application et le répertoire d'application • Copier des fichiers et des répertoires • Déplacer des fichiers et des répertoires • Supprimer des fichiers et des répertoires (ou les transférer dans la corbeille) • Afficher la liste des fichiers et répertoires que contient un répertoire • Créer des fichiers et des dossiers temporaires Une fois qu'un objet File pointe vers un chemin de fichier, vous pouvez l'utiliser pour lire et écrire des données de fichier, à l'aide de la classe FileStream. Un objet File peut pointer vers le chemin d'un fichier ou d'un répertoire qui n'existe pas encore. Vous pouvez utiliser un tel objet File pour créer un fichier ou un répertoire. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 110 Utilisation du système de fichiers Chemin des objets File Tout objet File possède deux propriétés qui définissent son chemin : Propriété Description nativePath Indique le chemin d'accès à un fichier en fonction de la plate-forme. Par exemple, sous Windows, un chemin se présente sous la forme « c:\Sample directory\test.txt » alors que sous Mac OS, il correspond à « /Sample directory/test.txt ». La propriété nativePath utilise la barre oblique inverse (\) comme séparateur de répertoires sous Windows et la barre oblique normale (/) sous Mac OS et Linux. url Cette propriété peut utiliser le modèle d'URL file pour pointer vers un fichier. Par exemple, sous Windows, un chemin se présente sous la forme « file:///c:/Sample%20directory/test.txt » alors que sous Mac OS, il correspond à « file:///Sample%20directory/test.txt ». Outre file, le moteur d'exécution propose d'autres modèles d'URL particuliers, qui sont décrits à la section « Modèles d'URL pris en charge » à la page 114. La classe File comprend des propriétés de pointage vers les répertoires standard sous Mac, Windows et Linux. Pointage d'un objet File vers un répertoire Vous disposez de plusieurs méthodes pour configurer un objet File afin qu'il pointe vers un répertoire. Pointage vers le répertoire d'accueil de l'utilisateur Vous pouvez pointer un objet File vers le répertoire d'accueil de l'utilisateur. Sous Windows, le répertoire d'accueil est le parent du répertoire « Mes Documents » (par exemple, « C:\Documents and Settings\nom d'utilisateur\Mes Documents »). Sous Mac OS, c'est le répertoire Utilisateurs/nom d'utilisateur. Sous Linux, c'est le répertoire /home/nom d'utilisateur. Le code suivant configure l'objet File afin qu'il pointe vers le sous-répertoire AIR Test du répertoire d'accueil : var file:File = File.userDirectory.resolvePath("AIR Test"); Pointage vers le répertoire de documents de l'utilisateur Vous pouvez pointer un objet File vers le répertoire de documents de l'utilisateur. Sous Windows, l'emplacement par défaut est « Mes documents » (par exemple « C:\Documents and Settings\nomUtilisateur\Mes documents »). Sous Mac OS, l'emplacement par défaut est Utilisateurs/nomUtilisateur/Documents. Sous Linux, l'emplacement par défaut est /home/nomUtilisateur/Documents. Le code suivant configure un objet File afin qu'il pointe vers le sousrépertoire AIR Test du répertoire de documents : var file:File = File.documentsDirectory.resolvePath("AIR Test"); Pointage vers le répertoire du poste de travail Vous pouvez pointer un objet File vers le poste de travail. Le code suivant configure un objet File afin qu'il pointe vers le sous-répertoire AIR Test du poste de travail : var file:File = File.desktopDirectory.resolvePath("AIR Test"); Pointage vers le répertoire de stockage d'une application Vous pouvez pointer un objet File vers le répertoire de stockage d'une application. A toute application AIR est associé un chemin unique qui définit son répertoire de stockage. Ce répertoire est spécifique à chaque application et utilisateur. Vous pouvez y stocker des données spécifiques à l'application et à l'utilisateur, notamment des données utilisateur ou des fichiers de préférences. Par exemple, le code suivant pointe un objet File vers un fichier de préférences, prefs.xml, qui réside dans le répertoire de stockage de l'application : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 111 Utilisation du système de fichiers var file:File = File.applicationStorageDirectory; file = file.resolvePath("prefs.xml"; L'emplacement du répertoire de stockage d'une application est basé sur le nom d'utilisateur, l'ID d'application et l'ID d'éditeur : • Sous Mac OS, dans : /Utilisateurs/nom d'utilisateur/Bibliothèque/Preferences/ID d'application.ID d'éditeur/Local Store/ Exemple : /Users/babbage/Library/Preferences/com.example.TestApp.02D88EEED35F84C264A183921344EEA353 A629FD.1/Local Store • Sous Windows, dans le répertoire Documents and Settings, dans : nom d'utilisateur/Application Data/ID d'application.ID d'éditeur/Local Store/ Exemple : C:\Documents and Settings\babbage\Application Data\com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Local Store • Sous Linux, dans : /home/nom d'utilisateur/.appdata/applicationID.ID d'éditeur/Local Store/ Exemple : /home/babbage/.appdata/com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1/Loc al Store L'URL (et la propriété url) d'un objet File créé à l'aide de File.applicationStorageDirectory utilise le modèle d'URL app-storage (voir « Modèles d'URL pris en charge » à la page 114), comme l'illustre l'exemple suivant : var dir:File = File.applicationStorageDirectory; dir = dir.resolvePath("preferences"); trace(dir.url); // app-storage:/preferences Pointage vers le répertoire de l'application Vous pouvez pointer un objet File vers le répertoire dans lequel une application est installée, ou répertoire d'application. Vous pouvez référencer ce répertoire à l'aide de la propriété File.applicationDirectory. Il permet d'examiner le fichier descripteur d'application ou d'autres ressources installées avec l'application. Par exemple, le code suivant pointe un objet File vers le répertoire images du répertoire d'application : var dir:File = File.applicationDirectory; dir = dir.resolvePath("images"); L'URL (et la propriété url) d'un objet File créé à l'aide de File.applicationDirectory utilise le modèle d'URL app (voir « Modèles d'URL pris en charge » à la page 114), comme l'illustre l'exemple suivant : var dir:File = File.applicationDirectory; dir = dir.resolvePath("images"); trace(dir.url); // app:/images Pointage vers la racine du système de fichiers La méthode File.getRootDirectories() répertorie tous les volumes racine, tels que C: et les volumes montés, sur un ordinateur Windows. Sous Mac et Linux, cette méthode renvoie le répertoire racine unique de l'ordinateur (le répertoire « / »). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 112 Utilisation du système de fichiers Pointage vers un répertoire explicite Vous pouvez pointer l'objet File vers un répertoire explicite en définissant sa propriété nativePath, comme l'illustre l'exemple ci-dessous (sous Windows) : var file:File = new File(); file.nativePath = "C:\\AIR Test\"; Navigation vers des chemins relatifs La méthode resolvePath() permet d'obtenir un chemin relatif à un autre chemin donné. Par exemple, le code suivant configure un objet File afin qu'il pointe vers le sous-répertoire « AIR Test » du répertoire d'accueil de l'utilisateur : var file:File = File.userDirectory; file = file.resolvePath("AIR Test"); En outre, la propriété url d'un objet File permet de pointer celui-ci vers un répertoire basé sur une chaîne d'URL, comme illustré ci-dessous : var urlStr:String = "file:///C:/AIR Test/"; var file:File = new File() file.url = urlStr; Pour plus d'informations, consultez la section « Modification de chemins de fichier » à la page 114. Sélection d'un répertoire par l'utilisateur La classe File comprend la méthode browseForDirectory(), qui présente une boîte de dialogue système dans laquelle l'utilisateur peut sélectionner un répertoire à affecter à l'objet. La méthode browseForDirectory() est asynchrone. Elle distribue un événement select si l'utilisateur sélectionne un répertoire et clique sur le bouton Ouvrir, ou un événement cancel si l'utilisateur clique sur le bouton Annuler. Par exemple, le code suivant permet à l'utilisateur de sélectionner un répertoire et renvoie le chemin de celui-ci une fois la sélection effectuée : var file:File = new File(); file.addEventListener(Event.SELECT, dirSelected); file.browseForDirectory("Select a directory"); function dirSelected(e:Event):void { trace(file.nativePath); } Pointage vers le répertoire d'appel de l'application Vous pouvez déterminer l'emplacement du répertoire à partir duquel une application est appelée en consultant la propriété currentDirectory de l'objet InvokeEvent distribué lors de l'appel de l'application. Pour plus d'informations, consultez la section « Capture des arguments de ligne de commande » à la page 297. Pointage d'un objet File vers un fichier Il existe plusieurs manières de définir le fichier vers lequel pointe un objet File. Pointage vers un chemin de fichier explicite La méthode resolvePath() permet d'obtenir un chemin relatif à un autre chemin donné. Par exemple, le code suivant définit un objet File de sorte qu'il pointe vers le fichier log.txt du répertoire de stockage d'application : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 113 Utilisation du système de fichiers var file:File = File.applicationStorageDirectory; file = file.resolvePath("log.txt"); La propriété url d'un objet File permet de pointer celui-ci vers un fichier ou un répertoire basé sur une chaîne d'URL, comme illustré ci-dessous : var urlStr:String = "file:///C:/AIR Test/test.txt"; var file:File = new File() file.url = urlStr; Vous pouvez aussi transmettre l'URL à la fonction constructeur File(), comme illustré ci-dessous : var urlStr:String = "file:///C:/AIR Test/test.txt"; var file:File = new File(urlStr); La propriété url renvoie systématiquement la version URI de l'URL (les espaces sont remplacés par "%20, par exemple) : file.url = "file:///c:/AIR Test"; trace(file.url); // file:///c:/AIR%20Test Vous pouvez aussi utiliser la propriété nativePath d'un objet File pour définir un chemin explicite. Par exemple, le code suivant, exécuté sur un ordinateur Windows, définit un objet File sur le fichier test.txt du sous-répertoire AIR Test du lecteur C: : var file:File = new File(); file.nativePath = "C:/AIR Test/test.txt"; Vous pouvez aussi transmettre ce chemin à la fonction constructeur File(), comme illustré ci-dessous : var file:File = new File("C:/AIR Test/test.txt"); Sous Windows, vous pouvez utiliser la barre oblique (/) ou la barre oblique inverse (\) comme délimiteur de chemin avec la propriété nativePath. Sous Mac OS et Linux, utilisez la barre oblique (/) comme délimiteur de chemin dans la propriété nativePath : var file:File = new File(/Users/dijkstra/AIR Test/test.txt"); Pour plus d'informations, consultez la section « Modification de chemins de fichier » à la page 114. Enumération des fichiers d'un répertoire La méthode getDirectoryListing() d'un objet File permet d'obtenir un tableau d'objets File pointant vers les fichiers et sous-répertoires situés au niveau racine d'un répertoire. Pour plus d'informations, consultez la section « Enumération de répertoires » à la page 119. Sélection d'un fichier par l'utilisateur La classe File comprend les méthodes suivantes, qui présentent une boîte de dialogue système dans laquelle l'utilisateur peut sélectionner un fichier à affecter à l'objet : • browseForOpen() • browseForSave() • browseForOpenMultiple() DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 114 Utilisation du système de fichiers Toutes ces méthodes sont asynchrones. Les méthodes browseForOpen() et browseForSave() distribuent l'événement select lorsque l'utilisateur sélectionne un fichier (ou, dans le cas de browseForSave(), un chemin cible). Avec les méthodes browseForOpen() et browseForSave(), lors de la sélection, l'objet File pointe vers les fichiers sélectionnés. La méthode browseForOpenMultiple() distribue un événement selectMultiple lorsque l'utilisateur sélectionne des fichiers. L'événement selectMultiple est de type FileListEvent et possède une propriété files, c'està-dire un tableau d'objets File (pointant vers les fichiers sélectionnés). Par exemple, le code suivant présente une boîte de dialogue d'ouverture de fichier à l'utilisateur, lui permettant ainsi de sélectionner un fichier : 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); } Si une autre boîte de dialogue de navigation est ouverte dans l'application lors de l'appel d'une méthode browse, le moteur d'exécution renvoie une exception Error. Modification de chemins de fichier Vous pouvez également modifier le chemin d'un objet File existant en appelant la méthode resolvePath() ou en intervenant sur la propriété nativePath ou url de l'objet, comme l'illustrent les exemples suivants (sous 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 Lorsque vous utilisez la propriété nativePath, sous Windows, employez la barre oblique (/) ou la barre oblique inverse (\) en tant que séparateur de répertoire ; sous Mac OS et Linux, utilisez la barre oblique (/). Sous Windows, pensez à taper deux fois la barre oblique inverse dans un littéral de chaîne. Modèles d'URL pris en charge Lorsque vous définissez la propriété url d'un objet File, vous pouvez utiliser les modèles d'URL suivants : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 115 Utilisation du système de fichiers Modèle d'URL Description file Permet de spécifier un chemin relatif à la racine du système de fichiers. Exemple : file:///c:/AIR Test/test.txt La norme URL spécifie qu'un modèle d'URL file se présente comme suit : file://<hôte>/<chemin>. <hôte> peut correspondre à la chaîne vide, ce qui signifie « la machine à partir de laquelle l'URL est interprétée ». C'est pourquoi les modèles d'URL file comportent souvent trois barres obliques (///). app Permet de spécifier un chemin relatif au répertoire racine de l'application installée (le répertoire contenant le fichier application.xml de l'application installée). Par exemple, le chemin suivant pointe vers le sousrépertoire images du répertoire de l'application installée : app:/images app-storage Permet de spécifier un chemin relatif au répertoire de stockage de l'application. Pour chaque application installée, AIR définit un répertoire de stockage d'application unique. C'est un emplacement pratique auquel stocker des données spécifiques à l'application concernée. Par exemple, le chemin suivant pointe vers le fichier prefs.xml, qui réside dans le sous-répertoire settings du répertoire de stockage de l'application : app-storage:/settings/prefs.xml Détermination du chemin relatif entre deux fichiers La méthode getRelativePath() vous permet de déterminer le chemin relatif entre deux fichiers : 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 Le deuxième paramètre de la méthode getRelativePath(), useDotDot, permet le renvoi de la syntaxe .. dans les résultats, pour représenter les répertoires parent : 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 Obtention des versions canoniques des noms de fichier Les noms de fichier et de chemin ne respectent pas la casse sous Windows et Mac OS. Dans l'exemple suivant, deux objets File pointent vers un même fichier : File.documentsDirectory.resolvePath("test.txt"); File.documentsDirectory.resolvePath("TeSt.TxT"); Les noms de document et de répertoire, en revanche, respectent la casse. Ainsi, l'exemple suivant considère comme acquis qu'il existe un dossier appelé AIR Test dans le répertoire documents : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 116 Utilisation du système de fichiers var file:File = File.documentsDirectory.resolvePath("AIR test"); trace(file.nativePath); // ... AIR test file.canonicalize(); trace(file.nativePath); // ... AIR Test La méthode canonicalize() convertit l'objet nativePath afin qu'il utilise la combinaison correcte de majuscules et de minuscules dans le nom de fichier ou de répertoire. Sur les systèmes de fichiers sensibles à la casse (tels que Linux), lorsque plusieurs noms de fichier ne diffèrent que par la casse, la méthode canonicalize() ajuste le chemin de sorte qu'il corresponde au premier fichier détecté (dans l'ordre déterminé par le système de fichiers). Vous pouvez aussi utiliser la méthode canonicalize() pour convertir les noms de fichier courts (« 8.3 ») en noms longs sous Windows, comme illustré ci-dessous : var path:File = new File(); path.nativePath = "C:\\AIR~1"; path.canonicalize(); trace(path.nativePath); // C:\AIR Test Utilisation de packages et de liens symboliques Divers systèmes d'exploitation prennent en charge les fichiers de package et les fichiers de lien symbolique : Packages—Sous Mac OS, les répertoires peuvent être désignés comme packages et apparaissent dans le Finder sous la forme d'un fichier unique plutôt que d'un répertoire. Liens symboliques—Mac OS, Linux, et Windows Vista prennent en charge les liens symboliques. Les liens symboliques permettent à un fichier de pointer vers un autre fichier ou répertoire du disque. Bien que similaires aux alias, les liens symboliques diffèrent toutefois de ceux-ci. Un alias est systématiquement identifié en tant que fichier (plutôt que répertoire). La lecture d'un alias (ou raccourci) ou l'écriture dans celui-ci n'a aucune incidence sur le fichier ou le répertoire d'origine vers lequel il pointe. En revanche, un lien symbolique se comporte exactement comme le fichier ou le répertoire vers lequel il pointe. Il peut être identifié en tant que fichier ou répertoire. La lecture d'un lien symbolique ou l'écriture dans celui-ci affecte le fichier ou le répertoire vers lequel il pointe, pas le lien symbolique luimême. De plus, sous Windows, la propriété isSymbolicLink d'un objet File référençant un point de jonction (utilisé dans le système de fichiers NTFS) est définie sur true. La classe File comprend les propriétés isPackage et isSymbolicLink qui permettent de vérifier si un objet File référence un package ou un lien symbolique. Le code suivant effectue une itération sur le répertoire du poste de travail de l'utilisateur, répertoriant les sousrépertoires qui ne sont pas des packages : 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); } } Le code suivant effectue une itération sur le répertoire du poste de travail de l'utilisateur, répertoriant les fichiers et répertoires qui ne sont pas des liens symboliques : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 117 Utilisation du système de fichiers var desktopNodes:File = File.desktopDirectory.getDirectoryListing(); for (var i:uint = 0; i < desktopNodes.length; i++) { if (!desktopNodes[i].isSymbolicLink) { trace(desktopNodes[i].name); } } La méthode canonicalize() modifie le chemin d'un lien symbolique de sorte qu'il pointe vers le fichier ou le répertoire auquel le fichier ou le répertoire fait référence. Le code suivant effectue une itération sur le répertoire du poste de travail de l'utilisateur et identifie les chemins référencés par des fichiers qui sont des liens symboliques : 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); } } Détermination de l'espace disponible sur un volume La propriété spaceAvailable d'un objet File représente l'espace disponible utilisable, en octets, à l'emplacement de l'objet. Par exemple, le code suivant vérifie l'espace disponible dans le répertoire de stockage d'application : trace(File.applicationStorageDirectory.spaceAvailable); Si l'objet File référence un répertoire, la propriété spaceAvailable indique l'espace que peuvent utiliser les fichiers dans le répertoire. Si l'objet File référence un fichier, la propriété spaceAvailable indique l'espace maximal que peut occuper le fichier. Si l'emplacement de fichier n'existe pas, la propriété spaceAvailable est définie sur 0. Si l'objet File référence un lien symbolique, la propriété spaceAvailable est définie sur l'espace disponible à l'emplacement vers lequel pointe le lien symbolique. En règle générale, l'espace disponible pour un répertoire ou un fichier correspond à l'espace disponible sur le volume contenant ce répertoire ou fichier. Cependant, l'espace disponible peut tenir compte de quotas et de limites par répertoire. Lors de l'ajout d'un fichier ou d'un répertoire à un volume, l'espace nécessaire est généralement supérieur à la taille réelle du fichier ou à la taille du contenu du répertoire. Il se peut, par exemple, que le système d'exploitation requiert de l'espace supplémentaire pour stocker des informations d'index. Les secteurs de disque requis utilisent peut-être de l'espace en plus. En outre, l'espace disponible change dynamiquement. Il est donc impossible d'allouer tout l'espace indiqué au stockage des fichiers. Pour plus d'informations sur l'écriture dans le système de fichiers, consultez la section « Lecture et écriture de fichiers » à la page 123. Obtention d'informations sur le système de fichiers La classe File comprend les propriétés statiques suivantes, qui fournissent des renseignements utiles sur le système de fichiers : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 118 Utilisation du système de fichiers Propriété Description File.lineEnding Séquence de caractères de fin de ligne utilisée par le système d'exploitation hôte. Sous Mac OS et Linux, il s'agit du caractère de nouvelle ligne. Sous Windows, il s'agit du retour chariot suivi du caractère de nouvelle ligne. File.separator Séparateur d'élément de chemin utilisé par le système d'exploitation hôte. Sous Mac OS et Linux, il s'agit de la barre oblique (/). Sous Windows il s'agit de la barre oblique inverse (\). File.systemCharset Codage appliqué par défaut aux fichiers par le système d'exploitation hôte. Ce codage relève du jeu de caractères utilisé par le système d'exploitation et correspond à la langue en vigueur sur celui-ci. La classe Capabilities comprend également des informations système qui peuvent être utiles lors de la manipulation des fichiers : Propriété Description Capabilities.hasIME Spécifie si le lecteur s'exécute sur un système qui dispose (true) ou non (false) d'un éditeur de méthode d'entrée (IME). Capabilities.language Indique le code de langue du système sur lequel s'exécute le lecteur. Capabilities.os Spécifie le système d'exploitation actuel. Utilisation de répertoires Le moteur d'exécution vous permet de manipuler les répertoires du système de fichiers local. Pour plus de détails sur la création d'objets File qui pointent vers des répertoires, consultez la section « Pointage d'un objet File vers un répertoire » à la page 110. Création de répertoires La méthode File.createDirectory() permet de créer un répertoire. Par exemple, le code suivant crée le répertoire AIR Test en tant que sous-répertoire du répertoire d'accueil de l'utilisateur : var dir:File = File.userDirectory.resolvePath("AIR Test"); dir.createDirectory(); Si le répertoire existe, la méthode createDirectory() n'agit pas. Par ailleurs, dans certains modes, un objet FileStream crée des répertoires à l'ouverture des fichiers. Les répertoires qui n'existent pas sont créés lorsque vous instanciez une occurrence de FileStream en définissant le paramètre fileMode du constructeur FileStream() sur FileMode.APPEND ou FileMode.WRITE. Pour plus d'informations, consultez la section « Flux de travail pour la lecture et l'écriture de fichiers » à la page 123. Création d'un répertoire temporaire La classe File comprend la méthode createTempDirectory(), qui crée un répertoire dans le répertoire temporaire système, comme l'illustre l'exemple suivant : var temp:File = File.createTempDirectory(); La méthode createTempDirectory() crée automatiquement un répertoire temporaire unique (ce qui vous évite d'avoir à déterminer un nouvel emplacement unique). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 119 Utilisation du système de fichiers Vous pouvez utiliser un répertoire temporaire pour stocker provisoirement des fichiers temporaires utilisés au cours d'une session de l'application. Vous remarquerez que la méthode createTempFile() permet de créer des fichiers temporaires uniques dans le répertoire temporaire système. Vous pouvez éventuellement supprimer le répertoire temporaire avant de fermer l'application car cette opération n'est pas effectuée automatiquement. Enumération de répertoires Les méthodes getDirectoryListing() ou getDirectoryListingAsync() d'un objet File permettent d'obtenir un tableau d'objets File pointant vers les fichiers et sous-répertoires d'un répertoire. Par exemple, le code suivant répertorie le contenu du répertoire de documents de l'utilisateur (sans examiner les sousrépertoires) : 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); } Lorsque vous utilisez la version asynchrone de la méthode, l'objet événement directoryListing possède la propriété files, qui consiste en un tableau d'objets File appartenant aux répertoires : 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); } } Copie et déplacement de répertoires Vous pouvez copier ou déplacer un répertoire, en utilisant les mêmes méthodes que pour un fichier. Par exemple, le code suivant copie un répertoire en mode synchrone : var sourceDir:File = File.documentsDirectory.resolvePath("AIR Test"); var resultDir:File = File.documentsDirectory.resolvePath("AIR Test Copy"); sourceDir.copyTo(resultDir); Lorsque vous définissez le paramètre overwrite de la méthode copyTo() sur true, tous les fichiers et dossiers d'un répertoire cible existant sont supprimés et remplacés par les fichiers et dossiers du répertoire source (même si le fichier cible n'existe pas dans le répertoire source). Le répertoire sur lequel vous définissez le paramètre newLocation de la méthode copyTo() spécifie le chemin d'accès au répertoire résultant, et non le répertoire parent qui contiendra le répertoire résultant. Pour plus d'informations, consultez la section « Copie et déplacement de fichiers » à la page 121. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 120 Utilisation du système de fichiers Suppression du contenu d'un répertoire La classe File comprend les méthodes deleteDirectory() et deleteDirectoryAsync(). Ces méthodes suppriment des répertoires. La première s'exécute en mode synchrone et la seconde en mode asynchrone (consultez la section « Principes de base des classes File d'AIR » à la page 108). Elles comprennent toutes deux le paramètre deleteDirectoryContents (qui accepte une valeur booléenne). Lorsque ce paramètre est défini sur true (la valeur par défaut correspond à false), l'appel de la méthode supprime les répertoires non vides ; sinon, seuls les répertoires vides sont supprimés. Par exemple, le code suivant supprime en mode synchrone le sous-répertoire AIR Test du répertoire de documents de l'utilisateur : var directory:File = File.documentsDirectory.resolvePath("AIR Test"); directory.deleteDirectory(true); Le code suivant supprime en mode asynchrone le sous-répertoire AIR Test du répertoire de documents de l'utilisateur : var directory:File = File.documentsDirectory.resolvePath("AIR Test"); directory.addEventListener(Event.COMPLETE, completeHandler) directory.deleteDirectoryAsync(true); function completeHandler(event:Event):void { trace("Deleted.") } Vous disposez également des méthodes moveToTrash() et moveToTrashAsync(), qui permettent de déplacer un répertoire vers la corbeille système. Pour plus d'informations, consultez la section « Déplacement d'un fichier vers la corbeille » à la page 122 Utilisation des fichiers L'API de fichiers d'AIR vous permet d'ajouter des fonctionnalités de manipulation des fichiers de base à vos applications. Vous pouvez ainsi accéder à des fichiers en lecture ou en écriture, copier et supprimer des fichiers, etc. Comme vos applications ont accès au système de fichiers local, consultez le chapitre « Sécurité AIR » à la page 24, si ce n'est déjà fait. Remarque : vous pouvez associer un type de fichier à une application AIR (afin qu'un double-clic sur le fichier entraîne l'ouverture de l'application). Pour plus d'informations, consultez la section « Gestion des associations de fichiers » à la page 305. Obtention d'informations sur les fichiers La classe File comprend les propriétés suivantes qui fournissent des informations sur un fichier ou un répertoire vers lequel pointe un objet File : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 121 Utilisation du système de fichiers Propriété File Description creationDate Date de création du fichier sur le disque local. creator Obsolète. Utilisez la propriété extension. (Cette propriété renvoie le type de créateur Macintosh du fichier, qui est uniquement utilisé dans les versions de Mac OS antérieures à Mac OS X.) exists Indique si le fichier ou répertoire référencé existe. extension Extension de fichier, partie du nom qui suit (sans l'inclure) le point (« . »). Si le nom de fichier ne comprend pas de point, l'extension est null. icon Objet Icon contenant les icônes définies pour le fichier. isDirectory Indique si l'objet File référence un répertoire. modificationDate Date de la dernière modification du fichier ou du répertoire sur le disque local. name Nom du fichier ou répertoire (y compris l'éventuelle extension de fichier) sur le disque local. nativePath Chemin complet dans la représentation du système d'exploitation hôte (consultez la section « Chemin des objets File » à la page 110). parent Dossier qui contient le dossier ou fichier représenté par l'objet File. Cette propriété est null si l'objet File référence un fichier ou un répertoire dans la racine du système de fichiers. size Taille du fichier sur le disque local, en octets. type Obsolète. Utilisez la propriété extension. (Sur le Macintosh, cette propriété correspond au type de fichier de quatre caractères qui est uniquement utilisé dans les versions de Mac OS antérieures à Mac OS X). url URL du fichier ou du répertoire (consultez la section « Chemin des objets File » à la page 110). Pour plus d'informations sur ces propriétés, consultez la rubrique Classe File du Guide de référence du langage et des composants ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_fr). Copie et déplacement de fichiers La classe File comprend deux méthodes permettant de copier des fichiers ou des répertoires : copyTo() et copyToAsync(). Elle propose également deux méthodes permettant de déplacer des fichiers ou des répertoires : moveTo() et moveToAsync(). Les méthodes copyTo() et moveTo() s'exécutent en mode synchrone, les méthodes copyToAsync() et moveToAsync() en mode asynchrone (consultez la section « Principes de base des classes File d'AIR » à la page 108). Pour copier ou déplacer un fichier, vous définissez deux objets File. L'un pointe vers le fichier à copier ou déplacer et appelle la méthode copy ou move. L'autre pointe vers le chemin de destination (résultant). Le code suivant copie le fichier test.txt qui réside dans le sous-répertoire AIR Test du répertoire de documents de l'utilisateur vers le fichier copy.txt dans le même répertoire : var original:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var newFile:File = File.resolvePath("AIR Test/copy.txt"); original.copyTo(newFile, true); Dans cet exemple, la valeur du deuxième paramètre, overwrite, de la méthode copyTo() est définie sur true. Si ce paramètre est défini sur true, tout fichier cible existant est remplacé. Ce paramètre est facultatif. Si vous le définissez sur false (valeur par défaut), un événement IOErrorEvent est distribué si le fichier cible existe (et le fichier n'est pas copié). La version « Async » des méthodes copy et move s'exécute en mode asynchrone. La méthode addEventListener() permet de surveiller la fin de la tâche ou les erreurs, comme l'illustre le code suivant : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 122 Utilisation du système de fichiers 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 comprend également les méthodes File.moveToTrash() et File.moveToTrashAsync(), qui déplacent un fichier ou un répertoire vers la corbeille système. Suppression d'un fichier La classe File comprend les méthodes deleteFile() et deleteFileAsync(). Ces méthodes suppriment des fichiers. La première s'exécute en mode synchrone et la seconde en mode asynchrone (consultez la section « Principes de base des classes File d'AIR » à la page 108). Par exemple, le code suivant supprime, en mode synchrone, le fichier test.txt du répertoire de documents de l'utilisateur : var file:File = File.documentsDirectory.resolvePath("test.txt"); file.deleteFile(); Le code suivant supprime, en mode asynchrone, le fichier test.txt du répertoire de documents de l'utilisateur : var file:File = File.documentsDirectory.resolvePath("test.txt"); file.addEventListener(Event.COMPLETE, completeHandler) file.deleteFileAsync(); function completeHandler(event:Event):void { trace("Deleted.") } Vous disposez également des méthodes moveToTrash() et moveToTrashAsync(), qui permettent de déplacer un fichier ou un répertoire vers la corbeille système. Pour plus d'informations, consultez la section « Déplacement d'un fichier vers la corbeille » à la page 122. Déplacement d'un fichier vers la corbeille La classe File comprend les méthodes moveToTrash() et moveToTrashAsync(). Ces méthodes envoient un fichier ou un répertoire dans la corbeille système. La première s'exécute en mode synchrone et la seconde en mode asynchrone (consultez la section « Principes de base des classes File d'AIR » à la page 108). Par exemple, le code suivant déplace, en mode synchrone, le fichier test.txt du répertoire de documents de l'utilisateur vers la corbeille système : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 123 Utilisation du système de fichiers var file:File = File.documentsDirectory.resolvePath("test.txt"); file.moveToTrash(); Création d'un fichier temporaire La classe File comprend la méthode createTempFile(), qui crée un fichier dans le répertoire temporaire système, comme l'illustre l'exemple suivant : var temp:File = File.createTempFile(); La méthode createTempFile() crée automatiquement un fichier temporaire unique (ce qui vous évite d'avoir à déterminer un nouvel emplacement unique). Vous pouvez utiliser un fichier temporaire pour stocker provisoirement des informations utilisées au cours d'une session de l'application. Vous remarquerez que vous disposez également de la méthode createTempDirectory(), qui permet de créer un répertoire temporaire unique dans le répertoire temporaire système. Vous pouvez éventuellement supprimer le fichier temporaire avant de fermer l'application car cette opération n'est pas effectuée automatiquement. Lecture et écriture de fichiers La classe FileStream permet aux applications AIR d'accéder en lecture et en écriture au système de fichiers. Flux de travail pour la lecture et l'écriture de fichiers Le flux de travail de lecture et d'écriture de fichier est décrit ci-après. Initialisez un objet File pointant vers le chemin. C'est le chemin du fichier que vous souhaitez utiliser (ou d'un fichier que vous créerez ultérieurement). var file:File = File.documentsDirectory; file = file.resolvePath("AIR Test/testFile.txt"); Cet exemple utilise la propriété File.documentsDirectory et la méthode resolvePath() d'un objet File pour initialiser celui-ci. Toutefois, vous pouvez pointer un objet File vers un fichier de plusieurs autres façons. Pour plus d'informations, consultez la section « Pointage d'un objet File vers un fichier » à la page 112. Initialisez un objet FileStream. Appelez la méthode open() ou openAsync() de l'objet FileStream. La méthode que vous appelez varie selon que vous souhaitez ouvrir le fichier en mode synchrone ou asynchrone. Utilisez l'objet File comme paramètre file de la méthode open. Pour le paramètre fileMode, spécifiez une constante de la classe FileMode qui définit le mode d'utilisation du fichier. Par exemple, le code suivant initialise un objet FileStream utilisé pour créer un fichier et, éventuellement, remplacer les données existantes : var fileStream:FileStream = new FileStream(); fileStream.open(file, FileMode.WRITE); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 124 Utilisation du système de fichiers Pour plus d'informations, consultez les sections « Initialisation d'un objet FileStream et ouverture et fermeture de fichiers » à la page 125 et « Modes d'ouverture FileStream » à la page 124. Si vous avez ouvert le fichier en mode asynchrone (à l'aide de la méthode openAsync()), ajoutez et définissez des écouteurs d'événement pour l'objet FileStream. Ces méthodes d'écouteur d'événement répondent aux événements distribués par l'objet FileStream dans diverses situations, par exemple lors de la lecture de données dans le fichier, de la détection d'erreurs E/S ou au terme de l'écriture de la totalité des données à écrire. Pour plus d'informations, consultez la section « Programmation asynchrone et événements générés par un objet FileStream ouvert en mode asynchrone » à la page 129. Incluez du code permettant de lire et d'écrire des données, le cas échéant. La classe FileStream propose de nombreuses méthodes relatives à la lecture ou l'écriture (elles commencent toutes par « read » ou « write »). La méthode que vous choisissez pour lire et écrire des données varie en fonction du format des données dans le fichier cible. Par exemple, si les données du fichier cible sont au format texte UTF, vous pouvez utiliser les méthodes readUTFBytes() et writeUTFBytes(). Pour manipuler les données en tant que tableaux d'octets, utilisez les méthodes readByte(), readBytes(), writeByte() et writeBytes(). Pour plus d'informations, consultez la section « Format de données et choix des méthodes de lecture et d'écriture » à la page 130. Si vous avez ouvert le fichier en mode asynchrone, veillez à ce qu'un volume suffisant de données soit disponible avant d'appeler une méthode de lecture. Pour plus d'informations, consultez la section « Mémoire tampon de lecture et propriété bytesAvailable d'un objet FileStream » à la page 127. Si, avant d'accéder en écriture à un fichier, vous souhaitez vérifier la quantité d'espace disque disponible, vous pouvez consulter la propriété spaceAvailable de l'objet File. Pour plus d'informations, consultez la section « Détermination de l'espace disponible sur un volume » à la page 117. Appelez la méthode close() de l'objet FileStream lorsque vous avez terminé de manipuler le fichier. Le fichier peut alors être utilisé par d'autres applications. Pour plus d'informations, consultez la section « Initialisation d'un objet FileStream et ouverture et fermeture de fichiers » à la page 125. Vous trouverez un exemple d'application utilisant la classe FileStream pour accéder en lecture et en écriture à des fichiers dans les articles suivants du Centre des développeurs Adobe AIR : • Développement d'un éditeur de fichier texte Utilisation des objets FileStream La classe FileStream définit des méthodes permettant d'ouvrir des fichiers et d'y accéder en lecture ou en écriture. Modes d'ouverture FileStream Les méthodes open() et openAsync() d'un objet FileStream comprennent le paramètre fileMode, qui définit certaines propriétés d'un flux de fichier, pour indiquer notamment : • s'il est possible d'accéder au fichier en lecture ; • s'il est possible d'accéder au fichier en écriture ; • si les données sont systématiquement ajoutées à la fin du fichier (lors de l'écriture) ; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 125 Utilisation du système de fichiers • que faire lorsque le fichier n'existe pas (et que ses répertoires parent n'existent pas). Les différents modes de fichier disponibles (que vous pouvez spécifier dans le paramètre fileMode des méthodes open() et openAsync()) sont les suivants : Mode de fichier Description FileMode.READ Indique que le fichier est ouvert à des fins de lecture seulement. FileMode.WRITE Indique que le fichier est ouvert à des fins d'écriture. Si le fichier n'existe pas, il est créé à l'ouverture de l'objet FileStream. S'il existe, les données existantes sont supprimées. FileMode.APPEND Indique que le fichier est ouvert et qu'il est possible d'ajouter des données en fin de fichier. Si le fichier n'existe pas, il est créé. S'il existe, les données existantes ne sont pas remplacées. L'écriture commence à la fin du fichier. FileMode.UPDATE Indique que le fichier est ouvert à des fins de lecture et d'écriture. Si le fichier n'existe pas, il est créé. Choisissez ce mode pour un accès en lecture/écriture aléatoire au fichier. Vous pouvez lire à partir de tout emplacement du fichier et, lorsque vous écrivez dans celui-ci, seuls les octets concernés sont remplacés (les autres restent inchangés). Initialisation d'un objet FileStream et ouverture et fermeture de fichiers Lorsque vous ouvrez un objet FileStream, vous autorisez un accès en lecture ou en écriture à un fichier. Pour ouvrir un objet FileStream, vous transmettez un objet File à sa méthode open() ou openAsync() : var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.READ); Le paramètre fileMode (le deuxième des méthodes open() et openAsync()) détermine si le fichier est ouvert à des fins de lecture, écriture, ajout en fin de fichier ou mise à jour. Pour plus d'informations, consultez la section précédente, « Modes d'ouverture FileStream » à la page 124. Si vous ouvrez le fichier en mode asynchrone à l'aide de la méthode openAsync(), configurez des écouteurs d'événement pour gérer les événements asynchrones : 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 { // ... } Le fichier est ouvert en mode synchrone ou asynchrone, selon que vous utilisez la méthode open() ou openAsync(). Pour plus d'informations, consultez la section « Principes de base des classes File d'AIR » à la page 108. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 126 Utilisation du système de fichiers Si vous définissez le paramètre fileMode sur FileMode.READ ou FileMode.UPDATE dans la méthode d'ouverture de l'objet FileStream, les données sont lues et insérées dans la mémoire tampon de lecture dès l'ouverture de l'objet FileStream. Pour plus d'informations, consultez la section « Mémoire tampon de lecture et propriété bytesAvailable d'un objet FileStream » à la page 127. Vous pouvez appeler la méthode close() d'un objet FileStream pour fermer le fichier associé, ce qui le met à la disposition d'autres applications. Propriété position d'un objet FileStream La propriété position d'un objet FileStream détermine l'emplacement de lecture ou d'écriture des données de la méthode de lecture ou d'écriture suivante. Préalablement à une opération de lecture ou d'écriture, définissez la propriété position sur une position valide dans le fichier. Par exemple, le code suivant écrit la chaîne "hello" (au codage UTF) à la position 8 dans le fichier : 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"); Lorsque vous ouvrez initialement un objet FileStream, la propriété position est définie sur 0. Avant une opération de lecture, la valeur de la propriété position doit être comprise entre 0 et le nombre maximal d'octets du fichier (autrement dit, une position existante dans le fichier). La valeur de la propriété position est uniquement modifiée dans les cas suivants : • Vous définissez explicitement la propriété position. • Vous appelez une méthode de lecture. • Vous appelez une méthode d'écriture. Lorsque vous appelez une méthode de lecture ou d'écriture d'un objet FileStream, la propriété position est immédiatement incrémentée du nombre d'octets lus ou écrits. Selon la méthode de lecture utilisée, la propriété position est incrémentée du nombre d'octets que vous spécifiez pour la lecture ou du nombre d'octets disponibles. Lorsque, par la suite, vous appelez une méthode de lecture ou d'écriture, elle commence la lecture ou l'écriture à la nouvelle position. 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 Il existe cependant une exception : si un objet FileStream est ouvert en mode d'ajout en fin de fichier, la propriété position ne change pas à la suite de l'appel d'une méthode d'écriture. (Dans ce mode, les données sont toujours ajoutées à la fin du fichier, quelle que soit la valeur de la propriété position.) Si un fichier est ouvert en mode asynchrone, l'opération d'écriture ne se termine pas avant l'exécution de la ligne de code suivante. Vous pouvez néanmoins appeler successivement plusieurs méthodes asynchrones : le moteur d'exécution les exécute dans l'ordre. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 127 Utilisation du système de fichiers 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."); } Le résultat de l'instruction trace de ce code est le suivant : started. finished. Il est possible de spécifier la valeur de la propriété position immédiatement après l'appel d'une méthode de lecture ou d'écriture (ou à tout moment). L'opération de lecture ou d'écriture suivante commence alors à cette position. Par exemple, vous remarquerez que le code suivant définit la propriété position immédiatement après un appel de l'opération writeBytes() et que la position est définie sur cette valeur (300) même à l'issue de l'opération d'écriture : 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 Mémoire tampon de lecture et propriété bytesAvailable d'un objet FileStream Lors de l'ouverture d'un objet FileStream doté de fonctionnalités de lecture (le paramètre fileMode de sa méthode open() ou openAsync() étant défini sur READ ou UPDATE), le moteur d'exécution stocke les données dans une mémoire tampon interne. L'objet FileStream commence la lecture et l'insertion des données dans la mémoire tampon dès l'ouverture du fichier (par appel de la méthode open() ou openAsync() de l'objet FileStream). Si un fichier est ouvert en mode synchrone (à l'aide de la méthode open()), vous pouvez définir le pointeur position sur n'importe quelle position valide (dans les limites du fichier) et commencer à lire tout volume de données (dans les limites du fichier), comme l'illustre le code suivant (qui considère comme acquis que le fichier contient au moins 100 octets) : 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); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 128 Utilisation du système de fichiers Qu'un fichier soit ouvert en mode synchrone ou asynchrone, les méthodes de lecture lisent systématiquement les octets « disponibles », représentés par la propriété bytesAvalable. En mode de lecture synchrone, tous les octets du fichier sont disponibles en permanence. En mode asynchrone, les octets deviennent disponibles à partir de la position indiquée par la propriété position, dans une série de remplissages asynchrones de la mémoire tampon signalés par des événements progress. En mode synchrone, la propriété bytesAvailable représente systématiquement le nombre d'octets compris entre la propriété position et la fin du fichier (tous les octets du fichier sont toujours disponibles pour la lecture). En mode asynchrone, vous devez vous assurer que la mémoire tampon de lecture contient suffisamment de données avant d'appeler une méthode de lecture. Dans ce mode, au fur et à mesure de la lecture, les données du fichier sont ajoutées à la mémoire tampon, à partir de la position spécifiée au début de l'opération de lecture, et la propriété bytesAvailable est incrémentée à chaque octet lu. La propriété bytesAvailable indique le nombre d'octets disponibles entre l'octet situé à la position spécifiée par la propriété position et la fin de la mémoire tampon. L'objet FileStream envoie régulièrement un événement progress. En mode asynchrone, l'objet FileStream distribue régulièrement l'événement progress à mesure que des données sont disponibles dans la mémoire tampon de lecture. Par exemple, le code suivant insère des données dans un objet ByteArray, bytes, au fur et à mesure de leur insertion dans la mémoire tampon de lecture : 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); } En mode asynchrone, seules les données que contient la mémoire tampon de lecture peuvent être lues. En outre, les données sont supprimées de la mémoire tampon au fur et à mesure de leur lecture. Avant d'appeler une opération de lecture, vous devez donc vous assurer que les données existent dans la mémoire tampon de lecture. Par exemple, le code suivant lit 8 000 octets de données à partir de la position 4 000 dans le fichier : 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"); } } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 129 Utilisation du système de fichiers Lors d'une opération d'écriture, l'objet FileStream n'insère pas de données dans la mémoire tampon de lecture. Au terme de l'opération (toutes les données de la mémoire tampon d'écriture étant écrites dans le fichier), l'objet FileStream commence une nouvelle mémoire tampon de lecture (en supposant que l'objet FileStream ouvert associé possède des fonctionnalités de lecture) et commence à insérer des données dans la mémoire tampon de lecture à partir de la position spécifiée par la propriété position. La propriété position peut correspondre à la position du dernier octet écrit, mais elle est différente si l'utilisateur lui affecte une autre valeur après l'opération d'écriture. Programmation asynchrone et événements générés par un objet FileStream ouvert en mode asynchrone Lorsqu'un fichier est ouvert en mode asynchrone (à l'aide de la méthode openAsync()), la lecture et l'écriture de fichiers sont asynchrones. Un autre code ActionScript peut s'exécuter au fur et à mesure de l'insertion de données dans la mémoire tampon de lecture et de l'écriture de données de sortie. Vous devez donc vous enregistrer pour les événements générés par l'objet FileStream ouvert en mode asynchrone. En vous enregistrant pour l'événement progress, vous pouvez être averti dès que de nouvelles données sont disponibles à des fins de lecture, comme l'illustre le code suivant : 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"); } Vous pouvez lire la totalité des données en vous enregistrant pour l'événement complete, comme l'illustre le code suivant : 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"); } De même que des données en entrée sont mises en mémoire tampon à des fins de lecture asynchrone, les données que vous écrivez dans un flux asynchrone sont mises en mémoire tampon et écrites dans le fichier de manière asynchrone. Alors que des données sont écrites dans un fichier, l'objet FileStream distribue régulièrement un objet OutputProgressEvent. Un objet OutputProgressEvent comprend une propriété bytesPending définie sur le nombre d'octets restants à écrire. Vous pouvez vous enregistrer pour l'événement outputProgress afin d'être averti lorsque cette mémoire tampon est écrite dans le fichier, peut-être pour afficher une boîte de dialogue de progression. Toutefois, cette opération n'est généralement pas nécessaire. Vous pouvez notamment appeler la méthode close() sans vous soucier des octets non écrits. L'objet FileStream continue d'écrire des données et l'événement close est envoyé une fois le dernier octet écrit dans le fichier et le fichier sous-jacent fermé. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 130 Utilisation du système de fichiers Format de données et choix des méthodes de lecture et d'écriture Tout fichier est un ensemble d'octets sur disque. Dans ActionScript, les données d'un fichier peuvent toujours être représentées sous la forme d'un objet ByteArray. Par exemple, le code suivant lit les données d'un fichier et les insère dans un objet ByteArray nommé bytes : 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); } De même, le code suivant écrit les données de l'objet ByteArray bytes dans un fichier : 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); Cependant, vous souhaitez rarement stocker les données dans un objet ByteArray ActionScript. Les fichiers de données sont souvent dans un format de fichier spécifique. Il se peut par exemple que les données du fichier soient au format texte et que vous souhaitiez les représenter dans un objet String. C'est pourquoi la classe FileStream comprend des méthodes de lecture et d'écriture de données de types autres que les objets ByteArray. Par exemple, la méthode readMultiByte() permet de lire des données dans un fichier et de les stocker dans une chaîne, comme l'illustre le code suivant : 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"); } Le deuxième paramètre de la méthode readMultiByte() spécifie le format texte utilisé par ActionScript pour interpréter les données (« iso-8859-1 », en l'occurrence). ActionScript prend en charge les codages de jeu de caractères courants. Vous en trouverez la liste dans le Guide de référence du langage ActionScript 3.0 (voir Jeu de caractères pris en charge à l'adresse http://livedocs.macromedia.com/flex/2/langref/charset-codes.html). La classe FileStream comprend également la méthode readUTFBytes(), qui lit des données de la mémoire tampon de lecture et les insère dans une chaîne à l'aide du jeu de caractères UTF-8. Les caractères du jeu de caractères UTF-8 sont de longueur variable. N'utilisez donc pas readUTFBytes() dans une méthode répondant à l'événement progress car les données situées à la fin de la mémoire tampon de lecture sont susceptibles de représenter un caractère incomplet. (Cette règle s'applique également à l'utilisation de la méthode readMultiByte() avec un codage de caractères de longueur variable.) Lorsque l'objet FileStream distribue l'événement progress, vous devez donc lire l'ensemble complet de données. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 131 Utilisation du système de fichiers Vous disposez également de méthodes d'écriture similaires, writeMultiByte() et writeUTFBytes(), pour manipuler les objets String et les fichiers de texte. Les méthodes readUTF() et writeUTF() (à ne pas confondre avec readUTFBytes() et writeUTFBytes()) permettent également la lecture ou l'écriture de données dans un fichier, mais elles considèrent comme acquis que des données indiquant la longueur des données texte précèdent ces dernières, ce qui n'est pas une pratique courante dans les fichiers de texte standard. Certains fichiers de texte UTF commencent par un caractère « UTF-BOM » (de l'anglais Byte Order Mark) qui définit le boutisme, ainsi que le format de codage (UTF-16 ou UTF-32). Vous trouverez un exemple de lecture et d'écriture dans un fichier de texte à la section « Exemple : lecture et insertion d'un fichier XML dans un objet XML » à la page 132. Les méthodes readObject() et writeObject() facilitent le stockage et la récupération de données pour les objets ActionScript complexes. Les données sont codées au format AMF (ActionScript Message Format). Ce format ActionScript est propriétaire. Les applications autres que AIR, Flash Player, Flash Media Server et Flex Data Services ne possèdent pas d'API intégrées permettant de manipuler des données dans ce format. Il existe d'autres méthodes de lecture et d'écriture, notamment readDouble() et writeDouble(). Cependant si vous les utilisez, assurez-vous que le format de fichier correspond au format des données définies par ces méthodes. Les formats de fichier sont souvent plus complexes que de simples formats de texte. Par exemple, un fichier MP3 contient des données compressées qui peuvent uniquement être interprétées par le biais des algorithmes de décompression et de décodage spécifiques à ce format. Les fichiers MP3 peuvent également comprendre des balises ID3 qui contiennent des informations de métabalise concernant le fichier (tel que le titre et l'interprète d'une chanson). Il existe plusieurs versions du format ID3, mais le plus simple (ID3 version 1) est présenté à la section « Exemple : lecture et écriture de données en mode aléatoire » à la page 133. D'autres formats de fichier (pour les images, bases de données, documents d'application, etc.) ont une structure de données différente. Vous devez comprendre celle-ci pour pouvoir les utiliser dans ActionScript. Utilisation des méthodes load() et save() Flash Player 10 a ajouté les méthodes load() et save() dans la classe FileReference. Ces méthodes sont également présentes dans AIR 1.5, et la classe File hérite des méthodes de la classe FileReference. L'objectif de ces méthodes est de fournir aux utilisateurs un moyen sécurisé pour charger et enregistrer les données des fichiers dans Flash Player. Toutefois, les applications AIR peuvent également les utiliser pour charger et enregistrer les fichiers de façon asynchrone. Par exemple, le code suivant enregistre une chaîne dans un fichier texte : 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."); } Le paramètre data de la méthode save() peut prendre une valeur String, XML ou ByteArray. Lorsque l'argument est une valeur String ou XML, la méthode enregistre le fichier sous forme de fichier texte au format UTF-8. Lorsque cet exemple de code s'exécute, l'application présente une boîte de dialogue qui permet à l'utilisateur de sélectionner la destination du fichier enregistré. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 132 Utilisation du système de fichiers Le code suivant charge une chaîne à partir d'un fichier texte UTF-8 : 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 plus de fonctionnalités que celles fournies par les méthodes load() et save() : • La classe FileStream vous permet de lire et d'écrire des données de façon synchrone et asynchrone. • La classe FileStream vous permet d'écrire dans un fichier de façon incrémentielle. • La classe FileStream vous permet d'ouvrir un fichier en mode aléatoire (lecture et écriture dans toute section du fichier). • La classe FileStream vous permet de spécifier le type d'accès au fichier disponible pour le fichier via la définition du paramètre fileMode de la méthode open() ou openAsync(). • La classe FileStream vous permet d'enregistrer des données dans des fichiers sans présenter à l'utilisateur une boîte de dialogue Ouvrir ou Enregistrer. • Lors de la lecture de données avec la classe FileStream, vous pouvez utiliser directement des types autres que des tableaux d'octets. Exemple : lecture et insertion d'un fichier XML dans un objet XML Les exemples suivants expliquent comment accéder en lecture et en écriture à un fichier de texte contenant des données XML. Pour lire le fichier, initialisez les objets File et FileStream, appelez la méthode readUTFBytes() de l'objet FileStream et convertissez la chaîne en objet 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(); De même, pour écrire dans le fichier, il suffit de définir les objets File et FileStream appropriés, puis d'appeler une méthode d'écriture de l'objet FileStream. Transmettez la version chaîne des données XML à la méthode d'écriture, comme l'illustre le code suivant : 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(); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 133 Utilisation du système de fichiers Ces exemples utilisent les méthodes readUTFBytes() et writeUTFBytes(), car il est considéré comme acquis que les fichiers sont au format UTF-8. Si tel n'est pas le cas, vous devrez peut-être recourir à une autre méthode (consultez la section « Format de données et choix des méthodes de lecture et d'écriture » à la page 130). Les exemples précédents utilisent des objets FileStream ouverts en mode synchrone. Vous pouvez aussi ouvrir des fichiers en mode asynchrone (ce type d'opération nécessite l'utilisation de fonctions d'écouteur d'événement pour répondre aux événements). Par exemple, le code suivant illustre comment lire un fichier XML en mode asynchrone : 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(); } La méthode processXMLData() est appelée lorsque le fichier est intégralement lu et inséré dans la mémoire tampon de lecture (autrement dit, lorsque l'objet FileStream distribue l'événement complete). Elle appelle la méthode readUTFBytes() pour obtenir une version chaîne des données lues, puis elle crée un objet XML, prefsXML, basé sur cette chaîne. Exemple : lecture et écriture de données en mode aléatoire Les fichiers MP3 peuvent renfermer des balises ID3, autrement dit, des sections en début ou fin de fichier contenant des métadonnées identifiant l'enregistrement. Il existe différentes versions du format de balise ID3. L'exemple suivant explique comment accéder en lecture et écriture à un fichier MP3 contenant le format ID3 le plus simple (ID3 version 1.0) par le biais d'un « accès aléatoire aux données », c'est-à-dire en lisant et écrivant des données à des emplacements arbitraires dans le fichier. Dans un fichier MP3 contenant une balise ID3 version 1, les données ID3 figurent dans les 128 derniers octets du fichier. Lorsque vous accédez à un fichier en mode de lecture/écriture aléatoire, il est important de définir le paramètre fileMode de la méthode open() ouopenAsync() sur FileMode.UPDATE : var file:File = File.documentsDirectory.resolvePath("My Music/Sample ID3 v1.mp3"); var fileStr:FileStream = new FileStream(); fileStr.open(file, FileMode.UPDATE); Vous pouvez ainsi accéder au fichier en lecture et écriture. A l'ouverture du fichier, vous pouvez définir le pointeur position sur 128 octets avant la fin du fichier : fileStr.position = file.size - 128; Ce code définit la propriété position sur cet emplacement du fichier car le format ID3 v1.0 stipule que les balises ID3 sont stockées dans les derniers 128 octets du fichier. La spécification définit également les informations suivantes : • Les 3 premiers octets de la balise représentent la chaîne "TAG". • Les 30 caractères suivants représentent le titre de la piste MP3, sous forme de chaîne. • Les 30 caractères suivants représentent le nom de l'interprète, sous forme de chaîne. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 134 Utilisation du système de fichiers • Les 30 caractères suivants représentent le nom de l'album, sous forme de chaîne. • Les 4 caractères suivants représentent l'année, sous forme de chaîne. • Les 30 caractères suivants représentent le commentaire, sous forme de chaîne. • L'octet suivant contient un code identifiant le genre de la piste. • Toutes les données texte sont au format ISO 8859-1. La méthode id3TagRead() vérifie les données après leur lecture (sur envoi de l'événement complete) : 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); } } Vous pouvez également écrire dans le fichier en mode aléatoire. Par exemple, vous pourriez analyser la variable id3Title pour vérifier que l'utilisation des majuscules est correcte (à l'aide des méthodes de la classe String), puis écrire une chaîne modifiée, newTitle, dans le fichier, comme l'illustre l'exemple suivant : fileStr.position = file.length - 125; // 128 - 3 fileStr.writeMultiByte(newTitle, "iso-8859-1"); Conformément à la norme ID3 version 1, la chaîne newTitle doit comprendre 30 caractères et être remplie à droite par le code de caractère 0 (String.fromCharCode(0)). 135 Chapitre 15 : Opération glisser-déposer Les classes de l'API glisser-déposer permettent de prendre en charge les mouvements glisser-déposer dans l'interface utilisateur. Dans ce contexte, un mouvement est une action effectuée par l'utilisateur, gérée à la fois par le système d'exploitation et votre application, qui exprime son intention de copier, déplacer ou lier des informations. Il se produit un mouvement de glissement vers l'extérieur lorsque l'utilisateur fait glisser un objet hors d'un composant ou d'une application. Il se produit un mouvement de glissement vers l'intérieur lorsque l'utilisateur fait glisser un objet externe vers un composant ou une application. L'API glisser-déposer permet à un utilisateur de faire glisser des données d'une application à l'autre ou d'un composant d'application à l'autre. Parmi les formats de transfert pris en charge figurent : • Images bitmap • Fichiers • Texte au format HTML • Texte • Données RTF (Rich Text Format) • URL • Objets sérialisés • Références aux objets (valables uniquement dans leur application d'origine) Informations complémentaires en ligne sur l'opération glisser-déposer Pour plus d'informations sur l'utilisation de l'API glisser-déposer, consultez les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Prise en charge des opérations glisser-déposer et copier-coller Guide de référence du langage • NativeDragManager • NativeDragOptions • Clipboard • NativeDragEvent Adobe Developer Connection - Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « AIR drag and drop ») DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 136 Opération glisser-déposer Principes de base de l'opération glisser-déposer L'API glisser-déposer contient les classes suivantes. Package Classes flash.desktop • NativeDragManager • NativeDragOptions • Clipboard • NativeDragActions • ClipboardFormat • ClipboardTransferModes Les constantes utilisées dans l'API glisser-déposer sont définies dans les classes suivantes : flash.events • NativeDragActions • ClipboardFormat • ClipboardTransferModes NativeDragEvent Décomposition des mouvements glisser-déposer Le mouvement glisser-déposer est composé de trois étapes, comme suit : Initialisation Un utilisateur initialise une opération glisser-déposer en faisant glisser un composant ou un élément de composant tout en maintenant enfoncé le bouton de la souris. Le composant source de l'élément glissé porte généralement le nom d'initiateur du glissement et distribue les événements nativeDragStart et nativeDragComplete. Une application Adobe® AIR™ démarre une opération de glissement en appelant la méthode NativeDragManager.doDrag() en réponse à un événement mouseDown ou mouseMove. Si l'opération de glissement commence à l'extérieur d'une application AIR, aucun objet initiateur ne déclenche les événements nativeDragStart ou nativeDragComplete. Glissement Tout en maintenant enfoncé le bouton de la souris, l'utilisateur déplace le curseur vers un autre composant, une autre application ou le bureau. Pendant la durée du glissement, l'objet initiateur distribue des événements nativeDragUpdate. Lorsque l'utilisateur place la souris sur une cible de dépôt potentielle dans une application AIR, la cible distribue un événement nativeDragEnter. Le gestionnaire d'événement peut inspecter l'objet événement pour déterminer si les données glissées sont disponibles dans un format géré par la cible. Si tel est le cas, il autorise l'utilisateur à déposer les données sur la cible en appelant la méthode NativeDragManager.acceptDragDrop(). Tant que le mouvement de glissement survole un objet interactif, celui-ci distribue des événements nativeDragOver. Lorsque le mouvement de glissement quitte l'objet interactif, celui-ci distribue un événement nativeDragExit. Dépôt L'utilisateur relâche la souris sur une cible de dépôt appropriée. Si la cible est un composant ou une application AIR, l'objet cible déclenche un événement nativeDragDrop. Le gestionnaire d'événement peut accéder aux données transférées à partir de l'objet événement. Si la cible n'est ni un composant, ni une application AIR, le système d'exploitation ou une autre application gère le dépôt. Dans les deux cas de figure, l'objet initiateur distribue un événement nativeDragComplete (sous réserve que le glissement ait débuté à partir d'AIR). La classe NativeDragManager contrôle les mouvements de glissement vers l'intérieur et l'extérieur. Tous les membres de la classe NativeDragManager étant statiques, ils ne créent pas d'occurrence de cette dernière. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 137 Opération glisser-déposer Objet Clipboard Les données glissées vers une application ou un composant ou à partir de ces derniers sont contenues dans un objet Clipboard. Un objet Clipboard unique peut proposer plusieurs représentations des mêmes informations pour augmenter les chances qu'une autre application comprenne et utilise les données. Une image peut par exemple être incluse en tant que données d'image, objet Bitmap sérialisé ou fichier. Le rendu des données dans un format peut être confié à une fonction de rendu qui n'est pas appelée tant que les données n'ont pas été lues. Une fois le mouvement de glissement démarré, il n'est possible d'accéder à l'objet Clipboard qu'à partir d'un gestionnaire associé aux événements nativeDragEnter, nativeDragOver et nativeDragDrop. Lorsque le mouvement de glissement est terminé, l'objet Clipboard ne peut être ni lu ni réutilisé. Un objet application peut être transféré sous forme de référence et d'objet sérialisé. Les références sont valables uniquement dans leur application d'origine. Les transferts d'objets sérialisés sont valides d'une application AIR à une autre, mais sont réservés aux objets qui demeurent valides lorsqu'ils sont sérialisés et désérialisés. Les objets sérialisés sont convertis au format AMF3 (Action Message Format for ActionScript 3), qui permet de transférer des données sous forme de chaînes. Utilisation de la structure Flex Dans la plupart des cas, il est recommandé d'utiliser l'API glisser-déposer d'Adobe® Flex™ lors de la création d'applications Flex. La structure Flex propose un jeu de fonctions équivalentes lorsqu'une application Flex est exécutée dans AIR (elle utilise la classe NativeDragManager d'AIR en interne). Flex gère également un jeu plus limité de fonctions lorsqu'une application ou un composant s'exécute dans l'environnement plus restrictif d'un navigateur. Il est impossible d'utiliser les classes AIR dans des composants ou applications qui tournent en dehors de l'environnement d'exécution AIR. Prise en charge du mouvement de glissement vers l'extérieur Pour prendre en charge le mouvement de glissement vers l'extérieur, vous devez créer un objet Clipboard en réponse à un événement mouseDown et l'envoyer à la méthode NativeDragManager.doDrag(). Votre application peut alors écouter l'événement nativeDragComplete sur l'objet initiateur pour déterminer la marche à suivre lorsque l'utilisateur termine ou abandonne le mouvement. Préparation des données à transférer Pour préparer les données ou un objet à faire glisser, créez un objet Clipboard et ajoutez les informations à transférer dans un ou plusieurs formats. Vous disposez des formats de données standard pour transmettre des données susceptibles d'être converties automatiquement en formats Presse-papiers natifs, ainsi que des formats définis par l'application pour transmettre des objets. Si la conversion d'informations à transférer dans un format déterminé mobilise un volume élevé de ressources de calcul, vous pouvez indiquer le nom d'une fonction de gestionnaire qui exécutera la conversion. La fonction est appelée sous réserve que le composant ou l'application qui reçoit les données lise le format correspondant. Pour plus d'informations sur les formats de presse-papiers, consultez le chapitre Opération copier-coller du document Programmation avec ActionScript 3.0 (http://www.adobe.com/go/learn_fl_cs4_programmingAS3_fr). L'exemple suivant illustre la création d'un objet Clipboard qui comporte une image bitmap en plusieurs formats : un objet Bitmap, un format d'image bitmap natif et un format de liste de fichiers contenant le fichier source de l'image bitmap : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 138 Opération glisser-déposer 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; } Démarrage d'une opération de glissement vers l'extérieur Pour démarrer une opération de glissement, appelez la méthode NativeDragManager.doDrag() en réponse à un événement mouse down. La méthode doDrag() est statique et gère les paramètres suivants : Paramètre Description initiator Objet où débute le glissement, qui distribue les événements dragStart et dragComplete. Il doit impérativement être interactif. clipboard Objet Clipboard contenant les données à transférer. L'objet Clipboard est référencé dans l'objet NativeDragEvent distribué lors de la séquence glisser-déposer. dragImage (Facultatif) Objet BitmapData à afficher lors du glissement. L'image peut stipuler une valeur alpha. (Remarque : Microsoft Windows applique systématiquement un fondu alpha fixe aux images glissées.) offset (Facultatif) Objet Point qui stipule le décalage de l'image glissée par rapport à la zone sensible de la souris. Utilisez des coordonnées négatives pour déplacer l'image vers le haut et la gauche par rapport au curseur de la souris. Si vous ne définissez pas de décalage, l'angle gauche de l'image glissée est placé sur la zone sensible de la souris. actionsAllowed (Facultatif) Objet NativeDragOptions qui indique les actions (copie, déplacement ou liaison) gérées par l'opération de glissement. Si vous n'indiquez aucun argument, toutes les actions sont autorisées. L'objet DragOptions est référencé dans les objets NativeDragEvent pour permettre à la cible potentielle d'un glissement de vérifier si les actions autorisées sont compatibles avec l'objectif du composant cible. Par exemple, un composant « trash » est susceptible de n'accepter que les mouvements de glissement qui autorisent l'action de déplacement. L'exemple suivant illustre le démarrage d'une opération de glissement d'un objet bitmap chargé à partir d'un fichier. L'exemple charge une image et, lors d'un événement mouseDown, démarre l'opération de glissement. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 139 Opération glisser-déposer 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, DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 140 Opération glisser-déposer 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); } } } Achèvement d'un transfert par glissement vers l'extérieur Lorsqu'un utilisateur dépose l'élément glissé en relâchant la souris, l'objet initiateur distribue un événement nativeDragComplete. Vous pouvez vérifier la propriété dropAction de l'objet événement, puis exécuter l'action appropriée. Par exemple, si l'action correspond à NativeDragAction.MOVE,, vous pourriez supprimer l'élément source de son emplacement d'origine. L'utilisateur peut abandonner un mouvement de glissement en relâchant le bouton de la souris lorsque le curseur figure en dehors d'une cible de dépôt appropriée. Le gestionnaire de glissement définit la propriété dropAction d'un mouvement abandonné sur NativeDragAction.NONE. Prise en charge du mouvement de glissement vers l'intérieur Pour prendre en charge le mouvement de glissement vers l'intérieur, votre application (ou, le plus souvent, un composant visuel de cette dernière) doit répondre aux événements nativeDragEnter ou nativeDragOver. Etapes d'une opération de dépôt standard La séquence d'événements suivante est caractéristique d'une opération de dépôt : 1 L'utilisateur fait glisser un objet Clipboard vers un composant. 2 Le composant distribue un événement nativeDragEnter. 3 Le gestionnaire d'événement nativeDragEnter examine l'objet événement pour vérifier les formats de données disponibles et les actions autorisées. Si le composant peut gérer le dépôt, il appelle NativeDragManager.acceptDragDrop(). 4 NativeDragManager modifie le curseur de la souris pour indiquer que l'objet peut être déposé. 5 L'utilisateur dépose l'objet sur le composant. 6 Le composant cible distribue un événement nativeDragDrop. 7 Le composant cible lit les données au format approprié à partir de l'objet Clipboard au sein de l'objet événement. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 141 Opération glisser-déposer 8 Si le mouvement de glissement a débuté dans une application AIR, l'objet initiateur interactif distribue un événement nativeDragComplete. Si le mouvement a débuté en dehors d'AIR, aucun compte rendu n'est envoyé. Confirmation d'un mouvement de glissement vers l'intérieur Lorsqu'un utilisateur fait glisser un élément Clipboard vers les limites d'un composant visuel, celui-ci distribue les événements nativeDragEnter et nativeDragOver. Pour déterminer si le composant peut accepter l'élément Clipboard, les gestionnaires de ces événements peuvent vérifier les propriétés clipboard et allowedActions de l'objet événement. Pour signaler que le composant peut accepter le dépôt, le gestionnaire d'événement doit appeler la méthode NativeDragManager.acceptDragDrop() et transmettre une référence au composant récepteur. Si plusieurs écouteurs d'événement enregistrés appellent la méthode acceptDragDrop(), le dernier gestionnaire de la liste prime. L'appel acceptDragDrop() demeure valide jusqu'à ce que la souris quitte les limites de l'objet qui accepte l'élément, déclenchant ainsi l'événement nativeDragExit. Si plusieurs actions sont autorisées par le paramètre allowedActions transmis à doDrag(), l'utilisateur peut indiquer l'action autorisée qu'il souhaite exécuter en maintenant enfoncée une touche de modification. Le gestionnaire de glissement modifie l'image associée au curseur pour indiquer à l'utilisateur l'action qui se produirait s'il achevait le dépôt. L'action prévue est signalée par la propriété dropAction de l'objet NativeDragEvent. L'action associée à un mouvement de glissement est définie à titre indicatif uniquement. Les composants impliqués dans le transfert doivent mettre en œuvre le comportement approprié. Pour achever une action de déplacement, par exemple, l'initiateur du glissement peut supprimer l'élément glissé et la cible du dépôt peut l'ajouter. La cible du glissement peut limiter l'action de dépôt à l'une des trois actions gérées en définissant la propriété dropAction de la classe NativeDragManager. Si un utilisateur tente de sélectionner une autre action par le biais du clavier, NativeDragManager affiche le curseur unavailable. Définissez la propriété dropAction des gestionnaires associés aux événements nativeDragEnter et nativeDragOver. L'exemple suivant illustre un gestionnaire associé à l'événement nativeDragEnter ou nativeDragOver. Ce gestionnaire accepte un mouvement de glissement vers l'intérieur sous réserve que l'objet Clipboard en cours de glissement contienne des données au format texte. 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 } } Achèvement du dépôt Lorsque l'utilisateur dépose un élément glissé sur un objet interactif qui a accepté le mouvement, ce dernier distribue un événement nativeDragDrop. Le gestionnaire de cet événement peut extraire les données de la propriété clipboard de l'objet événement. Si la propriété clipboard contient un format défini par l'application, le paramètre transferMode transmis à la méthode getData() de l'objet Clipboard détermine si le gestionnaire de glissement renvoie une référence ou une version sérialisée de l'objet. L'exemple suivant illustre un gestionnaire associé à l'événement nativeDragDrop : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 142 Opération glisser-déposer 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)); } Lorsque le gestionnaire d'événement se referme, l'objet Clipboard n'est plus valide. Toute tentative d'accès à l'objet ou aux données correspondantes génère une erreur. Mise à jour de l'apparence visuelle d'un composant Un composant peut mettre à jour son apparence visuelle en fonction des événements NativeDragEvent. Le tableau cidessous décrit les types de modifications effectuées par un composant standard en réponse à divers événements : Evénement Description nativeDragStart L'objet interactif initiateur peut utiliser l'événement nativeDragStart pour indiquer visuellement qu'il est la source du mouvement de glissement. nativeDragUpdate L'objet interactif initiateur peut utiliser l'événement nativeDragUpdate pour mettre à jour son état au cours du mouvement. nativeDragEnter Un objet interactif récepteur potentiel peut utiliser cet événement pour prendre le focus ou indiquer visuellement s'il peut ou non accepter le dépôt. nativeDragOver Un objet interactif récepteur potentiel peut utiliser cet événement pour répondre au mouvement de la souris au sein de l'objet interactif (lorsque la souris pénètre dans une zone « sensible » d'un composant complexe tel qu'un plan de rues, par exemple). nativeDragExit Un objet interactif récepteur potentiel peut utiliser cet événement pour restaurer son état lorsqu'un mouvement de glissement quitte ses limites. nativeDragComplete L'objet interactif initiateur peut utiliser cet événement pour mettre à jour le modèle de données correspondant (en supprimant un élément d'une liste, par exemple) et restaurer son état visuel. Suivi de la position de la souris lors d'un mouvement de glissement vers l'intérieur Si un mouvement de glissement survole un composant, ce dernier distribue des événements nativeDragOver. Ces événements sont distribués toutes les quelques millisecondes, ainsi qu'à chaque déplacement de la souris. L'objet événement nativeDragOver permet également de déterminer la position de la souris au-dessus du composant. Connaître la position de la souris peut s'avérer utile dans des circonstances où le composant récepteur est complexe, mais ne possède pas de sous-composants. Par exemple, si votre application a affiché une image bitmap contenant une carte de rue et que vous souhaitez mettre en évidence les zones de la carte dans lesquelles l'utilisateur a fait glisser des informations, vous pouvez utiliser les coordonnées de la souris indiquées par l'événement nativeDragOver pour assurer le suivi de la position de la souris au sein de la carte. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 143 Opération glisser-déposer Evénements glisser-déposer HTML Pour faire glisser des données vers une application HTML ou hors de cette dernière (ou vers le code HTML affiché dans un objet HTMLLoader et hors de ce dernier), vous disposez des événements glisser-déposer HTML. L'API glisserdéposer HTML vous permet de faire glisser des données vers des éléments DOM ou à partir de ces derniers dans le contenu HTML. Remarque : vous pouvez également utiliser les API NativeDragEvent et NativeDragManager d'AIR en écoutant les événements sur l'objet HTMLLoader qui comporte le contenu HTML. L'API HTML est toutefois mieux intégrée au DOM HTML et permet de contrôler le comportement par défaut. Comportement par défaut des mouvements glisser-déposer L'environnement HTML définit le comportement par défaut des actions glisser-déposer qui impliquent du texte, des images et des URL. Le comportement par défaut permet de faire glisser ces types de données hors d'un élément. Vous ne pouvez toutefois faire glisser que du texte vers un élément, sous réserve qu'il réside dans une zone modifiable de page. Lorsque vous faites glisser du texte entre des zones modifiables d'une page ou au sein de l'une de ces zones, le comportement par défaut consiste à exécuter une action de déplacement. Lorsque vous faites glisser du texte vers une zone modifiable à partir d'une zone non modifiable ou de l'extérieur de l'application, le comportement par défaut consiste à exécuter une action de copie. Vous pouvez remplacer le comportement par défaut en gérant vous-même les événements glisser-déposer. Pour annuler le comportement par défaut, vous devez appeler les méthodes preventDefault() des objets distribués suite aux événements glisser-déposer. Vous pouvez ensuite insérer des données dans la cible du dépôt et supprimer les données de la source du glissement pour exécuter l'action sélectionnée. Par défaut, l'utilisateur peut sélectionner et faire glisser n'importe quel texte. Il peut faire glisser des images et des liens. La propriété CSS WebKit, -webkit-user-select, permet de contrôler le mode de sélection de tout élément HTML. Par exemple, si vous définissez -webkit-user-select sur none, il est impossible de sélectionner les contenus d'élément et, par conséquent, de les faire glisser. La propriété CSS -webkit-user-drag permet également de déterminer s'il est possible de faire glisser un élément global. Le contenu de l'élément est toutefois traité séparément. L'utilisateur peut néanmoins faire glisser une section sélectionnée de texte. Pour plus d'informations, consultez la section « Extensions des propriétés CSS » à la page 235. Evénements glisser-déposer dans HTML Les événements distribués par l'élément initiateur à l'origine d'un glissement sont indiqués dans le tableau suivant : Evénement Description dragstart Distribué lorsque l'utilisateur démarre l'action de glissement. Le gestionnaire de cet événement peut, le cas échéant, interdire le glissement en appelant la méthode preventDefault() de l'objet événement. Pour déterminer si les données glissées peuvent être copiées, liées ou déplacées, définissez la propriété effectAllowed. Le texte, les images et les liens sélectionnés sont placés dans le Presse-papiers par défaut, mais vous pouvez définir d'autres données pour le mouvement de glissement par le biais de la propriété dataTransfer de l'objet événement. drag Distribué continuellement pendant le mouvement de glissement. dragend Distribué lorsque l'utilisateur relâche le bouton de la souris pour achever l'action de glissement. Les événements distribués par une cible de glissement sont les suivants : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 144 Opération glisser-déposer Evénement Description dragover Distribué continuellement tant que le mouvement de glissement ne dépasse pas les limites de l'élément. Le gestionnaire de cet événement doit définir la propriété dataTransfer.dropEffect pour indiquer si le dépôt entraîne une action de copie, de déplacement ou de lien lorsque l'utilisateur relâche la souris. dragenter Distribué lorsque le mouvement de glissement pénètre dans les limites de l'élément. Si vous modifiez toute propriété d'un objet dataTransfer dans un gestionnaire d'événement dragenter, ces modifications sont rapidement annulées par l'événement dragover suivant. En revanche, il se produit un bref délai entre un événement dragenter et le premier événement dragover susceptible d'entraîner le clignotement du curseur si d'autres propriétés sont définies. Dans de nombreux cas de figure, vous pouvez utiliser le même gestionnaire pour les deux événements. dragleave Distribué lorsque le mouvement de glissement quitte les limites de l'élément. drop Distribué lorsque l'utilisateur dépose les données sur l'élément. Seul le gestionnaire de l'événement peut accéder aux données en cours de glissement. L'objet événement distribué en réponse à ces événements est similaire à un événement souris. Les propriétés d'événement souris telles que (clientX, clientY) et (screenX, screenY) permettent de déterminer la position de la souris. La principale propriété d'un objet événement drag correspond à dataTransfer, qui contient les données en cours de glissement. L'objet dataTransfer en tant que tel dispose des propriétés et méthodes suivantes : Propriété ou méthode Description effectAllowed Effet autorisé par la source du glissement. Le gestionnaire de l'événement dragstart définit généralement cette valeur. Pour plus d'informations, consultez la section « Effets de glissement dans HTML » à la page 145. dropEffect Effet sélectionné par la cible ou l'utilisateur. Si vous définissez la propriété dropEffect dans un gestionnaire d'événement dragover ou dragenter, AIR met à jour le curseur de la souris pour indiquer l'effet qui se produit lorsque l'utilisateur relâche le bouton de la souris. Si la propriété dropEffect définie ne correspond pas à l'un des effets autorisés, aucun dépôt n'est autorisé et le curseur unavailable s'affiche. Si vous n'avez pas défini de propriété dropEffect en réponse à l'événement dragover ou dragenter le plus récent, l'utilisateur peut choisir l'un des effets autorisés par le biais des touches de modification standard gérées par le système d'exploitation. Le dernier effet est signalé par la propriété dropEffect de l'objet distribué pour dragend. Si l'utilisateur abandonne le dépôt en relâchant le bouton de la souris hors d'une cible appropriée, la propriété dropEffect est définie sur none. types Tableau contenant les chaînes de type MIME associées à chaque format de données que contient l'objet dataTransfer. getData(mimeType) Extrait les données au format stipulé par le paramètre mimeType. La méthode getData() ne peut être appelée qu'en réponse à l'événement drop. setData(mimeType) Ajoute des données à l'objet dataTransfer au format stipulé par le paramètre mimeType. Vous pouvez ajouter des données dans divers formats en appelant la méthode setData() pour chaque type MIME. Toute donnée placée dans l'objet dataTransfer par le comportement de glissement par défaut est effacée. La méthode setData() ne peut être appelée qu'en réponse à l'événement dragstart. clearData(mimeType) Efface toute donnée au format stipulé par le paramètre mimeType. setDragImage(image, offsetX, offsetY) Définit une image de glissement personnalisée. La méthode setDragImage() ne peut être appelée qu'en réponse à l'événement dragstart. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 145 Opération glisser-déposer Types MIME associés à l'événement glisser-déposer HTML Les types MIME à utiliser avec l'objet dataTransfer d'un événement glisser-déposer HTML sont indiqués dans le tableau suivant : Format de données Type MIME Texte "text/plain" HTML "text/html" URL "text/uri-list" Image bitmap "image/x-vnd.adobe.air.bitmap" Liste de fichiers "application/x-vnd.adobe.air.file-list" Vous disposez également d'autres chaînes MIME, notamment les chaînes définies par une application. D'autres applications risquent toutefois de ne pas pouvoir reconnaître ou utiliser les données transférées. Il vous incombe d'ajouter des données à l'objet dataTransfer dans le format attendu. Important : seul le code qui s'exécute dans le sandbox d'application peut accéder aux fichiers déposés. Toute tentative de lecture ou de définition de propriété d'un objet File au sein d'un sandbox hors application génère une erreur de sécurité. Pour plus d'informations, consultez la section « Gestion des dépôts de fichier dans un sandbox HTML hors application » à la page 149. Effets de glissement dans HTML L'initiateur du mouvement de glissement peut limiter les effets de glissement autorisés en définissant la propriété dataTransfer.effectAllowed du gestionnaire de l'événement dragstart. Les valeurs de chaîne suivantes sont prises en charge : Valeur de chaîne Description "none" Aucune opération de glissement n'est autorisée. "copy" Les données sont copiées sur la cible, sans modifier l'original. "link" Les données sont partagées avec la cible du dépôt par le biais d'un lien associé à l'original. "move” Les données sont copiées sur la cible et supprimées de l'emplacement d'origine. "copyLink" Les données peuvent être copiées ou liées. "copyMove" Les données peuvent être copiées ou déplacées. "linkMove" Les données peuvent être liées ou déplacées. "all" Les données peuvent être copiées, déplacées ou liées. All correspond à l'effet par défaut lorsque vous interdisez le comportement par défaut. La cible du mouvement de glissement peut définir la propriété dataTransfer.dropEffect pour indiquer l'action exécutée si l'utilisateur achève le dépôt. Si l'effet de dépôt fait partie des actions autorisées, le système affiche le curseur de copie, déplacement ou lien approprié. Dans le cas contraire, le système affiche le curseur unavailable. Si aucun effet de dépôt n'est défini par la cible, l'utilisateur peut choisir les actions autorisées par le biais des touches de modification. Le code suivant définit la valeur dropEffect dans les gestionnaires des événements dragover et dragenter : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 146 Opération glisser-déposer 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"; } Remarque : bien qu'il soit recommandé de définir systématiquement la propriété dropEffect dans le gestionnaire de l'événement dragenter, notez que l'événement dragover suivant réinitialise la valeur par défaut de la propriété. Définissez dropEffect en réponse aux deux événements. Glissement des données hors d'un élément HTML Le comportement par défaut permet de copier par glissement la plupart des contenus d'une page HTML. Vous pouvez contrôler le contenu autorisé à faire l'objet d'un glissement à l'aide des propriétés CSS -webkit-user-select et webkit-user-drag. Remplacez le comportement glisser-déposer par défaut dans le gestionnaire de l'événement dragstart. Appelez la méthode setData() de la propriété dataTransfer de l'objet événement pour associer vos propres données au mouvement de glissement. Pour indiquer les effets de glissement pris en charge par un objet source lorsque vous ne vous fondez pas sur le comportement par défaut, définissez la propriété dataTransfer.effectAllowed de l'objet distribué pour l'événement dragstart. Vous disposez de n'importe quelle combinaison d'effets. Par exemple, si un élément source prend en charge les effets copy et link, définissez la propriété sur copyLink. Définition des données glissées Ajoutez les données associées au mouvement de glissement dans le gestionnaire de l'événement dragstart par le biais de la propriété dataTransfer. La méthode dataTransfer.setData() permet de placer les données dans le Pressepapiers en transmettant le type MIME et les données à transférer. Par exemple, si votre application contient un élément image doté de l'identifiant imageOfGeorge, vous pouvez utiliser le gestionnaire d'événement dragstart suivant. Cet exemple ajoute des représentations d'une photo de George en plusieurs formats de données, augmentant ainsi les chances d'utilisation des données glissées par d'autres applications. 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)); } Remarque : lorsque vous appelez la méthode setData() de l'objet dataTransfer, aucune donnée n'est ajoutée par le comportement glisser-déposer par défaut. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 147 Opération glisser-déposer Glissement de données dans un élément HTML Le comportement par défaut n'autorise que le glissement de texte vers des zones modifiables de la page. Vous pouvez indiquer qu'un élément et ses enfants peuvent devenir modifiables en incluant l'attribut contenteditable dans la balise de début de l'élément. Vous pouvez également rendre un document entier modifiable en définissant la propriété designMode de l'objet Document sur on. Vous pouvez prendre en charge d'autres comportements de glissement vers l'intérieur en gérant les événements dragenter, dragover et drop de tout élément capable d'accepter les données glissées. Activation du glissement vers l'intérieur Pour gérer le mouvement de glissement vers l'intérieur, vous devez au préalable annuler le comportement par défaut. Ecoutez les événements dragenter et dragover sur tout élément HTML à utiliser à titre de cible de dépôt. Dans les gestionnaires de ces événements, appelez la méthode preventDefault() de l'objet événement distribué. Annuler le comportement par défaut permet aux zones non modifiables de recevoir un dépôt. Obtention des données déposées Vous pouvez accéder aux données déposées dans le gestionnaire de l'événement ondrop : function doDrop(event){ droppedText = event.dataTransfer.getData("text/plain"); } Utilisez la méthode dataTransfer.getData() pour lire les données dans le Presse-papiers en transmettant le type MIME du format de données à lire. Pour identifier les formats de données disponibles, utilisez la propriété types de l'objet dataTransfer. Le tableau types contient la chaîne de type MIME de chaque format disponible. Lorsque vous annulez le comportement par défaut pour les événements dragenter ou dragover, il vous incombe d'insérer toute donnée déposée à l'emplacement approprié dans le document. Il n'existe pas d'API permettant de convertir une position souris en point d'insertion au sein d'un élément. Cette restriction risque de compliquer la mise en œuvre des mouvements de glissement de type insertion. Exemple : annulation du comportement de glissement vers l'intérieur HTML par défaut Cet exemple met en œuvre une cible de dépôt qui affiche un tableau contenant tous les formats de données disponibles dans l'élément déposé. Le comportement par défaut permet d'autoriser le glissement du texte, des liens et des images au sein de l'application. L'exemple remplace le comportement de glissement vers l'intérieur par défaut de l'élément div faisant office de cible du dépôt. La principale étape du processus d'activation du contenu non modifiable de sorte à accepter un mouvement de glissement vers l'intérieur consiste à appeler la méthode preventDefault() de l'objet événement distribué pour les événements dragenter et dragover. En réponse à un événement drop, le gestionnaire convertit les données transférées en élément row HTML et insère la ligne dans un tableau pour l'afficher. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 148 Opération glisser-déposer <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> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 149 Opération glisser-déposer <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> </td><td> </td><td> </td><td> </td><td> </ td></tr> </table> </div> </div> </body> </html> Gestion des dépôts de fichier dans un sandbox HTML hors application Un contenu hors application ne peut pas accepter les objets File qui résultent d'un glissement des fichiers vers une application AIR. Il est également impossible de transmettre l'un de ces objets File à un contenu d'application via un pont de sandbox. (Il est nécessaire d'accéder aux propriétés d'objet pendant la sérialisation.) Vous pouvez toutefois continuer à déposer des fichiers dans votre application en écoutant les événements nativeDragDrop AIR de l'objet HTMLLoader. En temps normal, si un utilisateur dépose un fichier dans un cadre qui héberge un contenu hors application, l'événement dépôt n'est pas propagé de l'enfant au parent. Toutefois, puisque les événements distribués par l'objet HTMLLoader (qui comporte tous les contenus HTML d'une application AIR) ne sont pas intégrés au flux d'événement HTML, vous pouvez continuer à recevoir l'événement dépôt dans un contenu d'application. Pour recevoir l'événement associé à un dépôt de fichier, le document parent ajoute un écouteur d'événement à l'objet HTMLLoader par le biais de la référence fournie par window.htmlLoader : window.htmlLoader.addEventListener("nativeDragDrop",function(event){ var filelist = event.clipboard.getData(air.ClipboardFormats.FILE_LIST_FORMAT); air.trace(filelist[0].url); }); L'exemple suivant utilise un document parent qui charge une page enfant dans un sandbox distant (http://localhost/). Le parent écoute l'événement nativeDragDrop sur l'objet HTMLLoader et suit en sortie le modèle d'URL file. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 150 Opération glisser-déposer <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> Le document enfant doit présenter une cible de dépôt valide en interdisant la méthode preventDefault() de l'objet Event dans les gestionnaires des événements HTML dragenter et dragover, sous peine que l'événement dépôt ne se produise jamais. <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> Pour plus d'informations, consultez le chapitre « Programmation en HTML et JavaScript » à la page 237. 151 Chapitre 16 : Opération copier-coller Utilisez les classes de l'API du presse-papiers pour copier les informations à destination et en provenance du pressepapiers du système. Les formats de données que l'on peut échanger avec une application Adobe® AIR™ sont les suivants : • Images bitmaps • Fichiers • Texte • Texte au format HTML • Données au format RTF (Rich Text Format) • Chaînes URL • Objets sérialisés • Références aux objets (valables uniquement dans leur application d'origine) Adobe Flash Player 10 a intégré la fonction de copier-coller introduite dans AIR 1.0. Ce chapitre présente la fonction de copier-coller exclusive d'Adobe AIR. Pour plus d'informations sur cette fonctionnalité partagée, consultez la section Opération copier-coller (manuel Programmation avec Adobe ActionScript 3.0. Informations complémentaires en ligne sur l'opération copier-coller Pour plus d'informations sur l'opération copier-coller, consultez les sources suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Prise en charge des opérations glisser-déposer et copier-coller Guide de référence du langage • Clipboard • ClipboardFormats • ClipboardTransferMode Autres informations • Opération copier-coller (manuel Programmation avec Adobe ActionScript 3.0) • Adobe AIR Developer Connection for Flash (rechercher « AIR copy and paste ») DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 152 Opération copier-coller Opération copier-coller dans l'environnement HTML L'environnement HTML fournit son propre comportement et son lot d'événements par défaut pour l'opération copiercoller. Seul le code en cours d'exécution dans le sandbox de l'application est en mesure d'accéder directement au pressepapiers du système via l'objet Clipboard.generalClipboard. Le code JavaScript d'un sandbox hors application peut accéder au presse-papiers via l'objet événement envoyé en réponse à l'un des événements copier-coller envoyé par un élément provenant d'un document HTML. Les événements copier-coller sont les suivants : copy, cut et paste. L'objet envoyé pour ces événements fournit un accès au presse-papiers par la propriété clipboardData. Comportement par défaut Par défaut, AIR copie les éléments sélectionnées en réponse à la commande copier qui peut être engendrée soit par un raccourci-clavier, soit par un menu contextuel. Au sein des zones modifiables, AIR coupe du texte en réponse à des commandes couper ou bien colle du texte au curseur ou à la sélection en réponse à la commande coller. Pour éviter le comportement par défaut, votre gestionnaire d'événement peut appeler la méthode preventDefault() de l'objet événement envoyé. Utilisation de la propriété clipboardData de l'objet événement La propriété clipboardData de l'objet événement envoyé à la suite de l'un des événements copier-coller vous permet de lire des données du presse-papiers et d'écrire dedans. Pour écrire dans le presse-papiers lors de l'exécution d'un événement copier-coller, utilisez la méthode setData() de l'objet clipboardData en faisant passer les données à copier et le type de MIME : function customCopy(event){ event.clipboardData.setData("text/plain", "A copied string."); } Pour accéder aux données en cours de collage, vous pouvez utiliser la méthode getData() de l'objet clipboardData en faisant passer le type de MIME du format de données. Les formats disponibles sont indiqués par la propriété types. function customPaste(event){ var pastedData = event.clipboardData("text/plain"); } Ce n'est que par l'objet événement envoyé par l'événement paste que l'on peut accéder à la méthode getData() et à la propriété types. L'exemple ci-dessous illustre la façon de remplacer le comportement copier-coller par défaut dans une page HTML. Le gestionnaire d'événement copy met en italiques le texte copié et le copie dans le presse-papiers sous la forme de texte HTML. Le gestionnaire d'événement cut copie les données sélectionnées dans le presse-papiers et les supprime du document. Le gestionnaire paste insère le contenu du presse-papiers sous forme de HTML en caractères gras : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 153 Opération copier-coller <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> Commandes de menu et frappes pour l'opération copier-coller La fonction copier-coller est déclenchée le plus souvent par des commandes de menu et des raccourcis clavier. Sous OS X, un menu d'édition avec les commandes copier et coller est automatiquement créé par le système d'exploitation, mais il vous faut ajouter des écouteurs à ces commandes afin d'accrocher vos propres fonctions de copie et de collage. Sous Windows, vous pouvez ajouter un menu d'édition à toute fenêtre qui utilise un arrière-plan système. Vous pouvez également créer des menus non-natifs avec Flex et ActionScript ou, dans un contenu HTML, utiliser DHTML, mais il s'agit là d'un domaine que nous n'aborderons pas ici. Pour déclencher des commandes copier et coller en réponse à des raccourcis clavier, vous pouvez soit affecter des équivalents de clés aux éléments de commande appropriés dans une application native ou dans un menu contextuel, soit guetter directement les frappes au clavier. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 154 Opération copier-coller Démarrage d'une opération copier-coller depuis une commande de menu Pour déclencher une opération copier-coller depuis une commande de menu, vous devez ajouter des écouteurs pour l'événement select aux éléments du menu qui appellent vos fonctions de gestionnaire. Lorsque votre fonction de gestionnaire est appelée, vous pouvez trouver l'objet à copier ou à coller à l'aide de la propriété focus de la scène. Vous pouvez alors appeler la méthode appropriée de l'objet ayant le focus (ou une méthode de secours universelle si l'objet ne possède pas le focus) pour exécuter les opérations copier, couper et coller. Par exemple, le gestionnaire d'événement copy ci-dessous vérifie si l'objet ayant un focus est bien du type approprié (dans le cas présent, il s'agit d'une classe appelée Scrap), puis il appelle la méthode doCopy() de l'objet. function copyCommand(event:Event):void{ if(NativeApplication.nativeApplication.activeWindow.stage.focus is Scrap){ Scrap(NativeApplication.nativeApplication.activeWindow.stage.focus).doCopy(); } else { NativeApplication.nativeApplication.copy(); } } Dans l'exemple, si copyCommand() ne reconnaît pas la classe de l'objet ayant un focus, il appelle la méthode copy() de NativeApplication. La méthode copy() de NativeApplication envoie une commande de copie interne à l'objet ayant un focus. Si l'objet est une classe intégrée qui implémente l'opération de copier-coller en interne, l'objet exécute la commande. Les classes Textfield et HTMLLoader représentent actuellement les seules classes intégrées de ce type. Les autres objets interactifs déclenchent l'événement copy. Des commandes similaires sont disponibles pour couper, coller, sélectionner tout et, dans le cas de TextArea uniquement : effacer, restaurer et restaurer par progression. Dans un contenu HTML, le comportement copier-coller par défaut peut être déclenché à l'aide des commandes d'édition de NativeApplication. L'exemple ci-dessous crée un menu d'édition pour un document HTML modifiable : L'exemple précédent remplace le menu des applications de Mac OS X. Mais vous pouvez aussi utiliser le menu d'édition par défaut en trouvant les éléments existants et en leur ajoutant des écouteurs d'événement. Si vous utilisez un menu contextuel pour appeler une commande copier ou coller, vous pouvez utiliser la propriété contextMenuOwner de l'objet ContextMenuEvent envoyé lorsque le menu est ouvert ou qu'un élément est sélectionné pour déterminer quel objet est la cible appropriée de la commande copier ou coller. Découverte d'éléments de menu par défaut sous Mac OS X Pour trouver les éléments du menu d'édition par défaut et des commandes spécifiques copier, couper et coller dans le menu des applications sous Mac OS X, vous pouvez dépouiller la hiérarchie des menus à l'aide de la propriété label des objets NativeMenuItem. Par exemple, la fonction suivante se saisit d'un nom et trouve l'article doté de l'étiquette correspondante dans le menu : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 155 Opération copier-coller 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; } Vous pouvez définir le paramètre recurse sur true pour inclure des sous-menus dans la recherche ou sur false pour inclure uniquement le menu qu'on a fait passer. Démarrage d'une commande copier-coller à l'aide d'une frappe de touche Si votre application fait appel à des menus contextuels ou des menus d'application pour l'opération copier-coller, vous pouvez ajouter des équivalents de touche aux éléments de menu pour implémenter les raccourcis clavier. Si votre application fait appel à des menus contextuels ou des menus d'application pour l'opération copier-coller, vous pouvez ajouter des équivalents de touche aux éléments de menu pour implémenter les raccourcis clavier. Sinon, vous pouvez écouter vous-même les frappes pertinentes, comme le montre l'exemple ci-dessous : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 156 Opération copier-coller 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; } } } Dans le contenu HTML, les raccourcis clavier des commandes copier et coller sont implémentés par défaut. Il n'est pas possible, à l'aide d'un écouteur d'événement de touche, d'intercepter toutes les frappes utilisées habituellement pour la copie et le collage. S'il vous faut remplacer le comportement par défaut, une meilleure stratégie consiste à écouter les événements copy et paste eux-mêmes. 157 Chapitre 17 : Utilisation de tableaux d'octets La classe ByteArray vous permet de lire à partir d'un flux de données binaire (qui, pour l'essentiel, correspond à un tableau d'octets) ou d'écrire dans un tel flux. Elle offre un moyen d'accéder aux données au niveau le plus élémentaire. Etant donné que les données informatiques se composent d'octets ou de groupes de 8 bits, la capacité de lire des données en octets implique qu'il est possible d'accéder à des données pour lesquelles aucune classe et aucune méthode d'accès n'existent. La classe ByteArray vous permet d'analyser tous les flux de données (d'une image bitmap à un flux de données transitant par le réseau) au niveau de l'octet. La méthode writeObject() vous permet d'écrire un objet au format AMF (Action Message Format) sérialisé dans une classe ByteArray, tandis que la méthode readObject() vous donne la possibilité de lire un objet sérialisé à partir d'une classe ByteArray vers une variable du type de données d'origine. Vous avez la possibilité de sérialiser n'importe quel objet, à l'exception des objets d'affichage, lesquels peuvent être placés dans la liste d'affichage. Vous pouvez également réaffecter des objets sérialisés à des occurrences d'une classe personnalisée si celle-ci est disponible pour le moteur d'exécution. Une fois qu'un objet a été converti au format AMF, vous pouvez le transférer rapidement par le biais d'une connexion réseau ou l'enregistrer dans un fichier. L'application Adobe® AIR™ décrite dans cet exemple lit un fichier .zip pour illustrer le traitement d'un flux d'octets. Elle extrait une liste des fichiers contenus dans le fichier .zip et les écrit dans le poste de travail. Lecture et écriture d'un objet ByteArray La classe ByteArray fait partie du package flash.utils. Afin de créer un objet ByteArray dans ActionScript 3.0, importez la classe ByteArray et appelez le constructeur, comme décrit dans l'exemple suivant : import flash.utils.ByteArray; var stream:ByteArray = new ByteArray(); Méthodes ByteArray Tout flux de données significatif est organisé selon un format spécifique que vous pouvez analyser afin d'y trouver les informations souhaitées. Par exemple, un enregistrement dans un fichier d'employé simple, comprendrait très certainement un numéro d'ID, un nom, une adresse, un numéro de téléphone, etc. Un fichier audio MP3 contient une balise ID3 permettant d'identifier le titre, l'auteur, l'album, la date d'édition et le genre du fichier en cours de téléchargement. Le format vous permet de connaître l'ordre dans lequel vous devez vous attendre à recevoir les données du flux de données. Il vous permet de lire le flux d'octets de manière intelligente. La classe ByteArray comprend plusieurs méthodes destinées à faciliter la lecture depuis un flux de données et l'écriture vers lui. Parmi les méthodes disponibles, on compte celles-ci : readBytes() et writeBytes(), readInt() et writeInt(), readFloat() et writeFloat(), readObject() et writeObject(), et readUTFBytes() et writeUTFBytes(). Grâce à ces méthodes, vous pouvez lire des données provenant du flux de données dans des variables de types de données spécifiques et écrire directement depuis ces types de données vers un flux de données binaire. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 158 Utilisation de tableaux d'octets Par exemple, le code suivant lit un simple tableau de chaînes et de nombres à virgule flottante, puis écrit chaque élément vers un objet ByteArray. La structure du tableau permet au code d'appeler les méthodes ByteArray appropriées (writeUTFBytes() et writeFloat()) afin d'écrire les données. Le modèle de données répétitif permet de lire le tableau au moyen d'une boucle. // 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 Propriété position La propriété position stocke la position actuelle du pointeur qui indexe la classe ByteArray au cours de la lecture ou de l'écriture. La valeur initiale de la propriété position est égale à 0 (zéro) comme l'illustre l'exemple de code suivant : var bytes:ByteArray = new ByteArray(); trace("bytes.position is initially: " + bytes.position); // 0 Lors de la lecture à partir d'une classe ByteArray ou de l'écriture vers elle, la méthode utilisée met à jour la propriété position de sorte qu'elle pointe vers l'emplacement suivant immédiatement le dernier octet lu ou écrit. Par exemple, le code suivant écrit une chaîne dans une classe ByteArray. Ensuite, la propriété position pointe vers l'octet qui suit immédiatement la chaîne dans 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 De la même manière, une opération de lecture incrémente la propriété position en fonction du nombre d'octets lus. 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! Vous noterez qu'il est possible de définir la propriété position sur un emplacement spécifique dans la classe ByteArray afin de lire ou d'écrire selon ce décalage. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 159 Utilisation de tableaux d'octets Propriétés bytesAvailable et length Les propriétés length et bytesAvailable vous indiquent la longueur d'une classe ByteArray et le nombre d'octets restants entre la position active et la fin. L'exemple suivant illustre des modes d'utilisation de ces propriétés. L'exemple écrit une chaîne de texte dans la classe ByteArray, puis lit la classe ByteArray octet par octet jusqu'à la détection du caractère « a » ou l'arrivée au terme (bytesAvailable <= 0). 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 } Propriété endian Les ordinateurs ne stockent pas tous de la même manière les nombres à plusieurs octets, autrement dit, les nombres nécessitant plus d'un octet de mémoire de stockage. Un nombre entier, par exemple, peut prendre 4 octets (ou 32 bits) de mémoire. Certains ordinateurs commencent par stocker l'octet le plus important du nombre (dans l'adresse mémoire de plus bas niveau) tandis que d'autres stockent d'abord l'octet le moins important. Cet attribut d'ordinateur (ou ordre d'octets) est connu comme étant soit gros-boutiste (l'octet le plus important en premier lieu) soit petitboutiste (l'octet le moins important en premier lieu). Par exemple, le nombre 0x31323334 serait stocké de la manière suivante pour les ordres d'octets gros-boutiste et petit-boutiste, où a0 représente l'adresse mémoire de plus bas niveau des 4 octets et a3 correspond à celle de plus haut niveau : Grosboutist e Grosboutist e Grosboutist e Grosboutist e a0 a1 a2 a3 31 32 33 34 Petitboutist e Petitboutist e Petitboutist e Petitboutist e a0 a1 a2 a3 34 33 32 31 La propriété endian de la classe ByteArray vous permet de désigner cet ordre d'octets pour les nombres à plusieurs octets que vous traitez. Les valeurs admises pour cette propriété sont bigEndian (gros-boutiste) et littleEndian (petit-boutiste). La classe Endian définit les constantes BIG_ENDIAN et LITTLE_ENDIAN pour configurer la propriété endian à l'aide de ces chaînes. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 160 Utilisation de tableaux d'octets Méthodes compress() et uncompress() La méthode compress() vous permet de compresser une classe ByteArray conformément à un algorithme de compression spécifié sous forme de paramètre. La méthode uncompress() vous permet de décompresser un tableau ByteArray compressé conformément à un algorithme de compression. Une fois que vous avez appelé compress() et uncompress(), la longueur du tableau d'octets est fixée selon la nouvelle longueur et la propriété position est configurée sur la fin. La classe CompressionAlgorithm définit des constantes pouvant servir à spécifier l'algorithme de compression. AIR prend en charge les algorithmes deflate et zlib. L'algorithme de compression deflate est utilisé dans plusieurs formats de compression tels que zlib, gzip et certaines implémentations zip. Le format de données compressées zlib est décrit sur la page http://www.ietf.org/rfc/rfc1950.txt et l'algorithme de compression sur la page http://www.ietf.org/rfc/rfc1951.txt. Dans l'exemple suivant, un tableau ByteArray appelé bytes est compressé à l'aide de l'algorithme deflate : bytes.compress(CompressionAlgorithm.DEFLATE); Dans l'exemple suivant, un tableau ByteArray compressé est décompressé à l'aide de l'algorithme deflate : bytes.uncompress(CompressionAlgorithm.DEFLATE); Lecture et écriture d'objets Les méthodes readObject() et writeObject() permettent de lire un objet à partir d'une classe ByteArray et d'en écrire un dans une telle classe. Cet objet est codé au format AMF sérialisé. AMF est un protocole de message propriétaire créé par Adobe et utilisé par différentes classes ActionScript 3.0, notamment les objets Netstream, NetConnection, NetStream, LocalConnection et Shared. Un marqueur de type « un octet » décrit le type des données codées qui suivent. Le format AMF fait appel aux 13 types de données suivants : 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 Les données codées suivent le marqueur de type à moins que ce dernier ne représente qu'une seule valeur possible (nulle, vraie ou fausse, par exemple), auquel cas aucun autre élément n'est codé. Il existe deux versions du format AMF : AMF0 et AMF3. AMF 0 prend en charge l'envoi d'objets complexes par référence et permet aux points de fin de restaurer les relations entre objets. AMF 3 améliore le format AMF 0 en envoyant les traits et chaînes de l'objet par référence, en plus des références d'objet, et en prenant en charge de nouveaux types de données introduits dans la version 3.0 d'ActionScript. La propriété ByteArray.objectEcoding spécifie la version du format AMF utilisée pour coder les données d'objet. La classe flash.net.ObjectEncoding définit des constantes permettant de préciser la version du format AMF : ObjectEncoding.AMF0 et ObjectEncoding.AMF3. import flash.filesystem.*; import flash.utils.ByteArray; // Label component must be in Library import fl.controls.Label; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 161 Utilisation de tableaux d'octets 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(); } La méthode readObject() lit un objet au format AMF sérialisé à partir d'une classe ByteArray et le stocke dans un objet du type spécifié. Dans l'exemple suivant, le fichier order est lu à partir du poste de travail dans une classe ByteArray (inBytes), puis il est décompressé. readObject() est ensuite appelé pour stocker le fichier dans l'objet XML orderXML. Dans cet exemple, une construction de boucle for each() est utilisée pour ajouter chaque nœud à une zone de texte à des fins d'affichage. L'exemple indique également la valeur de la propriété objectEncoding accompagnée d'un en-tête pour le contenu du fichier order. import flash.filesystem.*; import flash.utils.ByteArray; // TextArea component must be in Library import fl.controls.TextArea; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 162 Utilisation de tableaux d'octets 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(); } Exemple ByteArray : lecture d'un fichier .zip Cet exemple indique comment lire un fichier .zip simple contenant plusieurs fichiers de types différents. Pour parvenir à lire un tel fichier, les données pertinentes sont extraites des métadonnées pour chacun des fichiers, lesquels sont décompressés dans des classes ByteArray individuelles et écrits dans le poste de travail. La structure générale d'un fichier .zip repose sur la spécification PKWARE Inc., laquelle est tenue à jour à l'adresse http://www.pkware.com/documents/casestudies/APPNOTE.TXT. Elle commence par l'en-tête et les données du premier fichier de l'archive .zip, suivis de la paire en-tête/données de chaque fichier supplémentaire. (La structure de l'en-tête des fichiers est décrite plus loin dans ce document.) Le fichier .zip comprend éventuellement un enregistrement du descripteur de données (généralement lorsque le fichier zip de sortie a été créé dans la mémoire au lieu d'être enregistré sur un disque). Divers éléments facultatifs viennent ensuite : en-tête de déchiffrement de l'archive, enregistrement des données supplémentaires de l'archive, structure de répertoires centrale, fin Zip64 de l'enregistrement de répertoires central, fin Zip64 du localisateur de répertoires central et fin de l'enregistrement de répertoires. Le code présenté dans cet exemple a été rédigé dans le seul objectif d'analyser des fichiers zip ne contenant pas de dossiers ; il n'attend pas d'enregistrements de descripteurs de données. Il ne tient pas compte des informations suivant les données du dernier fichier. Le format de l'en-tête de fichier de chaque fichier est défini de la manière suivante : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 163 Utilisation de tableaux d'octets signature de l'en-tête de fichier 4 octets version requise 2 octets indicateur de bit à usage général 2 octets méthode de compression 2 octets (8=DEFLATE; 0=UNCOMPRESSED) heure de la dernière modification du fichier 2 octets date de la dernière modification du fichier 2 octets crc-32 4 octets taille compressée 4 octets taille décompressée 4 octets longueur du nom de fichier 2 octets longueur du champ supplémentaire 2 octets nom du fichier variable champ supplémentaire variable L'en-tête du fichier est suivi des véritables données du fichier, au format compressé ou décompressé, suivant l'indicateur de méthode de compression utilisé. L'indicateur est égal à 0 (zéro) si les données du fichier sont décompressées, à 8 si les données sont compressées à l'aide de l'algorithme DEFLATE ou à une autre valeur lorsque les données utilisent d'autres algorithmes de compression. L'interface utilisateur choisie dans cet exemple se compose d'une étiquette et d'une zone de texte (taFiles). L'application écrit les informations suivantes dans la zone de texte pour chaque fichier détecté dans le fichier .zip : nom du fichier, taille compressée et taille décompressée. Le début du programme effectue les tâches suivantes : • Importation des classes requises import flash.filesystem.*; import flash.utils.ByteArray; import flash.events.Event; • Définition de l'interface utilisateur 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); • Définition de la classe ByteArray bytes var bytes:ByteArray = new ByteArray(); • Définition des variables destinées à stocker les métadonnées provenant de l'en-tête du fichier DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 164 Utilisation de tableaux d'octets // 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; • Définition des objets File (zfile) et FileStream (zStream) devant représenter le fichier .zip et indication de l'emplacement du fichier .zip à partir duquel les fichiers sont extraits (fichier intitulé HelloAIR.zip dans le répertoire du poste de travail) // File variables for accessing .zip file var zfile:File = File.desktopDirectory.resolvePath("HelloAIR.zip"); var zStream:FileStream = new FileStream(); Le programme commence par ouvrir le fichier .zip en mode READ (lecture). zStream.open(zfile, FileMode.READ); Il configure ensuite la propriété endian de bytes sur la valeur LITTLE_ENDIAN afin d'indiquer que l'ordre d'octets des champs numériques commence par l'octet le moins important. bytes.endian = Endian.LITTLE_ENDIAN; Une instruction while() commence ensuite une boucle qui s'interrompt uniquement lorsque la position active dans le flux de fichier est supérieure ou égale à la taille du fichier. while (zStream.position < zfile.size) { La première instruction au sein de la boucle lit les 30 premiers octets du flux de fichier dans la classe ByteArray bytes. Les 30 premiers octets constituent la partie à taille fixe de l'en-tête du premier fichier. // read fixed metadata portion of local file header zStream.readBytes(bytes, 0, 30); Le code lit ensuite un nombre entier (signature) à partir des premiers octets de l'en-tête de 30 octets. La définition du format ZIP indique que la signature de chaque en-tête de fichier correspond à la valeur hexadécimale 0x04034b50 ; si la signature est différente, cela signifie que le code a dépassé la section des fichiers contenus dans le fichier .zip et qu'il ne reste plus aucun fichier à extraire. Dans ce cas, le code quitte immédiatement la boucle while au lieu d'attendre la fin du tableau d'octets. bytes.position = 0; signature = bytes.readInt(); // if no longer reading data files, quit if (signature != 0x04034b50) { break; } La partie suivante du code lit l'octet d'en-tête à la position décalée 8 et stocke la valeur dans la variable compMethod. Cet octet contient une valeur indiquant la méthode de compression appliquée à ce fichier. Plusieurs méthodes de compression sont autorisées, mais en pratique, presque tous les fichiers .zip utilisent l'algorithme de compression DEFLATE. Si le fichier actif est compressé à l'aide de la méthode de compression DEFLATE, compMethod est égal à 8 ; si le fichier n'est pas compressé, compMethod est égal à 0. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 165 Utilisation de tableaux d'octets bytes.position = 8; compMethod = bytes.readByte(); // store compression method (8 == Deflate) Les 30 premiers octets sont suivis par une partie d'en-tête à longueur variable contenant le nom du fichier et, éventuellement, un champ supplémentaire. La variable offset stocke la taille de cette partie. La taille est calculée en ajoutant la longueur du nom de fichier à la longueur du champ supplémentaire, lue à partir de l'en-tête aux décalages 26 et 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 Le programme lit ensuite la partie à longueur variable de l'en-tête du fichier pour identifier le nombre d'octets stockés dans la variable offset. // read variable length bytes between fixed-length header and compressed file data zStream.readBytes(bytes, 30, offset); Le programme lit le nom du fichier à partir de la partie variable de l'en-tête et l'affiche dans la zone de texte accompagné des tailles compressée (zippée) et décompressée (initiale) du fichier. 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'exemple de code lit le reste du fichier à partir du flux de fichier en octets (bytes) selon la longueur indiquée par la taille compressée, écrasant ainsi l'en-tête de fichier dans les 30 premiers octets. La taille compressée est exacte et ce, même si le fichier n'est pas compressé, car elle équivaut alors à la taille décompressée du fichier. // read compressed file to offset 0 of bytes; for uncompressed files // the compressed and uncompressed size is the same zStream.readBytes(bytes, 0, compSize); Dans la suite de l'exemple, le fichier compressé est décompressé et la fonction outfile() est appelée afin de l'écrire dans le flux du fichier de sortie. Le code passe à outfile() le nom du fichier et le tableau d'octets contenant les données du fichier. if (compMethod == 8) // if file is compressed, uncompress { bytes.uncompress(CompressionAlgorithm.DEFLATE); } outFile(fileName, bytes); // call outFile() to write out the file L'accolade de fermeture indique la fin de la boucle while et du code de l'application, à l'exception de la méthode outFile(). L'exécution revient au début de la boucle while et poursuit le traitement des octets suivants du fichier .zip, soit en extrayant un autre fichier soit en mettant un terme au traitement du fichier .zip si le dernier fichier a été traité. } // end of while loop DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 166 Utilisation de tableaux d'octets La fonction outfile() ouvre un fichier de sortie en mode WRITE (écriture) dans le poste de travail en lui donnant le nom fourni par le paramètre filename. Elle écrit ensuite les données du fichier issues du paramètre data dans le flux du fichier de sortie (outStream) et ferme le fichier. 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 Chapitre 18 : Utilisation des bases de données SQL locales Adobe AIR permet de créer et d'utiliser des bases de données SQL locales. L'environnement d'exécution inclut un moteur de base de données SQL avec prise en charge de nombreuses fonctionnalités SQL standard, à l'aide du système de base de données SQLite open source. Une base de données SQL locale peut être utilisée pour le stockage des données persistantes locales. Par exemple, elle peut servir pour les données d'application, les paramètres utilisateur d'application, des documents ou tout autre type de données que votre application doit enregistrer localement. Informations complémentaires en ligne sur les bases de données SQL locales Pour plus d'informations sur l'utilisation des bases de données SQL locales, consultez les références suivantes : Guides de démarrage rapide (Adobe AIR Developer Connection) • Utilisation asynchrone d'une base de données SQL locale • Utilisation asynchrone d'une base de données SQL locale • Utilisation d'une base de données chiffrée Guide de référence du langage • SQLCollationType • SQLColumnNameStyle • SQLColumnSchema • SQLConnection • SQLError • SQLErrorEvent • SQLErrorOperation • SQLEvent • SQLIndexSchema • SQLMode • SQLResult • SQLSchema • SQLSchemaResult • SQLStatement • SQLTableSchema • SQLTransactionLockType • SQLTriggerSchema DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 168 Utilisation des bases de données SQL locales • SQLUpdateEvent • SQLViewSchema Adobe Developer Connection - Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « AIR SQL ») A propos des bases de données SQL locales Adobe AIR comprend un moteur de base de données relationnelle de type SQL qui fonctionne au sein de l'environnement d'exécution. Les données sont stockées localement dans des fichiers de bases de données dans l'ordinateur sur lequel l'application AIR s'exécute (par exemple, dans le disque dur de l'ordinateur). L'exécution de la base de données et le stockage des fichiers de données s'effectuant localement, une application AIR peut utiliser une base de données qu'une connexion réseau soit disponible ou non. Le moteur de base de données SQL locale de l'environnement d'exécution constitue ainsi un mécanisme pratique pour le stockage des données d'application locales persistantes, en particulier si vous maîtrisez les bases de données relationnelles et SQL. Cas d'utilisation des bases de données SQL locales La fonctionnalité de base de données SQL locale de l'application AIR peut répondre à tout objectif de stockage des données d'application sur l'ordinateur local d'un utilisateur. Adobe AIR inclut plusieurs mécanismes de stockage local des données, chacun présentant des avantages distincts. Voici quelques utilisations possibles d'une base de données SQL locale dans votre application AIR : • Avec une application orientée données (par exemple, un carnet d'adresses), une base de données peut être utilisée pour stocker les données de l'application principale. • Avec une application orientée documents, dans laquelle les utilisateurs créent des documents à enregistrer et éventuellement à partager, chaque document peut être enregistré sous forme de fichier de base de données, à l'emplacement désigné par l'utilisateur. (Notez, toutefois, que si la base de données n'est pas chiffrée, toute application AIR peut ouvrir le fichier de bases de données. Le chiffrement est donc recommandé pour tous les documents potentiellement sensibles.) • Avec une application réseau, il est possible d'utiliser une base de données pour stocker un cache local des données d'application ou pour stocker temporairement des données lorsque la connexion réseau n'est pas disponible. Un mécanisme de synchronisation peut dans ce cas être créé pour synchroniser la base de données locale avec le magasin de données en réseau. • Quelle que soit l'application, une base de données peut être utilisée pour stocker les paramètres d'application des utilisateurs individuels, tels que les informations relatives aux applications ou aux options des utilisateurs, comme la taille et la position de la fenêtre. A propos des fichiers de bases de données et des bases de données AIR Une base de données SQL locale Adobe AIR individuelle est stockée sous la forme d'un seul fichier dans le système de fichiers de l'ordinateur. Le moteur de base de données SQL de l'environnement d'exécution gère la création et le formatage des fichiers de base de données, de même que la manipulation et la récupération des données dans un fichier de base de données. L'environnement d'exécution ne spécifie pas comment ni où les données de la base de données sont stockées dans le système de fichiers, mais chaque base de données est stockée dans son intégralité dans un seul fichier. Vous spécifiez l'emplacement de stockage du fichier de base de données dans le système de fichiers. Une même application AIR peut accéder à une ou plusieurs bases de données distinctes (c'est-à-dire à des fichiers de base de DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 169 Utilisation des bases de données SQL locales données distincts). L'environnement d'exécution stockant chaque base de données sous forme d'un seul fichier dans le système de fichiers, vous pouvez localiser votre base de données selon vos besoins, en fonction de la conception de votre application et des contraintes d'accès aux fichiers du système d'exploitation. Chaque utilisateur peut disposer d'un fichier de base de données distinct pour ses données spécifiques, ou tous les utilisateurs de l'application peuvent accéder à un fichier de bases de données sur un ordinateur dans le cas de données partagées. Les données étant stockées localement sur un seul ordinateur, elles ne sont pas automatiquement partagées avec les utilisateurs d'autres ordinateurs. Le moteur de la base de données SQL locale ne permet pas d'exécuter des instructions SQL sur une base de données distante ou basée sur un serveur. A propos des bases de données relationnelles Une base de données relationnelle est un mécanisme de stockage (et de récupération) des données sur un ordinateur. Les données sont organisées en tables : les lignes représentent les enregistrements ou les éléments, et les colonnes (parfois appelées « champs ») divisent chaque enregistrement en valeurs individuelles. Par exemple, une application de carnet d'adresses peut contenir une table nommée « amis ». Chaque ligue de la table représente alors un ami stocké dans la base de données. Les colonnes de cette table représentent des données telles que le prénom, le nom, la date de naissance, etc. Pour chaque ligne de la table, la base de données stocke une valeur distincte dans chaque colonne. Les bases de données relationnelles sont conçues pour stocker des données complexes, chaque élément étant associé ou relié à des éléments d'un autre type. Dans une base de données relationnelle, toute donnée présentant une relation « un à plusieurs » (où un seul enregistrement peut être relié à plusieurs enregistrements de types différents) doit être répartie parmi les différentes tables. Par exemple, si vous souhaitez stocker plusieurs numéros de téléphone pour chaque ami dans votre application de carnet d'adresses, il s'agit d'une relation « un à plusieurs ». La table « amis » contiendrait alors toutes les informations personnelles de chaque ami. Une table distincte « numéros de téléphone » contiendrait tous les numéros de téléphone de tous les amis. Outre le stockage des données de vos amis et de leurs numéros de téléphone, chaque table a besoin d'un élément de données qui lui permette de relier les deux tables (pour mettre en correspondance les enregistrements individuels des amis et leurs numéros de téléphone). Ces données sont appelées clé primaire (identifiant unique qui différencie chaque ligne de la table des autres lignes de cette même table). La clé primaire peut être une « clé naturelle », c'est-à-dire un élément de données qui différencie naturellement chaque enregistrement d'une table. Dans le cas de la table « amis », si vous savez qu'aucun de vos amis n'a la même date de naissance, vous pouvez utiliser la colonne date de naissance comme clé primaire (clé naturelle) de cette table. S'il n'existe pas de clé naturelle, vous pouvez créer une colonne de clé primaire distincte telle que « ID ami » (valeur artificielle utilisée par l'application pour différencier les lignes). L'utilisation d'une clé primaire permet de définir les relations existant entre plusieurs tables. Supposons par exemple que la colonne « ID ami » de la table « amis » contienne un numéro unique pour chaque ligne (chaque ami). La table reliée « numéros de téléphone » peut être structurée sur deux colonnes : l'une contenant l'identifiant de l'ami à qui le numéro de téléphone appartient, l'autre contenant le numéro de téléphone lui-même. Ainsi, quel que soit le nombre de numéros de téléphone d'un ami, tous peuvent être stockés dans la table « numéros de téléphone » et reliés à l'ami associé via la clé primaire « ID ami ». Lorsque la clé primaire d'une table est utilisée dans une table reliée pour spécifier la connexion entre les enregistrements, la valeur de la table reliée est appelée clé étrangère. Contrairement à de nombreuses bases de données, le moteur de base de données locale de l'application AIR ne vous permet pas de créer des contraintes de clé étrangère. Ces contraintes vérifient automatiquement qu'une valeur de clé étrangère mise à jour ou insérée correspond à une ligne de la table de clés primaires. Les relations entre les clés étrangères sont toutefois un élément important de la structure d'une base de données relationnelle, et les clés étrangères doivent être utilisées lors de la création de relations entre les tables de votre base de données. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 170 Utilisation des bases de données SQL locales A propos de SQL Le langage SQL (Structured Query Language) est utilisé avec les bases de données relationnelles pour manipuler et récupérer les données. SQL est davantage un langage descriptif qu'un langage procédural. Au lieu de donner à l'ordinateur des instructions sur la façon dont les données doivent être récupérées, une instruction SQL décrit le jeu de données désiré. Le moteur de base de données détermine lui comment récupérer ces données. Le langage SQL a été normalisé par l'institut ANSI (American National Standards Institute). La base de données SQL locale d'Adobe AIR prend en charge la plupart des standards SQL-92. Pour une description spécifique du langage SQL pris en charge dans Adobe AIR, consultez l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. A propos des classes de base de données SQL Pour travailler avec des bases de données SQL locales dans ActionScript 3.0, vous utilisez les occurrences des classes suivantes du package flash.data : Classe Description flash.data.SQLConnection Permet de créer et d'ouvrir des bases de données (fichiers de base de données), de même que des méthodes pour effectuer des opérations au niveau des bases de données et pour contrôler leurs transactions. flash.data.SQLStatement Représente une seule instruction SQL (une unique requête ou commande) exécutée sur une base de données, avec la définition du texte de l'instruction et les valeurs des paramètres. flash.data.SQLResult Permet de récupérer des informations ou les résultats provenant de l'exécution d'une instruction, par exemple le résultat des lignes provenant d'une instruction SELECT, le nombre de lignes affectées par une instruction UPDATE ou DELETE, etc. Pour obtenir les informations du schéma décrivant la structure d'une base de données, utilisez les classes suivantes du package flash.data : Classe flash.data.SQLSchemaResult Description Sert de conteneur aux résultats du schéma de la base de données générés par un appel à la méthode SQLConnection.loadSchema(). flash.data.SQLTableSchema Fournit des informations décrivant une table spécifique dans une base de données. flash.data.SQLViewSchema Fournit des informations décrivant une vue spécifique dans une base de données. flash.data.SQLIndexSchema Fournit des informations décrivant une colonne spécifique dans une table ou une vue d'une base de données. flash.data.SQLTriggerSchem a Fournit des informations décrivant un déclencheur spécifique dans une base de données. Les autres classes du package flash.data fournissent des constantes utilisées avec les classes SQLConnection et SQLColumnSchema : Classe Description flash.data.SQLMode Définit un ensemble de constantes représentant les valeurs possibles du paramètre openMode des méthodes SQLConnection.open() et SQLConnection.openAsync(). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 171 Utilisation des bases de données SQL locales Classe Description flash.data.SQLColumnNameStyle Définit un ensemble de constantes représentant les valeurs possibles de la propriété SQLConnection.columnNameStyle. flash.data.SQLTransactionLockType Définit un ensemble de constantes représentant les valeurs possibles du paramètre option de la méthode SQLConnection.begin(). flash.data.SQLCollationType Défini un ensemble de constantes représentants les valeurs possibles de la propriété SQLColumnSchema.defaultCollationType et du paramètre defaultCollationType du constructeur SQLColumnSchema(). De plus, les classes suivantes du package flash.events représentent les événements (et les constantes prises en charge) que vous utilisez : Classe Description flash.data.SQLEvent Définit les événements distribués par une occurrence de SQLConnection ou SQLStatement lorsque l'une de ses opérations s'exécute avec succès. Chaque opération est associée à une constante de type d'événement définie dans la classe SQLEvent. flash.data.SQLErrorEvent Définit l'événement distribué par une occurrence de SQLConnection ou SQLStatement lorsque l'une de ses opérations provoque une erreur. flash.data.SQLUpdateEvent Définit l'événement distribué par une occurrence de SQLConnection lorsque les données d'une table de l'une de ses bases de données connectées changent du fait de l'exécution d'une instruction SQL INSERT, UPDATE ou DELETE. Enfin, les classes suivantes du package flash.errors fournissent des informations sur les erreurs des opérations de base de données : Classe Description flash.data.SQLError Fournit des informations sur une erreur d'opération de base de données, y compris l'opération tentée et la cause de son échec. flash.data.SQLErrorEvent Définit un ensemble de constantes représentant les valeurs possibles de la propriété operation de la classe SQLError, indiquant l'opération de base de données ayant provoqué une erreur. A propos des modes d'exécution synchrone et asynchrone Lorsque vous écrivez du code pour travailler avec une base de données SQL locale, vous spécifiez que les opérations de cette base de données doivent s'exécuter dans l'un des deux modes d'exécution suivants : asynchrone ou synchrone. En général, les exemples de code montrent comment effectuer chaque opération des deux manières. Vous pouvez donc utiliser l'exemple répondant le mieux à vos besoins. En mode d'exécution asynchrone, vous envoyez une instruction à l'environnement d'exécution et ce dernier distribue un événement lorsque l'opération demandée se termine ou échoue. Vous commencez par indiquer au moteur de base de données d'effectuer une opération. Celui-ci travaille en arrière-plan pendant que l'application poursuit son exécution. Enfin, lorsque l'opération est terminée (ou lorsqu'elle échoue), le moteur de base de données distribue un événement. Votre code, déclenché par l'événement, effectue les opérations consécutives. Cette approche présente un avantage important : l'environnement d'exécution effectue les opérations de base de données en arrière-plan pendant que le code de l'application principale poursuit son exécution. Si l'opération de base de données prend un certain temps, l'exécution de l'application n'est pas interrompue. Plus important encore, l'utilisateur peut continuer à interagir avec elle sans que l'écran ne se fige. Toutefois, la rédaction du code d'opérations asynchrones peut se révéler plus complexe que la rédaction d'autres codes. Cette complexité survient généralement lorsque plusieurs opérations dépendantes doivent être réparties entre diverses méthodes d'écouteur d'événement. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 172 Utilisation des bases de données SQL locales De façon conceptuelle, il est plus simple de coder les opérations sous forme d'une seule séquence d'étapes (ensemble d'opérations synchrones) plutôt que sous forme d'un ensemble d'opérations divisées en plusieurs méthodes d'écouteur d'événement. Outre les opérations de base de données asynchrones, Adobe AIR vous permet également d'exécuter des opérations de base de données de façon synchrone. Dans ce mode, les opérations ne s'exécutent pas en arrière-plan mais dans la même séquence d'exécution que le reste du code de l'application. Vous indiquez au moteur de base de données d'effectuer une opération. Le code s'interrompt alors à ce stade pendant que le moteur de base de données effectue son travail. Lorsque l'opération est terminée, l'exécution se poursuit avec la ligne suivante de votre code. L'exécution asynchrone ou synchrone des opérations est définie au niveau de l'occurrence de SQLConnection. L'utilisation d'une seule connexion de base de données ne permet pas d'exécuter certaines opérations ou instructions de façon synchrone et d'autres de façon asynchrone. Pour indiquer si une occurrence de SQLConnection fonctionne en mode d'exécution synchrone ou asynchrone, appelez une méthode SQLConnection pour ouvrir la base de données. Si vous appelez SQLConnection.open(), la connexion opère en mode d'exécution synchrone, et si vous appelez SQLConnection.openAsync(), le mode d'exécution asynchrone est utilisé. Lorsqu'une occurrence de SQLConnection est connectée à une base de données à l'aide de open() ou openAsync(), elle est figée en mode d'exécution synchrone ou asynchrone, sauf si vous fermez et rouvrez la connexion à la base de données. Chaque mode d'exécution a ses propres avantages. Bien que similaires dans la plupart de leurs aspects, chaque mode présente des différences que vous devez connaître pour les exploiter correctement. Pour plus d'informations et pour obtenir des suggestions quant au choix de chaque mode, consultez la section « Utilisation des opérations de base de données synchrones et asynchrones » à la page 193. Création et modification d'une base de données Pour que votre application puisse ajouter ou récupérer des données, elle doit pouvoir accéder à une base de données avec des tables définies. Cette section décrit la création d'une base de données et de la structure de ses données. Bien que moins fréquemment utilisées que l'insertion et la récupération de données, ces tâches sont nécessaires pour la plupart des applications. Création d'une base de données Pour créer un fichier de base de données, vous devez d'abord créer une occurrence de SQLConnection. Vous appelez sa méthode open() pour l'ouvrir en mode d'exécution synchrone, ou sa méthode openAsync() pour l'ouvrir en mode d'exécution asynchrone. Les méthodes open() et openAsync() sont utilisées pour ouvrir une connexion à une base de données. Si vous transmettez une occurrence de File faisant référence à un emplacement de fichier non existant pour le paramètre reference (premier paramètre), la méthode open() ou openAsync() crée un fichier de base de données à cet emplacement et ouvre une connexion à la nouvelle base de données. Quelle que soit la méthode appelée pour créer une base de données, open() ou openAsync(), le nom du fichier de la base de données peut être tout nom de fichier valide, avec n'importe quelle extension. Si vous appelez la méthode open() ou openAsync() en définissant null pour le paramètre reference, une nouvelle base de données en mémoire est créée et non un fichier de base de données sur disque. Le code suivant montre le processus de création d'un fichier de base de données (nouvelle base de données) en mode d'exécution asynchrone. Dans ce cas, le fichier de base de données est enregistré dans le répertoire de stockage de l'application, sous le nom « DBSample.db » : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 173 Utilisation des bases de données SQL locales 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); } Pour exécuter des opérations en mode synchrone, lorsque vous ouvrez une connexion à la base de données avec l'occurrence de SQLConnection, appelez la méthode open(). L'exemple suivant montre comment créer et ouvrir une occurrence de SQLConnection qui exécute ses opérations de façon synchrone : 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); } Création de tables de base de données La création d'une table dans une base de données implique l'exécution d'une instruction SQL sur cette base de données, selon la même procédure utilisée pour exécuter une instruction SQL telle que SELECT, INSERT, etc. Pour créer une table, vous utilisez une instruction CREATE TABLE, qui inclut les définitions des colonnes et les contraintes de la nouvelle table. Pour plus d'informations sur l'exécution d'instructions SQL, consultez la section « Utilisation des instructions SQL » à la page 176. L'exemple suivant montre la création d'une table nommée « employees » dans un fichier de base de données existant, en mode d'exécution asynchrone. Remarquez que ce code présuppose l'existence d'une occurrence de SQLConnection nommée conn, déjà instanciée et connectée à une base de données. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 174 Utilisation des bases de données SQL locales 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'exemple suivant montre la création d'une table nommée « employees » dans un fichier de base de données existant, en mode d'exécution synchrone. Remarquez que ce code présuppose l'existence d'une occurrence de SQLConnection nommée conn, déjà instanciée et connectée à une base de données. 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); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 175 Utilisation des bases de données SQL locales Manipulation des données de bases de données SQL Lorsque vous utilisez des bases de données SQL locales, vous effectuez certaines tâches courantes. Ces tâches incluent la connexion à une base de données et l'ajout et la récupération de données dans ses tables. Vous devez également être conscient(e) de différents problèmes lorsque vous effectuez ces tâches, par exemple l'utilisation des types de données et la gestion des erreurs. Notez également que plusieurs tâches de base de données sont effectuées moins fréquemment mais doivent souvent l'être avant de vous attaquer à ces tâches plus courantes. Par exemple, pour pouvoir vous connecter à une base de données et récupérer des données dans l'une de ses tables, vous devez créer la base de données et la structure de ses tables. Ces tâches de configuration initiales moins fréquentes sont traitées à la section « Création et modification d'une base de données » à la page 172. Vous pouvez choisir d'effectuer des opérations de base de données de façon asynchrone, ce qui signifie que le moteur de base de données s'exécute en arrière-plan et vous avertit en distribuant un événement lorsque l'opération réussit ou échoue. Vous pouvez également effectuer ces opérations de façon synchrone. Dans ce cas, les opérations de base de données sont exécutées l'une après l'autre et l'ensemble de l'application (y compris l'actualisation de l'écran) attend la fin des opérations avant d'exécuter le reste du code. Les exemples de cette section montrent comment effectuer les opérations de façon asynchrone et synchrone. Pour plus d'informations sur l'utilisation des modes d'exécution asynchrone ou synchrone, consultez la section « Utilisation des opérations de base de données synchrones et asynchrones » à la page 193. Connexion à une base de données Avant d'effectuer toute opération sur une base de données, commencez par ouvrir une connexion au fichier de cette base de données. Une occurrence de SQLConnection est utilisée pour représenter une connexion à une ou plusieurs bases de données. La première base de données connectée par une occurrence de SQLConnection est appelée base de données « principale ». Cette base de données est connectée par la méthode open() (en mode d'exécution synchrone) ou par la méthode openAsync() (en mode d'exécution asynchrone). Si vous ouvrez une base de données via l'opération asynchrone openAsync(), enregistrez l'événement open de l'occurrence de SQLConnection pour être averti(e) lorsque l'opération openAsync() se termine. Enregistrez l'événement error de l'occurrence de SQLConnection pour savoir si l'opération a échoué. L'exemple suivant montre comment ouvrir un fichier de base de données existant pour une exécution asynchrone. Le fichier de base de données est nommé « DBSample.db » et se trouve dans le répertoire de stockage de l'application de l'utilisateur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 176 Utilisation des bases de données SQL locales 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); } L'exemple suivant montre comment ouvrir un fichier de base de données existant pour une exécution synchrone. Le fichier de base de données est nommé « DBSample.db » et est situé dans le répertoire de stockage de l'application de l'utilisateur. 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); } Notez que dans l'appel de méthode openAsync() de l'exemple asynchrone et dans l'appel de méthode open() de l'exemple synchrone, le second argument est la constante SQLMode.UPDATE. La définition de SQLMode.UPDATE pour le second paramètre (openMode) oblige l'environnement d'exécution à distribuer une erreur si le fichier spécifié n'existe pas. Si vous transmettez SQLMode.CREATE pour le paramètre openMode (ou si vous laissez le paramètre openMode désactivé), l'environnement d'exécution tente de créer un fichier de base de données lorsque le fichier spécifié n'existe pas. Toutefois, s'il existe, le fichier est ouvert, ce qui revient à utiliser SQLMode.Update. Vous pouvez également spécifier SQLMode.READ pour le paramètre openMode afin d'ouvrir une base de données existante en lecture seule. Dans ce cas, les données peuvent être récupérées dans la base de données, mais ne peuvent pas être ajoutées, supprimées ou modifiées. Utilisation des instructions SQL Les instructions SQL individuelles (requêtes ou commandes) sont représentées dans l'environnement d'exécution par des objets SQLStatement. Pour créer et exécuter une instruction SQL, procédez comme suit : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 177 Utilisation des bases de données SQL locales Créez une occurrence de SQLStatement. L'objet SQLStatement représente l'instruction SQL dans votre application. var selectData:SQLStatement = new SQLStatement(); Spécifiez sur quelle base de données la requête doit s'exécuter. Pour ce faire, définissez la propriété sqlConnection de l'objet SQLStatement sur l'occurrence de SQLConnection connectée à la base de données désirée. // A SQLConnection named "conn" has been created previously selectData.sqlConnection = conn; Définissez la véritable instruction SQL. Créez le texte de l'instruction sous forme d'occurrence de String et affectez-la à la propriété text de l'occurrence de SQLStatement. selectData.text = "SELECT col1, col2 FROM my_table WHERE col1 = :param1"; Définissez les fonctions gérant le résultat de l'exécution (mode d'exécution asynchrone uniquement). Utilisez la méthode addEventListener() pour enregistrer les fonctions en tant qu'écouteurs des événements result et error de l'occurrence de 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 } Vous pouvez également spécifier des méthodes d'écouteur d'événement à l'aide d'un objet Responder. Dans ce cas, créez l'occurrence de Responder et associez-la aux méthodes d'écouteur d'événement. // 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 } Si le texte de l'instruction comprend des définitions de paramètres, donnez les valeurs de ces paramètres. Pour affecter les valeurs des paramètres, utilisez la propriété de tableau associatif parameters de l'occurrence de SQLStatement. selectData.parameters[":param1"] = 25; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 178 Utilisation des bases de données SQL locales Exécutez l'instruction SQL. Appelez la méthode execute() de l'occurrence de SQLStatement. // using synchronous execution mode // or listener methods in asynchronous execution mode selectData.execute(); En outre, si vous utilisez une occurrence de Responder à la place des écouteurs d'événement en mode d'exécution asynchrone, transmettez cette occurrence à la méthode execute(). // using a Responder in asynchronous execution mode selectData.execute(-1, selectResponder); Vous trouverez des exemples spécifiques de ces procédures aux rubriques suivantes : « Récupération de données dans une base de données » à la page 180 « Insertion de données » à la page 186 « Modification ou suppression de données » à la page 188 Utilisation de paramètres dans des instructions L'ajout d'un paramètre dans une instruction SQL permet de créer une instruction SQL réutilisable. Lorsque vous ajoutez des paramètres à une instruction, les valeurs de celle-ci peuvent changer (par exemple des valeurs ajoutées dans une instruction INSERT), alors que le texte de base de l'instruction ne change pas. Cela constitue donc un avantage en termes de performances et simplifie le codage des applications. Présentation des paramètres d'instruction Il est fréquent qu'une application utilise plusieurs fois une même instruction SQL, avec de légères variations. Prenons par exemple le cas d'une application de suivi de stock qui permet à l'utilisateur d'ajouter de nouveaux articles dans la base de données. Le code de l'application qui ajoute un article de stock dans la base de données exécute une instruction SQL INSERT qui ajoute véritablement les données dans la base de données. Toutefois, chaque exécution de l'instruction présente une légère variation. En particulier, les véritables valeurs insérées dans la table diffèrent puisqu'elles sont spécifiques à l'article ajouté au stock. Lorsqu'une instruction SQL est utilisée plusieurs fois avec des valeurs différentes dans l'instruction, la meilleure approche consiste à utiliser une instruction SQL incluant des paramètres plutôt que des valeurs littérales dans le texte SQL. Un paramètre est un espace réservé dans le texte de l'instruction qui est remplacé par une valeur réelle à chaque exécution de l'instruction. Pour utiliser des paramètres dans une instruction SQL, vous créez comme d'habitude une occurrence de SQLStatement. Dans le cas de la véritable instruction SQL affectée à la propriété text, utilisez des espaces réservés aux paramètres plutôt que des valeurs littérales. Définissez ensuite la valeur de chaque paramètre en définissant la valeur d'un élément dans la propriété parameters de l'occurrence de SQLStatement. La propriété parameters étant un tableau associatif, définissez une valeur particulière à l'aide de la syntaxe suivante : statement.parameters[parameter_identifier] = value; parameter_identifier est une chaîne si vous utilisez un paramètre nommé ou un index de nombres entiers si vous utilisez un paramètre non nommé. Utilisation de paramètres nommés Un paramètre peut être un paramètre nommé. Un paramètre nommé a un nom spécifique que la base de données utilise pour mettre en correspondance sa valeur avec l'emplacement de l'espace réservé dans le texte de l'instruction. Un nom de paramètre se compose du caractère « : » ou « @ » suivi d'un nom, comme dans les exemples suivants : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 179 Utilisation des bases de données SQL locales :itemName @firstName Le code suivant décrit l'utilisation des paramètres nommés : 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(); Utilisation de paramètres non nommés En alternative à l'utilisation de paramètres nommés, vous pouvez utiliser des paramètres non nommés. Pour utiliser un paramètre non nommé, vous désignez un paramètre dans une instruction SQL en utilisant un caractère « ? » . Un index numérique est affecté à chaque paramètre, par ordre d'apparition des paramètres dans l'instruction, en commençant par l'index 0 pour le premier paramètre. L'exemple suivant est une version différente de l'exemple précédent, à l'aide de paramètres non nommés : 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(); Avantages de l'utilisation de paramètres L'utilisation de paramètres dans une instruction SQL présente plusieurs avantages : Performances optimisées L'exécution d'une occurrence de SQLStatement avec paramètres est plus efficace que celle d'une occurrence qui crée dynamiquement le texte SQL à chaque exécution. L'amélioration des performances est due au fait que l'instruction n'est préparée qu'une seule fois mais peut ensuite être exécutée à plusieurs reprises avec des valeurs différentes de paramètres, sans qu'il soit nécessaire de recompiler l'instruction SQL. Typage explicite des données Les paramètres autorisent la substitution avec type de valeurs inconnues au moment de la construction de l'instruction SQL. L'utilisation des paramètres est le seul moyen de garantir la classe de stockage d'une valeur transmise à la base de données. Lorsque les paramètres ne sont pas utilisés, l'environnement d'exécution tente de convertir toutes les valeurs de leur représentation texte en une classe de stockage en fonction de l'affinité du type de la colonne associée. Pour plus d'informations sur les classes de stockage et l'affinité des colonnes, consultez la section Prise en charge des types de données de l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. Sécurité renforcée Les paramètres sont également utilisés comme mesure de sécurité pour prévenir toute technique malveillante appelée attaque par injection de code SQL. Dans une attaque par injection de code SQL, l'utilisateur entre du code SQL dans un emplacement accessible (par exemple dans un champ de saisie). Si le code de l'application construit une instruction SQL en concaténant directement la saisie de l'utilisateur dans le texte SQL, le code SQL saisi DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 180 Utilisation des bases de données SQL locales par l'utilisateur est exécuté sur la base de données. L'exemple suivant illustre la concaténation de la saisie de l'utilisateur dans le texte SQL. N'utilisez pas cette technique : // 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; Le fait d'utiliser des paramètres d'instruction plutôt que la concaténation de valeurs saisies par utilisateur dans le texte d'une instruction permet d'éviter les attaques par injection de code SQL. L'attaque par injection de code SQL ne peut se produire car les valeurs des paramètres sont traitées explicitement sous forme de valeurs substituées au lieu de devenir une partie du texte de l'instruction littérale. L'exemple suivant est l'alternative recommandée : // 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; Récupération de données dans une base de données La récupération de données dans une base de données comprend deux étapes. Vous exécutez d'abord une instruction SQL SELECT, en décrivant le jeu de données désiré de la base de données. Vous accédez ensuite aux données récupérées et vous les affichez ou les manipulez selon les besoins de votre application. Exécution d'une instruction SELECT Pour récupérer des données existantes dans une base de données, utilisez une occurrence de SQLStatement. Affectez l'instruction SQL SELECT appropriée à la propriété text de l'occurrence, puis appelez sa méthode execute(). Pour plus d'informations sur la syntaxe de l'instruction SELECT, consultez l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. L'exemple suivant décrit l'exécution d'une instruction SELECT pour récupérer des données dans une table nommée « products », en mode d'exécution asynchrone : 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(); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 181 Utilisation des bases de données SQL locales L'exemple suivant décrit l'exécution d'une instruction SELECT pour récupérer des données dans une table nommée « products », en mode d'exécution asynchrone : 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 } En mode d'exécution asynchrone, lorsque l'instruction se termine, l'occurrence de SQLStatement déclenche un événement result (SQLEvent.RESULT) indiquant que l'instruction s'est exécutée avec succès. Alternativement, si un objet Responder est transmis en tant qu'argument dans l'appel à execute(), la fonction du gestionnaire de résultats de l'objet Responder est appelée. En mode d'exécution synchrone, l'exécution s'interrompt jusqu'à la fin de l'opération execute(), puis passe à la ligne de code suivante. Accès aux données du résultat de l'instruction SELECT Lorsque l'exécution de l'instruction SELECT est terminée, l'étape suivante consiste à accéder aux données récupérées. Chaque ligne de données du jeu de résultats SELECT devient une occurrence d'Object. Cet objet a les propriétés dont les noms correspondent aux noms des colonnes du jeu de résultats. Les propriétés contiennent les valeurs provenant des colonnes du jeu de résultats. Par exemple, supposons qu'une instruction SELECT spécifie un jeu de résultats avec trois colonnes nommées « itemId », « itemName » et « price ». Pour chaque ligne du jeu de résultats, une occurrence d'Object est créée avec les propriétés nommées itemId, itemName et price. Ces propriétés contiennent les valeurs de leurs colonnes respectives. Le code suivant s'exécute après le code précédent pour récupérer des données en mode d'exécution asynchrone. Il montre comment accéder aux données récupérées dans la méthode de l'écouteur d'événement du résultat. 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. } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 182 Utilisation des bases de données SQL locales Le code suivant étend le code précédent pour récupérer des données en mode exécution synchrone. Il développe le bloc try..catch de l'exemple d'exécution synchrone précédent, en montrant comment accéder aux données récupérées. 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. } Comme le montre le code précédent, les objets du résultat sont contenus dans un tableau disponible en tant que propriété data d'une occurrence de SQLResult. Si vous utilisez une exécution asynchrone avec un écouteur d'événement, pour récupérer cette occurrence de SQLResult, appelez la méthode getResult() de l'occurrence de SQLStatement. Si vous spécifiez un argument Responder dans l'appel à execute(), l'occurrence de SQLResult est transmise à la fonction du gestionnaire de résultats en tant qu'argument. En mode d'exécution synchrone, vous appelez la méthode getResult() de l'occurrence de SQLStatement après chaque appel à la méthode execute(). Dans tous les cas, dès que vous obtenez l'objet SQLResult, vous pouvez accéder aux lignes du résultat à l'aide de la propriété du tableau data. Le code suivant définit une occurrence de SQLStatement dont le texte est une instruction SELECT. L'instruction récupère les lignes contenant les valeurs des colonnes firstName et lastName de toutes les lignes d'une table nommée employees. Cet exemple utilise le mode d'exécution asynchrone. Lorsque l'exécution est terminée, la méthode selectResult() est appelée, et vous accédez aux lignes de données résultantes à l'aide de la méthode SQLStatement.getResult() et vous les affichez à l'aide de la méthode trace(). Notez que ce code présuppose l'existence d'une occurrence de SQLConnection nommée conn, déjà instanciée et connectée à la base de données. Il suppose également que la table « employees » a déjà été créée et contient des données. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 183 Utilisation des bases de données SQL locales 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); } Le code suivant décrit les mêmes techniques que le précédent, mais avec le mode d'exécution synchrone. L'exemple définit une occurrence de SQLStatement dont le texte est une instruction SELECT. L'instruction récupère les lignes contenant les valeurs des colonnes firstName et lastName de toutes les lignes d'une table nommée employees. Vous accédez aux lignes de données résultantes à l'aide de la méthode SQLStatement.getResult() et vous les affichez à l'aide de la méthode trace(). Notez que ce code présuppose l'existence d'une occurrence de SQLConnection nommée conn, déjà instanciée et connectée à la base de données. Il suppose également que la table « employees » a déjà été créée et contient des données. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 184 Utilisation des bases de données SQL locales 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); } Définition du type des données du résultat de l'instruction SELECT Par défaut, chaque ligne renvoyée par une instruction SELECT est créée en tant qu'occurrence d'Object avec des propriétés nommées pour les noms de colonnes du jeu de résultats et la valeur de chaque colonne en tant que valeur de sa propriété associée. Toutefois, avant d'exécuter une instruction SQL SELECT, vous pouvez définir la propriété itemClass de l'occurrence de SQLStatement sur une classe. En définissant la propriété itemClass, chaque ligne renvoyée par l'instruction SELECT est créée sous la forme d'une occurrence de la classe désignée. L'environnement d'exécution affecte les valeurs des propriétés aux valeurs des colonnes de résultats en mettant en correspondance les noms de colonnes du jeu de résultats SELECT et les noms des propriétés de la classe itemClass. Toute classe affectée en tant que propriété itemClass doit avoir un constructeur qui ne requiert aucun paramètre. En outre, la classe doit avoir une seule propriété pour chaque colonne renvoyée par l'instruction SELECT. Le fait qu'une colonne de la liste SELECT ne présente pas de nom de propriété correspondant dans la classe itemClass est considéré comme une erreur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 185 Utilisation des bases de données SQL locales Récupération partielle des résultats d'une instruction SELECT Par défaut, l'exécution d'une instruction SELECT récupère simultanément toutes les lignes du jeu de résultats. Une fois l'instruction terminée, vous traitez généralement les données récupérées d'une manière ou d'une autre, par exemple en créant des objets ou en affichant les données à l'écran. Si l'instruction renvoie un très grand nombre de lignes, le traitement simultané de toutes les données peut se révéler très exigeant pour l'ordinateur, qui à son tour peut ne pas redessiner l'interface pour l'utilisateur. Pour améliorer les performances de votre application, vous pouvez demander à l'environnement d'exécution de ne renvoyer simultanément qu'un nombre spécifique de lignes de résultats. Les données de résultats initiales sont ainsi renvoyées plus rapidement. Vous pouvez également diviser les lignes du résultat en jeux, de sorte que l'interface utilisateur soit mise à jour après le traitement de chaque jeu de lignes. Notez que cette technique n'est pratique qu'en mode d'exécution asynchrone. Pour récupérer les résultats partiels de SELECT, donnez une valeur au premier paramètre de la méthode SQLStatement.execute() (paramètre prefetch). Le paramètre prefetch indique le nombre de lignes à récupérer à la première exécution de l'instruction. Lorsque vous appelez la méthode execute() d'une occurrence de SQLStatement, spécifiez une valeur pour le paramètre prefetch afin que seul ce nombre de lignes soit récupéré : 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'instruction déclenche l'événement result, indiquant que le premier jeu de lignes de résultat est disponible. La propriété data de l'occurrence de SQLResult résultante contient les lignes de données, et sa propriété complete indique s'il reste des lignes de résultat supplémentaires à récupérer. Pour récupérer ces lignes supplémentaires, appelez la méthode next() de l'occurrence de SQLStatement. Comme la méthode execute(), le premier paramètre de la méthode next() sert à indiquer le nombre de lignes à récupérer lors du prochain déclenchement de l'événement de résultat. 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'occurrence de SQLStatement déclenche un événement result chaque fois que la méthode next() renvoie un jeu suivant de lignes de résultat. Par conséquent, la même fonction d'écouteur peut être utilisée pour continuer à traiter les résultats (par des appels à next()) jusqu'à ce que toutes les lignes aient été récupérées. Pour plus d'informations, consultez les descriptions de la référence du langage des méthodes SQLStatement.execute() (description du paramètre prefetch) et SQLStatement.next(). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 186 Utilisation des bases de données SQL locales Insertion de données La récupération de données dans une base de données implique l'exécution d'une instruction SQL INSERT. Lorsque l'exécution de l'instruction est terminée, vous pouvez accéder à la clé primaire de la ligne nouvellement insérée si la base de données en a généré une. Exécution d'une instruction INSERT Pour ajouter des données dans une table de base de données, créez et exécutez une occurrence de SQLStatement dont le texte est une instruction SQL INSERT. L'exemple suivant utilise une occurrence de SQLStatement pour ajouter une ligne de données dans la table des employés déjà existante. Cet exemple décrit l'insertion de données en mode d'exécution asynchrone. Notez que ce code présuppose l'existence d'une occurrence de SQLConnection nommée conn, déjà instanciée et connectée à une base de données. Il suppose également que la table « employees » a déjà été créée. 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'exemple suivant ajoute une ligne de données à la table des employés existante, en mode d'exécution synchrone. Notez que ce code présuppose l'existence d'une occurrence de SQLConnection nommée conn, déjà instanciée et connectée à une base de données. Il suppose également que la table « employees » a déjà été créée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 187 Utilisation des bases de données SQL locales 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); } Récupération de la clé primaire d'une ligne insérée, générée par la base de données Après l'insertion d'une ligne de données dans une table, il arrive souvent que le code doive connaître la clé primaire générée par la base de données ou une valeur d'identificateur de ligne pour la ligne nouvellement insérée. Par exemple, après avoir inséré une ligne dans une table, vous pouvez en ajouter d'autres dans une table associée. Dans ce cas, vous pouvez insérer la valeur de la clé primaire en tant que clé étrangère de la table associée. La clé primaire d'une ligne nouvellement insérée peut être récupérée avec l'objet SQLResult généré par l'exécution de l'instruction. Il s'agit du même objet qui est utilisé pour accéder aux données du résultat après l'exécution d'une instruction SELECT. Comme pour toute instruction SQL, lorsque l'exécution d'une instruction INSERT se termine, l'environnement d'exécution crée une occurrence de SQLResult. Pour accéder à l'occurrence de SQLResult, vous appelez la méthode getResult() de l'objet SQLStatement si vous utilisez un écouteur d'événement ou le mode d'exécution synchrone. De même, si vous utilisez le mode d'exécution asynchrone et que vous transmettez une occurrence de Responder à l'appel de la méthode execute(), l'occurrence de SQLResult est transmise en tant qu'argument à la fonction du gestionnaire de résultat. Dans tous les cas, l'occurrence de SQLResult a une propriété, lastInsertRowID, qui contient l'identificateur de la dernière ligne insérée si l'instruction SQL exécutée est une instruction INSERT. L'exemple suivant montre comment accéder à la clé primaire d'une ligne insérée en mode d'exécution asynchrone : 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'exemple suivant montre comment accéder à la clé primaire d'une ligne insérée en mode d'exécution synchrone : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 188 Utilisation des bases de données SQL locales 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 } Notez que l'identificateur de ligne peut ou non correspondre à la valeur de la colonne désignée en tant colonne de clé primaire dans la définition de la table, en fonction de la règle suivante : • Si la table est définie avec une colonne de clé primaire dont l'affinité (son type de données) est INTEGER, la propriété lastInsertRowID contient la valeur insérée dans cette ligne (ou celle générée par l'environnement d'exécution s'il s'agit d'une colonne AUTOINCREMENT). • Si la table est définie avec plusieurs colonnes de clés primaires (clé composite) ou avec une seule colonne de clés primaires dont l'affinité n'est pas INTEGER, la base de données génère une valeur d'identificateur de ligne en arrièreplan. La valeur générée est celle de la propriété lastInsertRowID. • La valeur est toujours l'identificateur de la dernière ligne insérée. Si une instruction INSERT provoque un déclencheur qui à son tour insère une ligne, la propriété lastInsertRowID contient l'identificateur de la dernière ligne insérée par le déclencheur et non la ligne créée par l'instruction INSERT. Par conséquent, pour obtenir une colonne de clé primaire définie de façon explicite dont la valeur est disponible après une commande INSERT via la propriété SQLResult.lastInsertRowID, définissez la colonne en tant que colonne INTEGER PRIMARY KEY. Notez toutefois que, même si votre table ne comprend pas de colonne INTEGER PRIMARY KEY explicite, il est tout aussi possible d'utiliser l'identificateur de ligne généré par la base de données comme clé primaire de votre table, comme définissant les relations avec les tables associées. La valeur de colonne de l'identificateur de ligne est disponible dans toute instruction SQL via l'utilisation des noms de colonne spéciaux ROWID, _ROWID_ ou OID. Vous pouvez créer une colonne de clé étrangère dans une table associée et utiliser la valeur de l'identificateur de ligne en tant que valeur de colonne de clé étrangère comme vous le feriez dans le cas d'une colonne INTEGER PRIMARY KEY explicitement déclarée. Ainsi, si vous utilisez une clé primaire arbitraire plutôt qu'une clé naturelle, et tant que la génération par l'environnement d'exécution d'une valeur de clé primaire à votre place ne vous dérange pas, l'utilisation d'une colonne INTEGER PRIMARY KEY ou d'un identificateur de ligne généré par le système comme clé primaire de la table ne présente que peu de différence quant à la définition d'une relation de clé étrangère entre les deux tables. Pour plus d'informations sur les clés primaires et les identificateurs de lignes générés, consultez les sections CREATE TABLE et Expressions de l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. Modification ou suppression de données La procédure d'exécution des autres opérations de manipulation des données est identique à la celle utilisée pour exécuter une instruction SQL SELECT ou INSERT. Substituez simplement une instruction SQL différente dans la propriété text de l'occurrence de SQLStatement : • Pour modifier les données existantes d'une table, utilisez une instruction UPDATE. • Pour supprimer une ou plusieurs lignes de données dans une table, utilisez une instruction DELETE. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 189 Utilisation des bases de données SQL locales Pour obtenir la description de ces instructions, consultez l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. Utilisation de plusieurs bases de données Utilisez la méthode SQLConnection.attach() pour ouvrir une connexion à une base de données supplémentaire sur une occurrence de SQLConnection pour laquelle une base de données est déjà ouverte. Nommez la base de données reliée à l'aide du paramètre name dans l'appel de la méthode attach(). Lorsque vous écrivez des instructions pour manipuler cette base de données, vous pouvez alors utiliser ce nom dans un préfixe (sous la forme nom-base de données.nom-table) pour qualifier les noms de table dans vos instructions SQL, indiquant ainsi à l'environnement d'exécution que la table est disponible dans la base de données nommée. Vous pouvez exécuter une même instruction SQL incluant des tables de plusieurs bases de données connectées à la même occurrence de SQLConnection. Si une transaction est créée sur l'occurrence de SQLConnection, cette transaction s'applique à toutes les instructions SQL exécutées à l'aide de cette occurrence de SQLConnection. Cela est vrai quelle que soit la base de données reliée sur laquelle l'instruction s'exécute. Vous pouvez également créer plusieurs occurrences de SQLConnection dans une application, chacune connectée à une ou plusieurs bases de données. Toutefois, si vous utilisez cette technique, n'oubliez pas qu'une transaction de bases de données n'est pas partagée entre les occurrences de SQLConnection. Par conséquent, si vous vous connectez au même fichier de base de données à l'aide de plusieurs occurrences de SQLConnection, ne vous attendez pas à ce que les modifications de données des deux connexions s'appliquent de façon prévue. Par exemple, si deux instructions UPDATE ou DELETE s'exécutent sur la même base de données par l'intermédiaire d'occurrences de SQLConnection différentes et qu'une erreur survient après une opération, les données de la base peuvent être laissées dans un état intermédiaire éventuellement non réversible et affecter l'intégrité de la base de données (donc de l'application). Gestion des erreurs de base de données En général, la gestion des erreurs de base de données est similaire à celle des autres erreurs d'exécution. Il est préférable d'écrire du code préparé aux erreurs susceptibles de survenir, et de répondre aux erreurs plutôt que de laisser ce rôle à l'environnement d'exécution. De façon générale, les erreurs de base de données potentielles se divisent en trois catégories : les erreurs de connexion, les erreurs de syntaxe SQL et les erreurs de contrainte. Erreurs de connexion La plupart des erreurs de base de données sont des erreurs de connexion et peuvent survenir durant n'importe quelle opération. Si certaines stratégies permettent d'éviter les erreurs de connexion, il est rarement simple de récupérer correctement d'une erreur de connexion si la base de données est une partie sensible de votre application. La plupart des erreurs de connexion sont liés aux interactions entre l'environnement d'exécution et le système d'exploitation, le système de fichiers et le fichier de la base de données. Par exemple, une erreur de connexion se produit si l'utilisateur n'est pas autorisé à créer un fichier de base de données dans un emplacement particulier du système de fichiers. Les stratégies suivantes permettent d'éviter les erreurs de connexion : Utilisation de fichiers de base de données spécifiques aux utilisateurs Au lieu d'utiliser un seul fichier de base de données pour tous les utilisateurs de l'application sur un même ordinateur, donnez à chaque utilisateur son propre fichier de base de données. Ce fichier doit être situé dans un répertoire associé au compte de l'utilisateur. Par exemple, il peut être placé dans le répertoire de stockage de l'application, le dossier Mes documents de l'utilisateur, sur le bureau de celui-ci, etc. Prise en compte des différents types d'utilisateurs Testez votre application avec les différents types de comptes d'utilisateur, sur des systèmes d'exploitation différents. Ne supposez pas que l'utilisateur possède des privilèges DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 190 Utilisation des bases de données SQL locales d'administrateur sur l'ordinateur. De même, ne partez pas du principe que la personne qui a installé l'application est l'utilisateur qui l'exécute. Prise en compte des divers emplacements des fichiers Si vous autorisez l'utilisateur à spécifier l'emplacement d'enregistrement d'un fichier de base de données ou à sélectionner le fichier à ouvrir, tenez compte des emplacements de fichiers auxquels les utilisateurs peuvent accéder. Pensez en outre à limiter les emplacements dans lesquels les utilisateurs peuvent stocker des fichiers de base de données (ou à partir desquels ils peuvent en ouvrir). Par exemple, vous pouvez autoriser uniquement les utilisateurs à ouvrir les fichiers situés dans l'emplacement de stockage de leur compte d'utilisateur. Si une erreur de connexion se produit, elle surviendra probablement lors de la première tentative de création ou d'ouverture de la base de données. Cela signifie que l'utilisateur ne peut effectuer aucune opération de base de données dans l'application. Pour certains types d'erreurs, par exemple les erreurs d'autorisation ou de lecture seule, une technique de récupération possible consiste à copier le fichier de base de données dans un emplacement différent. L'application peut copier les fichiers de bases de données dans un emplacement pour lequel l'utilisateur est autorisé à créer et à écrire dans des fichiers, et utiliser cet emplacement à la place. Erreurs de syntaxe Une erreur de syntaxe se produit lorsque l'application tente d'exécuter une instruction SQL qui n'est pas correctement rédigée. Les instructions SQL de base de données locales étant créées sous forme de chaîne, la vérification de la syntaxe SQL au moment de la compilation n'est pas possible. Toutes les instructions SQL doivent être exécutées pour vérifier leur syntaxe. Pour éviter les erreurs de syntaxe SQL, utilisez les stratégies suivantes : Test approfondi de toutes les instructions SQL Si possible, testez vos instructions SQL séparément lors du développement de votre application avant de les coder sous forme de texte d'instruction dans le code de l'application. De plus, utilisez une approche de test de code telle que le test des unités pour créer un ensemble de tests vérifiant chaque option possible et chaque variation du code. Utilisation des paramètres d'instruction au lieu de la concaténation (création dynamique) de code SQL Le fait d'utiliser des paramètres et d'éviter la construction dynamique d'instruction SQL permet d'utiliser le même texte d'instruction SQL à chaque exécution d'une instruction. En conséquence, le test de vos instructions est plus simple et les variations possibles sont limitées. Si vous devez générer une instruction SQL de façon dynamique, réduisez au strict minimum ses parties dynamiques. De même, validez soigneusement toutes les saisies éventuelles des utilisateurs afin de vous assurer qu'elles n'entraîneront pas d'erreur de syntaxe. Pour récupérer d'une erreur de syntaxe, une application a besoin de code complexe pour pouvoir examiner l'instruction SQL et en corriger la syntaxe. En respectant les stratégies précédentes, votre code peut identifier toute source potentielle d'erreur de syntaxe SQL au moment de l'exécution (par exemple la saisie de l'utilisateur dans une instruction). Pour récupérer d'une erreur de syntaxe, donnez des consignes à l'utilisateur. Indiquez-lui ce qu'il doit faire pour que l'instruction s'exécute correctement. Erreurs de contrainte Les erreurs de contrainte se produisent lorsqu'une instruction INSERT ou UPDATE tente d'ajouter des données dans une colonne. L'erreur survient si les nouvelles données ne respectent pas l'une des contraintes définies pour la table ou la colonne. L'ensemble des contraintes possibles comprend : Contrainte unique Indique que pour toutes les lignes d'une table, il ne peut pas y avoir de valeurs en double dans une colonne. Alternativement, lorsque plusieurs colonnes sont combinées dans une contrainte unique, la combinaison des valeurs de ces colonnes ne doit pas être dupliquée. En d'autres termes, pour la ou les colonnes uniques spécifiées, chaque ligne doit être distincte. Contrainte de clé primaire En termes de données autorisées et interdites par une contrainte, une contrainte de clé primaire est identique à une contrainte unique. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 191 Utilisation des bases de données SQL locales Contrainte non nulle Spécifie qu'une colonne ne peut pas stocker de valeur NULL et, par conséquent, qu'elle doit avoir une valeur pour chaque ligne. Contrainte de vérification Permet de spécifier une contrainte arbitraire pour une ou plusieurs tables. La règle qui définit que la valeur d'une colonne doit être comprise entre certaines limites est une contrainte de vérification courante (par exemple que la valeur d'une colonne numérique doit être supérieure à 0). Un autre type courant de contrainte de vérification spécifie les relations entre les valeurs des colonnes (par exemple que la valeur d'une colonne doit être différente de la valeur d'une autre colonne pour la même ligne). Contrainte de type de données (affinité des colonnes) L'environnement d'exécution impose le type de données des valeurs des colonnes et une erreur se produit en cas de tentative de stockage d'une valeur de type incorrect dans une colonne. Toutefois, les valeurs sont très souvent converties de manière à correspondre au type de données déclaré de la colonne. Pour plus d'informations, consultez la section « Utilisation des types de données des bases de données » à la page 192. L'environnement d'exécution n'impose pas de contrainte sur les valeurs des clés étrangères. En d'autres termes, ces valeurs de clé étrangère ne doivent pas obligatoirement correspondre à une valeur de clé primaire existante. Outre les types de contraintes prédéfinies, le moteur d'exécution SQL prend en charge l'utilisation de déclencheurs. Un déclencheur est semblable à un gestionnaire d'événement. Il s'agit d'un jeu d'instructions prédéfini qui est exécuté lorsqu'une certaine action se produit. Par exemple, un déclencheur peut être défini pour s'exécuter lorsque des données sont insérées ou supprimées dans une table particulière. Une utilisation possible d'un déclencheur consiste à examiner les modifications apportées aux données et à provoquer une erreur lorsque les conditions spécifiées ne sont pas satisfaites. Ainsi, un déclencheur peut avoir le même objectif qu'une contrainte, et les stratégies qui permettent d'éviter les erreurs et de récupérer à partir d'erreurs de contrainte s'appliquent également aux erreurs générées par les déclencheurs. Toutefois, l'identificateur des erreurs générées par les déclencheurs diffère de celui des erreurs de contrainte. L'ensemble des contraintes s'appliquant à une table particulière est déterminé lors de la conception d'une application. La conception soignée des contraintes simplifie la conception de l'application quand au fait d'éviter et de récupérer à partir d'erreurs de contrainte. Les erreurs de contrainte sont toutefois difficiles à prévoir et à éviter systématiquement. Les anticipations sont difficiles car les erreurs de contrainte n'apparaissent pas avant l'ajout de données dans l'application. Des erreurs de contraintes surviennent lorsque des données sont ajoutées dans une base de données après sa création. Ces erreurs sont souvent dues aux relations entre les nouvelles données et les données existantes dans la base de données. Les stratégies suivantes permettent d'éviter de nombreuses erreurs de contrainte : Planification rigoureuse des contraintes et de la structure de la base de données L'objectif des contraintes est d'imposer des règles d'application et de protéger l'intégrité des données de la base de données. Lorsque vous planifiez votre application, prévoyez la structure que doit avoir votre base de données pour prendre en charge cette application. Dans le cadre de ce processus, identifiez les règles devant s'appliquer à vos données, par exemple si certaines valeurs sont obligatoires, si une valeur est définie par défaut, si les valeurs en double sont autorisées, etc. Ces règles vous guident dans la définition des contraintes des bases de données. Définition explicite des noms des colonnes Il est possible d'écrire une instruction INSERT sans spécifier de façon explicite les colonnes dans lesquelles les valeurs doivent être insérées, mais cette technique comporte un risque inutile. En nommant explicitement les colonnes dans lesquelles des valeurs doivent être insérées, vous pouvez autoriser des valeurs générées automatiquement, des colonnes avec des valeurs par défaut et des colonnes autorisant les valeurs NULL. Cela vous permet en outre de vous assurer qu'une valeur explicite est insérée dans toutes les colonnes NOT NULL. Utilisation de valeurs par défaut Chaque fois que vous spécifiez une contrainte NOT NULL pour une colonne, spécifiez autant que possible une valeur par défaut dans la définition de la colonne. Le code de l'application peut également fournir des valeurs par défaut. Par exemple, votre application peut vérifier si une variable String est null et lui affecter une valeur avant de l'utiliser pour définir une valeur de paramètre d'instruction. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 192 Utilisation des bases de données SQL locales Validation des données saisies par l'utilisateur Vérifiez les données saisies par l'utilisateur en amont pour vous assurer qu'elles respectent les contraintes, en particulier dans le cas des contraintes NOT NULL et CHECK. Bien évidemment, une contrainte UNIQUE est plus difficile à vérifier puisqu'elle demanderait l'exécution d'une requête SELECT pour déterminer si les données sont uniques. Utilisation de déclencheurs Vous pouvez écrire un déclencheur qui valide (et éventuellement remplace) les données insérées ou prend d'autres mesures pour corriger les données non valides. Cette validation et cette correction permettent d'éviter les erreurs de contrainte. Les erreurs de contrainte sont dans tous les cas plus difficiles à prévenir que les autres types d'erreurs. Bien heureusement, plusieurs stratégies permettent de récupérer à partir d'erreurs de contrainte sans affecter la stabilité de l'application ni la rendre inutilisable : Utilisation d'algorithmes de conflit Lorsque vous définissez une contrainte sur une colonne et que vous créez une instruction INSERT ou UPDATE, vous avez la possibilité de spécifier un algorithme de conflit. Un algorithme de conflit définit la mesure que la base de données doit prendre en cas de violation d'une contrainte. Le moteur de bases de données peut avoir le choix entre plusieurs actions possibles. Il peut mettre fin à une seule instruction ou à l'ensemble d'une transaction. Il peut ignorer l'erreur. Il peut même supprimer les anciennes données et les remplacer par celles que le code tente de stocker. Pour plus d'informations, consultez la section « ON CONFLICT (algorithmes de conflit) » de l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. Rédaction de commentaires de correction L'ensemble des contraintes susceptibles d'affecter une commande SQL particulière peut être identifié en amont. Vous pouvez par conséquent anticiper les erreurs de contrainte pouvant se produire avec chaque instruction. Ces connaissances vous permettent de développer une logique d'application répondant à une erreur de contrainte. Par exemple, supposons qu'une application comprenne un formulaire de saisie de données pour l'entrée de nouveaux produits. Si la colonne du nom des produits de la base de données est définie avec une contrainte UNIQUE, l'insertion d'une nouvelle ligne de produit dans la base de données peut provoquer une erreur de contrainte. Par conséquent, l'application est conçue pour anticiper une telle erreur. Lorsque l'erreur se produit, l'application avertit l'utilisateur, en lui indiquant que le nom du produit spécifié est déjà utilisé et en l'invitant à choisir un autre nom. Une autre réponse possible consiste à autoriser l'utilisateur à consulter les informations relatives au produit portant le même nom. Utilisation des types de données des bases de données Lorsqu'une table est créée dans une base de données, l'instruction de création définit l'affinité, ou le type de données, pour chaque colonne de cette table. Bien que les déclarations d'affinité puissent être omises, il est préférable de déclarer explicitement l'affinité des colonnes dans vos instructions SQL CREATE TABLE. En règle générale, tout objet stocké dans une base de données par une instruction INSERT est renvoyé sous forme d'occurrence du même type de données lorsque vous exécutez une instruction SELECT. Toutefois, le type de données de la valeur récupérée peut différer selon l'affinité de la colonne de la base de données dans laquelle la valeur est stockée. Lorsqu'une valeur est stockée dans une colonne, si son type de données ne correspond pas à l'affinité de la colonne, la base de données tente de convertir cette valeur en fonction de cette affinité. Par exemple, si une colonne de base de données est déclarée avec une affinité NUMERIC, la base de données tente de convertir les données insérées en classe de stockage numérique (INTEGER ou REAL) avant de stocker les données. Si les données ne peuvent pas être converties, la base de données renvoie une erreur. Selon cette règle, si la chaîne « 12345 » est insérée dans une colonne NUMERIC, la base de données la convertit automatiquement en la valeur entière 12345 avant de la stocker dans la base de données. Lorsqu'elle est récupérée par une instruction SELECT, la valeur est renvoyée sous forme d'occurrence d'un type de données numérique (tel que Number) plutôt que sous la forme d'une occurrence de String. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 193 Utilisation des bases de données SQL locales Le meilleur moyen d'éviter une conversion non désirable du type de données est de respecter deux règles. D'abord, définissez chaque colonne avec l'affinité correspondant au type de données à stocker. Ensuite, insérez uniquement les valeurs dont le type de données correspond à l'affinité définie. Le respect de ces règles présente deux avantages. Les données ne sont pas converties de façon imprévue lors de leur insertion (ce qui peut éventuellement en modifier le sens). De plus, lorsque vous récupérez les données, elles sont renvoyées avec leur type de données d'origine. Pour plus d'informations sur les types d'affinité de colonne disponibles et l'utilisation des types de données dans des instructions SQL, consultez la section « Prise en charge des types de données » de l'annexe « Prise en charge de SQL dans les bases de données locales » du Guide de référence du langage et des composants ActionScript 3.0. Utilisation des opérations de base de données synchrones et asynchrones Les sections précédentes ont décrit les opérations de bases de données courantes, telles que la récupération, l'insertion, la mise à jour et la suppression de données, ainsi que la création d'un fichier de bases de données, de tables et d'autres objets dans une base de données. Les exemples montraient comment effectuer ces opérations de façon asynchrone et synchrone. Nous vous rappelons qu'en mode d'exécution asynchrone, vous demandez au moteur de base de données d'effectuer une opération. Celui-ci travaille ensuite en arrière-plan pendant que l'application poursuit son exécution. Lorsque l'opération est terminée, le moteur de base de données déclenche un événement pour vous le signaler. Le principal avantage de l'exécution asynchrone est que l'environnement d'exécution effectue les opérations de base de données en arrière-plan pendant que l'application principale poursuit son exécution. Cela est d'autant plus précieux lorsque l'exécution de l'opération prend beaucoup de temps. D'un autre côté, les opérations en mode d'exécution synchrone ne s'exécutent pas en arrière-plan. Vous indiquez au moteur de base de données d'effectuer une opération. Le code s'interrompt à ce stade pendant que le moteur de base de données effectue son travail. Lorsque l'opération est terminée, l'exécution se poursuit avec la ligne suivante de votre code. Une seule connexion de base de données ne permet pas d'exécuter certaines opérations ou instructions de façon synchrone et d'autres de façon asynchrone. Vous précisez si une occurrence de SQLConnection s'exécute en mode synchrone ou asynchrone lors de l'ouverture de la connexion à la base de données. Si vous appelez SQLConnection.open(), la connexion opère en mode d'exécution synchrone, et si vous appelez SQLConnection.openAsync(), le mode d'exécution asynchrone est utilisé. Dès qu'une occurrence de SQLConnection est connectée à une base de données par une méthode open() ou openAsync(), elle fonctionne définitivement en mode synchrone ou asynchrone. Utilisation des opérations de base de données synchrones Le code utilisé pour exécuter et répondre aux opérations en mode d'exécution synchrone et celui utilisé en mode exécution asynchrone ne présentent que peu de différences. Les principales différences entre les deux approches sont de deux types. Le premier est l'exécution d'une opération qui dépend d'une autre opération (telles que les lignes de résultat de SELECT ou la clé primaire d'une ligne ajoutée par une instruction INSERT). Le second type de différence est la gestion des erreurs. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 194 Utilisation des bases de données SQL locales Ecriture de code pour les opérations synchrones La principale différence entre une exécution synchrone et asynchrone est qu'en mode synchrone, la rédaction du code prend la forme d'une suite d'étapes. Par contre, dans le code asynchrone, vous enregistrez des écouteurs d'événement et vous répartissez souvent les opérations entre les méthodes des écouteurs. Lorsqu'une base de données est connectée en mode synchrone, vous pouvez exécuter une suite d'opérations de base de données successivement dans un seul bloc de code. L'exemple suivant décrit cette technique : 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(); Comme vous pouvez le constater, vous appelez les mêmes méthodes pour effectuer les opérations de base de données, que vous utilisiez le mode synchrone ou asynchrone. Les principales différences entre les deux approches sont l'exécution d'une opération dépendant d'une autre opération et la gestion des erreurs. Exécution d'une opération dépendant d'une autre opération Lorsque vous êtes en mode synchrone, il n'est pas nécessaire d'écrire du code qui écoute un événement pour déterminer la fin d'une opération. Vous pouvez supposer que, lorsque l'opération d'une ligne de code se termine avec succès, l'exécution passe à la ligne de code suivante. Par conséquent, pour effectuer une opération dépendant du succès d'une autre, écrivez simplement le code dépendant immédiatement après l'opération dont il dépend. Par exemple, pour coder une application de sorte qu'elle commence une transaction, exécute une instruction INSERT, récupère la clé primaire de la ligne insérée, insère cette clé primaire dans une autre ligne d'une autre table et finisse par valider la transaction, l'ensemble du code peut être écrit sous la forme d'une série d'instructions. L'exemple suivant illustre ces opérations : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 195 Utilisation des bases de données SQL locales 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(); Gestion des erreurs en mode synchrone En mode synchrone, vous n'écoutez pas un événement d'erreur pour déterminer si une opération a échoué. A l'inverse, vous renfermez le code susceptible de déclencher des erreurs dans un jeu de blocs try..catch..finally. Vous enveloppez le code rejetant l'erreur dans le bloc try. Vous écrivez les actions à effectuer en réponse à chaque type d'erreur dans des blocs catch distincts. Vous placez le code qui doit toujours s'exécuter, sans tenir compte de la réussite ou de l'échec (par exemple, la fermeture d'une connexion à la base de données devenue inutile) dans un bloc finally. L'exemple suivant démontre l'utilisation des blocs try..catch..finally pour la gestion des erreurs. Il développe l'exemple précédent en ajoutant du code de gestion d'erreur : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 196 Utilisation des bases de données SQL locales 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(); } Présentation du modèle d'exécution asynchrone Un problème courant lié à l'utilisation du mode asynchrone est l'hypothèse que vous ne pouvez pas commencer à exécuter une occurrence de SQLStatement lorsqu'une autre est déjà en cours sur la même connexion de base de données. En fait, cette hypothèse est fausse. Lorsqu'une occurrence de SQLStatement s'exécute, vous ne pouvez pas modifier la propriété text de l'instruction. Toutefois, si vous utilisez une occurrence de SQLStatement distincte pour chaque instruction SQL à exécuter, vous pouvez appeler la méthode execute() d'une occurrence de SQLStatement pendant l'exécution d'une autre sans provoquer d'erreur. En interne, lorsque vous exécutez des opérations de base de données en mode asynchrone, chaque connexion de base de données (chaque occurrence de SQLConnection) possède sa propre file d'attente ou liste d'opérations à exécuter. L'environnement d'exécution effectue chaque opération l'une après l'autre, selon leur ordre d'apparition dans la file d'attente. Lorsque vous créez une occurrence de SQLStatement et appelez sa méthode execute(), cette opération d'exécution d'instruction est ajoutée à la file d'attente de la connexion. Si aucune opération n'est en cours d'exécution sur cette occurrence de SQLConnection, l'exécution de l'instruction commence en arrière-plan. Supposons maintenant, que dans le même bloc de code, vous créiez une autre occurrence de SQLStatement et appeliez sa méthode DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 197 Utilisation des bases de données SQL locales execute(). Cette seconde opération d'exécution d'instruction est ajoutée à la file d'attente derrière la première instruction. Dès que l'exécution de la première instruction est terminée, l'environnement d'exécution passe à la prochaine opération de la file d'attente. Le traitement des opérations successives de la file d'attente s'effectue en arrièreplan, même lorsque l'événement result de la première opération est déclenché dans le code de l'application principale. Le code suivant illustre cette technique : // 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. L'exécution automatique des instructions successives en attente a un effet secondaire important pour la base de données. Lorsqu'une instruction dépend du résultat d'une autre opération, vous ne pouvez pas l'ajouter en file d'attente (en d'autres termes, vous ne pouvez pas appeler sa méthode execute()) avant que la première opération ne soit terminée. La raison en est qu'après avoir appelé la méthode execute() de la seconde instruction, vous ne pouvez plus modifier les propriétés text et parameters de l'instruction. Dans ce cas, vous devez attendre l'événement indiquant que la première opération est terminée avant de commencer la suivante. Par exemple, si vous souhaitez exécuter une instruction dans le contexte d'une transaction, l'exécution de cette instruction dépend de l'opération d'ouverture de la transaction. Après l'appel à la méthode SQLConnection.begin() pour ouvrir la transaction, vous devez attendre que l'occurrence de SQLConnection déclenche son événement begin. A ce stade seulement vous pouvez appeler la méthode execute() de l'occurrence de SQLStatement. Dans cet exemple, le moyen le plus simple d'organiser l'application pour s'assurer que les opérations s'exécutent correctement consiste à créer une méthode enregistrée en tant qu'écouteur de l'événement begin. Le code qui appelle la méthode SQLStatement.execute() est placé dans cette méthode d'écouteur. Utilisation du chiffrement avec les bases de données SQL Toutes les applications Adobe AIR partagent le même moteur de base de données locale. Par conséquent, toute application AIR peut se connecter, lire et écrire dans un fichier d'une base de données non chiffrée. Depuis Adobe AIR 1.5, AIR a la capacité de créer et de se connecter à des fichiers d'une base de données chiffrée. Lorsque vous utilisez une base de données chiffrée, l'application doit fournir la clé de chiffrement appropriée pour se connecter à cette base de données. Si la clé de chiffrement fournie n'est pas correcte (ou s'il n'y a pas de clé), l'application ne peut pas se connecter à la base de données. Elle ne peut donc pas lire les données de la base de données ni y écrire ou modifier des données. Pour utiliser une base de données chiffrée, vous devez la créer en tant que base de données chiffrée. Avec une base de données chiffrée existante, vous pouvez ouvrir une connexion à la base de données. Vous pouvez également modifier la clé de chiffrement d'une base de données chiffrée. Mises à part la création et la connexion aux bases de données chiffrées, les techniques de travail sont les mêmes que pour une base de données non chiffrée. En particulier, l'exécution des instructions SQL est identique, que la base de données soit chiffrée ou non. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 198 Utilisation des bases de données SQL locales Utilisation d'une base de données chiffrée Le chiffrement se révèle très utile dès que vous souhaitez limiter l'accès aux informations stockées dans une base de données. Dans Adobe AIR, la fonction de chiffrement de base de données peut être utilisée dans plusieurs objectifs. Voici quelques exemples pour lesquels l'utilisation d'une base de données chiffrée peut être utile : • Cache en lecture seule de données d'application privées et téléchargées depuis un serveur • Stockage d'application local de données privées synchronisées avec un serveur (données envoyées et chargées depuis le serveur) • Fichiers chiffrés utilisés en tant que format de fichier pour les documents créés et modifiés par l'application Les fichiers peuvent être réservés à un utilisateur, donc privés, ou conçus pour être partagés par tous les utilisateurs de l'application. • Toute autre utilisation d'un magasin local de données, par exemple les utilisations décrites à la section « Cas d'utilisation des bases de données SQL locales » à la page 168, où les données peuvent être réservées aux personnes disposant d'un accès à l'ordinateur ou aux fichiers de la base de données. Comprendre la raison pour laquelle vous souhaitez utiliser une base de données chiffrée vous permet de choisir l'architecture de votre application. En particulier, cela peut affecter la manière dont votre application crée, obtient ou stocke la clé de chiffrement pour la base de données. Pour plus d'informations sur ces considérations, consultez la section « Considérations relatives à l'utilisation du chiffrement avec une base de données » à la page 203. L'utilisation d'une base de données chiffrée mise à part, le magasin local chiffré est un autre mécanisme qui permet de préserver la confidentialité des données sensibles. Avec le magasin local chiffré, vous stockez une unique valeur ByteArray avec une clé String. Seule l'application AIR qui a stocké la valeur peut y accéder, uniquement dans l'ordinateur sur lequel elle est stockée. Avec le magasin local chiffré, il n'est pas nécessaire de créer votre propre clé de chiffrement. Pour ces raisons, le magasin local chiffré convient davantage au stockage aisé d'une seule valeur ou d'un ensemble de valeurs facilement encodé dans un objet ByteArray. Une base de données chiffrée convient mieux aux grands ensembles de données où l'interrogation et le stockage de données structurées sont souhaitables. Pour plus d'informations sur l'utilisation d'un magasin local chiffré, consultez la section « Stockage des données chiffrées » à la page 219. Création d'une base de données chiffrée Pour utiliser une base de données chiffrée, son fichier doit être chiffré lors de sa création. Lorsqu'une base de données a été créée sans chiffrement, elle ne peut plus être chiffrée par la suite. De la même façon, une base de données chiffrée ne peut pas devenir non chiffrée. Si nécessaire, vous pouvez modifier la clé de chiffrement d'une base de données chiffrée. Pour plus d'informations, consultez la section « Modification de la clé de chiffrement d'une base de données » à la page 202. Si votre base de données n'est pas chiffrée et que vous souhaitez utiliser le chiffrement de bases de données, vous pouvez créer une nouvelle base de données chiffrée, puis y copier la structure et les données des tables existantes. La création d'une base de données chiffrée est très similaire à la création d'une base de données non chiffrée, décrite à la section « Création d'une base de données » à la page 172. Vous commencez par créer une occurrence de SQLConnection représentant la connexion à la base de données. Vous créez la base de données en appelant la méthode open() ou openAsync() de l'objet SQLConnection, en spécifiant un fichier qui n'existe pas encore pour l'emplacement de la base de données. La seule différence lors de la création d'une base de données chiffrée est que vous fournissez une valeur au paramètre encryptionKey (cinquième paramètre de la méthode open() et sixième paramètre de la méthode openAsync()). Une valeur de paramètre encryptionKey valide est un objet ByteArray contenant exactement 16 octets. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 199 Utilisation des bases de données SQL locales L'exemple suivant démontre la création d'une base de données chiffrée ouverte en mode d'exécution asynchrone. Pour plus de simplicité, dans cet exemple, la clé de chiffrement est codée en dur dans le code de l'application. Toutefois, cette technique est fortement déconseillée car elle n'est pas sécurisée. 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); } L'exemple suivant décrit la création d'une base de données chiffrée ouverte en mode d'exécution synchrone. Pour plus de simplicité, dans cet exemple, la clé de chiffrement est codée en dur dans le code de l'application. Toutefois, cette technique est fortement déconseillée car elle n'est pas sécurisée. 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); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 200 Utilisation des bases de données SQL locales Vous trouverez un exemple décrivant un moyen conseillé de générer une clé de chiffrement à la section « Exemple : génération et utilisation d'une clé de chiffrement » à la page 204. Connexion à une base de données chiffrée Comme la création d'une base de données chiffrée, la procédure qui permet d'ouvrir une connexion à une base de données chiffrée est la même que pour une base de données non chiffrée. Cette procédure est détaillée à la section « Connexion à une base de données » à la page 175. Vous utilisez la méthode open() pour ouvrir une connexion en mode d'exécution synchrone, ou la méthode openAsync() pour ouvrir une connexion en mode d'exécution asynchrone. La seule différence est que, pour ouvrir une base de données chiffrée, vous spécifiez la valeur correcte du paramètre encryptionKey (cinquième paramètre de la méthode open() et sixième paramètre de la méthode openAsync()). Si la clé de chiffrement fournie n'est pas correcte, une erreur se produit. Dans le cas de la méthode open(), une exception SQLError est renvoyée. Dans le cas de la méthode openAsync(), l'objet SQLConnection distribue un événement SQLErrorEvent, dont la propriété error contient un objet SQLError. Dans les deux cas, l'objet SQLError généré par l'exception a une valeur de propriété errorID 3138. Cet ID d'erreur correspond au message d'erreur « Le fichier ouvert n'est pas un fichier de base de données ». L'exemple suivant décrit l'ouverture d'une base de données chiffrée en mode d'exécution asynchrone. Pour plus de simplicité, dans cet exemple, la clé de chiffrement est codée en dur dans le code de l'application. Toutefois, cette technique est fortement déconseillée car elle n'est pas sécurisée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 201 Utilisation des bases de données SQL locales 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); } } L'exemple suivant décrit l'ouverture d'une base de données chiffrée en mode d'exécution synchrone. Pour plus de simplicité, dans cet exemple, la clé de chiffrement est codée en dur dans le code de l'application. Toutefois, cette technique est fortement déconseillée car elle n'est pas sécurisée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 202 Utilisation des bases de données SQL locales 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); } } Vous trouverez un exemple décrivant un moyen conseillé de générer une clé de chiffrement à la section « Exemple : génération et utilisation d'une clé de chiffrement » à la page 204. Modification de la clé de chiffrement d'une base de données Lorsqu'une base de données est chiffrée, vous pouvez modifier sa clé de chiffrement ultérieurement. Pour modifier la clé de chiffrement d'une base de données, commencez par ouvrir une connexion à cette base de données en créant une occurrence de SQLConnection et en appelant sa méthode open() ou openAsync(). Lorsque la connexion à la base de données est établie, appelez la méthode reencrypt(), en transmettant la nouvelle clé de chiffrement en tant qu'argument. Comme la plupart des opérations de base de données, le comportement de la méthode reencrypt() varie selon si la connexion à la base de données utilise le mode d'exécution synchrone ou asynchrone. Si vous utilisez la méthode open() pour vous connecter à la base de données, l'opération reencrypt() s'exécute de façon synchrone. Lorsque l'opération est terminée, l'exécution se poursuit avec la ligne suivante du code : var newKey:ByteArray = new ByteArray(); // ... generate the new key and store it in newKey conn.reencrypt(newKey); À l'inverse, si la connexion à la base de données est établie avec la méthode openAsync(), l'opération reencrypt() est asynchrone. L'appel à la méthode reencrypt() commence le processus de rechiffrement. Lorsque l'opération est terminée, l'objet SQLConnection distribue un événement reencrypt. Vous utilisez un écouteur d'événement pour connaître le moment où le rechiffrement se termine : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 203 Utilisation des bases de données SQL locales 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'opération reencrypt() s'exécute dans sa propre transaction. Si l'opération est interrompue ou échoue (par exemple, si l'application est fermée avant la fin de l'opération), la transaction est annulée. Dans ce cas, la clé de chiffrement d'origine demeure en vigueur pour la base de données. La méthode reencrypt() ne peut pas être utilisée pour supprimer le chiffrage d'une base de données. La transmission d'une valeur null ou d'une clé de chiffrement qui ne correspond pas à un objet ByteArray de 16 octets à la méthode reencrypt() provoque une erreur. Considérations relatives à l'utilisation du chiffrement avec une base de données La section « Utilisation d'une base de données chiffrée » à la page 198 présente plusieurs cas de figure pour lesquels l'utilisation d'une base de données chiffrée peut être nécessaire. À l'évidence, les besoins de confidentialité diffèrent selon les différents cas d'utilisation des applications (les scénarios présentés, ainsi que d'autres). L'architecture du chiffrement dans votre application joue un rôle important sur le contrôle de la confidentialité des données d'une base de données. Par exemple, si vous utilisez une base de données chiffrée pour assurer la confidentialité des données personnelles, même vis-à-vis des autres utilisateurs de l'ordinateur, la base de données de chaque utilisateur a besoin de sa propre clé de chiffrement. Pour une sécurité optimale, votre application peut générer la clé à partir d'un mot de passe saisi par l'utilisateur. Baser la clé de chiffrement sur un mot de passe permet d'être certain que les données demeurent inaccessibles, même si une autre personne utilise le compte de l'utilisateur sur l'ordinateur. À l'extrême opposé, supposons à présent que vous souhaitiez qu'un fichier de bases de données soit lisible par tout utilisateur de votre application, mais pas par les utilisateurs d'autres applications. Dans ce cas, chaque copie installée de l'application doit pouvoir accéder à une clé de chiffrement partagée. Vous pouvez concevoir votre application, et en particulier la technique utilisée pour générer la clé de chiffrement, en fonction du niveau de confidentialité désiré pour les données de l'application. Voici une liste de quelques suggestions de conception répondant à divers niveaux de confidentialité des données : • Pour qu'une base de données soit accessible à tout utilisateur autorisé à accéder à l'application sur n'importe quel ordinateur, utilisez une seule clé disponible pour toutes les instances de l'application. Par exemple, lors de sa première exécution, l'application peut télécharger la clé de chiffrement partagée sur un serveur en utilisant un protocole sécurisé de type SSL. Elle peut ensuite enregistrer la clé dans le magasin local chiffré pour l'utiliser ultérieurement. Une autre alternative consiste à chiffrer les données par utilisateur sur l'ordinateur, puis de synchroniser ces données à l'aide d'un magasin de données distant, tel qu'un serveur, pour rendre les données portables. • Pour qu'un seul utilisateur puisse accéder à la base de données sur n'importe quel ordinateur, générez la clé de chiffrement en utilisant un secret propre à l'utilisateur (par exemple un mot de passe). En particulier, n'utilisez pas de valeur associée à un ordinateur particulier (par exemple une valeur stockée dans le magasin local chiffré) pour générer la clé. Une autre alternative consiste à chiffrer les données par utilisateur sur l'ordinateur, puis de synchroniser ces données à l'aide d'un magasin de données distant, tel qu'un serveur, pour rendre les données portables. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 204 Utilisation des bases de données SQL locales • Pour qu'un seul utilisateur puisse accéder à la base de données sur un seul ordinateur, générez la clé à partir d'un mot de passe et d'une valeur générée arbitrairement, appelée salt. Un exemple de cette technique est disponible à la section « Exemple : génération et utilisation d'une clé de chiffrement » à la page 204. Voici d'autres considérations relatives à la sécurité qu'il est important de ne pas oublier lors de la conception d'une application utilisant une base de données chiffrée : • Un système est autant sécurisé que ce que peut l'être son lien le plus faible. Si vous utilisez un mot de passe saisi par l'utilisateur pour générer une clé de chiffrement, pensez à imposer une longueur minimale et des contraintes de complexité pour les mots de passe. Un mot de passe court qui utilise seulement des caractères de base est facile à deviner. • Le code source d'une application AIR est stocké sur l'ordinateur de l'utilisateur en texte brut (dans le cas de contenu HTML) ou dans un format binaire facile à décompiler (dans le cas de contenu SWF). Le code source étant accessible, les deux éléments à ne pas oublier sont : • Ne jamais coder en dur la clé de chiffrement dans votre code source • Toujours partir du principe qu'un attaquant peut aisément découvrir la technique utilisée pour générer une clé de chiffrement (par exemple un générateur de caractères aléatoire ou un algorithme de hachage particulier) • Le chiffrement de base de données d'AIR utilise le chiffrement AES (Advanced Encryption Standard) avec le mode CBC-MAC (CCM). Pour être sécurisé, ce chiffrement combine la clé saisie par l'utilisateur avec une valeur salt. Un exemple de cette technique est disponible à la section « Exemple : génération et utilisation d'une clé de chiffrement » à la page 204. • Lorsque vous choisissez de chiffrer une base de données, tous les fichiers disque utilisés par le moteur de base de données en combinaison avec celle-ci sont chiffrés. Toutefois, le moteur de base de données stocke certaines données temporaires en mémoire cache pour améliorer les performances en lecture et écriture au cours des transactions. Toutes les données qui résident en mémoire ne sont pas chiffrées. Si un attaquant peut accéder à la mémoire utilisée par l'application AIR, par exemple avec un débogueur, les données de la base de données ouverte et non chiffrée sont disponibles. Exemple : génération et utilisation d'une clé de chiffrement Cet exemple d'application présente une technique de génération de clé de chiffrement. Cette application est conçue pour assurer le plus haut niveau de confidentialité et de sécurité aux données des utilisateurs. Un point essentiel de la sécurisation des données privées consiste à obliger l'utilisateur à saisir un mot de passe à chaque connexion de l'application à la base de données. Par conséquent, comme nous l'avons vu dans cet exemple, une application exigeant ce niveau de confidentialité ne doit jamais stocker directement la clé de chiffrement de la base de données. L'application comprend deux parties : une classe ActionScript qui génère une clé de chiffrement (la classe EncryptionKeyGenerator) et une interface utilisateur de base qui décrit l'utilisation de cette classe. Pour obtenir le code source complet, consultez la section « Exemple de code complet pour la génération et l'utilisation d'une clé de chiffrement » à la page 212. Utilisation de la classe EncryptionKeyGenerator pour obtenir une clé de chiffrement sécurisée La section « Fonctionnement de la classe EncryptionKeyGenerator » à la page 206 décrit les techniques utilisées par cette classe pour générer une clé de chiffrement destinée à une base de données. Il n'est cependant pas nécessaire de comprendre ces techniques pour utiliser la classe EncryptionKeyGenerator dans votre application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 205 Utilisation des bases de données SQL locales Pour utiliser la classe EncryptionKeyGenerator dans votre application, procédez comme suit : 1 La classe EncryptionKeyGenerator est incluse dans le projet de bibliothèque centrale open-source ActionScript 3.0 (as3corelib). Vous pouvez télécharger le package as3corelib comprenant le code source et la documentation. Vous pouvez également télécharger des fichiers du code source ou SWC depuis la page du projet. 2 Placez le code source de la classe EncryptionKeyGenerator (ou le fichier SWC as3corelib) dans un emplacement accessible au code source de votre application. 3 Dans le code source de votre application, ajoutez une instruction import pour la classe EncryptionKeyGenerator. import com.adobe.air.crypto.EncryptionKeyGenerator; 4 Avant l'endroit où le code crée la base de données ou ouvre une connexion vers celle-ci, ajoutez le code qui crée une occurrence EncryptionKeyGenerator en appelant le constructeur EncryptionKeyGenerator(). var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); 5 Demandez le mot de passe à l'utilisateur : var password:String = passwordInput.text; if (!keyGenerator.validateStrongPassword(password)) { // display an error message return; } L'occurrence de EncryptionKeyGenerator utilise ce mot de passe comme base de la clé de chiffrement (décrite à l'étape suivante). L'occurrence de EncryptionKeyGenerator teste le mot de passe par rapport aux exigences de validation de mot de passe renforcé. Si la validation échoue, une erreur survient. Comme le montre l'exemple de code, vous pouvez vérifier le mot de passe en amont en appelant la méthode validateStrongPassword() de l'objet EncryptionKeyGenerator. Cette opération vous permet de déterminer si le mot de passe répond aux exigences minimales d'un mot de passe renforcé et d'éviter une erreur. 6 Générez la clé de chiffrement à partir du mot de passe : var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password); La méthode getEncryptionKey() génère et renvoie la clé de chiffrement (objet ByteArray à 16 octets). Vous pouvez alors utiliser la clé de chiffrement pour créer votre nouvelle base des données chiffrée ou ouvrir une base de données existante. La méthode getEncryptionKey() a un paramètre obligatoire, le mot de passe obtenu à l'étape 5. Remarque : Pour assurer le plus haut niveau de sécurité et de confidentialité des données, l'application doit obliger l'utilisateur à saisir un mot de passe à chaque connexion de l'application à la base de données. Ne stockez pas directement le mot de passe de l'utilisateur ni la clé de chiffrement de la base de données. Cela entraînerait des risques de sécurité. Au contraire, comme le montre cet exemple, l'application doit utiliser la même technique pour faire dériver la clé de chiffrement du mot de passe lors de la création de la base des données chiffrée et lors des connexions ultérieures à celle-ci. La méthode getEncryptionKey() accepte également un second paramètre (facultatif) overrideSaltELSKey. L'occurrence de EncryptionKeyGenerator crée une valeur aléatoire (appelée valeur salt) qui fait partie de la clé de chiffrement. Pour pouvoir recréer la clé de chiffrement, la valeur salt est stockée dans le magasin local chiffré (ELS) de votre application AIR. Par défaut, la classe EncryptionKeyGenerator utilise une chaîne particulière en tant que clé ELS. Bien que cela soit improbable, il est possible que cette clé soit en conflit avec une autre clé utilisée par votre application. Au lieu d'utiliser la clé par défaut, vous pouvez spécifier votre propre clé ELS. Dans ce cas, spécifiez une clé personnalisée en la transmettant en tant que second paramètre getEncryptionKey(), comme illustré ici : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 206 Utilisation des bases de données SQL locales var customKey:String = "My custom ELS salt key"; var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password, customKey); 7 Création ou ouverture de la base de données Avec la clé de chiffrement renvoyée par la méthode getEncryptionKey(), votre code peut créer une nouvelle base de données chiffrée ou tenter d'ouvrir la base de données chiffrée existante. Dans les deux cas, vous utilisez la méthode open() ou openAsync() de la classe SQLConnection, tel que décrit dans les sections « Création d'une base de données chiffrée » à la page 198 et « Connexion à une base de données chiffrée » à la page 200. Dans cet exemple, l'application est conçue pour ouvrir la base de données en mode d'exécution asynchrone. Le code configure les écouteurs d'événement appropriés et appelle la méthode openAsync(), en transmettant la clé de chiffrement en tant qu'argument final : conn.addEventListener(SQLEvent.OPEN, openHandler); conn.addEventListener(SQLErrorEvent.ERROR, openError); conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey); Dans les méthodes des écouteurs, le code supprime les enregistrements des écouteurs d'événement. Il affiche ensuite un message d'état indiquant si la base de données a été créée, ouverte, ou si une erreur s'est produite. La partie la plus importante de ces gestionnaires d'événement se trouve dans la méthode openError(). Dans cette méthode, une instruction if vérifie l'existence de la base de données (c'est-à-dire que le code tente de se connecter à une base de données existante) et si l'ID d'erreur correspond à la constante EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID. Si ces deux conditions sont vraies, il est probable que le mot de passe saisi par l'utilisateur soit incorrect. (Cela peut également signifier que le fichier spécifié n'est pas un fichier de base de données.) Voici le code qui vérifie l'ID d'erreur : if (!createNewDB && event.error.errorID == EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID) { statusMsg.text = "Incorrect password!"; } else { statusMsg.text = "Error creating or opening database."; } Vous trouverez le code complet des exemples d'écouteurs d'événement à la section « Exemple de code complet pour la génération et l'utilisation d'une clé de chiffrement » à la page 212. Fonctionnement de la classe EncryptionKeyGenerator Il n'est pas nécessaire de comprendre le fonctionnement intrinsèque de la classe EncryptionKeyGenerator pour l'utiliser afin de créer une clé de chiffrement sécurisée pour la base de données de votre application. Le processus d'utilisation de la classe est décrit à la section « Utilisation de la classe EncryptionKeyGenerator pour obtenir une clé de chiffrement sécurisée » à la page 204. Il peut cependant se révéler précieux pour comprendre les techniques utilisées par la classe. Par exemple, vous pourriez vouloir adapter la classe ou intégrer certaines de ses techniques lorsqu'un niveau différent de confidentialité des données est nécessaire. La classe EncryptionKeyGenerator est incluse dans le Projet de bibliothèque centrale open-source ActionScript 3.0 (as3corelib). Vous pouvez télécharger le package as3corelib comprenant le code source et la documentation. Vous pouvez également afficher le code source dans le site du projet ou le télécharger pour suivre les explications. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 207 Utilisation des bases de données SQL locales Lorsque le code crée une occurrence de EncryptionKeyGenerator et appelle sa méthode getEncryptionKey(), plusieurs mesures permettent de s'assurer que seul l'utilisateur autorisé peut accéder aux données. Le processus correspond à la génération d'une clé de chiffrement à partir d'un mot de passe saisi par l'utilisateur avant la création de la base de données ou à la recréation de la clé de chiffrement pour ouvrir la base de données. Obtention et validation d'un mot de passe renforcé Lorsque le code appelle la méthode getEncryptionKey(), il transmet un mot de passe sous forme de paramètre. Ce mot de passe est utilisé comme base de la clé de chiffrement. En utilisant des informations que seul l'utilisateur connaît, cette technique permet de s'assurer que seul l'utilisateur qui connaît le mot de passe peut accéder au contenu de la base de données. Même s'il accède au compte de l'utilisateur sur l'ordinateur, l'attaquant ne peut pas accéder à la base de données sans connaître le mot de passe. Pour une sécurité maximale, l'application ne stocke jamais le mot de passe. Dans l'exemple d'application, passwordInput correspond au nom d'occurrence d'un composant TextInput dans lequel l'utilisateur saisit le mot de passe. Au lieu de manipuler directement la valeur text du composant, l'application copie le mot de passe dans une variable nommée password. var password:String = passwordInput.text; L'exemple d'application crée ensuite une occurrence de EncryptionKeyGenerator et appelle sa méthode getEncryptionKey() en utilisant la variable password comme argument : var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password); La première étape effectuée par la classe EncryptionKeyGenerator lors de l'appel à la méthode getEncryptionKey() consiste à vérifier que le mot de passe saisi par l'utilisateur respecte les exigences définies en matière de renforcement. Dans ce cas, le mot de passe doit comprendre entre 8 et 32 caractères. Il doit combiner des lettres majuscules et minuscules et comprendre au moins un chiffre ou un symbole. L'expression régulière qui vérifie ce modèle est définie en tant que constante nommée STRONG_PASSWORD_PATTERN : private static const STRONG_PASSWORD_PATTERN:RegExp = /(?=^.{8,32}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; Le code qui vérifie le mot de passe est dans la méthode validateStrongPassword() de la classe EncryptionKeyGenerator. Le code se présente comme suit : public function vaidateStrongPassword(password:String):Boolean { if (password == null || password.length <= 0) { return false; } return STRONG_PASSWORD_PATTERN.test(password)) } La méthode getEncryptionKey() appelle la méthode validateStrongPassword() et renvoie une exception si le mot de passe n'est pas valide. La méthode validateStrongPassword() étant publique, le code peut vérifier le mot de passe sans appeler la méthode getEncryptionKey() pour éviter la production d'erreur. Extension du mot de passe à 256 bits Dans la suite du processus, le mot de passe doit avoir une longueur de 256 bits. Plutôt que de demander à chaque utilisateur de saisir un mot de passe faisant exactement 256 bits (32 caractères), le code crée un mot de passe plus long en répétant ses caractères. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 208 Utilisation des bases de données SQL locales Pour exécuter la tâche de création d'un mot de passe long, la méthode getEncryptionKey() appelle la méthode concatenatePassword(). var concatenatedPassword:String = concatenatePassword(password); Voici le code de la méthode concatenatePassword() : 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; } Si le mot de passe n'atteint pas 256 bits, le code le concatène pour obtenir une longueur de 256 bits. Si la longueur ne fonctionne pas exactement, la dernière répétition est raccourcie jusqu'à correspondre à 256 bits. Génération ou récupération d'une valeur salt de 256 bits L'étape suivante consiste à obtenir une valeur salt de 256 bits qui sera ensuite combinée au mot de passe dans une étape ultérieure. Une valeur salt est une valeur aléatoire ajoutée ou combinée à la valeur saisie par l'utilisateur pour composer le mot de passe. L'utilisation d'une valeur salt avec un mot de passe permet de s'assurer que, même si l'utilisateur choisit un mot du dictionnaire ou un terme courant comme mot de passe, la combinaison mot de passe-plus-salt utilisée par le système est une valeur aléatoire. Cet aspect aléatoire assure une protection contre les attaques de type dictionnaire, dans lesquelles l'attaquant utilise une liste de mots pour tenter de deviner le mot de passe. De plus, la génération de cette valeur salt et son stockage dans le magasin local chiffré permet de l'associer au compte de l'utilisateur sur l'ordinateur dans lequel le fichier de base de données est situé. Si l'application appelle la méthode getEncryptionKey() pour la première fois, le code crée une valeur salt aléatoire de 256 bits. Sinon, le code récupère la valeur salt dans le magasin local chiffré. La valeur salt est stockée dans une variable nommée salt. Le code détermine si une valeur salt a déjà été créée en tentant de la récupérer dans le magasin local chiffré : var salt:ByteArray = EncryptedLocalStore.getItem(saltKey); if (salt == null) { salt = makeSalt(); EncryptedLocalStore.setItem(saltKey, salt); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 209 Utilisation des bases de données SQL locales Si le code crée une nouvelle valeur salt, la méthode makeSalt() génère une valeur aléatoire de 256 bits. Comme la valeur est ensuite stockée dans le magasin local chiffré, elle est générée sous forme d'objet ByteArray. La méthode makeSalt() utilise la méthode Math.random() pour générer la valeur de façon aléatoire. La méthode Math.random() ne peut pas générer 256 bits en une seule opération. À la place, le code utilise une boucle pour appeler Math.random() à huit reprises. Chaque fois, une valeur uint aléatoire comprise entre 0 et 4294967295 (valeur uint maximale) est générée. La valeur uint est utilisée pour plus de commodité car elle comprend exactement 32 bits. L'écriture de huit valeurs uint dans l'objet ByteArray permet de générer une valeur de 256 bits. Voici le code de la méthode 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; } Lorsque le code enregistre la valeur salt dans le magasin local chiffré ou tente de l'y récupérer, il a besoin d'une clé String dans laquelle la valeur salt est enregistrée. Sans cette clé, la valeur salt ne peut pas être récupérée. Dans ce cas, la clé de chiffrement ne peut pas être recréée à chaque nouvelle ouverture de la base de données. Par défaut, la classe EncryptionKeyGenerator utilise une clé prédéfinie du magasin local chiffré qui est définie dans la constante SALT_ELS_KEY. Au lieu d'utiliser la clé par défaut, le code de l'application peut également spécifier la clé de magasin local chiffré à utiliser dans l'appel à la méthode getEncryptionKey(). La clé de magasin local chiffré de la valeur salt par défaut ou spécifiée par l'application est stockée dans une variable nommée saltKey. Cette variable est utilisée dans les appels aux méthodes EncryptedLocalStore.setItem() et EncryptedLocalStore.getItem(), comme nous l'avons vu dans le code précédent. Combinaison du mot de passe 256 bits et de la valeur salt via l'opérateur XOR Le code dispose à présent d'un mot de passe de 256 bits et d'une valeur salt de 256 bits. Il utilise ensuite une opération XOR au niveau du bit pour combiner la valeur salt avec le mot de passe concaténé dans une valeur unique. Cette technique crée un mot de passe de 256 bits à partir de tous les caractères possibles de la plage complète. Ce principe reste vrai même si la saisie du véritable mot de passe est plus probablement constituée des principaux caractères alphanumériques. Cet aspect encore plus aléatoire a l'avantage de créer le plus vaste ensemble possible de mots de passe sans que l'utilisateur ne doive lui-même saisir un mot de passe long et complexe. Le résultat de l'opération XOR est stocké dans la variable unhashedKey. La véritable opération XOR au niveau du bit sur les deux valeurs se produit dans la méthode xorBytes() : var unhashedKey:ByteArray = xorBytes(concatenatedPassword, salt); L'opérateur XOR au niveau du bit (^) prend deux valeurs uint et n'en renvoie qu'une. (Une valeur uint contient 32 bits.) Les valeurs d'entrée transmises en tant qu'arguments à la méthode xorBytes() sont une valeur String (le mot de passe) et une valeur ByteArray (la valeur salt). Par conséquent, le code utilise une boucle pour extraire 32 bits de chaque entrée à combiner à l'aide de l'opérateur XOR. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 210 Utilisation des bases de données SQL locales private function xorBytes(passwordString:String, salt:ByteArray):ByteArray { var result:ByteArray = new ByteArray(); for (var i:uint = 0; i < 32; i += 4) { // ... } return result; } Dans la boucle, les premiers 32 bits (4 octets) sont extraits du paramètre passwordString. Ces bits sont extraits et convertis en valeur uint (o1) dans un processus à deux parties. D'abord, la méthode charCodeAt() récupère la valeur numérique de chaque caractère. Cette valeur est ensuite décalée jusqu'à la position appropriée dans la valeur uint par l'opérateur de décalage gauche au niveau du bit (<<), puis la valeur décalée est ajoutée à o1. Par exemple, le premier caractère (i) devient les premiers 8 bits grâce à l'opérateur de décalage gauche au niveau du bit (<<) qui décale les bits de 24 bits à gauche et affecte cette valeur à o1. Le second caractère (i + 1) prend la place des seconds 8 bits en décalant sa valeur vers la gauche de 16 bits et en ajoutant le résultat à o1. Les valeurs des troisième et quatrième caractères sont ajoutées de la même manière. // ... // 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 variable o1 contient à présent 32 bits provenant du paramètre passwordString. Ensuite, 32 bits sont extraits du paramètre salt via un appel à sa méthode readUnsignedInt(). Les 32 bits sont stockés dans la variable uint o2. // ... salt.position = i; var o2:uint = salt.readUnsignedInt(); // ... Enfin, les deux valeurs de 32 bits (uint) sont combinées par l'opérateur XOR et le résultat est écrit dans un objet ByteArray nommé result. // ... var xor:uint = o1 ^ o2; result.writeUnsignedInt(xor); // ... Lorsque la boucle est terminée, l'objet ByteArray contenant le résultat XOR est renvoyé. // ... } return result; } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 211 Utilisation des bases de données SQL locales Hachage de la clé Une fois le mot de passe concaténé et la valeur salt combinée, l'étape suivante consiste à sécuriser encore davantage cette valeur en la hachant avec un algorithme SHA-256. Le hachage de la valeur rend encore plus difficile sa rétroconception par un attaquant. À ce stade, le code possède un objet ByteArray nommé unhashedKey contenant le mot de passe concaténé combiné à la valeur salt. Le projet de bibliothèque ActionScript 3.0 (as3corelib) comprend une classe SHA256 dans le package com.adobe.crypto. La méthode SHA256.hashBytes() qui exécute un hachage SHA-256 sur l'objet ByteArray et renvoie une valeur String contenant le résultat du hachage 256 bits sous forme de nombre hexadécimal. La classe EncryptionKeyGenerator utilise la classe SHA256 pour hacher la clé : var hashedKey:String = SHA256.hashBytes(unhashedKey); Extraction de la clé de chiffrement du hachage La clé de chiffrement doit être un objet ByteArray faisant exactement 16 octets (128 bits). Le résultat de l'algorithme de hachage SHA-256 fait toujours 256 bits. Par conséquent, l'étape finale consiste à sélectionner 128 bits dans le résultat haché et à les utiliser comme véritable clé de chiffrement. Dans la classe EncryptionKeyGenerator, le code réduit la clé à 128 bits en appelant la méthode generateEncryptionKey(). Il renvoie ensuite le résultat de cette méthode en tant que résultat de la méthode getEncryptionKey() : var encryptionKey:ByteArray = generateEncryptionKey(hashedKey); return encryptionKey; Il n'est pas nécessaire d'utiliser les premiers 128 bits comme clé de chiffrement. Vous pouvez sélectionner une plage de bits à partir d'un point arbitraire, sélectionner tous les autres bits ou sélectionner les bits d'une autre manière. L'important est que le code sélectionne 128 bits distincts, et que ces mêmes 128 bits soient utilisés chaque fois. Dans ce cas, la méthode generateEncryptionKey() utilise la plage de bits commençant au 18ème octet en tant que clé de chiffrement. Comme nous l'avons déjà mentionné, la classe SHA256 renvoie une valeur String contenant un hachage 256 bits sous forme de nombre hexadécimal. Un unique bloc de 128 bits comprend trop d'octets pour qu'ils soient ajoutés en une seule fois à un objet ByteArray. Par conséquent, le code utilise une boucle for pour extraire les caractères de la valeur String hexadécimale, les convertit en valeurs numériques réelles et les ajoute à l'objet ByteArray. La valeur String SHA-256 résultante comprend 64 caractères. Une plage de 128 bits correspond à 32 caractères dans la valeur String et chaque caractère représente 4 bits. Le plus petit incrément de données que vous pouvez ajouter à un objet ByteArray correspond à un seul octet (8 bits), ce qui équivaut à deux caractères dans la valeur String hash. De ce fait, la boucle compte de 0 à 31 (32 caractères) par incréments de 2 caractères. Dans la boucle, le code commence par déterminer la position de départ de la paire de caractères en cours. Comme la plage désirée commence au niveau du caractère situé à l'index 17 (18ème octet), la variable position est affectée à la valeur de l'itérateur actuel (i) plus 17. Le code utilise la méthode substr() de l'objet String pour extraire les deux caractères situés au niveau de la position en cours. Ces caractères sont stockés dans la variable hex. Ensuite, le code utilise la méthode parseInt() pour convertir la valeur String hex en une valeur décimale entière. Il stocke cette valeur dans la variable int byte. Enfin, le code ajoute la valeur de byte à l'objet ByteArray result à l'aide de sa méthode writeByte(). Lorsque la boucle se termine, l'objet ByteArray result contient 16 octets et peut être utilisé comme clé de chiffrement pour la base de données. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 212 Utilisation des bases de données SQL locales 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; } Exemple de code complet pour la génération et l'utilisation d'une clé de chiffrement Voici le code complet d'un exemple d'application « Génération et utilisation d'une clé de chiffrement » : Le code comprend deux parties. L'exemple utilise la classe EncryptionKeyGenerator pour créer une clé de chiffrement à partir d'un mot de passe. La classe EncryptionKeyGenerator est incluse dans le projet de bibliothèque centrale open-source ActionScript 3.0 (as3corelib). Vous pouvez télécharger le package as3corelib comprenant le code source et la documentation. Vous pouvez également télécharger des fichiers du code source ou SWC depuis la page du projet. Le fichier FLA de l'application contient le code source d'une application simple qui crée ou ouvre une connexion à une base de données chiffrée. Le fichier FLA comprend quatre composants placés sur la scène : Nom d'occurrence Type de composant Description instructions Label Contient les instructions données à l'utilisateur passwordInput TextInput Champ de saisie dans lequel l'utilisateur tape le mot de passe openButton Button Bouton sur lequel l'utilisateur clique après avoir saisi le mot de passe statusMsg Label Affiche des messages d'état (réussite ou échec) Le code de l'application est défini sur une image-clé de l'image 1 du scénario principal. Voici le code de l'application : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 213 Utilisation des bases de données SQL locales 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; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 214 Utilisation des bases de données SQL locales 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."; } } Stratégies d'utilisation des bases de données SQL Une application peut accéder à une base de données SQL locale et l'exploiter de différentes manières. La conception de l'application peut varier en termes d'organisation du code, d'ordre et de synchronisation d'exécution des opérations, etc. Les techniques choisies peuvent affecter la simplicité du développement de votre application, par exemple, la facilité avec laquelle l'application pourra être modifiée dans les futures mises à jour. Elles peuvent également avoir un impact sur le bon fonctionnement de l'application du point de vue des utilisateurs. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 215 Utilisation des bases de données SQL locales Distribution d'une base de données pré-renseignée Lorsque vous utilisez une base de données SQL locale AIR dans votre application, cette dernière attend une base de données présentant une certaine structure de tables, de colonnes, etc. Certaines applications s'attendent également à ce que certaines données soient pré-renseignées dans le fichier de la base de données. Créer la base de données au sein du code de l'application est un moyen de s'assurer que la base de données présente la structure appropriée. Lors du chargement de l'application, celle-ci vérifie la présence de son fichier de base de données dans un emplacement particulier. Si le fichier n'existe pas, l'application exécute un ensemble de commandes pour le créer, crée la structure de la base de données et renseigne les tables avec les données initiales. Le code qui crée la base de données et ses tables est souvent complexe. Bien souvent, il n'est utilisé qu'une fois au début de la durée de vie d'une application installée, mais augmente tout de même la taille et la complexité de celle-ci. Au lieu de créer la base de données, sa structure et ses données par programmation, vous pouvez distribuer une base de données pré renseignée avec votre application. Pour distribuer une base de données prédéfinie, incluez le fichier de base de données dans le package AIR de l'application. Comme tous les fichiers inclus dans ce package AIR, un fichier de base de données regroupé est installé dans le répertoire de l'application (celui représenté par la propriété File.applicationDirectory). Toutefois, les fichiers de ce répertoire sont en lecture seule. Servez-vous du fichier du package AIR en tant que base de données « modèle ». La première fois que l'utilisateur exécute l'application, copiez le fichier de base de données d'origine dans le répertoire de stockage de l'application de l'utilisateur (ou en un autre emplacement), et utilisez cette base de données dans l'application. Amélioration des performances de la base de données Plusieurs techniques intégrées à une application Adobe AIR permettent d'améliorer les performances des opérations de sa base de données. Outre les techniques décrites ici, la façon dont une instruction SQL est écrite peut également affecter les performances de la base de données. Il existe souvent plusieurs manières d'écrire une instruction SQL SELECT pour récupérer un jeu de résultats particulier. Dans certains cas, les différentes approches sollicitent plus ou moins le moteur d'exécution de la base de données. Cet aspect de l'amélioration des performances de la base de données (conception des instructions SQL pour de meilleures performances) n'est pas traité dans la documentation d'Adobe AIR. Utilisation d'une occurrence de SQLStatement pour chaque instruction SQL Avant d'exécuter une instruction SQL, l'environnement d'exécution la prépare (la compile) pour déterminer les étapes effectuées en interne pour l'exécuter. Lorsque vous appelez SQLStatement.execute() sur une occurrence de SQLStatement qui n'a encore jamais été exécutée, l'instruction est automatiquement préparée avant son exécution. Lors des prochains appels à la méthode execute(), et tant que la propriété SQLStatement.text ne change pas, l'instruction est déjà préparée. Son exécution est donc plus rapide. Pour optimiser au maximum la réutilisation des instructions, si des valeurs doivent être modifiées entre les exécutions de l'instruction, personnalisez votre instruction à l'aide de paramètres d'instruction. (Les paramètres d'instruction sont spécifiés à l'aide de la propriété de tableau associatif SQLStatement.parameters.) Contrairement à la modification de la propriété text de l'occurrence de SQLStatement, lorsque vous modifiez les valeurs des paramètres d'instruction, l'environnement d'exécution n'a pas besoin de préparer à nouveau l'instruction. Pour plus d'informations sur l'utilisation de paramètres dans les instructions, consultez la section « Utilisation de paramètres dans des instructions » à la page 178. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 216 Utilisation des bases de données SQL locales Comme la préparation et l'exécution d'une instruction est une opération potentiellement exigeante, précharger les données initiales, puis exécuter les autres instructions en arrière-plan est une bonne stratégie. Chargez les données dont l'application a d'abord besoin. Lorsque les opérations de démarrage initial de votre application sont terminées, ou lors d'un autre moment d'inactivité de l'application, exécutez les autres instructions. Par exemple, si votre application n'accède pas du tout à la base de données pour afficher son écran initial, attendez que l'écran s'affiche, ouvrez la connexion à la base de données, puis créez les occurrences de SQLStatement et exécutez tout ce qui est possible. A l'inverse, supposons que votre application affiche immédiatement certaines données lors de son démarrage, par exemple le résultat d'une requête particulière. Dans ce cas, continuez et exécutez l'occurrence de SQLStatement pour cette requête. Dès que les données initiales sont chargées et affichées, créez des occurrences de SQLStatement pour les autres opérations de base de données et, si possible, exécutez ultérieurement les autres instructions nécessaires. Lorsque vous réutilisez une occurrence de SQLStatement, votre application doit conserver une référence à cette occurrence une fois celle-ci préparée. Pour conserver une référence à l'occurrence, déclarez la variable en tant que variable de domaine de classe et non en tant que variable de domaine de fonction. Pour ce faire, une bonne méthode consiste à structurer votre application de sorte que l'instruction SQL soit enveloppée dans une seule classe. Un groupe d'instructions exécutées en combinaison peut également être enveloppé dans une même classe. Définies en tant que variables de membre de la classe, la ou les occurrences de SQLStatement persistent tant que l'occurrence de la classe enveloppe existe dans l'application. Au minimum, vous pouvez simplement définir une variable contenant l'occurrence de SQLStatement à l'extérieur d'une fonction de sorte que cette occurrence reste en mémoire. Par exemple, déclarez l'occurrence de SQLStatement en tant que variable de membre d'une classe ActionScript ou en tant que variable autre qu'une fonction dans un fichier JavaScript. Vous pouvez ensuite définir les valeurs de paramètres de l'instruction et appeler sa méthode execute() lorsque vous souhaitez véritablement exécuter la requête. Regroupement de plusieurs opérations dans une transaction Supposons que vous exécutiez un grand nombre d'instructions SQL impliquant l'ajout ou la modification de données (instructions INSERT ou UPDATE). Vous pouvez augmenter significativement les performances en exécutant toutes les instructions dans une transaction explicite. Si vous ne commencez pas une transaction de façon explicite, chacune des instructions s'exécute dans sa propre transaction créée automatiquement. Lorsque l'exécution de chaque transaction (chaque instruction) est terminée, l'environnement d'exécution écrit les données résultantes dans le fichier de la base de données sur disque. Regardez à présent ce qu'il se passe si vous créez explicitement une transaction et exécutez les instructions dans le contexte de cette transaction. L'environnement d'exécution effectue toutes les modifications en mémoire, puis écrit simultanément toutes les modifications dans le fichier de la base de données lorsque la transaction est validée. L'écriture de données sur le disque est généralement la partie la plus longue de l'opération. Par conséquent, écrire sur le disque une seule fois plutôt qu'une fois par instruction SQL peut améliorer significativement les performances. Réduction du traitement de l'environnement d'exécution Les techniques suivantes peuvent éviter au moteur de base de données un travail inutile et améliorer le fonctionnement des applications : • Indiquez toujours explicitement les noms de base de données et les noms de table dans chaque instruction. (Utilisez « main » s'il s'agit de la base de données principale). Par exemple, utilisez SELECT employeeId FROM main.employees plutôt que SELECT employeeId FROM employees. Le fait de spécifier de façon explicite le nom de la base de données évite à l'environnement d'exécution d'avoir à rechercher la table correspondante dans chaque base de données. Cela lui évite également toute possibilité de se tromper de base de données. Respectez cette règle même lorsque l'occurrence de SQLConnection n'est connectée qu'à une seule base de données. En effet, en arrièreplan, l'occurrence de SQLConnection est également connectée à une base de données temporaire accessible par l'intermédiaire d'instructions SQL. • Spécifiez toujours explicitement les noms des colonnes dans une instruction SELECT ou INSERT. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 217 Utilisation des bases de données SQL locales • Divisez les lignes renvoyées par une instruction SELECT récupérant un grand nombre de lignes ; consultez la section « Récupération partielle des résultats d'une instruction SELECT » à la page 185. Evitement des modifications du schéma Si possible, évitez de modifier le schéma (structure des tables) d'une base de données après avoir ajouté des données dans ses tables. Normalement, un fichier de base de données est structuré avec les définitions de ses tables au début du fichier. Lorsque vous ouvrez une connexion à une base de données, l'environnement d'exécution charge ces définitions. Lorsque vous ajoutez des données dans les tables d'une base de données, ces données sont ajoutées dans le fichier après les données de définition des tables. Toutefois, si vous modifiez le schéma, par exemple en ajoutant une colonne dans une table ou en créant une nouvelle table, les nouvelles données de définition des tables sont mélangées aux données des tables dans le fichier de la base de données. Si les données de définition des tables ne sont pas toutes au début du fichier de la base de données, l'ouverture d'une connexion à la base de données demande plus de temps car l'environnement d'exécution doit lire ces données en différents emplacements du fichier. Si vous devez modifier le schéma, vous pouvez appeler la méthode SQLConnection.compact() lorsque les modifications sont terminées. Cette opération restructure le fichier de la base de données de sorte que les données de définition des tables soient regroupées au début du fichier. L'opération compact() peut cependant se révéler assez longue, en particulier au fur et à mesure que la taille du fichier de la base de données augmente. Recommandations concernant l'utilisation des bases de données SQL locales Voici une liste de techniques conseillées qui vous permettront d'améliorer les performances, la sécurité et la simplicité de maintenance de vos applications lors de l'utilisation de bases de données SQL locales. D'autres techniques d'amélioration des applications de base de données sont disponibles à la section « Amélioration des performances de la base de données » à la page 215. Création préalable des connexions à la base de données Même si votre application n'exécute aucune instruction lors de son premier chargement, instanciez un objet SQLConnection et appelez sa méthode open() ou openAsync() en amont (par exemple après le démarrage initial de l'application) pour éviter les délais lors de l'exécution des instructions. Consultez la section « Connexion à une base de données » à la page 175. Réutilisation des connexions à la base de données Si vous accédez à une certaine base de données pendant l'exécution de votre application, gardez une référence à l'occurrence de SQLConnection et réutilisez-la dans toute l'application au lieu de fermer et de rouvrir la connexion. Consultez la section « Connexion à une base de données » à la page 175. Choix préférentiel du mode asynchrone Lors de l'écriture du code d'accès aux données, il peut être tentant d'exécuter les opérations de façon synchrone plutôt que de façon asynchrone car cela demande souvent un code plus court et moins complexe. Toutefois, comme nous l'avons vu à la section « Utilisation des opérations de base de données synchrones et asynchrones » à la page 193, les opérations synchrones peuvent affecter les performances de façon évidente pour les utilisateurs et nuire à leur exploitation de l'application. Le temps nécessaire à l'exécution d'une seule opération varie d'une opération à l'autre et notamment en fonction de la quantité de données impliquées. Par exemple, une instruction SQL INSERT qui n'ajoute qu'une seule ligne à la base de données prend moins de temps qu'une instruction SELECT qui récupère des milliers de lignes de données. Toutefois, lorsque vous utilisez le mode synchrone pour exécuter plusieurs opérations, les opérations sont généralement enchaînées. Même si le temps nécessaire à chaque opération est très court, l'application se bloque jusqu'à ce que toutes les opérations synchrones soient terminées. En résultat, le temps cumulé des différentes opérations peut être suffisant pour bloquer votre application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 218 Utilisation des bases de données SQL locales Utilisez les opérations asynchrones comme approche habituelle, en particulier dans le cas d'opérations impliquant un grand nombre de lignes. Une technique permet de diviser le traitement des vastes jeux de résultats de l'instruction SELECT. Cette technique est décrite à la section « Récupération partielle des résultats d'une instruction SELECT » à la page 185. Cette technique ne peut cependant être utilisée qu'en mode d'exécution asynchrone. Utilisez uniquement les opérations synchrones lorsque vous ne pouvez pas obtenir certaines fonctionnalités avec la programmation asynchrone, lorsque vous avez pris en compte les baisses de performances que les utilisateurs de votre application rencontreront éventuellement et après avoir testé votre application de manière à connaître l'impact sur les performances. L'utilisation du mode d'exécution asynchrone peut impliquer un codage plus complexe. Toutefois, n'oubliez pas que le code ne doit être écrit qu'une seule fois alors que les utilisateurs emploient l'application de façon répétée, qu'elle soit rapide ou lente. Dans la plupart des cas, l'utilisation d'une occurrence de SQLStatement distincte pour chaque instruction SQL à exécuter permet de mettre plusieurs opérations SQL en file d'attente à la fois, ce qui, en termes d'écriture du code, rend le code asynchrone similaire au code synchrone. Pour plus d'informations, consultez la section « Présentation du modèle d'exécution asynchrone » à la page 196. Utilisation d'instructions SQL distinctes sans modification de la propriété text de l'occurrence de SQLStatement Pour chaque instruction SQL exécutée plusieurs fois dans une application, créez une occurrence de SQLStatement distincte. Servez-vous de cette occurrence de SQLStatement chaque fois que cette commande SQL s'exécute. Supposons par exemple que vous développiez une application comprenant quatre opérations SQL différentes exécutées à plusieurs reprises. Dans ce cas, créez quatre occurrences de SQLStatement distinctes et appelez la méthode execute() de chaque instruction pour l'exécuter. Evitez d'utiliser une seule occurrence de SQLStatement pour toutes les instructions SQL, en redéfinissant chaque fois sa propriété text avant d'exécuter l'instruction. Consultez la section « Utilisation d'une occurrence de SQLStatement pour chaque instruction SQL » à la page 215. Utilisation de paramètres d'instruction Utilisez des paramètres pour SQLStatement. Ne concaténez jamais la saisie de l'utilisateur dans le texte de l'instruction. L'utilisation de paramètres sécurise votre application car elle empêche les attaques par injection de code SQL. Il est alors possible d'utiliser des objets dans les requêtes (au lieu d'utiliser uniquement des valeurs littérales SQL). Cela renforce également l'efficacité de l'exécution des instructions car ces dernières peuvent être réutilisées sans qu'il soit nécessaire de les recompiler chaque fois qu'elles sont exécutées. Consultez la section « Utilisation de paramètres dans des instructions » à la page 178. Utilisation de constantes pour les noms des colonnes et des paramètres Lorsque vous ne spécifiez pas de propriété itemClass pour une occurrence de SQLStatement, définissez des constantes String contenant le nom des colonnes d'une table pour éviter les erreurs d'orthographe. Utilisez ensuite ces constantes dans le texte de l'instruction et pour les noms de propriété lors de la récupération des valeurs dans les objets de résultat. Utilisez également des constantes pour les noms des paramètres. 219 Chapitre 19 : Stockage des données chiffrées Le moteur d'exécution d'Adobe® AIR™ propose un magasin local chiffré persistant par application AIR installée sur l'ordinateur d'un utilisateur. Vous pouvez ainsi enregistrer et extraire les données stockées sur le disque dur local de l'utilisateur sous forme chiffrée, qui ne peuvent pas être aisément déchiffrées par d'autres applications ou utilisateurs. Un magasin local chiffré distinct est utilisé pour chaque application AIR et chacune d'elle fait appel à un magasin local chiffré par utilisateur. Remarque : outre le magasin local chiffré, AIR assure également le chiffrement du contenu stocké dans les bases de données SQL. Pour plus d'informations, consultez la section « Utilisation du chiffrement avec les bases de données SQL » à la page 197. Vous pouvez stocker dans le magasin local chiffré des informations à sécuriser, telles que les informations de connexion aux services Web. Pour associer le magasin local chiffré à chaque application et chaque utilisateur, AIR utilise DPAPI sous Windows, KeyChain sous Mac OS et KeyRing ou KWallet sous Linux. Le magasin local chiffré utilise le chiffrement AES-CBC 128 bits. Les informations stockées dans le magasin local chiffré sont réservées au contenu d'application AIR dans le sandbox de sécurité de l'application. Utilisez les méthodes statiques setItem() et removeItem() de la classe EncryptedLocalStore pour stocker et extraire les données du magasin local. Les données sont stockées dans une table de hachage, dans laquelle les chaînes font office de clés et les données stockées de tableaux d'octets. Par exemple, le code suivant stocke une chaîne dans le magasin local chiffré : 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" Le troisième paramètre de la méthode setItem(), stronglyBound, est facultatif. Lorsque ce paramètre est défini sur true, le magasin local chiffré assure un niveau de sécurité plus élevé en liant l'élément stocké à la signature numérique et aux bits de l'application AIR de stockage, ainsi qu'à l'identifiant d'éditeur de l'application dans le cas suivant : var str:String = "Bob"; var bytes:ByteArray = new ByteArray(); bytes.writeUTFBytes(str); EncryptedLocalStore.setItem("firstName", bytes, true); Si un élément est stocké alors que stronglyBound est défini sur true, les appels suivants de getItem() n'aboutissent que si l'application AIR à l'origine de l'appel est identique à l'application de stockage (en d'autres termes, si aucune donnée des fichiers résidant dans le répertoire de l'application n'a été modifiée). Si l'application AIR à l'origine de l'appel n'est pas identique à l'application de stockage, une exception Error est renvoyée lorsque vous appelez getItem() pour un élément à liaison forte. Si vous mettez à jour votre application, elle n'est plus en mesure de lire les données à liaison forte précédemment écrites dans le magasin local chiffré. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 220 Stockage des données chiffrées Par défaut, une application AIR ne peut pas lire le magasin local chiffré d'une autre application. Le paramètre stronglyBound renforce la liaison aux données dans les bits d'application, empêchant ainsi une application malveillante de tenter d'accéder au magasin local chiffré de votre application en utilisant l'identifiant d'éditeur de votre application. Si vous mettez à jour une application de sorte à utiliser un autre certificat de signature (par le biais d'une signature de migration), la version mise à jour ne sera pas en mesure d'accéder aux éléments stockés dans le magasin d'origine, même si le paramètre stronglyBound était défini sur false. Pour plus d'informations, consultez la section « Changement de certificats » à la page 332. Pour supprimer une valeur du magasin local chiffré, utilisez la méthode EncryptedLocalStore.removeItem(), comme dans l'exemple suivant : EncryptedLocalStore.removeItem("firstName"); Pour supprimer toutes les valeurs du magasin local chiffré, appelez la méthode EncryptedLocalStore.reset(), comme dans l'exemple suivant : EncryptedLocalStore.reset(); Lorsque vous déboguez une application dans l'application de débogage du lanceur AIR (ADL), celle-ci utilise un autre magasin local chiffré que celui utilisé par la version installée de l'application. Les performances du magasin local chiffré risquent d'être plus lentes si les données stockées dépassent 10 Mo. Lorsque vous désinstallez une application AIR, le programme de désinstallation ne supprime pas les données stockées dans le magasin local chiffré. Ces données sont transférées dans un sous-répertoire du répertoire de données d'applications de l'utilisateur, dont le chemin correspond à Adobe/AIR/ELS/, suivi de l'identifiant d'application. 221 Chapitre 20 : A propos de l'environnement HTML Adobe®AIR™ fait appel à WebKit (www.webkit.org), également utilisé par le navigateur Web Safari, pour analyser, disposer et rendre un contenu HTML ou JavaScript. Il n'est pas indispensable d'utiliser les API AIR dans un contenu HTML. Vous avez la possibilité de programmer intégralement le contenu d'un objet HTMLLoader ou d'une fenêtre HTML à l'aide des langages HTML et JavaScript. La plupart des pages et applications HTML existantes devraient être exécutées en présentant peu de modifications (à condition qu'elles utilisent des fonctions HTML, CSS, DOM et JavaScript compatibles avec WebKit). Etant donné que les applications AIR sont exécutées directement dans le poste de travail, en bénéficiant d'un accès complet au système de fichiers, le modèle de sécurité applicable au contenu HTML est plus strict que celui d'un navigateur Web standard. Dans AIR, seul le contenu chargé à partir du répertoire d'installation de l'application est placé dans le sandbox de l'application. Le sandbox de l'application dispose du niveau de privilège le plus élevé, l'autorisant à accéder aux API AIR. AIR place les autres contenus dans des sandbox distincts en fonction de leur origine. Les fichiers chargés à partir du système de fichiers sont placés dans un sandbox local tandis que ceux qui ont été chargés à partir du réseau à l'aide des protocoles http: ou https: sont dirigés vers un sandbox dépendant du domaine du serveur distant. L'accès à toute API AIR est interdit au contenu de ces sandbox qui ne sont pas des applications. Ce type de contenu est exécuté comme il le serait dans un navigateur Web classique. AIR fait appel à WebKit (www.webkit.org), également utilisé par le navigateur Web Safari, pour analyser, disposer et rendre un contenu HTML ou JavaScript. Les objets et les classes hôte d'AIR fournissent une API pour des fonctions généralement associées aux applications de bureau. Il s'agit, entre autres, de fonctions telles que la lecture et l'écriture de fichiers, et la gestion de fenêtres. Adobe AIR hérite également d'API provenant d'Adobe® Flash® Player, lequel comprend des fonctions telles que le son et les sockets binaires. Le contenu HTML visible dans AIR n'affiche pas de contenu SWF ou PDF si des paramètres alpha, de mise à l'échelle ou de transparence sont appliqués. Pour plus d'informations, consultez les sections Eléments à prendre en compte lors du chargement d'un contenu SWF ou PDF dans une page HTML et « Transparence de la fenêtre » à la page 65. Présentation de l'environnement HTML Adobe AIR propose un environnement JavaScript de type navigateur complet, doté d'une fonctionnalité de rendu HTML, d'un modèle d'objet de document et d'un interpréteur JavaScript. L'environnement JavaScript est représenté par la classe HTMLLoader d'AIR. Dans les fenêtres HTML, un objet HTMLLoader inclut tout le contenu HTML et est, à son tour, compris dans un objet NativeWindow. Dans un contenu SWF, il est possible d'ajouter la classe HTMLLoader, qui étend la classe Sprite, à la liste d'affichage d'une scène à l'instar de tout autre objet d'affichage. Les propriétés ActionScript™ de la classe sont décrites dans la section « Programmation du conteneur HTML » à la page 263 ainsi que dans le Guide de référence du langage ActionScript Flex 3. A propos de l'environnement JavaScript et de sa relation avec AIR Le diagramme suivant illustre la relation existant entre l'environnement JavaScript et l'environnement du moteur d'exécution AIR. Bien qu'une seule fenêtre native soit affichée, une application AIR peut contenir plusieurs fenêtres. (De même, une seule fenêtre peut comprendre de multiples objets HTMLLoader.) DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 222 A propos de l'environnement HTML AIR Run-time Environment NativeWindow HTMLLoader window JavaScript Environment window window body head htmlLoader native4Window runtime h1 div table p L'environnement JavaScript possède ses propres objets Document et Window. Le code JavaScript a des interactions avec l'environnement du moteur d'exécution AIR via les propriétés runtime, nativeWindow et htmlLoader. Quant au code ActionScript, il interagit avec l'environnement JavaScript par le biais de la propriété window d'un objet HTMLLoader, lequel fait référence à l'objet Window JavaScript. En outre, les objets ActionScript et JavaScript permettent d'écouter des événements envoyés à la fois par des objets AIR et JavaScript. La propriété runtime offre un accès aux classes API AIR, ce qui vous permet de créer de nouveaux objets AIR de même que d'accéder aux membres de la classe (également appelée statique). Pour accéder à une API AIR, ajoutez le nom de la classe (package compris) à la propriété runtime. Par exemple, pour créer un objet File, utilisez l'instruction suivante : var file = new window.runtime.filesystem.File(); Remarque : le kit de développement d'AIR contient un fichier JavaScript, intitulé AIRAliases.js, qui définit des alias plus pratiques pour les classes AIR les plus courantes. Lors de l'importation de ce fichier, vous pouvez utiliser la forme abrégée air.Class au lieu de window.runtime.package.Class. Vous pourriez, par exemple, créer l'objet File à l'aide de new air.File(). L'objet NativeWindow offre des propriétés permettant de contrôler la fenêtre du poste de travail. A partir d'une page HTML, vous pouvez accéder à l'objet NativeWindow conteneur à l'aide de la propriété window.nativeWindow. L'objet HTMLLoader propose des propriétés, des méthodes et des événements destinés à contrôler les modes de chargement et de rendu du contenu. A partir d'une page HTML, vous pouvez accéder à l'objet HTMLLoader parent à l'aide de la propriété window.htmlLoader. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 223 A propos de l'environnement HTML Important : seules les pages installées dans le cadre d'une application disposent des propriétés htmlLoader, nativeWindow ou runtime et ce, uniquement lorsqu'elles sont chargées en tant que document de niveau supérieur. Ces propriétés ne sont pas ajoutées dans le cas où le document est chargé dans une image ou une iframe. (Un document enfant peut accéder à ces propriétés dans le document parent du moment qu'il se trouve dans le même sandbox de sécurité. Par exemple, un document chargé dans un cadre pourrait accéder à la propriété runtime de son parent au moyen de parent.runtime.) A propos de la sécurité AIR exécute la totalité du code au sein d'un sandbox de sécurité dépendant du domaine d'origine. Le contenu de l'application, qui se limite au contenu chargé à partir du répertoire d'installation de l'application, est placé dans le sandbox de l'application. L'accès à l'environnement d'exécution et aux API AIR est uniquement disponible pour les scripts HTML et JavaScript exécutés dans ce sandbox. Parallèlement à cela, les opérations d'évaluation et d'exécution dynamiques de code JavaScript sont en grande partie bloquées dans le sandbox de l'application une fois que tous les gestionnaires de l'événement load de la page ont été renvoyés. Vous avez la possibilité de mapper une page d'application dans un sandbox autre que d'application. Pour ce faire, chargez la page dans une image ou une iframe et définissez les attributs sandboxRoot etdocumentRoot du cadre propres à AIR. En configurant la valeur de sandboxRoot sur un domaine distant réel, vous permettez au contenu placé dans le sandbox d'intercoder le contenu de ce domaine. Cette méthode de mappage de pages peut s'avérer pratique lors du chargement et du codage du contenu distant, dans le cadre d'une application composite par exemple. Une autre solution permettant d'intercoder des contenus d'application et autre (et la seule manière de donner accès à des API AIR à un contenu autre que d'application) consiste à créer un pont de sandbox. Un pont parent-enfant permet au contenu d'une image enfant, d'une iframe ou d'une fenêtre d'accéder à des méthodes et propriétés désignées définies dans le sandbox de l'application. A l'inverse, un pont enfant-parent permet au contenu de l'application d'accéder à des méthodes et propriétés désignées définies dans le sandbox de l'enfant. Pour définir un pont de sandbox, vous devez définir les propriétés parentSandboxBridge et childSandboxBridge de l'objet window. Pour plus d'informations, consultez les sections « Sécurité HTML » à la page 31 et « Eléments image et iframe HTML » à la page 231. A propos des modules externes et des objets incorporés AIR prend en charge le module externe Adobe® Acrobat®. Pour afficher le contenu PDF, les utilisateurs doivent disposer d'Acrobat ou d'Adobe® Reader® 8.1 (ou version ultérieure). L'objet HTMLLoader comprend une propriété permettant de vérifier si le système d'un utilisateur peut afficher ou non des documents PDF. Il est également possible d'afficher le contenu des fichiers SWF au sein de l'environnement HTML. Cette fonction étant intégrée dans AIR, elle ne fait appel à aucun module externe. AIR ne prend en charge aucun autre module externe Webkit. Voir aussi « Sécurité HTML » à la page 31 « Sandbox HTML » à la page 224 « Eléments image et iframe HTML » à la page 231 « Objet Window JavaScript » à la page 230 « Objet XMLHttpRequest » à la page 225 « Ajout de contenu PDF » à la page 277 DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 224 A propos de l'environnement HTML AIR et extensions Webkit Adobe AIR a recours au moteur Webkit, disponible en open source et également utilisé dans le navigateur Web Safari. AIR ajoute plusieurs extensions pour accéder aux objets et aux classes d'exécution ainsi que pour des raisons de sécurité. En outre, Webkit lui-même insère des fonctions non incluses dans les normes W3C des langages HTML, CSS et JavaScript. Seuls les ajouts d'AIR et les extensions Webkit les plus significatives sont évoquées dans cette section. Pour obtenir de la documentation supplémentaire sur les langages HTML, CSS et JavaScript non standard, consultez les sites www.webkit.org et developer.apple.com. Pour en savoir plus sur les normes, visitez le site Web W3C. Mozilla propose également une page de référence très intéressante portant sur les technologies HTML, CSS et DOM (bien évidemment, les moteurs Webkit et Mozilla sont différents l'un de l'autre). Remarque : AIR ne prend pas en charge les fonctions WebKit standard et étendues suivantes : la méthode print() de l'objet Window JavaScript, les modules externes (sauf Acrobat ou Adobe Reader 8.1 et versions ultérieures), les images SVG (Scalable Vector Graphics), la propriété opacity CSS. Code JavaScript dans AIR AIR apporte plusieurs modifications au comportement classique des objets JavaScript courants. La plupart de ces modifications sont destinées à simplifier l'écriture d'applications sécurisées dans AIR. Parallèlement à cela, ces différences de comportement impliquent que certains modèles de codage JavaScript courants et les applications Web existantes qui s'en servent risquent de ne pas fonctionner comme prévu dans AIR. Pour plus d'informations sur la correction de ces types de problèmes, consultez la section « Contournement des erreurs JavaScript liées à la sécurité » à la page 239. Sandbox HTML AIR place les différents contenus dans des sandbox distincts en fonction de leur origine. Les règles de sandbox respectent la stratégie de « même origine » implémentée par la plupart des navigateurs Web, de même que les règles applicables aux sandbox mises en œuvre par Adobe Flash Player. AIR propose en outre un nouveau type de sandbox d'application conçu pour contenir et protéger le contenu de l'application. Pour plus d'informations sur les types de sandbox que vous êtes susceptible de rencontrer lors du développement d'applications AIR, consultez la section « Sandbox » à la page 28. L'accès à l'environnement d'exécution et aux API AIR est uniquement disponible pour les scripts HTML et JavaScript exécutés dans le sandbox de l'application. Parallèlement à cela, toutefois, les opérations d'évaluation et d'exécution dynamiques de code JavaScript, sous leurs diverses formes, sont largement limitées au sein du sandbox de l'application pour des raisons de sécurité. Ces restrictions s'appliquent que votre application charge réellement ou non des informations directement depuis un serveur. (Même le contenu des fichiers, les chaînes collées et les données saisies directement par l'utilisateur peuvent ne pas être fiables.) L'origine du contenu d'une page détermine le sandbox associé au contenu. Seul le contenu chargé à partir du répertoire de l'application (le répertoire d'installation auquel le modèle d'URL app: fait référence) est placé dans le sandbox de l'application. Tout contenu chargé à partir du système de fichiers est placé dans le sandbox local avec système de fichiers ou le sandbox de sécurité approuvé localement, lequel permet d'accéder au contenu situé sur le système de fichiers local (mais pas au contenu distant) et d'interagir avec lui. Tout contenu chargé à partir du réseau est dirigé vers un sandbox distant correspondant à son domaine d'origine. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 225 A propos de l'environnement HTML Pour qu'une page d'application puisse interagir librement avec un contenu situé dans un sandbox distant, vous pouvez la mapper au même domaine que le contenu distant. Si, par exemple, vous écrivez une application affichant des données de mappage provenant d'un service Internet, la page de l'application qui est chargée et qui présente le contenu émanant du service pourrait être mappée au domaine du service. Les attributs de mappage des pages dans un sandbox et un domaine distants sont de nouveaux attributs ajoutés aux éléments image et iframe HTML. Pour permettre à un contenu d'un sandbox autre que d'application d'utiliser les fonctions d'AIR en toute sécurité, vous pouvez configurer un pont de sandbox parent. Pour permettre au contenu de l'application d'appeler des méthodes et des propriétés d'accès de contenu en toute sécurité dans d'autres sandbox, configurez un pont de sandbox enfant. La notion de sécurité évoquée ici signifie que le contenu distant ne peut pas obtenir accidentellement de références à des objets, des propriétés ou des méthodes exposés de manière non explicite. Seuls les objets anonymes, fonctions et types de données simples peuvent être transmis via le pont. Vous devez néanmoins éviter d'exposer explicitement des fonctions potentiellement dangereuses. Si, par exemple, vous avez exposé une interface qui autorisait le contenu distant à lire et à écrire des fichiers n'importe où sur le système d'un utilisateur, vous risquez de donner à ce contenu les moyens de nuire considérablement aux utilisateurs. Fonction eval() JavaScript L'utilisation de la fonction eval() est limitée au contenu du sandbox de l'application une fois le téléchargement de la page terminé. Dans certains cas, cette fonction peut servir à analyser en toute sécurité des données au format JSON, mais toute évaluation aboutissant à des résultats d'instructions exécutables se traduit par une erreur. La section « Restrictions relatives au code pour un contenu dans des sandbox différents » à la page 33 décrit les utilisations autorisées pour la fonction eval(). Constructeurs de fonctions Dans le sandbox d'application, il est possible d'utiliser des constructeurs de fonctions avant la fin du chargement d'une page. Dès lors que tous les gestionnaires d'événement load de page sont terminés, il est impossible de créer de nouvelles fonctions. Chargement d'un script externe Les pages HTML du sandbox de l'application ne peuvent pas utiliser la balise script pour charger des fichiers JavaScript situés en dehors du répertoire de l'application. Pour qu'une page de votre application puisse charger un script stocké en dehors du répertoire de l'application, vous devez la mapper dans un sandbox autre que celui de d'application. Objet XMLHttpRequest AIR fournit un objet XMLHttpRequest (XHR) dont les applications peuvent se servir pour émettre des requêtes de données. L'exemple suivant illustre une demande de données simple : 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); Contrairement à un navigateur, AIR permet au contenu exécuté dans le sandbox de l'application de demander des données provenant de n'importe quel domaine. Le résultat d'une requête XHR contenant une chaîne JSON peut aboutir à des objets de données à moins de comprendre également du code exécutable. Si des instructions exécutables figurent dans le résultat de la requête XHR, une erreur est renvoyée et la tentative d'évaluation se solde par un échec. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 226 A propos de l'environnement HTML Pour empêcher l'introduction accidentelle de code provenant de sources distantes, les requêtes XHR synchrones renvoient un résultat vide lorsqu'elles sont émises avant la fin du chargement de la page. Les requêtes XHR asynchrones sont toujours renvoyées après le chargement d'une page. Par défaut, AIR bloque les requêtes XMLHttpRequest interdomaines dans les sandbox autres que d'application. Une fenêtre parent du sandbox de l'application peut choisir d'autoriser des requêtes interdomaines dans une image enfant dont le contenu ne se trouve pas dans un sandbox autre que d'application. Pour ce faire, définissez allowCrossDomainXHR, un attribut ajouté par AIR, sur la valeur true dans l'élément image ou iframe conteneur : <iframe id="mashup" src="http://www.example.com/map.html" allowCrossDomainXHR="true" </iframe> Remarque : si cela s'avère pratique, il est aussi possible de télécharger les données à l'aide de la classe URLStream AIR. Si vous distribuez une requête XMLHttpRequest vers un serveur distant à partir d'une image ou d'une iframe doté du contenu de l'application mappé dans un sandbox distant, assurez-vous que l'URL de mappage ne masque pas l'adresse du serveur utilisé dans la requête XHR. Tenez compte, par exemple, de la définition d'iframe suivante, laquelle mappe le contenu de l'application dans un sandbox distant pour le domaine example.com : <iframe id="mashup" src="http://www.example.com/map.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/" allowCrossDomainXHR="true" </iframe> Etant donné que l'attribut sandboxRoot remappe l'URL racine de l'adresse www.example.com, toutes les requêtes sont chargées à partir du répertoire de l'application et non du serveur distant. Les requêtes sont remappées, qu'elles soient issues de la navigation dans les pages ou d'une requête XMLHttpRequest. Afin d'éviter de bloquer accidentellement des requêtes de données en direction du serveur distant, mappez sandboxRoot à un sous-répertoire de l'URL distante plutôt qu'à la racine. Le répertoire ne doit pas nécessairement exister. Par exemple, pour permettre le chargement des requêtes en direction de www.example.com à partir du serveur distant plutôt que du répertoire de l'application, modifiez l'iframe précédente de la manière suivante : <iframe id="mashup" src="http://www.example.com/map.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/" allowCrossDomainXHR="true" </iframe> Dans ce cas, seul le contenu du sous-répertoire air est chargé en local. Pour plus d'informations sur le mappage de sandbox, consultez les sections « Eléments image et iframe HTML » à la page 231 et « Sécurité HTML » à la page 31. Objet Canvas L'objet Canvas définit une API permettant de dessiner des formes géométriques telles que des lignes, des arcs, des ellipses et des polygones. Pour utiliser l'API Canvas, commencez par ajouter un élément canvas au document, puis dessinez dedans à l'aide de l'API Canvas JavaScript. L'objet Canvas se comporte comme une image dans la plupart des autres domaines. Dans l'exemple suivant, un triangle est dessiné à l'aide d'un objet Canvas : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 227 A propos de l'environnement 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> Pour obtenir de la documentation sur l'API Canvas, visitez le site (en anglais) Safari JavaScript Reference d'Apple. Vous noterez que le projet Webkit vient de commencer à modifier l'API Canvas à des fins de normalisation avec le document HTML 5 Working Draft proposé par le groupe de travail WHATWG (Web Hypertext Application Technology Working Group) et le consortium W3C. De ce fait, certaines parties du guide de référence Safari JavaScript Reference peuvent ne pas concorder avec la version de l'objet canvas utilisée dans AIR. Cookies Dans les applications AIR, seul le contenu des sandbox distants (chargé à partir de sources http: et https:) peut utiliser des cookies (propriété document.cookie). Dans le sandbox de l'application, les API AIR offrent d'autres moyens de stockage des données persistantes (tels que les classes EncryptedLocalStore et FileStream). Objet Clipboard L'API Clipboard de WebKit est dotée des événements suivants : copy, cut et paste. L'objet événement transmis dans ces événements permet d'accéder au presse-papiers via la propriété clipboardData. Faites appel aux méthodes suivantes de l'objet clipboardData pour lire ou écrire des données de presse-papiers : Méthode Description clearData(mimeType) Efface les données du presse-papiers. Définissez le paramètre mimeType sur le type MIME des données à effacer. getData(mimeType) Permet d'obtenir les données du presse-papiers. Cette méthode peut uniquement être appelée dans un gestionnaire pour l'événement paste. Définissez le paramètre mimeType sur le type MIME des données à renvoyer. setData(mimeType, data) Copie les données dans le presse-papiers. Définissez le paramètre mimeType sur le type MIME des données. Le code JavaScript situé en dehors du sandbox de l'application peut uniquement accéder au presse-papiers par le biais de ces événements. Toutefois, le contenu du sandbox de l'application a la possibilité d'accéder directement au pressepapiers du système à l'aide de la classe Clipboard AIR. Par exemple, l'instruction suivante pourrait servir à obtenir des données au format texte du presse-papiers : var clipping = air.Clipboard.generalClipboard.getData("text/plain", air.ClipboardTransferMode.ORIGINAL_ONLY); Les types MIME de données valides sont les suivants : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 228 A propos de l'environnement HTML Type MIME Valeur Texte "text/plain" HTML "text/html" URL "text/uri-list" Image bitmap "image/x-vnd.adobe.air.bitmap" Liste de fichiers "application/x-vnd.adobe.air.file-list" Important : seul le contenu du sandbox de l'application peut accéder aux données de fichier stockées dans le pressepapiers. Si du contenu hors application tente d'accéder à un objet fichier du presse-papiers, une erreur de sécurité est générée. Pour plus d'informations sur l'utilisation du presse-papiers, consultez la section « Opération copier-coller » à la page 151 et la page Using the Pasteboard from JavaScript (du centre des développeurs Apple). Opération glisser-déposer Les mouvements de glisser-déposer vers et depuis un contenu HTML génèrent les événements DOM suivants : dragstart, drag, dragend, dragenter, dragover, dragleave et drop. L'objet événement transmis dans ces événements permet d'accéder aux données déplacées via la propriété dataTransfer. La propriété dataTransfer fait référence à un objet offrant les mêmes méthodes que l'objet clipboardData associé à un événement clipboard. Par exemple, la fonction suivante pourrait servir à obtenir des données au format texte à partir d'un événement drop : function onDrop(dragEvent){ return dragEvent.dataTransfer.getData("text/plain", air.ClipboardTransferMode.ORIGINAL_ONLY); } L'objet dataTransfer dispose des membres importants suivants : Membre Description clearData(mimeType) Efface les données. Définissez le paramètre mimeType sur le type MIME de la représentation de données à effacer. getData(mimeType) Permet d'obtenir les données que vous avez fait glisser. Cette méthode peut uniquement être appelée dans un gestionnaire pour l'événement drop. Définissez le paramètre mimeType sur le type MIME des données à obtenir. setData(mimeType, data) Définit les données à faire glisser. Définissez le paramètre mimeType sur le type MIME des données. types Tableau de chaînes contenant les types MIME de toutes les représentations de données actuellement disponibles dans l'objet dataTransfer. effectsAllowed Indique si les données que vous faites glisser peuvent être copiées, déplacées et/ou liées. Définissez la propriété effectsAllowed du gestionnaire pour l'événement dragstart. dropEffect Indique, parmi les effets de type drop (déposer) autorisés, ceux qui sont pris en charge par une cible de type drag (glisser). Définissez la propriété dropEffect du gestionnaire pour l'événement dragEnter. Au cours du glissement, le curseur change de forme afin d'indiquer l'effet qui se produirait si l'utilisateur relâchait le bouton de la souris. Si aucun effet dropEffect n'est spécifié, un effet doté de la propriété effectsAllowed est appliqué. L'effet copy (copier) est prioritaire sur l'effet move (déplacer), lequel a priorité sur l'effet link (lier). L'utilisateur peut modifier le niveau de priorité par défaut au moyen du clavier. Pour plus d'informations sur l'ajout de la prise en charge du glisser-déposer à une application AIR, consultez la section « Opération glisser-déposer » à la page 135 et la page Using the Drag-and-Drop from JavaScript (du centre de développeurs Apple). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 229 A propos de l'environnement HTML Propriétés innerHTML et outerHTML Pour des raisons de sécurité, AIR limite l'utilisation des propriétés innerHTML et outerHTML avec un contenu exécuté dans le sandbox de l'application. Avant l'événement de chargement de la page, de même que pendant l'exécution de tout gestionnaire d'événement de chargement, l'utilisation des propriétés innerHTML et outerHTML n'est pas restreinte. Toutefois, dès lors que la page est chargée, vous pouvez uniquement vous servir des propriétés innerHTML ou outerHTML afin d'ajouter un contenu statique au document. Toute instruction de la chaîne attribuée à innerHTML ou à outerHTML qui aboutit à du code exécutable est ignorée. Si, par exemple, vous incluez un attribut de rappel d'événement dans une définition d'élément, l'écouteur d'événement n'est pas inséré. De la même manière, les balises <script> intégrées ne sont pas évaluées. Pour plus d'informations, consultez la section « Sécurité HTML » à la page 31. Méthodes Document.write() et Document.writeln() L'utilisation des méthodes write() et writeln() n'est pas limitée dans le sandbox de l'application avant la survenue de l'événement load de la page. Toutefois, dès lors que la page est chargée, l'appel de l'une ou l'autre de ces méthodes n'efface pas la page ou n'en crée pas de nouvelle. Dans un sandbox autre que celui de l'application, comme dans la plupart des navigateurs Web, l'appel de la méthode document.write() ou writeln() après la fin du chargement de la page entraîne l'effacement de la page active et l'ouverture d'une nouvelle page vide. Propriété Document.designMode Définissez la propriété document.designMode sur la valeur on afin de rendre tous les éléments du document modifiables. L'éditeur intégré prend en charge les modifications de texte, la copie, le collage et le glisser-déposer. Définir designMode sur on revient au même que configurer la propriété contentEditable de l'élément body sur la valeur true. La propriété contentEditable permet de définir les sections modifiables d'un document pour la plupart des éléments HTML. Pour plus d'informations, consultez la section « Attribut contentEditable HTML » à la page 234. Evénements unload (pour les objets body et frameset) Dans la balise frameset ou body de niveau supérieur d'une fenêtre (y compris la fenêtre principale de l'application), ne répondez pas à la fenêtre (ou à l'application) en cours de fermeture au moyen de l'événement unload. Au lieu de cela, optez pour l'événement exiting de l'objet NativeApplication (afin de détecter le moment de fermeture d'une application). Une autre solution consiste à utiliser l'événement closing de l'objet NativeWindow (afin de détecter le moment de fermeture d'une fenêtre). Par exemple, le code JavaScript suivant affichage un message (« Goodbye ») lorsque l'utilisateur ferme l'application : var app = air.NativeApplication.nativeApplication; app.addEventListener(air.Event.EXITING, closeHandler); function closeHandler(event) { alert("Goodbye."); } Toutefois, les scripts peuvent réagir correctement à l'événement unload déclenché par la navigation dans une image, une iframe ou le contenu d'une fenêtre de niveau supérieur. Remarque : il est probable que ces limitations soient supprimées dans une prochaine version d'Adobe AIR. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 230 A propos de l'environnement HTML Objet Window JavaScript L'objet Window reste l'objet global dans le contexte d'exécution JavaScript. Dans le sandbox de l'application, AIR insère de nouvelles propriétés dans l'objet Window JavaScript en vue d'offrir un accès aux classes intégrées d'AIR de même qu'à des objets hôte importants. En outre, certaines méthodes et propriétés se comportent différemment selon qu'elles se trouvent dans le sandbox de l'application ou pas. Propriété Window.runtime La propriété runtime vous permet d'instancier et d'utiliser les classes d'exécution intégrées à partir du sandbox de l'application. Ces classes comprennent les API AIR et Flash Player (mais pas, par exemple, la structure Flex). L'instruction suivante crée par exemple un objet de fichier AIR : var preferencesFile = new window.runtime.flash.filesystem.File(); Le fichier AIRAliases.js, disponible dans le kit SDK d'AIR, contient des définitions d'alias permettant de raccourcir de telles références. Ainsi, lorsque le fichier AIRAliases.js est importé dans une page, il est possible de créer un objet File à l'aide de l'instruction suivante : var preferencesFile = new air.File(); La propriété window.runtime est exclusivement définie pour un contenu situé dans le sandbox de l'application et uniquement pour le document parent d'une page dotée d'images ou d'iframes. Consultez la section « Utilisation du fichier AIRAliases.js » à la page 244. Propriété Window.nativeWindow La propriété nativeWindow fournit une référence à l'objet window natif sous- jacent. Grâce à cette propriété, vous pouvez coder des fonctions et propriétés de fenêtre (window) telles que la position, la taille et la visibilité, et gérer des événements de fenêtre comme la fermeture, le redimensionnement et le déplacement. Dans l'exemple suivant, l'instruction permet de fermer la fenêtre : window.nativeWindow.close(); Remarque : les fonctions de contrôle de la fenêtre fournies par l'objet NativeWindow chevauchent celles fournies par l'objet Window JavaScript. Dans de tels cas, vous pouvez opter pour la méthode qui vous semble la plus pratique. La propriété window.nativeWindow est exclusivement définie pour un contenu situé dans le sandbox de l'application et pour le document parent d'une page dotée d'images ou d'iframes. Propriété Window.htmlLoader La propriété htmlLoader fournit une référence à l'objet HTMLLoader AIR disposant du contenu HTML. Grâce à cette propriété, vous pouvez coder l'aspect et le comportement de l'environnement HTML. Vous pouvez ainsi utiliser la propriété htmlLoader.paintsDefaultBackground afin de déterminer si la commande dessine un arrière-plan blanc par défaut : window.htmlLoader.paintsDefaultBackground = false; Remarque : l'objet HTMLLoader proprement dit est doté d'une propriété window, laquelle fait référence à l'objet Window JavaScript du contenu HTML inclus. Cette propriété vous permet d'accéder à l'environnement JavaScript via une référence à l'objet HTMLLoader conteneur. La propriété window.htmlLoader est exclusivement définie pour un contenu situé dans le sandbox de l'application et pour le document parent d'une page dotée d'images ou d'iframes. Propriétés Window.parentSandboxBridge et Window.childSandboxBridge Les propriétés parentSandboxBridge et childSandboxBridge vous permettent de définir une interface entre un cadre parent et un cadre enfant. Pour plus d'informations, consultez la section « Programmation croisée du contenu dans des sandbox de sécurité distincts » à la page 252. Fonctions Window.setTimeout() et Window.setInterval() Pour des raisons de sécurité, AIR limite l'utilisation des fonctions setTimeout() et setInterval() dans le sandbox de l'application. Il est impossible de définir le code à exécuter sous forme de chaîne lors de l'appel de la fonction setTimeout() ou setInterval(). Vous devez DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 231 A propos de l'environnement HTML impérativement utiliser une référence à la fonction. Pour plus d'informations, consultez la section « setTimeout() et setInterval() » à la page 241. Fonction Window.open() Lorsqu'elle est appelée par du code exécuté dans un sandbox autre que d'application, la méthode open() ouvre seulement une fenêtre si elle est appelée suite à une action utilisateur (telle qu'un clic de souris ou l'activation d'une touche du clavier). De plus, le titre de la fenêtre est précédé du titre de l'application (afin d'empêcher l'ouverture de fenêtres par du contenu distant provenant de fenêtres d'usurpation d'identité ouvertes par l'application). Pour plus d'informations, consultez la section « Restrictions relatives à l'appel de la méthode window.open() de JavaScript » à la page 36. Objet air.NativeApplication L'objet NativeApplication fournit des informations sur l'état de l'application, distribue différents événements de niveau application importants et offre des fonctions pratiques de contrôle du comportement de l'application. Une occurrence unique de l'objet NativeApplication est créée automatiquement. Elle est accessible via la propriété NativeApplication.nativeApplication définie dans la classe. Pour accéder à l'objet à partir du code JavaScript, vous pouvez utiliser : var app = window.runtime.flash.desktop.NativeApplication.nativeApplication; Autre solution, si le script AIRAliases.js a été importé, vous adoptez la forme plus courte suivante : var app = air.NativeApplication.nativeApplication; L'objet NativeApplication est uniquement accessible à partir du sandbox de l'application. La section « Utilisation des informations sur le moteur d'exécution et les systèmes d'exploitation » à la page 305 décrit en détail l'objet NativeApplication. Modèle d'URL JavaScript L'exécution d'un code défini dans un modèle d'URL JavaScript (comme dans href="javascript:alert('Test')") est bloquée au sein du sandbox de l'application. Aucune erreur n'est renvoyée. Extensions d'éléments HTML AIR et WebKit définissent une série d'éléments et d'attributs HTML non standard, à savoir : « Eléments image et iframe HTML » à la page 231 « Elément Canvas HTML » à la page 233 « Gestionnaires d'événement d'élément HTML » à la page 234 Eléments image et iframe HTML AIR ajoute de nouveaux attributs aux éléments image et iframe de contenu dans le sandbox de l'application : Attribut sandboxRoot L'attribut sandboxRoot spécifie un domaine de remplacement autre que d'application d'origine pour le fichier indiqué par l'attribut src du cadre. Le fichier est chargé dans le sandbox autre que d'application correspondant au domaine précisé. Le contenu du fichier et celui chargé à partir du domaine indiqué peuvent être intercodés. Important : si vous définissez la valeur de sandboxRoot sur l'URL de base du domaine, toutes les requêtes de contenu provenant de ce domaine sont chargées depuis le répertoire de l'application au lieu du serveur distant (qu'elles résultent d'une opération de navigation dans les pages, d'une requête XMLHttpRequest ou d'une autre méthode de chargement de contenu). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 232 A propos de l'environnement HTML Attribut documentRoot L'attribut documentRoot indique le répertoire local à partir duquel sont chargées les URL renvoyant à des fichiers situés à l'emplacement spécifié par sandboxRoot. Lors de la résolution des URL, soit dans l'attribut src du cadre soit dans le contenu chargé dans le cadre, la partie de l'URL correspondant à la valeur précisée dans sandboxRoot est remplacée par celle définie dans documentRoot. Par conséquent, dans la balise de cadre suivante : <iframe src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/"/> child.html est chargé depuis le sous-répertoire sandbox du dossier d'installation de l'application. Les URL relatives contenues dans child.html sont résolues en fonction du répertoire sandbox. Vous noterez que les fichiers situés sur le serveur distant à l'adresse www.example.com/air ne sont pas accessibles dans le cadre, car AIR tenterait sinon de les charger à partir du répertoire app:/sandbox/. Attribut allowCrossDomainXHR Incluez allowCrossDomainXHR="allowCrossDomainXHR" dans la balise de cadre d'ouverture afin de permettre au contenu du cadre d'émettre des requêtes XMLHttpRequest en direction de tout domaine distant. Par défaut, un contenu autre que d'application peut uniquement effectuer de telles requêtes en direction de son propre domaine d'origine. La possibilité d'effectuer des XHR interdomaines entraîne des risques importants au niveau de la sécurité. Le code de la page permet en effet d'échanger des données avec n'importe quel domaine. Si un contenu malveillant est introduit dans la page d'une manière quelconque, toutes les données accessibles au code dans le sandbox actif sont en danger. C'est pourquoi il est recommandé d'activer uniquement les requêtes XHR interdomaines pour les pages que vous créez et contrôlez, et à condition que le chargement de données interdomaines soit réellement nécessaire. En outre, validez avec précaution toutes les données externes chargées par la page afin d'empêcher l'introduction de code ou d'autres formes d'attaques. Important : si l'attribut allowCrossDomainXHR se trouve dans un élément image ou iframe, les requêtes XHR interdomaines sont activées (à moins que la valeur attribuée soit égale à 0 ou commence par les lettres f ou n). Par exemple, définir allowCrossDomainXHR sur la valeur deny maintient l'activation des requêtes XHR interdomaines. Excluez totalement l'attribut de la déclaration d'élément si vous préférez ne pas activer les requêtes interdomaines. Attribut ondominitialize Indique un gestionnaire d'événement pour l'événement dominitialize d'un cadre. Cet événement, spécifique à AIR, est déclenché une fois que les objets window et document du cadre ont été créés, mais avant l'analyse des scripts ou la création d'éléments de document. Le cadre distribue l'événement dominitialize suffisamment tôt dans la séquence de chargement pour qu'un script de la page enfant puisse référencer les objets, variables et fonctions ajoutés au document enfant par le gestionnaire dominitialize. La page parent doit se trouver dans le même sandbox que l'enfant pour pouvoir insérer ou ouvrir directement tout objet figurant dans un document enfant. Toutefois, un parent situé dans le sandbox de l'application peut établir un pont de sandbox afin de communiquer avec le contenu d'un sandbox autre que d'application. Les exemples suivants illustrent l'utilisation de la balise iframe dans AIR : Placez child.html dans un sandbox distant, sans définir de mappage à un domaine réel situé sur un serveur distant : <iframe src="http://localhost/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://localhost/air/"/> Placez child.html dans un sandbox distant, en autorisant uniquement les requêtes XMLHttpRequest émises en direction de www.example.com : <iframe src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/"/> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 233 A propos de l'environnement HTML Placez child.html dans un sandbox distant, en autorisant les requêtes XMLHttpRequest émises en direction de n'importe quel domaine distant : <iframe src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/" allowCrossDomainXHR="allowCrossDomainXHR"/> Placez child.html dans un sandbox local avec système de fichiers : <iframe src="file:///templates/child.html" documentRoot="app:/sandbox/" sandboxRoot="app-storage:/templates/"/> Placez child.html dans un sandbox distant en vous servant de l'événement dominitialize pour établir un pont de 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> Le document child.html suivant illustre la procédure d'accès du contenu enfant au pont de sandbox parent : <html> <head> <script> document.write(window.parentSandboxBridge.testProperty); </script> </head> <body></body> </html> Pour plus d'informations, consultez les sections « Programmation croisée du contenu dans des sandbox de sécurité distincts » à la page 252 et « Sécurité HTML » à la page 31. Elément Canvas HTML Définit une zone de dessin à utiliser avec l'API Canvas Webkit. Il est impossible de définir les commandes graphiques dans la balise elle-même. Pour dessiner dans le plan de travail, appelez les méthodes appropriées via le code JavaScript. <canvas id="drawingAtrium" style="width:300px; height:300px;"></canvas> Pour plus d'informations, consultez la section « Objet Canvas » à la page 226. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 234 A propos de l'environnement HTML Gestionnaires d'événement d'élément HTML Dans AIR et Webkit, les objets DOM distribuent certains événements introuvables dans le modèle d'événement DOM standard. Le tableau suivant dresse la liste des attributs d'événement associés que vous pouvez utiliser afin de spécifier des gestionnaires pour ces événements : Nom de l'attribut de rappel Description oncontextmenu Appelé lorsqu'un menu contextuel est invoqué, comme par le biais d'un clic droit ou d'un clic associé à une commande sur le texte sélectionné. oncopy Appelé lorsqu'une sélection d'un élément est copiée. oncut Appelé lorsqu'une sélection d'un élément est coupée. ondominitialize Appelé lorsque le DOM d'un document chargé dans une image ou une iframe est créé, mais avant que tout élément DOM ne soit créé ou que les scripts soient analysés. ondrag Appelé lorsqu'un élément est déplacé par glissement. ondragend Appelé lorsqu'un glissement est relâché. ondragenter Appelé lorsqu'un mouvement de glissement entre dans les limites d'un élément. ondragleave Appelé lorsqu'un mouvement de glissement quitte les limites d'un élément. ondragover Appelé continuellement lorsqu'un mouvement de glissement se trouve dans les limites d'un élément. ondragstart Appelé lorsqu'un mouvement de glissement commence. ondrop Appelé lorsqu'un mouvement de glissement est relâché au-dessus d'un élément. onerror Appelé lorsqu'une erreur se produit au cours du chargement d'un élément. oninput Appelé lorsque du texte est saisi dans un élément de formulaire. onpaste Appelé lorsqu'un élément est collé dans un élément. onscroll Appelé lorsque le contenu d'un élément qui défile est en train de défiler. onsearch Appelé lorsqu'un élément est recherché. (à vérifier dans la doc Apple) onselectstart Appelé lorsqu'une sélection commence. Attribut contentEditable HTML Vous pouvez ajouter l'attribut contentEditable à tout élément HTML permettant aux utilisateurs de modifier le contenu de l'élément. Par exemple, dans l'exemple suivant, le code HTML définit la totalité du document comme étant modifiable, à l'exception du premier élément p : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 235 A propos de l'environnement HTML <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> Remarque : si vous définissez la propriété document.designMode sur la valeur on, tous les éléments du document deviennent modifiables, quelle que soit la configuration de l'attribut contentEditable d'un élément particulier. Toutefois, la définition de designMode sur la valeur off ne désactive pas la modification des éléments pour lesquels l'attribut contentEditable est défini sur true. Pour plus d'informations, consultez la section « Propriété Document.designMode » à la page 229. Extensions des propriétés CSS WebKit prend en charge plusieurs propriétés CSS étendues. Le tableau suivant dresse la liste des propriétés étendues prises en charge. Des propriétés non standard supplémentaires sont disponibles dans WebKit, mais elles ne sont pas entièrement prises en charge par AIR, soit parce qu'elles sont encore en cours de développement dans WebKit, soit parce qu'il s'agit de fonctions expérimentales susceptibles d'être retirées du produit par la suite. Nom de la propriété CSS Valeurs Description -webkit-border-horizontal-spacing Unité de longueur non négative Indique le composant horizontal de l'espacement de la bordure. -webkit-border-vertical-spacing Unité de longueur non négative Indique le composant vertical de l'espacement de la bordure. -webkit-line-break after-white-space, normal Indique la règle de saut de ligne à utiliser dans les textes en chinois, japonais et coréen (CJK). -webkit-margin-bottom-collapse collapse, discard, separate Définit le mode de réduction de la marge inférieure d'une cellule de tableau. -webkit-margin-collapse collapse, discard, separate Définit le mode de réduction des marges supérieure et inférieure d'une cellule de tableau. -webkit-margin-start N'importe quelle unité de longueur Largeur de la marge de début. Pour les textes de gauche à droite, cette propriété remplace la valeur de la marge de gauche. Pour les textes de droite à gauche, cette propriété remplace la valeur de la marge de droite. -webkit-margin-top-collapse collapse, discard, separate Définit le mode de réduction de la marge supérieure d'une cellule de tableau. -webkit-nbsp-mode normal, space Définit le comportement des espaces insécables au sein du contenu. -webkit-padding-start N'importe quelle unité de longueur Indique la largeur du remplissage de début. Pour les textes de gauche à droite, cette propriété remplace la valeur de remplissage de gauche. Pour les textes de droite à gauche, cette propriété remplace la valeur de remplissage de droite. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 236 A propos de l'environnement HTML Nom de la propriété CSS Valeurs Description -webkit-rtl-ordering logical, visual Remplace le traitement par défaut des documents contenant à la fois du texte écrit de gauche à droite et de droite à gauche. -webkit-text-fill-color N'importe quelle couleur existante ou valeur de couleur numérique Indique la couleur de fond du texte. -webkit-text-security circle, disc, none, square Indique la forme de remplacement à utiliser dans le champ de saisie d'un mot de passe. -webkit-user-drag • auto : comportement par défaut Remplace le comportement de glissement automatique. • element : élément entier ayant glissé • none : impossible de faire glisser l'élément -webkit-user-modify read-only, read-write, read-writeplaintext-only Indique si le contenu d'un élément est modifiable. -webkit-user-select • auto : comportement par défaut Indique si un utilisateur peut sélectionner le contenu d'un élément. • none : impossible de sélectionner l'élément • text : seul le texte compris dans l'élément est sélectionnable Pour plus d'informations, consultez le document Safari CSS Reference d'Apple (http://developer.apple.com/documentation/AppleApplications/Reference/SafariCSSRef/). 237 Chapitre 21 : Programmation en HTML et JavaScript Un certain nombre de sujets sur la programmation portent exclusivement sur le développement d'applications Adobe® AIR™ avec HTML et JavaScript. Les informations qui suivent sont importantes, que vous programmiez une application AIR à base d'HTML ou bien sur SWF qui exécute HTML et JavaScript à l'aide de la classe HTMLLoader (ou du composant mx:HTML Flex™). A propos de la classe HTMLLoader La classe HTMLLoader d'Adobe AIR définit l'objet d'affichage qui peut afficher du contenu HTML dans une application AIR. Les applications basées sur SWF peuvent ajouter un contrôle HTMLLoader à une fenêtre existante ou créer une fenêtre HTML qui contienne automatiquement un objet HTMLLoader avec HTMLLoader.createRootWindow(). Il est possible d'accéder à l'objet HTMLLoader via la propriété window.htmlLoader de JavaScript au sein de la page HTML chargée. Chargement du contenu HTML d'une URL Le code suivant charge une URL dans un objet HTMLLoader (ajoutez le HTMLLoader en tant qu'enfant de la scène ou tout autre conteneur d'objet d'affichage pour afficher le contenu HTML dans votre application) : 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); Les propriétés width et height d'un objet HTMLLoader sont toutes deux définies sur 0 par défaut. Vous allez vouloir définir ces dimensions lorsque vous ajouterez un objet HTMLLoader à la scène. Cet objet distribue plusieurs événements à mesure qu'une page se charge. Vous pouvez utiliser ces événements pour déterminer à quel moment on peut interagir sans risque avec la page chargée. Ces événements sont décrits dans la section « Gestion des événements HTML » à la page 257. Vous pouvez également afficher le texte HTML à l'aide de la classe TextField, mais ses capacités sont limitées. La classe TextField d'Adobe® Flash® Player prend en charge un sous-ensemble du balisage de HTML ; mais, en raison de restrictions de taille, ses capacités sont réduites. La classe HTMLLoader contenue dans Adobe AIR n'est pas disponible dans Flash Player. Chargement de contenu HTML depuis une chaîne La méthode loadString() d'un objet HTMLLoader charge une chaîne de contenu HTML dans un objet HTMLLoader : var html:HTMLLoader = new HTMLLoader(); var htmlStr:String = "<html><body>Hello <b>world</b>.</body></html>"; html.loadString(htmlStr); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 238 Programmation en HTML et JavaScript Par défaut, le contenu chargé via la méthode loadString() est placé dans un sandbox hors de l'application avec les caractéristiques suivantes : • Il peut charger le contenu depuis le réseau (mais pas depuis le système de fichiers). • Il ne peut pas charger les données avec XMLHttpRequest. • La propriété window.location est définie sur "about:blank". • Le contenu ne peut pas accéder à la propriété window.runtime (alors que le contenu placé dans tout sandbox non applicatif le peut). Dans AIR 1.5, la classe HTMLLoader comprend une propriété placeLoadStringContentInApplicationSandbox. Lorsque cette propriété est définie sur true pour un objet HTMLLoader, le contenu chargé par la méthode loadString() est placé dans le sandbox de l'application. (La valeur par défaut est false.) Le contenu chargé par la méthode loadString() a ainsi accès à la propriété window.runtime et à toutes les API AIR. Si vous définissez cette propriété sur true, assurez-vous que la source des données d'une chaîne utilisée dans un appel à la méthode loadString() soit approuvée. Les instructions du code de la chaîne HTML sont exécutées avec tous les privilèges de l'application lorsque cette propriété est définie sur true. Ne définissez cette propriété sur true que si vous êtes certain(e) que la chaîne ne contient que du code inoffensif. Dans les applications compilées avec les kits SDK d'AIR 1.0 ou AIR 1.1, le contenu chargé par la méthode loadString() est placé dans le sandbox de l'application. Règles de sécurité importantes lors de l'utilisation de contenu HTML dans des applications AIR Les fichiers que vous installez avec l'application AIR ont accès aux interfaces de programmation d'AIR. Pour des raisons de sécurité, ce n'est pas le cas pour du contenu provenant d'autres sources. Par exemple, une telle restriction empêche le contenu provenant d'un domaine distant, comme http://example.com, de lire le contenu du répertoire dans l'ordinateur de bureau de l'utilisateur (ou pire encore). Comme il est possible d'exploiter des failles de sécurité en appelant la fonction eval() et les interfaces de programmation qui lui sont liées, l'utilisation de ces méthodes est interdite par défaut pour le contenu installé avec l'application. Toutefois, quelques structures Ajax utilisent la fonction eval() et les interfaces de programmation qui lui sont liées. Pour structurer convenablement le contenu qui va travailler dans une application AIR, il faut tenir compte des règles qui régissent les restrictions liées à la sécurité et qu'il faut appliquer à du contenu provenant de sources différentes. Un tel contenu est placé dans des classifications de sécurité distinctes appelées sandbox (consultez la section « Sandbox » à la page 28). Par défaut, un contenu installé avec l'application l'est dans un sandbox appelé sandbox de l'application. Il a alors accès aux interfaces de programmation d'AIR. Le sandbox de l'application est en règle générale le sandbox le plus sécurisé, doté de restrictions conçues pour empêcher l'exécution de code non approuvé. Le moteur d'exécution vous permet de charger le contenu installé avec votre application dans un sandbox autre que celui de l'application. Le contenu dans des sandbox hors application s'exécute dans un environnement similaire à celui d'un navigateur Web classique. Par exemple, le code dans des sandbox hors application peut utiliser eval() et des méthodes apparentées. Par contre, il ne peut pas accéder aux interfaces de programmation d'AIR. Le moteur d'exécution contient des dispositifs pour permettre aux contenus de sandbox différents de communiquer entre eux en toute sécurité, sans exposer les interfaces de programmation d'AIR à un contenu hors application, par exemple. Pour plus d'informations, consultez la section « Programmation croisée du contenu dans des sandbox de sécurité distincts » à la page 252. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 239 Programmation en HTML et JavaScript Si vous appelez du code interdit d'exécution dans un sandbox pour des raisons de sécurité, une erreur JavaScript est signalée par le message : « Violation des règles de sécurité d'Adobe AIR par du code JavaScript dans le sandbox de sécurité de l'application ». Pour éviter cette erreur, suivez les règles de codage présentées dans la section suivante, « Contournement des erreurs JavaScript liées à la sécurité » à la page 239. Pour plus d'informations, consultez la section « Sécurité HTML » à la page 31. Contournement des erreurs JavaScript liées à la sécurité Si vous appelez du code interdit d'exécution dans un sandbox en raison de ces restrictions liées à la sécurité, le moteur d'exécution distribue une erreur JavaScript : « Violation des règles de sécurité dans le sandbox de sécurité de l'application par le moteur d'exécution d'Adobe AIR sur du code JavaScript ». Pour éviter cette erreur, suivez les règles de codage suivantes. Causes des erreurs JavaScript liées à la sécurité Le code qui s'exécute dans le sandbox de l'application ne peut pas exécuter des opérations qui impliquent l'évaluation et l'exécution de chaînes dès le moment où l'événement load est lancé et que les gestionnaires d'événement load ne sont plus actifs. Les tentatives d'utilisation des types suivants d'instructions JavaScript, qui évaluent et exécutent des chaînes potentiellement non protégées, génèrent des erreurs JavaScript. • Fonction eval() • setTimeout() et setInterval() • Constructeur Function De plus, les types d'instructions JavaScript suivants échouent sans générer une erreur JavaScript risquée : • javascript: URL • Rappels d'événements affectés par les attributs onevent dans les instructions innerHTML et outerHTML • Chargement de fichiers JavaScript à partir d'emplacements hors du répertoire d'installation de l'application • document.write() et document.writeln() • XMLHttpRequests synchrones lancées avant l'événement load ou au cours de l'exécution d'un gestionnaire d'événement load • Eléments de script créés dynamiquement Remarque : dans des cas bien particuliers, l'évaluation de chaînes est autorisée. Consultez la section « Restrictions relatives au code pour un contenu dans des sandbox différents » à la page 33 pour plus d'informations. Adobe tient une liste de structures Ajax reconnus pour leur prise en charge du sandbox de sécurité de l'application à l'adresse http://www.adobe.com/go/airappsandboxframeworks_fr. Les sections ci-dessous décrivent comment réécrire des scripts pour éviter d'obtenir ces erreurs JavaScript risquées et ces échecs silencieux lors de l'exécution de code dans le sandbox de l'application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 240 Programmation en HTML et JavaScript Mappage du contenu de l'application dans un sandbox différent Le plus souvent, vous pouvez réécrire ou restructurer une application pour éviter des erreurs JavaScript liées à la sécurité. Toutefois, lorsque la réécriture ou la restructuration s'avèrent impossibles, vous pouvez charger le contenu de l'application dans un sandbox différent à l'aide de la technique décrite à la section « Chargement du contenu de l'application dans un sandbox hors application » à la page 253. Si ce contenu doit également accéder aux interfaces de programmation d'AIR, vous pouvez créer un pont de sandbox, tel que décrit à la section « Configuration d'une interface de pont de sandbox » à la page 254. Fonction eval() Dans le sandbox de l'application, la fonction eval() ne peut être utilisée qu'avant l'exécution de l'événement load de page ou qu'en cours d'exécution d'un gestionnaire d'événement load. Après le chargement de la page, les appels à eval() n'exécuteront pas de code. Toutefois, dans les situations suivantes, il vous est possible de réécrire le code pour éviter d'utiliser eval(). Affectation des propriétés à un objet Au lieu d'analyser une chaîne pour construire l'accesseur propriété : eval("obj." + propName + " = " + val); accédez aux propriétés par une notation crochets : obj[propName] = val; Création d'une fonction avec des variables disponibles dans le contexte Remplacez les instructions telles que les suivantes : function compile(var1, var2){ eval("var fn = function(){ this."+var1+"(var2) }"); return fn; } par : function compile(var1, var2){ var self = this; return function(){ self[var1](var2) }; } Création d'un objet à l'aide du nom de la classe comme paramètre de chaîne Considérez une classe de JavaScript hypothétique définie de la manière suivante : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 241 Programmation en HTML et JavaScript var CustomClass = { Utils: { Parser: function(){ alert('constructor') } }, Data: { } }; var constructorClassName = "CustomClass.Utils.Parser"; La façon la plus simple de créer une occurrence consisterait à utiliser eval() : var myObj; eval('myObj=new ' + constructorClassName +'()') Toutefois, vous pouvez éviter l'appel à eval() en analysant chaque composant du nom de la classe et en construisant le nouvel objet à l'aide de la notation crochets : 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; } Pour créer l'occurrence, utilisez : try{ var Parser = getter(constructorClassName); var a = new Parser(); }catch(e){ alert(e); } setTimeout() et setInterval() Remplacez la chaîne passée en tant que fonction gestionnaire avec une référence de fonction ou un objet de fonction. Par exemple, remplacez une instruction telle que : setTimeout("alert('Timeout')", 10); par : setTimeout(alert('Timeout'), 10); Ou bien, lorsque la fonction demande que l'objet this soit paramétré par l'appelant, remplacez une instruction telle que : this.appTimer = setInterval("obj.customFunction();", 100); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 242 Programmation en HTML et JavaScript par ce qui suit : var _self = this; this.appTimer = setInterval(function(){obj.customFunction.apply(_self);}, 100); Constructeur Function Les appels à new Function(param, body) peuvent être remplacés par une déclaration de fonction inline ou utilisés seulement avant que l'événement load de la page n'ait été traité. javascript: URL Le code défini dans un lien à l'aide du modèle javascript: URL est ignoré dans le sandbox de l'application. Aucune erreur JavaScript risquée n'est générée. Vous pouvez remplacer des liens à l'aide d'URL JavaScript: telles que : <a href="javascript:code()">Click Me</a> par : <a href="#" onclick="code()">Click Me</a> Rappels d'événements affectés par les attributs onevent dans les instructions innerHTML et outerHTML Lorsque vous utilisez innerHTML ou outerHTML pour ajouter des éléments au DOM d'un document, tous les rappels d'événements affectés au sein de l'instruction, tels que onclick ou onmouseover sont ignorés. Aucun message d'erreur sur la sécurité n'est généré. A la place, vous pouvez affecter un attribut id aux nouveaux éléments et paramétrer les fonctions de rappel de gestionnaires d'événement à l'aide de la méthode addEventListener(). Par exemple, étant donné un élément-cible dans un document tel que : <div id="container"></div> Remplacez les instructions telles que : document.getElementById('container').innerHTML = '<a href="#" onclick="code()">Click Me.</a>'; par : document.getElementById('container').innerHTML = '<a href="#" id="smith">Click Me.</a>'; document.getElementById('smith').addEventListener("click", function() { code(); }); Chargement de fichiers JavaScript à partir d'emplacements hors du répertoire d'installation de l'application Le chargement de fichiers de script à partir d'emplacements hors du sandbox de l'application n'est pas autorisé. Aucun message d'erreur sur la sécurité n'est généré. Tous les fichiers de script qui s'exécutent dans le sandbox de l'application doivent être installés dans le répertoire de l'application. Pour utiliser des scripts externes dans une page, il vous faut mapper la page dans un sandbox distinct. Consultez la section « Chargement du contenu de l'application dans un sandbox hors application » à la page 253. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 243 Programmation en HTML et JavaScript document.write() et document.writeln() Les appels à document.write() ou document.writeln() sont ignorés après le traitement de l'événement load de la page. Aucun message d'erreur sur la sécurité n'est généré. Vous pouvez également charger un nouveau fichier ou remplacer le corps du document à l'aide des techniques de manipulation du DOM : XMLHttpRequests synchrones lancées avant l'événement load ou au cours de l'exécution d'un gestionnaire d'événement load Les XMLHttpRequests synchrones lancées avant l'événement load de la page ou au cours du traitement d'un événement load ne renvoient pas de contenu. Les XMLHttpRequests asynchrones peuvent être lancées, mais elles ne renvoient rien avant la fin de l'événementload. Après le traitement de l'événement load, les XMLHttpRequests synchrones se comportent normalement. Eléments de script créés dynamiquement Les éléments de script créés dynamiquement, tels ceux créés avec les méthodes innerHTML ou document.createElement() sont ignorés. Accès aux classes de l'API AIR à partir de JavaScript En plus des éléments standard et étendus du Webkit, HTML et le code JavaScript peuvent accéder aux classes hôtes par le moteur d'exécution. Ces classes vous permettent d'accéder aux fonctions avancées fournies par AIR et notamment : • Accès au système de fichiers • Utilisation des bases de données SQL locales • Contrôle des menus Fenêtre et de l'application • Accès aux sockets pour la mise en réseau • Utilisation des classes et objets définis par l'utilisateur • Capacités de sonorisation Par exemple, l'API de fichiers d'AIR comprend une classe File contenue dans le package flash.filesystem Vous pouvez créer un objet File en JavaScript comme suit : var myFile = new window.runtime.flash.filesystem.File(); L'objet runtime est un objet JavaScript spécial, mis à la disposition du contenu HTML s'exécutant dans AIR, dans le sandbox de l'application. Il vous permet d'accéder aux classes runtime à partir de JavaScript. La propriété flash de l'objet runtime fournit un accès au package Flash. A son tour, la propriété flash.filesystem de l'objet runtime fournit un accès au package flash.filesystem. Celui-ci contient la classe File. Les packages constituent un moyen d'organiser les classes utilisées dans ActionScript. Remarque : la propriété runtime n'est pas automatiquement ajoutée aux objets window des pages chargées dans une image ou dans une iframe. Toutefois, tant que le document enfant se trouve dans le sandbox de l'application, l'enfant peut accéder à la propriété runtime du parent. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 244 Programmation en HTML et JavaScript La structure du package des classes runtime demanderait aux développeurs de taper de longues chaînes de code JavaScript pour accéder à chaque classe, comme dans window.runtime.flash.desktop.NativeApplication. C'est pourquoi le SDK d'AIR contient un fichier AIRAliases.js qui vous permet d'accéder à des classes runtime beaucoup plus facilement, par exemple en tapant tout simplement air.NativeApplication. Les classes de l'interface de programmation AIR sont abordées tout au long du présent guide. D'autres classes de l'interface de programmation Flash Player, qui peuvent intéresser les développeurs HTML, sont décrites dans le Guide de référence du langage Adobe AIR pour les développeurs HTML. ActionScript est le langage utilisé dans le contenu SWF (Flash Player). Toutefois, la syntaxe de JavaScript et celle d'ActionScript sont très proches. Elles sont toutes deux basées sur des versions du langage ECMAScript. Toutes les classes intégrées sont disponibles à la fois en JavaScript (dans un contenu HTML) et en ActionScript (dans un contenu SWF). Remarque : le code JavaScript ne peut utiliser les classes Dictionary, XML et XMLList qui sont disponibles dans ActionScript. Utilisation du fichier AIRAliases.js Les classes d'exécution sont organisées en une structure de package, comme suit : • window.runtime.flash.desktop.NativeApplication • window.runtime.flash.desktop.ClipboardManager • window.runtime.flash.filesystem.FileStream • window.runtime.flash.data.SQLDatabase Dans le SDK d'AIR se trouve un fichier AIRAliases.js qui fournit des définitions d'« alias » vous permettant d'accéder à des classes d'exécution avec moins de frappes au clavier. Par exemple, vous pouvez accéder aux classes répertoriées ci-dessus en tapant tout simplement ce qui suit : • air.NativeApplication • air.Clipboard • air.FileStream • air.SQLDatabase Cette liste est simplement un petit sous-ensemble des classes du fichier AIRAliases.js. La liste complète des classes et des fonctions au niveau du package est fournie dans le Guide de référence du langage Adobe AIR pour les développeurs HTML. En plus des classes d'exécution utilisées le plus souvent, le fichier AIRAliases.js contient des alias pour les fonctions les plus courantes au niveau du package : window.runtime.trace(), window.runtime.flash.net.navigateToURL() et window.runtime.flash.net.sendToURL() qui ont pour alias air.trace(), air.navigateToURL() et air.sendToURL(). Pour utiliser le fichier AIRAliases.js, insérez la référence script suivante dans votre page HTML : <script src="AIRAliases.js"></script> Ajustez la page dans la référence src selon les besoins. Important : sauf indication contraire, le code JavaScript présenté dans cette documentation à titre d'exemple suppose que vous avez inclus le fichier AIRAliases.js dans votre page HTML. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 245 Programmation en HTML et JavaScript A propos des URL dans AIR Dans un contenu HTML qui s'exécute sous AIR, vous pouvez utiliser les modèles d'URL suivants lorsque vous définissez les attributs src pour les balises img, frame, iframe et script, dans l'attribut href d'une balise link ou dans tout autre emplacement où vous pouvez fournir une URL. Modèle d'URL Description Exemple file Un chemin relatif à la racine du système de fichiers file:///c:/AIR Test/test.txt app Un chemin relatif au répertoire racine de l'application installée. app:/images app-storage app-storage:/settings/prefs.xml Un chemin relatif au répertoire de stockage de l'application Pour chaque application installée, AIR définit un répertoire de stockage de l'application qui est unique. C'est un emplacement pratique pour y enregistrer des données spécifiques à cette application. http Une requête HTTP standard http://www.adobe.com https Une requête HTTPS standard https://secure.example.com Pour plus d'informations sur l'utilisation des modèles d'URL d'AIR, consultez la section « Utilisation des modèles d'URL AIR dans les URL » à la page 312. De nombreuses interfaces de programmation AIR, y compris les classes File, Loader, URLStream et Sound, utilisent un objet URLRequest plutôt qu'une chaîne contenant l'URL. L'objet URLRequest lui-même est initialisé avec une chaîne qui peut utiliser l'un des mêmes modèles d'URL. Par exemple, l'instruction suivante crée un objet URLRequest qui peut être utilisé pour demander la page d'accueil d'Adobe : var urlReq = new air.URLRequest("http://www.adobe.com/"); Pour des informations sur les objets URLRequest, consultez la section « Requêtes d'URL et mise en réseau » à la page 311. Mise des objets ActionScript à disposition de JavaScript Le JavaScript dans la page HTML chargée par un objet HTMLLoader peut appeler les classes, les objets et les fonctions définis dans le contexte d'exécution d'ActionScript à l'aide des propriétés window.runtime, window.htmlLoader et window.nativeWindow de la page HTML. Par la création de références aux objets et fonctions ActionScript au sein d'un contexte d'exécution de JavaScript, vous pouvez également mettre ceux-ci à la disposition du code JavaScript. Exemple de base pour l'accès à des objets JavaScript à partir d'ActionScript L'exemple ci-dessous décrit comment ajouter des propriétés qui font référence à des objets dans l'objet window global d'une page HTML. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 246 Programmation en HTML et JavaScript 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; } Le contenu HTML, qui se trouve dans un fichier appelé test.html, chargé dans un objet HTMLLoader de l'exemple précédent, peut accéder à la propriété foo et à la méthode helloFromJS() définies dans le fichier SWF parent : <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> Lorsque vous accédez au contexte JavaScript d'un document en cours de chargement, vous pouvez utiliser l'événement htmlDOMInitialize pour créer des objets suffisamment tôt dans la séquence de création de la page pour que des scripts définis dans la page puissent y accéder. Si vous attendez l'événement complete, seuls les scripts de la page qui s'exécutent après l'événement load de la page peuvent accéder aux objets ajoutés. Mise des définitions de classe à disposition de JavaScript Pour mettre les classes ActionScript de votre application à la disposition de JavaScript, vous pouvez affecter le contenu HTML chargé au domaine de l'application qui contient les définition de classes. Le domaine d'application du contexte d'exécution de JavaScript peut être défini avec la propriété runtimeApplicationDomain de l'objet HTMLLoader. Pour définir le domaine d'application sur le domaine d'application principal, par exemple, définissez runtimeApplicationDomain sur ApplicationDomain.currentDomain, comme le montre le code ci-dessous : html.runtimeApplicationDomain = ApplicationDomain.currentDomain; Dès que la propriété runtimeApplicationDomain est définie, le contexte JavaScript partage les définitions de classe avec le domaine affecté. Pour créer une occurrence d'une classe personnalisée dans JavaScript, faites référence à la définition de classe par la propriété window.runtime et utilisez l'opérateur new. var customClassObject = new window.runtime.CustomClass(); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 247 Programmation en HTML et JavaScript Le contenu HTML doit provenir d'un domaine de sécurité compatible. S'il provient d'un domaine de sécurité autre que celui de l'application auquel vous l'affectez, la page utilise plutôt un domaine d'application par défaut. Par exemple, si vous chargez à partir d'Internet une page distante, vous ne pourriez pas affecter ApplicationDomain.currentDomain comme domaine d'application de la page. Suppression des écouteurs d'événement Lorsque vous ajoutez des écouteurs d'événement à des objets hors de la page en cours, y compris des objets d'exécution, des objets dans du contenu SWF chargé et même des objets JavaScript qui s'exécutent dans d'autres pages, vous devriez toujours supprimer les écouteurs d'événement lorsque la page décharge. Autrement, l'écouteur d'événement distribue l'événement à une fonction de gestionnaire qui n'existe plus. Si cela se produit, le message d'erreur suivant s'affiche : « The application attempted to reference a JavaScript object in an HTML page that is no longer loaded » (L'application a tenté de référencer un objet JavaScript sur une page HTML qui n'est plus chargée). La suppression d'écouteurs d'événement qui ne sont plus utiles permet aussi à AIR de récupérer la mémoire qui leur est associée. Pour plus d'informations, consultez la section « Suppression d'écouteurs d'événement sur une page HTML de navigation » à la page 261. Accès au DOM HTML et aux objets JavaScript à partir d'ActionScript Dès que l'objet HTMLLoader distribue l'événement complete, vous pouvez accéder à tous les objets dans le DOM (ou document object model) HTML pour la page. Les objets accessibles sont les éléments d'affichage, tels que les objets div et p dans la page, ainsi que les variables et fonctions JavaScript. L'événement complete correspond à l'événement load de la page JavaScript. Avant que complete ne soit distribué, les éléments DOM, les variables et les fonctions peuvent ne pas avoir été analysés ou créés. Si possible, attendez l'événement complete avant d'accéder au DOM HTML. Par exemple, examinez la page HTML suivante : <html> <script> foo = 333; function test() { return "OK."; } </script> <body> <p id="p1">Hi.</p> </body> </html> La page HTML simple définit une variable JavaScript appelée foo et une fonction JavaScript appelée test(). Ces deux éléments sont des propriétés de l'objet window global de la page. En outre, l'objet window.document comprend un élément appelé P, pourvu de l'ID p1), auquel vous pouvez accéder à l'aide de la méthode getElementById(). Dès que la page est chargée, c'est-à-dire lorsque l'objet HTMLLoader distribue l'événement complete, vous pouvez accéder à chacun de ces objets à partir d'ActionScript, comme le montre le code ActionScript ci-dessous : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 248 Programmation en HTML et JavaScript 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. } Pour accéder au contenu d'un élément HTML, utilisez la propriété innerHTML. Par exemple, le code ci-dessus utilise html.window.document.getElementById("p1").innerHTML pour lire le contenu de l'élément HTML appelé p1. Vous pouvez également paramétrer les propriétés de la page HTML à partir d'ActionScript. Ainsi, l'exemple ci-dessous définit le contenu de l'élément pl et la valeur de la variable JavaScript foo sur la page à l'aide d'une référence à l'objet conteneur HTMLLoader : html.window.document.getElementById("p1").innerHTML = "Goodbye"; html.window.foo = 66; Intégration d'un contenu SWF en HTML Vous pouvez intégrer un contenu SWF dans un contenu HTML au sein d'une application AIR comme vous le feriez dans un navigateur. Intégrez le contenu SWF à l'aide d'une balise object, d'une balise embed ou de toutes les deux. Remarque : une pratique courante de développement sur le Web consiste à utiliser à la fois une balise object et une balise embed pour afficher un contenu SWF dans une page HTML. Vous ne tirez aucun avantage de cette pratique avec AIR. Vous pouvez utilisez la seule balise object, conforme à la norme W3C, dans le contenu pour l'afficher dans AIR. Cependant, vous pouvez continuer à utiliser les balises object et embed ensemble, le cas échéant, pour du contenu HTML qui est également affiché dans un navigateur. L'exemple ci-dessous illustre l'utilisation de la balise object HTML pour afficher un fichier SWF au sein d'un contenu HTML. Le fichier SWF est chargé à partir du répertoire de l'application, mais vous pouvez utiliser tout modèle d'URL pris en charge par AIR. L'emplacement à partir duquel le fichier SWF est chargé détermine le sandbox de sécurité dans lequel AIR place le contenu. <object type="application/x-shockwave-flash" width="100%" height="100%"> <param name="movie" value="app:/SWFFile.swf"></param> </object> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 249 Programmation en HTML et JavaScript Vous pouvez également utiliser un script pour charger un contenu dynamiquement. L'exemple ci-dessous crée un nœud object pour afficher le fichier SWF spécifié dans le paramètre urlString. L'exemple ajoute le nœud en tant qu'enfant de l'élément de page avec l'ID spécifiée par le paramètre 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> Utilisation des bibliothèques ActionScript au sein d'une page HTML AIR étend l'élément de script HTML de telle sorte qu'une page peut importer des classes ActionScript dans un fichier SWF compilé. Par exemple, pour importer une bibliothèque appelée myClasses.swf qui se trouve dans le sousrépertoire lib du dossier racine de l'application, insérez la balise de script suivante au sein d'un fichier HTML : <script src="lib/myClasses.swf" type="application/x-shockwave-flash"></script> Important : l'attribut type doit être type="application/x-shockwave-flash" pour que la bibliothèque soit chargée convenablement. Si le contenu SWF est compilé sous forme de fichier SWF Flash Player 10 ou AIR 1.5, vous devez définir l'espace de nom XML du fichier descripteur d'application sur l'espace de nom AIR 1.5. Pour plus d'informations, consultez la section « Définition des propriétés dans le fichier descripteur d'application » à la page 47. Le répertoire lib et le fichier myClasses.swf doivent aussi être inclus lorsque le fichier AIR est mis en package. Accédez aux classes importées par la propriété runtime de l'objet Window de JavaScript : var libraryObject = new window.runtime.LibraryClass(); Si les classes du fichier SWF sont organisées en packages, vous devez également inclure le nom du package. Par exemple, si la définition LibraryClass se trouvait dans un package appelé utilities, vous créeriez une occurrence de la classe à l'aide de l'instruction suivante : var libraryObject = new window.runtime.utilities.LibraryClass(); Remarque : pour compiler une bibliothèque de SWF dans ActionScript afin qu'elle fasse partie d'une page HTML dans AIR, utilisez le compilateur acompc. L'utilitaire acompc fait partie du SDK de Flex 3. Il est décrit dans la http://www.adobe.com/go/learn_air_flex3_fr. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 250 Programmation en HTML et JavaScript Accès au DOM HTML et aux objets JavaScript à partir d'un fichier ActionScript importé Pour accéder à des objets dans une page HTML à partir d'ActionScript dans un fichier SWF importé dans la page à l'aide de la balise <script>, transmettez une référence à l'objet JavaScript, telle que window ou document, à une fonction définie dans le code ActionScript. Utilisez la référence au sein de la fonction pour accéder à l'objet ou à d'autres objets accessibles grâce à la référence qu'on a fait passer. Par exemple, examinez la page HTML suivante : <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> La page HTML simple contient une variable JavaScript appelée num et une fonction JavaScript appelée getStatus(). Ces deux éléments sont des propriétés de l'objet window de la page. En outre, l'objet window.document contient un élément p désigné et dont l'ID est p1. La page charge un fichier ActionScript, « ASLibrary.swf », qui contient une classe, ASClass. ASClass définit une fonction appelée accessDOM() qui enregistre simplement les valeurs de ces objets JavaScript. La méthode accessDOM() prend l'objet Window de JavaScript comme argument. A l'aide de cette référence Window, elle peut accéder à d'autres objets de la page tels que les variables, les fonctions et les éléments DOM, comme l'illustre la définition ci-dessous : public class ASClass{ public function accessDOM(window:*):void { trace(window.num); // 254 trace(window.document.getElementById("p1").innerHTML); // Body text.. trace(window.getStatus()); // OK. } } Vous pouvez à la fois lire et définir des propriétés de la page HTML à partir d'une classe ActionScript importée. Par exemple, la fonction suivante définit sur la page le contenu de l'élément pl et la valeur de la variable JavaScript foo : public function modifyDOM(window:*):void { window.document.getElementById("p1").innerHTML = "Bye"; window.foo = 66; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 251 Programmation en HTML et JavaScript Conversion des objets Date et RegExp Les langages JavaScript et ActionScript définissent tous deux les classes Date et RegExp, mais les objets de ces types ne sont pas automatiquement convertis d'un contexte d'exécution à l'autre. Vous devez d'abord convertir les objets Date et RegExp au type équivalent avant de les utiliser pour définir des propriétés ou des paramètres de fonction dans l'autre contexte d'exécution. Par exemple, le code ActionScript ci-dessous convertit un objet Date de JavaScript appelé jsDate en un objet Date ActionScript : var asDate:Date = new Date(jsDate.getMilliseconds()); Par exemple, le code ActionScript ci-dessous convertit un objet RegExp de JavaScript appelé jsRegExp en un objet RegExp d'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); Manipulation d'une feuille de style HTML à partir d'ActionScript Dès que l'objet HTMLLoader a distribué l'événement complete, vous pouvez étudier et manipuler les styles CSS dans une page. Par exemple, examinez la page HTML simple suivante : <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> Après le chargement de ce contenu par un objet HTMLLoader, vous pouvez manipuler les styles CSS dans la page par le tableau cssRules du tableau window.document.styleSheets, comme vous pouvez le voir ci-dessous : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 252 Programmation en HTML et JavaScript 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"; } Le code ajuste les styles CSS pour que le document HML résultant apparaisse comme ci-dessous : N'oubliez pas que le code ne peut ajouter des styles à la page qu'après la distribution de l'événement complete par l'objet HTMLLoader. Programmation croisée du contenu dans des sandbox de sécurité distincts Le modèle de sécurité du moteur d'exécution isole le code de différentes origines. La programmation croisée du contenu dans des sandbox de sécurité distincts permet au contenu d'un sandbox de sécurité d'accéder à des propriétés et à des méthodes sélectionnées dans un autre. Sandbox de sécurité AIR et code JavaScript AIR applique une politique d'origine commune qui empêche le code d'un domaine d'interagir avec le contenu d'un autre. Tous les fichiers sont placés dans un sandbox sur la base de leur origine. Habituellement, le contenu d'un sandbox d'application ne peut pas enfreindre le principe d'origine commune et inter-coder le contenu chargé depuis un emplacement qui se trouve hors du répertoire d'installation de l'application. Toutefois, AIR met à votre disposition quelques techniques qui vous permettent d'inter-coder du contenu hors application. L'une d'entre elles utilise des images ou des iframes pour mapper le contenu de l'application dans un sandbox de sécurité distinct. Toute page chargée à partir de la zone à sandbox de l'application se comporte comme si elle l'avait été à partir du domaine distant. Par exemple, le mappage du contenu de l'application sur le domaine example.com lui permettrait d'inter-coder des pages chargées à partir d'example.com. Comme cette technique place le contenu de l'application dans un sandbox distinct, le code au sein de ce contenu n'est non plus assujetti aux restrictions qui entourent l'exécution du code des chaînes évaluées. Vous pouvez utiliser la technique de mappage des sandbox pour assouplir ces restrictions, même s'il n'est pas nécessaire d'inter-coder un contenu distant. Le mappage de contenu de cette façon est particulièrement utile lorsque vous travaillez avec l'une des nombreuses structures de JavaScript ou avec du code existant qui se fonde sur l'évaluation des chaînes. Toutefois, vous devriez tenir compte d'un risque supplémentaire et vous en prémunir : celui d'un contenu non approuvé qui pourrait être introduit et exécuté lorsque le contenu tourne hors du sandbox de l'application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 253 Programmation en HTML et JavaScript Cependant, un contenu de l'application mappé sur un autre sandbox perd son droit d'accès à des interfaces de programmation d'AIR de telle sorte que la technique de mappage du sandbox ne peut pas être utilisée pour présenter des fonctionnalités d'AIR à du code exécuté hors du sandbox de l'application. Une autre technique de programmation croisée vous permet de créer une interface, appelée pont de sandbox, qui sert de passerelle entre le contenu d'un sandbox hors application et son document parent dans le sandbox de l'application. Le pont permet au contenu enfant d'accéder à des propriétés et à des méthodes définies par le parent et inversement, ou bien les deux à la fois. Enfin, vous pouvez lancer des XMLHttpRequests entre les domaines à partir du sandbox de l'application et, facultativement, d'autres sandbox. Pour plus d'informations, consultez les sections « Eléments image et iframe HTML » à la page 231, « Sécurité HTML » à la page 31 et « Objet XMLHttpRequest » à la page 225. Chargement du contenu de l'application dans un sandbox hors application Pour permettre à un contenu de l'application d'inter-coder sans risque un contenu chargé à partir d'un emplacement se trouvant hors du répertoire d'installation de l'application, vous pouvez utiliser l'élément image ou iframe pour charger ce contenu en tant que contenu externe dans le même sandbox de sécurité. Si vous ne voulez pas inter-coder de contenu distant mais que vous souhaitez charger une page de votre application hors du sandbox de l'application, vous pouvez utiliser la même technique, c'est-à-dire spécifier http://localhost/ ou toute autre valeur inoffensive comme domaine d'origine. AIR ajoute les nouveaux attributs, sandboxRoot et documentRoot à l'élément d'image pour vous permettre de spécifier si un fichier d'application chargé dans l'image devrait être mappé sur un sandbox hors application. Les fichiers dont la résolution aboutit à un chemin sous l'URL sandboxRoot sont plutôt chargés à partir du répertoire documentRoot. Pour des raisons de sécurité, le contenu de l'application chargé ainsi est traité comme s'il avait été chargé à partir de l'URL de sandboxRoot. La propriété sandboxRoot spécifie l'URL à utiliser pour déterminer le sandbox et le domaine dans lesquels placer le contenu de l'image. Les modèles d'URL file:, http: ou https: doivent être utilisés. Si vous spécifiez une URL relative, le contenu reste dans le sandbox de l'application. La propriété documentRoot spécifie le répertoire à partir duquel il faut charger le contenu de l'image. Les modèles d'URL app:, http: ou app-storage: doivent être utilisés. L'exemple ci-dessous mappe le contenu installé dans le sous-répertoire sandbox de l'application qui doit s'exécuter dans le sandbox distant et le domaine www.example.com : <iframe src="http://www.example.com/local/ui.html" sandboxRoot="http://www.example.com/local/" documentRoot="app:/sandbox/"> </iframe> La page ui.html pourrait charger un fichier JavaScript à partir du dossier sandbox local à l'aide de la balise de script suivante : <script src="http://www.example.com/local/ui.js"></script> Elle pourrait également charger un contenu à partir d'un répertoire sur le serveur distant à l'aide d'une balise de script telle que la suivante : <script src="http://www.example.com/remote/remote.js"></script> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 254 Programmation en HTML et JavaScript L'URL sandboxRoot masquera tout contenu sur la même URL du serveur distant. Dans l'exemple ci-dessus, vous ne pourriez pas avoir accès à un contenu distant, quel qu'il soit, à l'adresse www.example.com/local/ ou même à l'un de ses sous-répertoires, car AIR remappe la requête sur le répertoire local de l'application. Les requêtes sont remappées, qu'elles proviennent d'une navigation de pages, d'une XMLHttpRequest ou de tout autre moyen de chargement de contenu. Configuration d'une interface de pont de sandbox Vous pouvez utiliser un pont de sandbox lorsqu'un contenu dans le sandbox de l'application doit accéder à des propriétés ou des méthodes définies par un contenu dans un sandbox hors application ou encore lorsqu'un contenu hors application doit accéder à des propriétés et des méthodes définies par un contenu dans le sandbox de l'application. Créez un pont avec les propriétés childSandboxBridge et parentSandboxBridge de l'objet window de tout document enfant. Création d'un pont de sandbox enfant La propriété childSandboxBridge permet au document enfant de présenter une interface au contenu dans le document parent. Pour présenter une interface, vous définissez la propriété childSandbox sur une fonction ou un objet dans le document enfant. Vous pouvez alors accéder à l'objet ou la fonction à partir du contenu dans le document parent. L'exemple ci-dessous montre comment un script qui s'exécute dans un document enfant peut présenter un objet contenant une fonction ou une propriété à son parent : var interface = {}; interface.calculatePrice = function(){ return ".45 cents"; } interface.storeID = "abc" window.childSandboxBridge = interface; Si cet enfant a été chargé dans une iframe avec une id "child", vous pourriez accéder à l'interface à partir du contenu parent en lisant la propriété childSandboxBridge de l'image : var childInterface = document.getElementById("child").contentWindow.childSandboxBridge; air.trace(childInterface.calculatePrice()); //traces ".45 cents" air.trace(childInterface.storeID)); //traces "abc" Création d'un pont de sandbox parent La propriété parentSandboxBridge permet au document parent de présenter une interface au contenu dans le document enfant. Pour présenter une interface, le document parent définit la propriété parentSandbox du document enfant sur une fonction ou un objet spécifié dans le document parent. Vous pouvez alors accéder à l'objet ou à la fonction à partir du contenu dans le document enfant. L'exemple ci-dessous montre comment un script qui s'exécute dans une image parent peut présenter à un document enfant un objet contenant une fonction : var interface = {}; interface.save = function(text){ var saveFile = air.File("app-storage:/save.txt"); //write text to file } document.getElementById("child").contentWindow.parentSandboxBridge = interface; A l'aide de cette interface, un contenu dans l'image enfant pourrait enregistrer du texte dans un fichier appelé save.txt mais il n'aurait aucun autre accès au système de fichiers. Le contenu enfant pourrait appeler la fonction save comme suit : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 255 Programmation en HTML et JavaScript var textToSave = "A string."; window.parentSandboxBridge.save(textToSave); Le contenu de l'application devrait présenter l'interface la plus étroite possible aux autres sandbox. Un contenu hors application devrait être considéré comme douteux par nature étant donné qu'il peut être sujet à une introduction de code accidentel ou malveillant. Vous devez mettre en place des mesures de protection appropriées pour éviter un usage abusif de l'interface que vous présentez par le pont de sandbox parent. Accès à un pont de sandbox parent lors du chargement d'une page Pour qu'un script dans un document enfant accède à un pont de sandbox parent, le pont doit être paramétré avant l'exécution du script. Les objets fenêtre, image et iframe distribuent un événement dominitialize lorsqu'une page DOM est créée, mais avant qu'un script ne soit analysé ou des éléments DOM ajoutés. Vous pouvez utiliser l'événement dominitialize pour établir le pont suffisamment tôt dans la séquence de création de la page afin que tous les scripts du document enfant puissent y accéder. L'exemple ci-dessous montre comment créer un pont de sandbox parent en réponse à l'événement dominitialize distribué à partir de l'image enfant : <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> Le document child.html suivant montre comment un contenu enfant peut accéder au pont de sandbox parent : <html> <head> <script> document.write(window.parentSandboxBridge.testProperty); </script> </head> <body></body> </html> Pour écouter l'événement dominitialize sur une fenêtre enfant plutôt qu'une image, il vous faut ajouter l'écouteur à l'objet window enfant créé par la fonctionwindow.open() : var childWindow = window.open(); childWindow.addEventListener("dominitialize", engageBridge()); childWindow.document.location = "http://www.example.com/air/child.html"; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 256 Programmation en HTML et JavaScript Il n'y a alors pas moyen de mapper le contenu de l'application dans un sandbox hors application. Cette technique n'est utile que lors du chargement de child.html hors du répertoire de l'application. Vous pouvez néanmoins mapper un contenu de l'application dans un sandbox hors application, mais il vous faut d'abord charger une page intermédiaire, qui elle-même utilise des images, afin de charger le document enfant et le mapper dans le sandbox souhaité. Si vous utilisez la fonction createRootWindow() de la classe HTMLLoader pour créer une fenêtre, celle-ci n'est pas un enfant du document à partir duquel createRootWindow() est appelée. Ainsi, il n'est pas possible de créer un pont de sandbox à partir de la fenêtre appelante dans un contenu hors application chargé dans la nouvelle fenêtre. Il faut plutôt charger une page intermédiaire dans la nouvelle fenêtre qui elle-même utilise des images pour charger le document enfant. Vous pouvez alors établir le pont à partir du document parent de la nouvelle fenêtre avec le document enfant chargé dans l'image. 257 Chapitre 22 : Gestion des événements HTML Un système de gestion des événements permet au programmeur de répondre aux actions de l'utilisateur et aux événements système de manière pratique. Le modèle d'événement Adobe® AIR™ n'est pas seulement utile, il est également conforme aux standards en vigueur. Ce modèle repose sur la spécification d'événements Document Object Model (DOM) de niveau 3, une architecture de gestion d'événements normalisée. Il constitue donc pour les programmeurs un outil puissant, mais parfaitement intuitif. Evénements HTMLLoader Un objet HTMLLoader déclenche les événements Adobe® ActionScript® 3.0 suivants : Evénement Description htmlDOMInitialize Distribué lors de la création du document HTML, mais avant que tout script soit analysé ou que les nœuds DOM soient ajoutés à la page. complete Distribué lors de la création du DOM HTML en réponse à une opération de chargement, juste après l'événement onload sur la page HTML. htmlBoundsChanged Distribué lorsque l'une des propriétés contentWidth et contentHeight ou les deux à la fois ont été modifiées. locationChange Distribué lorsque la propriété location de l'objet HTMLLoader a été modifiée. scroll Distribué à chaque changement de position de défilement par le moteur HTML. Un événement scroll résulte d'un accès aux liens d'ancrage (liens #) sur la page ou d'un appel de la méthode window.scrollTo(). La saisie de texte dans une zone de texte ou d'entrée de texte peut également provoquer un événement scroll. uncaughtScriptException Distribué lorsqu'il se produit une exception JavaScript dans l'objet HTMLLoader et qu'elle n'est pas interceptée dans le code JavaScript. Vous pouvez également associer une fonction ActionScript à un événement JavaScript (tel que onClick). Pour plus d'informations, consultez la section « Gestion des événements DOM avec ActionScript » à la page 257. Gestion des événements DOM avec ActionScript Vous pouvez enregistrer des fonctions ActionScript qui répondent à des événements JavaScript. Examinons par exemple le contenu HTML suivant : <html> <body> <a href="#" id="testLink">Click me.</a> </html> Vous pouvez enregistrer une fonction ActionScript en tant que gestionnaire de tout événement de la page. Par exemple, le code suivant ajoute la fonction clickHandler() en tant qu'écouteur de l'événement onclick de l'élément testLink sur la page HTML : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 258 Gestion des événements 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!"); } Vous pouvez également utiliser la méthode addEventListener() pour enregistrer des fonctions associées à ces événements. Il est par exemple possible de remplacer la méthode completeHandler() dans l'exemple précédent par le code suivant : function completeHandler(event:Event):void { var testLink:Object = html.window.document.getElementById("testLink"); testLink.addEventListener("click", clickHandler); } Lorsqu'un écouteur se réfère à un élément DOM déterminé, il est recommandé d'attendre que l'objet HTMLLoader parent distribue l'événement complete avant d'ajouter les écouteurs d'événement. Les pages HTML chargent souvent plusieurs fichiers et le DOM HTML n'est pas totalement généré tant que tous les fichiers n'ont pas été chargés et analysés. Une fois tous les éléments créés, l'objet HTMLLoader distribue l'événement complete. Réponse aux exceptions JavaScript non interceptées Examinez le code HTML suivant : <html> <head> <script> function throwError() { var x = 400 * melbaToast; } </script> </head> <body> <a href="#" onclick="throwError()">Click me.</a> </html> Il contient une fonction JavaScript, throwError(), qui fait référence à une variable inconnue, melbaToast : var x = 400 * melbaToast; Lorsqu'une opération JavaScript rencontre une opération non valide qui n'est pas interceptée dans le code JavaScript par une structure try/catch, l'objet HTMLLoader contenant la page distribue un événement HTMLUncaughtScriptExceptionEvent. Vous pouvez enregistrer un gestionnaire associé à cet événement, comme illustré par le code suivant : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 259 Gestion des événements 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); } } JavaScript permet de gérer le même événement à l'aide de la propriété 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> Le gestionnaire d'événement htmlErrorHandler() annule le comportement par défaut de l'événement (qui consiste à envoyer le message d'erreur JavaScript à la sortie de suivi AIR) et génère son propre message de sortie. Il stipule la valeur exceptionValue de l'objet HTMLUncaughtScriptExceptionEvent. Il indique par ailleurs les propriétés de chaque objet dans le tableau stackTrace : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 260 Gestion des événements HTML exceptionValue: ReferenceError: Can't find variable: melbaToast sourceURL: app:/test.html line: 5 function: throwError sourceURL: app:/test.html line: 10 function: onclick Gestion des événements d'exécution avec JavaScript Les classes d'exécution gèrent l'ajout de gestionnaires d'événement à l'aide de la méthode addEventListener(). Pour ajouter une fonction de gestionnaire associée à un événement, appelez la méthode addEventListener() de l'objet qui distribue l'événement en indiquant le type d'événement et la fonction concernée. Par exemple, pour écouter l'événement closing distribué lorsqu'un utilisateur clique sur le bouton de fermeture de fenêtre dans la barre de titre, utilisez l'instruction suivante : window.nativeWindow.addEventListener(air.NativeWindow.CLOSING, handleWindowClosing); Création d'une fonction de gestionnaire d'événement Le code suivant crée un fichier HTML simple qui affiche des informations sur la position de la fenêtre principale. Une fonction de gestionnaire appelée moveHandler() écoute un événement move (défini par la classe NativeWindowBoundsEvent) de la fenêtre 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> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 261 Gestion des événements HTML Lorsqu'un utilisateur déplace la fenêtre, les éléments textarea affichent les positions X et Y actualisées de la fenêtre : Notez que l'objet événement est transmis sous forme d'argument à la méthode moveHandler. Le paramètre d'événement permet à la fonction de gestionnaire d'examiner l'objet événement. Dans cet exemple, vous utilisez la propriété type de l'objet événement pour indiquer si cet événement est de type move. Suppression des écouteurs d'événement La méthode removeEventListener() permet de supprimer un écouteur d'événement dont vous n'avez plus besoin. Il est judicieux de supprimer tous les écouteurs qui ne seront plus utilisés. Les paramètres requis sont notamment eventName et listener, soit les mêmes que ceux requis pour la méthode addEventListener(). Suppression d'écouteurs d'événement sur une page HTML de navigation Lorsqu'un contenu HTML navigue ou qu'il est éliminé parce qu'une fenêtre dans laquelle il figure est fermée, les écouteurs d'événement qui font référence aux objets sur la page déchargée ne sont pas automatiquement supprimés. Lorsqu'un objet distribue un événement à un gestionnaire qui a déjà été déchargé, le message d'erreur suivant s'affiche : « The application attempted to reference a JavaScript object in an HTML page that is no longer loaded » (L'application a tenté de référencer un objet JavaScript sur une page HTML qui n'est plus chargée). Pour éviter que ce message d'erreur ne s'affiche, supprimez les écouteurs d'événement JavaScript intégrés à une page HTML avant qu'elle ne soit déchargée. En cas de navigation de page (au sein d'un objet HTMLLoader), supprimez l'écouteur d'événement lors de l'événement unload de l'objet window. Par exemple, le code JavaScript suivant supprime un écouteur associé à un événement uncaughtScriptException : window.onunload = cleanup; window.htmlLoader.addEventListener('uncaughtScriptException', uncaughtScriptException); function cleanup() { window.htmlLoader.removeEventListener('uncaughtScriptException', uncaughtScriptExceptionHandler); } Pour empêcher que cette erreur ne se produise à la fermeture des fenêtres comportant un contenu HTML, appelez une fonction de nettoyage en réponse à l'événement closing de l'objet NativeWindow (window.nativeWindow). Par exemple, le code JavaScript suivant supprime un écouteur associé à un événement uncaughtScriptException : window.nativeWindow.addEventListener(air.Event.CLOSING, cleanup); function cleanup() { window.htmlLoader.removeEventListener('uncaughtScriptException', uncaughtScriptExceptionHandler); } Vous pouvez également éviter que cette erreur ne se produise en supprimant un écouteur d'événement dès son exécution. Par exemple, le code JavaScript suivant crée une fenêtre HTML en appelant la méthode createRootWindow() de la classe HTMLLoader et ajoute un écouteur associé à l'événement complete. Lorsque le gestionnaire d'événement complete est appelé, il supprime son propre écouteur d'événement par le biais de la fonction removeEventListener() : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 262 Gestion des événements 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 suppression d'écouteurs d'événement superflus permet également au nettoyeur de mémoire système de récupérer la mémoire éventuellement mobilisée par ces écouteurs. Vérification des écouteurs d'événement existants La méthode hasEventListener() vous permet de vérifier l'existence d'un écouteur d'événement associé à un objet. 263 Chapitre 23 : Programmation du conteneur HTML La classe HTMLLoader sert de conteneur au contenu HTML dans Adobe® AIR™. La classe fournit de nombreuses méthodes et propriétés, héritées de la classe Sprite, pour contrôler le comportement et l'aspect de l'objet dans la liste d'affichage d'ActionScript® 3.0. De plus, la classe définit les méthodes et propriétés pour les tâches telles que le chargement et l'interaction avec le contenu HTML et la gestion de l'historique. La classe HTMLHost définit un ensemble de comportements par défaut pour un HTMLLoader. Lorsque vous créez un objet HTMLLoader, aucune mise en œuvre de HTMLHost n'est fournie. Ainsi, lorsque le contenu HTML déclenche l'un des comportements par défaut, comme un changement d'emplacement de la fenêtre ou du titre de la fenêtre, rien ne se passe. Vous pouvez étendre la classe HTMLHost pour définir les comportements souhaités pour votre application. Une mise en œuvre par défaut du HTMLHost est fournie pour les fenêtres créées par AIR. Vous pouvez affecter la mise en œuvre de HTMLHost par défaut à un autre objet HTMLLoader en paramétrant la propriété htmlHost de l'objet à l'aide d'un nouvel objet HTMLHost créé avec le paramètre defaultBehavior défini sur true. Affichage des propriétés des objets HTMLLoader Un objet HTMLLoader hérite des propriétés d'affichage de la classe Adobe® Flash® Player Sprite. Vous pouvez redimensionner, déplacer, masquer et changer la couleur d'arrière-plan, par exemple. Ou vous pouvez appliquer des effets avancés comme les filtres, les masques, les mises à l'échelle et la rotation. Lorsque vous appliquez des effets, évaluez l'impact sur la lisibilité. Les contenus SWF et PDF chargés dans une page HTML ne peuvent pas s'afficher lorsque certains effets sont appliqués. Les fenêtres HTML contiennent un objet HTMLLoader qui restitue le contenu HTML. L'objet est limité à la zone de la fenêtre de sorte qu'un changement dans les dimensions, la position, la rotation ou l'échelle ne produit pas toujours les résultats escomptés. Propriétés d'affichage de base Les propriétés d'affichage de base de HTMLLoader vous permettent de positionner le contrôle au sein de l'objet d'affichage parent, de définir la taille et d'afficher ou masquer le contrôle. Vous ne devriez pas changer ces objets pour l'objet HTMLLoader d'une fenêtre HTML. Les propriétés de base contiennent : Propriété Remarques x, y Positionne l'objet au sein de son conteneur parent. width, height Change les dimensions de la zone d'affichage. visible Contrôle la visibilité de l'objet et tout contenu qu'il possède. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 264 Programmation du conteneur HTML Hors d'une fenêtre HTML, les propriétés width et height d'un objet HTMLLoader sont fixées à 0. Vous devez définir la largeur et la hauteur avant que le contenu HTML chargé ne devienne visible. Le contenu HTML est dessiné suivant la taille de HTMLLoader et disposé suivant les propriétés HTML et CSS du contenu. Un changement dans la taille de HTMLLoader redistribue le contenu. Lors du chargement de contenu dans un nouvel objet HTMLLoader (la propriété width est toujours définie sur 0), il peut être tentant de définir les paramètres width et height du HTMLLoader à l'aide des propriétés contentWidth et contentHeight. Cette technique est valable pour les pages qui disposent d'une largeur minimale raisonnable lorsqu'elles sont déployées selon les règles de HTML et du flux CSS. Toutefois, en l'absence d'une largeur raisonnable fournie par le HTMLLoader, certaines pages sont intégrées en une mise en page longue et étroite. Remarque : lorsque vous changez la largeur et la hauteur de l'objet HTMLLoader, les valeurs scaleX et scaleY ne changent pas, comme ce serait le cas avec la plupart des autres objets d'affichage. Transparence du contenu HTMLLoader La propriété paintsDefaultBackground d'un objet HTMLLoader, qui est true par défaut, détermine si l'objet HTMLLoader dessine un arrière-plan opaque. Lorsque paintsDefaultBackground est false, l'arrière-plan est clair. Le conteneur de l'objet d'affichage ou les autres objets d'affichage en dessous de l'objet HTMLLoader sont visibles derrière les éléments de premier plan du contenu HTML. Si l'élément de corps ou tout autre élément du document HTML spécifie une couleur d'arrière-plan, à l'aide de style="background-color:gray", par exemple, l'arrière-plan de cette portion de HTML est alors opaque et restituée dans la couleur d'arrière-plan spécifiée. Si vous définissez la propriété opaqueBackground de l'objet HTMLLoader et paintsDefaultBackground est false, la couleur définie pour le opaqueBackground est alors visible. Remarque : vous pouvez utiliser une illustration transparente et au format PNG pour fournir un arrière-plan semitransparent à un élément dans un document HTML. La définition du style d'opacité d'un élément HTML n'est pas prise en charge. Mise à l'échelle d'un contenu HTMLLoader Evitez la mise à l'échelle d'un objet HTMLLoader au delà d'un facteur 1.0. Le texte d'un contenu HTMLLoader est restitué à une résolution spécifique et il apparaît pixelisé si l'échelle de l'objet HTMLLoader est augmentée. Pour éviter que le HTMLLoader, ainsi que son contenu, ne soit redimensionné lorsqu'une fenêtre l'est, définissez la propriété scaleMode de la scène sur StageScaleMode.NO_SCALE. Points à examiner lors du chargement d'un contenu SWF ou PDF dans une page HTML Le contenu SWF ou PDF chargé dans un objet HTMLLoader disparaît dans les conditions suivantes : • Si vous mettez l'objet HTMLLoader à une échelle autre que 1.0. • Si vous attribuez à la propriété alpha de l'objet HTMLLoader une valeur autre que 1.0. • Si vous faites pivoter le contenu HTMLLoader. Le contenu réapparaît si vous retirez le paramétrage de la propriété fautive et supprimez les filtres actifs. Remarque : le moteur d'exécution ne peut afficher le contenu SWF ou PDF dans des fenêtres transparentes. Pour plus d'informations sur le chargement de ces types de média dans un objet HTMLLoader, consultez les sections « Intégration d'un contenu SWF en HTML » à la page 248 et « Ajout de contenu PDF » à la page 277. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 265 Programmation du conteneur HTML Propriétés d'affichage avancées La classe HTMLLoader hérite de plusieurs méthodes qui peuvent être utilisées pour des effets spéciaux. En règle générale, ces effets ont des limites lorsqu'ils sont utilisés avec l'affichage du HTMLLoader, mais ils peuvent être utiles pour les transitions ou autres effets temporaires. Par exemple, si vous affichez une fenêtre de dialogue pour rassembler les saisies de l'utilisateur, vous pourriez flouter l'affichage de la fenêtre principale jusqu'à ce que celui-ci mette fin au dialogue. De même, vous pourriez faire un fondu lors de la fermeture de la fenêtre Les propriétés d'affichage avancées sont les suivantes : Propriété Restrictions alpha Peut réduire la lisibilité du contenu HTML filtres Dans une fenêtre HTML, les effets extérieurs sont coupés par les bords de la fenêtre graphics Les formes dessinées à l'aide de commandes graphiques apparaissent en dessous du contenu HTML, ainsi que l'arrière-plan par défaut. La propriété paintsDefaultBackground doit être « false » pour que les formes dessinées soient visibles. opaqueBackground Ne change pas la couleur de l'arrière-plan par défaut. La propriété paintsDefaultBackground doit être "false" pour que cette couche de couleur soit visible. rotation Les coins de la zone HTMLLoader rectangulaire peuvent être découpées par le bord de fenêtre. Le contenu SWF ou PDF chargé dans le contenu HTML n'est pas affiché. scaleX, scaleY L'affichage restitué peut apparaître pixelisé pour des échelles supérieures à 1. Le contenu SWF ou PDF chargé dans le contenu HTML n'est pas affiché. transform Peut réduire la lisibilité du contenu HTML L'affichage HTML peut être coupé par le bord de la fenêtre. Le contenu SWF ou PDF chargé dans le contenu HTML n'est pas affiché si la transformation implique un pivotement, un redimensionnement ou une inclinaison. L'exemple suivant illustre la façon de paramétrer le tableau filters pour flouter l'affichage HTML au complet : 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; Défilement du contenu HTML La classe HTMLLoader contient les propriétés suivantes qui vous permettent de contrôler le défilement du contenu HTML : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 266 Programmation du conteneur HTML Propriété Description contentHeight La hauteur, exprimée en pixels, du contenu HTML. contentWidth La largeur, exprimée en pixels, du contenu HTML. scrollH La position de défilement horizontal du contenu HTML au sein de l'objet HTMLLoader. scrollV La position de défilement vertical du contenu HTML au sein de l'objet HTMLLoader. Le code ci-dessous définit la propriété scrollV pour que vous puissiez faire défiler le contenu HTML jusqu'au bas de la page : 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; } Le HTMLLoader ne contient pas les barres de défilement horizontal et vertical. Vous pouvez implémenter les barres de défilement dans ActionScript. Vous pouvez également utiliser la méthode HTMLLoader.createRootWindow() pour créer une fenêtre qui contienne un objet HTMLLoader avec des barres de défilement. Consultez la section « Création de fenêtres avec défilement de contenu HTML » à la page 275. Accès à l'historique de HTML A mesure que de nouvelles pages sont chargées dans un objet HTMLLoader, le moteur d'exécution actualise un historique pour l'objet. L'historique correspond à l'objet window.history dans la page HTML. La classe HTMLLoader contient les méthodes et propriétés suivantes qui vous permettent d'utiliser l'historique de HTML : Membre de la classe Description historyLength La longueur hors tout de l'historique englobant les entrées précédentes et suivantes. historyPosition La position actuelle dans l'historique. Les éléments de l'historique qui se trouvent avant cette position correspondent à la navigation « précédente » et ceux qui se trouvent après, à la navigation « suivante ». getHistoryAt() Renvoie l'objet URLRequest correspondant à l'entrée qui se trouve à la position spécifiée de l'historique. historyBack() Navigue en amont dans l'historique, si possible. historyForward() Navigue en aval dans l'historique, si possible. historyGo() Se déplace dans l'historique selon le nombre d'étapes indiqué. Navigue en aval dans l'historique si la valeur est positive ou en amont dans l'autre cas. Une valeur zéro conduit à un rechargement de la page. La spécification d'une position qui se trouve au-delà de la fin conduit à la dernière entrée de la liste. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 267 Programmation du conteneur HTML Les éléments de l'historique sont conservés comme objets de type HistoryListItem. La classe HistoryListItem possède les propriétés suivantes : Propriété Description isPost Définissez sur true si la page HTML contient des données POST. originalUrl L'URL d'origine de la page HTML, avant toute redirection. title Le titre de la page HTML. url L'URL de la page HTML. Paramétrage de l'agent d'utilisateur employé lors du chargement du contenu HTML La classe HTMLLoader possède une propriété userAgent qui vous permet de définir la chaîne de l'agent d'utilisateur employé par HTMLLoader. Paramétrez la propriété userAgent de l'objet HTMLLoader avant d'appeler la méthode load(). Si vous définissez cette propriété sur l'occurrence de HTMLLoader, la propriété userAgent de l'URLRequest transmise à la méthode load() n'est alors pas utilisée. Vous pouvez définir la chaîne de l'agent d'utilisateur employée par tous les objets HTMLLoader dans un domaine d'application en paramétrant la propriété URLRequestDefaults.userAgent. Les propriétés URLRequestDefaults statiques sont appliquées par défaut pour tous les objets URLRequest et pas seulement les URLRequests utilisés avec la méthode load() des objets HTMLLoader. Le paramétrage de la propriété userAgent d'un HTMLLoader remplace celui par défaut de URLRequestDefaults.userAgent. Si vous ne paramétrez pas une valeur de l'agent d'utilisateur pour la propriété userAgent de l'objet HTMLLoader ou pour URLRequestDefaults.userAgent, la valeur de l'agent d'utilisateur AIR par défaut est employée. Cette valeur par défaut varie suivant le système d'exploitation utilisé à l'exécution (Mac OS ou Windows, par exemple), le langage du moteur d'exécution et sa version, comme dans les deux exemples suivants : • "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) AdobeAIR/1.0" • "Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, like Gecko) AdobeAIR/1.0" Paramétrage du codage des caractères à utiliser pour le contenu HTML Une page HTML peut spécifier le codage des caractères qu'elle utilise en incluant la balise meta comme suit : meta http-equiv="content-type" content="text/html" charset="ISO-8859-1"; Remplacez le paramétrage de la page pour vous assurer que le codage d'un caractère spécifique est utilisé en définissant la propriété textEncodingOverride de l'objet HTMLLoader : var html:HTMLLoader = new HTMLLoader(); html.textEncodingOverride = "ISO-8859-1"; DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 268 Programmation du conteneur HTML Spécifiez le codage de caractère pour le contenu HTMLLoader à utiliser lorsqu'une page HTML ne spécifie pas un paramétrage avec la propriété textEncodingFallback de l'objet HTMLLoader : var html:HTMLLoader = new HTMLLoader(); html.textEncodingFallback = "ISO-8859-1"; La propriété textEncodingOverride remplace le paramétrage de la page HTML. Et la propriété textEncodingOverride ainsi que le paramétrage de la page HTML remplacent la propriété textEncodingFallback. Paramétrez l'une ou l'autre de ces propriétés avant le chargement du contenu HTML. Paramétrage des interfaces utilisateur de type navigateur pour un contenu HTML JavaScript propose plusieurs interfaces de programmation pour contrôler la fenêtre qui affiche le contenu HTML. Dans AIR, ces interfaces de programmation peuvent être remplacées par la mise en place d'une classe HTMLHost personnalisée. A propos de l'extension de la classe HTMLHost Si, par exemple, votre application présente plusieurs objets HTMLLoader dans une interface à onglets, vous pourriez souhaiter changer le libellé d'un onglet à l'aide des pages HTML chargées, sans toucher au titre de la fenêtre principale. De même, votre code pourrait répondre à un appel window.moveTo() en repositionnant l'objet HTMLLoader dans son conteneur d'objet d'affichage parent, en déplaçant la fenêtre qui contient l'objet HTMLLoader, en ne faisant rien du tout ou en faisant tout autre chose. La classe HTMLHost d'AIR contrôle les méthodes et propriétés JavaScript suivantes : • window.status • window.document.title • window.location • window.blur() • window.close() • window.focus() • window.moveBy() • window.moveTo() • window.open() • window.resizeBy() • window.resizeTo() Lorsque vous créez un objet HTMLLoader à l'aide de new HTMLLoader(), les propriétés ou méthodes répertoriées ne sont pas activées. La classe HTMLHost fournit par défaut une implémentation de ces interfaces de programmation JavaScript, similaire à celle des navigateurs. Vous pouvez aussi étendre la classe HTMLHost pour personnaliser le comportement. Pour créer un objet HTMLHost qui prenne en charge le comportement par défaut, définissez le paramètre defaultBehaviors sur true dans le constructeur HTMLHost. var defaultHost:HTMLHost = new HTMLHost(true); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 269 Programmation du conteneur HTML Lorsque vous créez une fenêtre HTML dans AIR à l'aide de la méthode createRootWindow() de la classe HTMLLoader, une occurrence de HTMLHost qui prend en charge les comportements est automatiquement affectée. Vous pouvez changer le comportement de l'objet hôte en affectant une implémentation HTMLLoader différente à la propriété htmlHost du HTMLLoader ou bien vous pouvez affecter null pour désactiver complètement les fonctions. Remarque : AIR affecte un objet HTMLHost par défaut à la fenêtre initiale créée pour une application AIR à base d'HTML et à toute fenêtre créée par l'implémentation par défaut de la méthode window.open()) JavaScript. Exemple : extension de la classe HTMLHost L'exemple ci-dessous montre comment personnaliser l'affectation de l'interface utilisateur par un objet HTMLLoader en étendant la classe HTMLLoader : 1 Créez un fichier Flash pour AIR. Définissez sa classe de document sur CustomHostExample, puis enregistrez le fichier sous CustomHostExample.fla. 2 Créez un fichier ActionScript appelé CustomHost.as contenant une classe qui étend la classe HTMLHost (une sous- classe). Cette classe remplace certaines méthodes de la nouvelle classe pour traiter les changements dans les paramètres de l'utilisateur liés à l'interface. Par exemple, la classe suivante, CustomHost, définit les comportements pour les appels à window.open() et les changements à window.document.title. Les appels à la méthode window.open() ouvrent la page HTML dans une nouvelle fenêtre et les changements à la propriété window.document.title, y compris le paramétrage de l'élément <title> d'une page HTML, définissent le titre de cette fenêtre. 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, DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 270 Programmation du conteneur HTML 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; } 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 Créez un autre fichier ActionScript appelé CustomHostExample.as pour contenir la classe document pour cette application. Cette classe crée un objet HTMLLoader et définit sa propriété hôte sur une occurrence de la classe CustomHost définie à l'étape précédente. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 271 Programmation du conteneur 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; } } } Pour tester le code décrit ici, incluez un fichier HTML qui ait le contenu suivant dans le répertoire de l'application : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 272 Programmation du conteneur 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> Traitement des changements apportés à la propriété window.location Remplacez la méthode locationChange() pour traiter les changements apportés à l'URL de la page HTML. La méthode locationChange() est appelée lorsque JavaScript dans une page change la valeur de window.location. L'exemple ci-dessous charge tout simplement l'URL demandée : override public function updateLocation(locationURL:String):void { htmlLoader.load(new URLRequest(locationURL)); } Remarque : vous pouvez utiliser la propriété HTMLLoader de l'objet HTMLHost pour faire référence à l'objet HTMLLoader actuel. Traitement des appels JavaScript à window.moveBy(), window.moveTo(), window.resizeTo(), window.resizeBy() Remplacez la méthode set windowRect() pour traiter les changements dans les limites du contenu HTML. La méthode set windowRect() est appelée lorsque JavaScript dans une page appelle window.moveBy(), window.moveTo(), window.resizeTo() ou window.resizeBy(). L'exemple ci-dessous met simplement à jour les limites de la fenêtre de l'ordinateur de bureau : override public function set windowRect(value:Rectangle):void { htmlLoader.stage.nativeWindow.bounds = value; } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 273 Programmation du conteneur HTML Traitement des appels JavaScript à window.open() Remplacez la méthode createWindow() pour traiter les appels JavaScript à window.open(). Les implémentations de la méthode createWindow() sont responsables de la création d'un objet HTMLLoader et de son renvoi. Vous afficheriez généralement le HTMLLoader dans une nouvelle fenêtre, mais la création d'une fenêtre n'est pas nécessaire. L'exemple suivant décrit comment implémenter la fonction createWindow() à l'aide du HTMLLoader.createRootWindow() pour créer à la fois la fenêtre et l'objet HTMLLoader. Vous pouvez aussi créer un objet NativeWindow à part et ajouter le HTMLLoader à la scène de la fenêtre. 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; } Remarque : cet exemple affecte l'implémentation personnalisée de HTMLHost à toute fenêtre créée avec window.open(). Vous pouvez également utiliser une implémentation différente ou définir la propriété htmlHost sur "null" pour de nouvelles fenêtres, si vous le souhaitez. L'objet transmis comme paramètre à la méthode createWindow() est un objet HTMLWindowCreateOptions. La classe HTMLWindowCreateOptions inclut des propriétés qui signalent les valeurs définies dans la chaîne du paramètre features, dans l'appel à window.open() : Propriété HTMLWindowCreateOptions Paramètre correspondant dans la chaîne des fonctions se trouvant dans l'appel JavaScript à window.open() fullscreen fullscreen height height locationBarVisible location menuBarVisible menubar resizeable resizable scrollBarsVisible scrollbars statusBarVisible status toolBarVisible toolbar width width x left ou screenX y top ou screenY La classe HTMLLoader n'implémente pas toutes les fonctions susceptibles d'être spécifiées dans la chaîne de fonctions. Votre application doit fournir des barres de défilement, des barres d'adresses, des barres de menus, des barres d'état et des barres d'outils lorsque cela convient. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 274 Programmation du conteneur HTML Les autres arguments pour la méthode window.open() de JavaScript sont traités par le système. Une implémentation createWindow() ne devrait pas charger de contenu dans l'objet HTMLLoader ou définir le titre de la fenêtre. Traitement des appels JavaScript à window.close() Remplacez window.close() pour que les appels JavaScript soient traités par la méthode window.close(). L'exemple ci-dessous ferme la fenêtre de l'ordinateur de bureau lorsque la méthode window.close() est appelée : override public function windowClose():void { htmlLoader.stage.nativeWindow.close(); } Les appels JavaScript à window.close() n'ont pas besoin de fermer la fenêtre de contenu. Vous pourriez, par exemple, retirer HTMLLoader de la liste d'affichage en laissant la fenêtre (qui peut avoir un autre contenu) ouverte, comme dans le code suivant : override public function windowClose():void { htmlLoader.parent.removeChild(htmlLoader); } Traitement des changements dans la propriété de l'état de la fenêtre Remplacez la méthode updateStatus() pour traiter les changements JavaScript à la valeur de window.status. L'exemple ci-dessous assure le suivi de la valeur d'état : override public function updateStatus(status:String):void { trace(status); } L'état demandé est transmis en tant que chaîne à la méthode updateStatus(). L'objet HTMLLoader ne fournit pas de barre d'état. Traitement des changements dans la propriété window.document.title Remplacez la méthode updateTitle() pour traiter les changements JavaScript à la valeur de window.document.title. L'exemple ci-dessous change le titre de la fenêtre et ajoute la chaîne "Sample" au titre : override public function updateTitle(title:String):void { htmlLoader.stage.nativeWindow.title = title + " - Sample"; } Lorsque document.title est défini sur une page HTML, le titre demandé est transmis en tant que chaîne à la méthode updateTitle(). Il n'est pas nécessaire que les changements à document.titlemodifient le titre de la fenêtre contenant l'objet HTMLLoader. Vous pourriez, par exemple, changer un autre élément d'interface, tel qu'un champ de texte. Traitement des appels JavaScript à window.blur() et window.focus() Remplacez les méthodes windowBlur() et windowFocus() pour traiter les appels JavaScript à window.blur() et window.focus(), comme le montre l'exemple ci-dessous : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 275 Programmation du conteneur 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); } Remarque : AIR ne fournit pas d'interface de programmation pour désactiver une fenêtre ou une application. Création de fenêtres avec défilement de contenu HTML La classe HTMLLoader inclut une méthode statique, HTMLLoader.createRootWindow(), vous permettant d'ouvrir une nouvelle fenêtre (représentée par un objet NativeWindow) qui contient un object HTMLLoader et qui définit quelques paramètres d'interface utilisateur pour cette fenêtre. Il faut à cette méthode quatre paramètres pour vous permettre de définir l'interface utilisateur. Paramètre Description visible Une valeur booléenne indiquant si la fenêtre est initialement visible (true) ou non (false). windowInitOptions Un objet NativeWindowInitOptions. La classe NativeWindowInitOptions définit les options d'initialisation pour un objet NativeWindow, y compris ce qui suit : si on peut réduire la fenêtre au minimum, la développer au maximum ou la redimensionner, si la fenêtre possède un arrière-plan système ou un arrière-plan personnalisable, si la fenêtre est transparente ou non (pour les fenêtres qui n'utilisant pas d'arrière-plan système) et le type de fenêtre. scrollBarsVisible Indique s'il existe des barres de défilement (true) ou non (false). bounds Un objet Rectangle qui définit la position et la taille de la nouvelle fenêtre. Par exemple, le code ci-dessous utilise la méthode HTMLLoader.createRootWindow() pour créer une fenêtre avec le contenu HTMLLoader qui utilise des barres de défilement : 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(); Remarque : les fenêtres créées par un appel direct de createRootWindow() dans JavaScript demeurent indépendantes de la fenêtre HTML d'ouverture. Les propriétés JavaScript Window opener et parent, par exemple, sont null. Toutefois, si vous appelez createRootWindow() indirectement en remplaçant la méthode HTMLHost createWindow() pour appeler createRootWindow(), opener et parent font effectivement référence à la fenêtre HTML d'ouverture. Création de sous-classes de la classe HTMLLoader Vous pouvez créer une sous-classe de la classe HTMLLoader pour créer des comportements. Par exemple, vous pouvez créer une sous-classe qui définisse des écouteurs d'événement par défaut pour les événements HTMLLoader, tels que ces événements distribués lorsque HTML est restitué ou que l'utilisateur clique sur un lien. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 276 Programmation du conteneur HTML L'exemple suivant étend la classe HTMLHost pour fournir un comportement normal lorsque la méthode window.open() JavaScript est appelée. L'exemple définit alors une sous-classe de HTMLLoader qui utilise la classe d'implémentation du HTMLHost personnalisé : 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 } } Le code ci-dessous définit une sous-classe de la classe HTMLLoader qui affecte un objet MyHTMLHost à sa propriété htmlHost : package { import flash.html.HTMLLoader; import MyHTMLHost; import HTMLLoader; public class MyHTML extends HTMLLoader { public function MyHTML() { super(); htmlHost = new MyHTMLHost(); } } } Pour des détails sur la classe HTMLHost et la méthode HTMLLoader.createRootWindow() utilisée dans cet exemple, consultez la section « Paramétrage des interfaces utilisateur de type navigateur pour un contenu HTML » à la page 268. 277 Chapitre 24 : Ajout de contenu PDF Les applications qui s'exécutent sous Adobe® AIR™ peuvent non seulement créer un contenu SWF ou HTML mais également un contenu PDF. Les applications AIR créent un contenu PDF à l'aide de la classe HTMLLoader, du moteur WebKit et du module externe du navigateur Adobe® Reader®. Dans une application AIR, le contenu PDF peut s'étendre sur toute la hauteur et toute la largeur de votre application ou bien sur une partie de l'interface. Le module externe du navigateur Adobe Reader contrôle l'affichage des fichiers PDF d'une application AIR. Par conséquent, les modifications effectuées dans l'interface de la boîte à outils Reader (portant sur la position, l'ancrage et la visibilité, par exemple) sont maintenues dans les affichages suivants des fichiers PDF dans les application et le navigateur AIR. Important : pour obtenir un rendu de contenu PDF dans AIR, l'utilisateur doit avoir installé Adobe Reader ou Adobe® Acrobat® version 8.1 (ou version ultérieure). Détection des capacités PDF Si l'utilisateur n'a pas installé une version d'Adobe Reader ou d'Adobe Acrobat 8.1, le contenu PDF n'est pas affiché dans une application PDF. Pour vous rendre compte si un utilisateur est en mesure de produire un contenu PDF, il faut d'abord vérifier la propriété HTMLLoader.pdfCapability. Elle est définie sur l'une des constantes suivantes de la classe HTMLPDFCapability : Constante Description HTMLPDFCapability.STATUS_OK Une version appropriée (8.1 ou plus récente) d'Adobe Reader a été décelée et le contenu PDF peut être chargé dans un objet HTMLLoader. HTMLPDFCapability.ERROR_INSTALLED_READER_NOT_FOUND Aucune version d'Adobe Reader n'a été décelée. Un objet HTMLLoader n'est pas en mesure d'afficher le contenu PDF. HTMLPDFCapability.ERROR_INSTALLED_READER_TOO_OLD Adobe Reader a bien été décelé, mais la version est périmée. Un objet HTMLLoader n'est pas en mesure d'afficher le contenu PDF. HTMLPDFCapability.ERROR_INSTALLED_READER_TOO_OLD Une version appropriée (8.1 ou plus récente) d'Adobe Reader a été détectée mais celle qui est configurée pour traiter le contenu PDF est plus ancienne que Reader 8.1. Un objet HTMLLoader n'est pas en mesure d'afficher le contenu PDF. Sous Windows, si Adobe Acrobat ou Adobe Reader version 7.x (ou une version ultérieure) est en cours d'exécution sur le système de l'utilisateur, c'est cette version-là qui est utilisée même si une version plus récente qui prend en charge les PDF est installée. Dans ce cas, si la valeur de la propriété pdfCampability est HTMLPDFCapability.STATUS_OK, lorsqu'une application AIR tente de charger un contenu PDF, la version la plus ancienne d'Acrobat ou de Reader affiche une alerte et aucune exception n'est renvoyée dans l'application AIR. Si cette situation est susceptible de se produire chez vos utilisateurs finaux, pensez à leur fournir des instructions pour qu'ils quittent Acrobat tandis qu'ils exécutent leur application. Vous pourriez afficher ces instructions si le contenu PDF ne se charge pas dans un délai raisonnable. Sous Linux, AIR recherche Adobe Reader dans le chemin exporté par l'utilisateur (s'il contient la commande acroread) et dans le répertoire /opt/Adobe/Reader. Le code ci-dessous décèle si un utilisateur est en mesure d'afficher un contenu PDF dans une application AIR. Dans la négative, il retrouve le code d'erreur qui correspond à l'objet erreur HTMLPDFCapability : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 278 Ajout de contenu PDF if(HTMLLoader.pdfCapability == HTMLPDFCapability.STATUS_OK) { trace("PDF content can be displayed"); } else { trace("PDF cannot be displayed. Error code:", HTMLLoader.pdfCapability); } Chargement du contenu PDF Vous pouvez ajouter un PDF à une application AIR en créant une occurrence de HTMLLoader, en paramétrant ses dimensions et en chargeant le chemin d'un PDF. L'exemple suivant charge un PDF à partir d'un site externe. Remplacez l'URLRequest par le chemin qui mène à un PDF externe disponible. 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); Vous pouvez également charger du contenu depuis des modèles d'URL file et des modèles d'URL spécifiques à AIR, comme app et app-storage. Par exemple, le code suivant charge le fichier test.pdf dans le sous-répertoire du PDF contenu dans le répertoire de l'application : app:/js_api_reference.pdf Pour plus d'informations sur les modèles d'URL d'AIR, consultez la section « Utilisation des modèles d'URL AIR dans les URL » à la page 312. Programmation du contenu PDF Vous pouvez utiliser JavaScript pour contrôler le contenu PDF de la même façon que vous le feriez dans une page Web du navigateur. Les extensions JavaScript incorporées dans Acrobat fournissent les fonctions suivantes, entre autres : • Contrôle de la navigation et de l'agrandissement de la page • Traitement des formulaires au sein du document • Contrôle des événements multimédia Des détails complets sur les extensions de JavaScript pour Adobe Acrobat se trouvent sur le site Adobe Acrobat Developer Connection à l'adresse http://www.adobe.com/devnet/acrobat/javascript.html. Principes de communication HTML-PDF JavaScript dans une page HTML peut envoyer un message à JavaScript dans un contenu PDF par un appel à la méthode postMessage() de l'objet DOM représentant le contenu PDF. Par exemple, examinez le contenu PDF intégré cidessous : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 279 Ajout de contenu PDF <object id="PDFObj" data="test.pdf" type="application/pdf" width="100%" height="100%"/> Le code JavaScript suivant dans le contenu HTML envoie un message au JavaScript du fichier PDF : pdfObject = document.getElementById("PDFObj"); pdfObject.postMessage(["testMsg", "hello"]); Le fichier PDF peut contenir JavaScript pour recevoir ce message. Vous pouvez ajouter du code JavaScript aux fichiers PDF dans certains contextes au niveau du document, du dossier, de la page, du champ ou du lot. Nous n'aborderons ici que le contexte au niveau du document, celui qui définit les scripts qui sont évalués lorsque le document PDF s'ouvre. Un fichier PDF peut ajouter une propriété messageHandler à l'objet hostContainer. La propriété messageHandler est un objet qui définit les fonctions du gestionnaire pour répondre aux messages. Par exemple, le code ci-dessous définit la fonction appelée à répondre aux messages provenant du fichier PDF du conteneur hôte. Celui-ci constitue le contenu HTML qui a intégré le fichier PDF : this.hostContainer.messageHandler = {onMessage: myOnMessage}; function myOnMessage(aMessage) { if(aMessage[0] == "testMsg") { app.alert("Test message: " + aMessage[1]); } else { app.alert("Error"); } } Le code JavaScript de la page HTML peut appeler la méthode postMessage() de l'objet PDF contenu dans la page. L'appel de cette méthode envoie un message "Hello from HTML" au JavaScript, au niveau du document, dans le fichier PDF : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 280 Ajout de contenu 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> Pour un exemple plus complexe ainsi que des informations sur l'utilisation d'Acrobat 8 dans l'ajout de JavaScript à un fichier PDF, consultez Programmation croisée du contenu PDF dans Adobe AIR. Programmation du contenu PDF depuis ActionScript Le code ActionScript (dans un contenu SWF) ne peut pas communiquer directement avec JavaScript dans un contenu PDF. Toutefois, ActionScript peut communiquer avec le JavaScript de la page HTML chargée dans un objet HTMLLoader qui charge le contenu PDF. Ce code JavaScript peut communiquer avec le JavaScript dans le fichier PDF chargé. Pour plus d'informations, consultez la section « Programmation en HTML et JavaScript » à la page 237. Limites connues pour du contenu PDF dans AIR Le contenu PDF dans Adobe AIR a les limites suivantes : • Le contenu PDF ne peut pas s'afficher dans une fenêtre (un objet NativeWindow) qui est transparente et où la propriété transparent est définie sur true. • L'ordre d'affichage d'un fichier PDF s'effectue différemment que les autres objets à afficher dans une application AIR. Bien que le contenu PDF se découpe correctement en respectant l'ordre d'affichage HTML, il s'installera toujours par-dessus le contenu dans l'ordre d'affichage de l'application AIR. • Le contenu PDF ne s'affiche pas dans une fenêtre en mode plein écran lorsque la propriété displayState de la scène est définie sur StageDisplayState.FULL_SCREEN ou StageDisplayState.FULL_SCREEN_INTERACTIVE. • Si certaines propriétés visuelles de l'objet HTMLLoader contenant un document PDF sont modifiées, le document PDF devient invisible. Ces propriétés comprennent filters, alpha, rotation et scaling. Leur modification rend le fichier PDF invisible jusqu'à ce que les propriétés soient réinitialisées. Ceci est également vrai si vous changez ces propriétés dans les conteneurs des objets d'affichage qui contiennent l'objet HTMLLoader. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 281 Ajout de contenu PDF • Le contenu du PDF n'est visible que lorsque la propriété scaleMode de l'objet Stage de l'objet NativeWindow renfermant le contenu PDF est définie sur StageScaleMode.NO_SCALE. Lorsqu'elle est définie sur une autre valeur, le contenu PDF n'est pas visible. • Un clic sur des liens pointant vers le contenu au sein du fichier PDF met à jour la position de défilement du contenu PDF. Un clic sur des liens pointant vers le contenu hors d'un fichier PDF réoriente l'objet HTMLLoader qui contient le PDF, même si la cible d'un lien est une nouvelle fenêtre. • Les flux de commentaires PDF ne fonctionnent pas dans AIR. 282 Chapitre 25 : Utilisation de la gestion des droits d'auteur numériques (DRM) Adobe® Flash® Media Rights Management Server (FMRMS) permet aux éditeurs multimédia de distribuer des contenus (spécifiquement des fichiers FLV et MP4) et de récupérer les coûts de production par le biais d'une contribution directe (financée par l'utilisateur) ou indirecte (financée par la publicité) de leurs consommateurs. Les éditeurs distribuent les contenus multimédia sous forme de fichiers FLV chiffrés téléchargeables pouvant être lus dans Adobe® Media Player™ ou toute application AIR qui exploite l'API de Gestion des droits numériques (DRM). FMRMS permet aux fournisseurs de contenus d'utiliser un système de licences basé sur l'identité pour protéger leurs contenus par le biais des informations d'identification des utilisateurs. Prenons le cas d'un consommateur qui souhaite visionner une émission de télévision, mais non les coupures publicitaires. Pour éviter de regarder la publicité, il s'enregistre auprès de l'éditeur de contenu et règle à ce dernier un tarif plus élevé. L'utilisateur peut alors utiliser ses informations d'identification pour accéder à l'émission et la lire sans coupure publicitaire. Un autre consommateur souhaite visionner le contenu hors ligne, car il ne dispose pas d'un accès à Internet pendant ses déplacements. Après s'être enregistré et acquitté du service Premium auprès de l'éditeur de contenu, l'utilisateur fait appel à ses informations d'identification pour accéder à l'émission et la télécharger à partir du site Web de l'éditeur. L'utilisateur peut alors visionner le contenu hors ligne pendant la période autorisée. Le contenu est également protégé par les informations d'identification de l'utilisateur et ne peut pas être partagé avec d'autres utilisateurs. Lorsqu'un utilisateur tente de lire un fichier chiffré par DRM, l'application contacte FMRMS, qui avertit à son tour le système de l'éditeur de contenu par le biais de son interface SPI (Service Provider Interface) pour authentifier l'utilisateur et lui octroyer une licence. Ce voucher détermine si l'utilisateur est autorisé à accéder au contenu et, si tel est le cas, pendant combien de temps. Le voucher détermine également si l'utilisateur peut accéder au contenu hors ligne et, si tel est le cas, pendant combien de temps. De ce fait, les informations d'identification des utilisateurs déterminent l'accès au contenu chiffré. L'octroi de licences basées sur l'identité prend également en charge l'accès anonyme. Le fournisseur peut ainsi faire appel à l'accès anonyme pour distribuer un contenu subventionné par la publicité ou autoriser un accès libre au contenu actuel pendant un nombre donné de jours. Les supports archivés pourraient être considérés comme un contenu Premium faisant l'objet d'une tarification et qui requiert des informations d'identification des utilisateurs. Le fournisseur de contenu peut également stipuler et limiter le type et la version du lecteur requis pour le visionnement du contenu. Ce chapitre vous indique comment activer votre application AIR de sorte à lire les contenus protégés par le chiffrement de gestion des droits numériques. S'il n'est pas nécessaire de maîtriser le chiffrement du contenu par DRM, il est considéré comme acquis que vous disposez de contenus chiffrés par DRM et que vous communiquez avec FMRMS pour authentifier l'utilisateur et extraire le voucher. Pour accéder à une présentation de FMRMS, notamment la création de régulations, consultez la documentation livrée avec FMRMS. Pour plus d'informations sur Adobe Media Player, consultez l'aide d'Adobe Media Player, disponible dans Adobe Media Player. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 283 Utilisation de la gestion des droits d'auteur numériques (DRM) Informations complémentaires en ligne sur la gestion des droits numériques Pour plus d'informations sur la gestion des droits numériques, consultez les sources suivantes : Guide de référence du langage • AuthenticationMethod • DRMAuthenticationCompleteEvent • DRMAuthenticationErrorEvent • DRMAuthenticateEvent • DRMContentData • DRMErrorEvent • DRMManager • DRMPlaybackTimeWindow • DRMStatusEvent • DRMVoucher • LoadVoucherSetting • NetStream Adobe Developer Connection - Articles et exemples • Adobe AIR Developer Connection pour Flash (rechercher « digital rights management » ou « drm ») Présentation du flux de travail associé aux fichiers FLV chiffrés Quatre types d'événements, StatusEvent. DRMAuthenticateEvent, DRMErrorEvent et DRMStatusEvent, sont susceptibles d'être distribués lorsqu'une application AIR tente de lire un fichier chiffré par DRM. Pour prendre en charge ces fichiers, l'application doit ajouter des écouteurs d'événement chargés de gérer les événements DRM. Les paragraphes suivants présentent le flux de travail appliqué par l'application AIR pour extraire et lire le contenu protégé par chiffrement DRM : 1 Par le biais d'un objet NetStream, l'application tente de lire un fichier FLV ou MP4. Si le contenu est chiffré, un événement events.StatusEvent est distribué avec le code, DRM.encryptedFLV, pour stipuler le chiffrement du fichier FLV. Remarque : si une application ne souhaite pas lire le fichier chiffré par DRM, elle peut écouter l'événement d'état distribué lorsqu'elle rencontre un contenu chiffré, puis avertir l'utilisateur que le fichier n'est pas pris en charge et fermer la connexion. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 284 Utilisation de la gestion des droits d'auteur numériques (DRM) 2 Si le fichier fait l'objet d'un chiffrement anonyme (ce qui signifie que tous les utilisateurs sont autorisés à visionner le contenu sans entrer d'informations d'identification), l'application AIR passe à la dernière étape du flux de travail. Toutefois, si le fichier requiert une licence basée sur l'identité de l'utilisateur (en d'autres termes, que ses informations d'identification sont obligatoires), l'objet NetStream déclenche un objet DRMAuthenticateEvent. L'utilisateur doit alors entrer ses informations d'identification pour que la lecture puisse démarrer. 3 L'application AIR doit intégrer un mécanisme de collecte des informations d'identification appropriées. Les propriétés usernamePrompt, passwordPrompt et urlPrompt de la classe DRMAuthenticationEvent, fournies par le serveur de contenu, permettent d'indiquer à l'utilisateur final les données requises. Vous pouvez utiliser ces propriétés lors du développement d'une interface utilisateur pour extraire les informations d'identification des utilisateurs requises. La chaîne de valeur usernamePrompt pourrait, par exemple, stipuler que le nom d'utilisateur doit être indiqué sous forme d'adresse électronique. Remarque : AIR ne propose pas d'interface utilisateur par défaut pour collecter les informations d'identification. Il incombe donc au développeur d'application de concevoir l'interface utilisateur et de gérer les événements DRMAuthenticateEvent. Si l'application n'intègre pas d'écouteur d'événement associé aux objets DRMAuthenticateEvent, l'objet chiffré par DRM conserve l'état « en attente d'informations d'identification » et le contenu n'est donc pas disponible. 4 Lorsque l'application obtient les informations d'identification, elle les transmet par le biais de la méthode setDRMAuthenticationCredentials() à l'objet NetStream. Ce processus avertit l'objet NetStream qu'il doit tenter d'authentifier l'utilisateur dès que possible. AIR transmet ensuite les informations d'identification à FMRMS pour qu'il authentifie l'utilisateur. Si l'authentification aboutit, l'application passe à l'étape suivante. Si l'authentification échoue, l'objet NetStream déclenche un nouvel objet DRMAuthenticateEvent et l'application revient à l'étape 3. Ce processus est répété indéfiniment. L'application doit intégrer un mécanisme de gestion et de restriction du nombre de tentatives d'authentification. Elle pourrait par exemple autoriser l'utilisateur à annuler la tentative, en vue de fermer la connexion NetStream. 5 Une fois l'utilisateur authentifié ou en cas d'utilisation d'un chiffrement anonyme, le sous-système DRM récupère le voucher. Le voucher permet de vérifier que l'utilisateur est autorisé à visionner le contenu. Les informations que contient le voucher peuvent s'appliquer aux utilisateurs authentifiés et aux utilisateurs anonymes. Par exemple, qu'ils soient authentifiés ou anonymes, les utilisateurs sont susceptibles de pouvoir accéder au contenu pendant une période de temps donnée avant que le contenu n'expire. Ils risquent de ne pas pouvoir accéder au contenu si le fournisseur de contenu ne prend pas en charge la version de l'application de visionnement. S'il ne s'est pas produit d'erreur et que l'utilisateur a été autorisé à visionner le contenu, l'objet NetStream déclenche un objet DRMStatusEvent et l'application AIR commence la lecture. L'objet DRMStatusEvent mémorise les informations relatives au voucher, qui identifient les régulations et autorisations de l'utilisateur. Il mémorise par exemple des informations relatives à la disponibilité hors ligne du contenu ou à la date d'expiration du voucher (au terme de laquelle il est impossible de visionner le contenu). L'application peut utiliser ces données pour avertir l'utilisateur de l'état de ses régulations. Elle peut par exemple afficher dans une barre d'état le nombre de jours restants pendant lesquels l'utilisateur est autorisé à visionner le contenu. Si l'utilisateur est autorisé à visionner le contenu hors ligne, le voucher est mis en cache et le contenu chiffré est téléchargé sur son ordinateur. Il y a accès pendant le nombre de jours indiqué par la période de location hors ligne. La propriété detail de l'événement contient « DRM.voucherObtained ». L'application décide de l'emplacement local de stockage du contenu pour assurer sa disponibilité hors ligne. Dans AIR 1.5, vous pouvez également précharger les vouchers à l'aide de la classe DRMManager. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 285 Utilisation de la gestion des droits d'auteur numériques (DRM) Toute erreur liée à DRM entraîne la distribution par l'application d'un objet événement DRMErrorEvent. AIR gère les échecs d'authentification survenant lors de l'utilisation de la méthode NetStream setDRMAuthenticationCredentials() en déclenchant à nouveau l'objet DRMAuthenticationEvent. Tous les autres événements d'erreur doivent être gérés explicitement par l'application. Ils incluent notamment les cas où l'utilisateur entre des informations d'identification valides, mais le voucher qui protège le contenu chiffré interdit l'accès à ce dernier. Un utilisateur authentifié risque, par exemple, de ne pas pouvoir accéder au contenu car il ne s'est pas acquitté des droits correspondants. Ce cas de figure se produit lorsque deux utilisateurs, tous deux membres enregistrés auprès du même éditeur de contenus multimédia, tentent de partager un contenu pour lequel seul l'un d'entre eux a réglé des droits. L'application doit avertir l'utilisateur de l'erreur, en interdisant par exemple l'accès au contenu, et proposer une alternative, sous la forme d'instructions indiquant comment s'enregistrer et régler les droits de visionnement du contenu. Préchargement de vouchers pour une lecture hors ligne Vous pouvez précharger les vouchers requis pour lire le contenu protégé par DRM. Les vouchers préchargés permettent aux utilisateurs d'afficher le contenu même si leur connexion Internet n'est pas active. (Le processus de préchargement lui-même requiert évidemment une connexion Internet.) Utilisez la méthode preloadEmbeddedMetadata() de la classe NetStream et la classe DRMManager d'AIR 1.5 pour précharger les vouchers. La procédure suivante décrit le préchargement du voucher pour un fichier multimédia protégé par DRM : 1 Téléchargez et stockez le fichier multimédia. (Les métadonnées DRM ne peuvent être préchargées qu'à partir de fichiers stockés localement.) 2 Créez les objets NetConnection et NetStream, en fournissant des implémentations pour les fonctions de rappel onDRMContentData() et onPlayStatus() de l'objet client NetStream. 3 Créez un objet NetStreamPlayOptions et définissez la propriété stream sur l'URL du fichier multimédia local. 4 Appelez la méthode NetStream preloadEmbeddedMetadata(), en transmettant l'objet NetStreamPlayOptions identifiant le fichier multimédia à analyser. 5 Si le fichier multimédia contient des métadonnées DRM, la fonction de rappel onDRMContentData() est invoquée. Les métadonnées sont transmises à cette fonction sous forme d'objet DRMContentData. 6 Utilisez l'objet DRMContentData pour obtenir le voucher à l'aide de la méthode DRMManager loadVoucher(). Si la valeur de la propriété authenticationMethod de l'objet DRMContentData est userNameAndPassword, vous devez alors authentifier l'utilisateur sur le serveur de gestion des droits avant de charger le voucher. Les propriétés serverURL et domain de l'objet DRMContentData peuvent être transmis à la méthode DRMManager authenticate(), de même que les informations d'identification de l'utilisateur. 7 La fonction de rappel onPlayStatus() est invoquée lorsque l'analyse du fichier est terminée. Si la fonction onDRMContentData() n'a pas été appelée, le fichier ne contient pas les métadonnées requises pour obtenir un voucher (et peut ne pas être protégé par DRM). L'exemple de code suivant illustre le préchargement d'un voucher DRM pour un fichier multimédia local : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 286 Utilisation de la gestion des droits d'auteur numériques (DRM) 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 ); 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 { DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 287 Utilisation de la gestion des droits d'auteur numériques (DRM) 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 { 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(); } } } Membres et événements DRM de la classe NetStream La classe NetStream propose une connexion en flux continu unidirectionnelle entre Flash Player ou une application AIR et Flash Media Server ou le système de fichiers local. (La classe NetStream gère également les téléchargements en mode progressif.) Un objet NetStream est un canal dans un objet NetConnection. Dans une application AIR, la classe NetStream distribue quatre événements liés à DRM : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 288 Utilisation de la gestion des droits d'auteur numériques (DRM) Evénement Description drmAuthenticate Défini dans la classe DRMAuthenticateEvent, cet événement est distribué lorsqu'un objet NetStream tente de lire un contenu chiffré par une solution de gestion des droits numériques (DRM) qui nécessite la saisie d'informations d'identification des utilisateurs pour démarrer la lecture. Les propriétés de cet événement incluent les propriétés header, usernamePrompt, passwordPrompt et urlPrompt, qui permettent d'obtenir et de définir les informations d'identification des utilisateurs. Cet événement est répété jusqu'à ce que l'objet NetStream reçoive des informations d'identification des utilisateurs valides. drmError Défini dans la classe DRMErrorEvent et distribué lorsqu'un objet NetStream qui tente de lire un fichier chiffré par DRM rencontre une erreur liée à DRM. Un objet événement associé à une erreur DRM est par exemple distribué lorsque l'autorisation de l'utilisateur échoue. Cet échec peut être dû au fait que l'utilisateur n'a pas réglé les droits de visionnement du contenu ou que le fournisseur de contenu ne prend pas en charge l'application de visionnement. drmStatus Défini dans la classe DRMStatusEvent, cet événement est distribué lorsque la lecture du contenu chiffré par DRM démarre (en d'autres termes, lorsque l'utilisateur est authentifié et autorisé à lire le contenu). L'objet DRMStatusEvent contient des informations relatives au voucher, telles que la disponibilité du contenu hors ligne ou la date d'expiration du voucher, auquel cas le contenu ne peut plus être visionné. status Défini dans events.StatusEvent et distribué uniquement lorsque l'application tente de lire un contenu chiffré par DRM, en appelant la méthode NetStream.play(). La valeur de la propriété status code est définie sur « DRM.encryptedFLV ». La classe NetStream comprend les méthodes réservées à DRM suivantes : Méthode Description resetDRMVouchers() Supprime toutes les données du voucher DRM placé dans le cache local. L'application doit télécharger à nouveau les vouchers pour que l'utilisateur puisse accéder au contenu chiffré. Par exemple, le code suivant supprime tous les vouchers du cache : NetStream.resetDRMVouchers(); setDRMAuthenticationCredentials() Transmet un jeu d'informations d'identification, à savoir le nom d'utilisateur, le mot de passe et le type d'authentification, à l'objet NetStream à titre d'authentification. Les types d'authentification valides sont « drm » et « proxy ». Pour le type d'authentification « drm », les informations d'identification indiquées sont comparées aux données stockées sur FMRMS. Pour le type d'authentification « proxy », les informations d'identification sont comparées aux données stockées sur le serveur proxy et doivent être identiques aux informations requises par ce dernier. Par exemple, l'option proxy permet à l'application de s'authentifier auprès d'un serveur proxy si une entreprise impose une étape de ce type avant que l'utilisateur ne puisse accéder à Internet. A moins que l'authentification anonyme ne soit utilisée, au terme de l'authentification proxy, l'utilisateur doit néanmoins s'authentifier après de FMRMS pour obtenir le voucher et lire le contenu. Vous pouvez utiliser setDRMAuthenticationcredentials() une seconde fois avec l'option « drm » pour procéder à une authentification auprès de FMRMS. preloadEmbeddedMetadata() Recherche les métadonnées intégrées dans un fichier multimédia local. Lorsque des métadonnées DRM sont détectées, AIR appelle la fonction de rappel onDRMContentData(). De plus, un objet NetStream invoque les fonctions de rappel onDRMContentData() et onPlayStatus() à la suite de l'appel à la méthode preloadEmbeddedMetaData(). La fonction onDRMContentData() est appelée lorsque des métadonnées DRM sont détectées dans un fichier multimédia. La fonction onPlayStatus() est appelée lorsque le fichier a été entièrement analysé. Les fonctions onDRMContentData() et onPlayStatus() doivent être définies sur l'objet client affecté à l'occurrence de NetStream. Si vous utilisez le même objet NetStream pour précharger les vouchers et lire le contenu, vous devez attendre l'appel onPlayStatus() généré par preloadEmbeddedMetaData() avant de commencer la lecture. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 289 Utilisation de la gestion des droits d'auteur numériques (DRM) Dans le code suivant, le nom d'utilisateur (« administrator »), le mot de passe (« password ») et le type d'authentification (« drm ») sont définis pour authentifier l'utilisateur. La méthode setDRMAuthenticationCredentials() doit fournir des informations d'identification identiques aux données connues et acceptées par le fournisseur de contenu (à savoir, les informations d'identification qui ont autorisé l'utilisateur à visionner le contenu). Ce chapitre ne contient pas le code permettant de lire la vidéo et de s'assurer qu'une connexion au flux vidéo a abouti. 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"); } Utilisation de la classe DRMStatusEvent Un objet NetStream distribue un objet DRMStatusEvent lorsque la lecture du contenu protégé par la solution de gestion des droits numériques (DRM) démarre (en d'autres termes, après vérification du voucher, authentification de l'utilisateur et autorisation de ce dernier à visionner le contenu). L'objet DRMStatusEvent est également distribué lorsqu'un utilisateur anonyme est autorisé à accéder au contenu. Le voucher est vérifié pour s'assurer que l'utilisateur anonyme, qui ne requiert pas d'authentification, est autorisé à lire le contenu. Il arrive qu'un utilisateur anonyme se voie refuser l'accès pour diverses raisons. Un utilisateur anonyme risque de ne pas pouvoir accéder au contenu parce qu'il a expiré. L'objet DRMStatusEvent contient des informations relatives au voucher, telles que la disponibilité du contenu hors ligne ou la date d'expiration du voucher, auquel cas le contenu ne peut plus être visionné. L'application peut utiliser ces données pour communiquer l'état des régulations de l'utilisateur et les autorisations correspondantes. Propriétés DRMStatusEvent La classe DRMStatusEvent comprend les propriétés suivantes : Propriété Description contentData Objet DRMContentData contenant les métadonnées DRM intégrées dans le contenu. detail Chaîne expliquant le contexte de l'événement d'état. Dans DRM 1.0, l'unique valeur valide est DRM.voucherObtained. isAnonymous Indique si le contenu, protégé par chiffrement DRM, est disponible sans nécessiter que l'utilisateur n'entre d'informations d'authentification (true) ou s'il doit les fournir (false). La valeur false signifie que l'utilisateur doit entrer un nom d'utilisateur et un mot de passe correspondant aux données connues et attendues par le fournisseur de contenu. isAvailableOffline Indique si le contenu, protégé par chiffrement DRM, peut être proposé hors ligne (true) ou non (false). Pour que le contenu protégé numériquement soit disponible hors ligne, le voucher correspondant doit être placé dans le cache de l'ordinateur local de l'utilisateur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 290 Utilisation de la gestion des droits d'auteur numériques (DRM) Propriété Description isLocal Indique si le voucher nécessaire pour la lecture du contenu est mis en cache localement. offlineLeasePeriod Nombre restant de jours pendant lesquels le contenu peut être visionné hors ligne. policies Objet personnalisé susceptible de contenir des propriétés DRM personnalisées. voucher DRMVoucher. voucherEndDate Date absolue d'expiration du voucher, après laquelle il est impossible de visionner le contenu. Création d'un gestionnaire DRMStatusEvent L'exemple suivant crée un gestionnaire d'événement qui renvoie des informations sur l'état du contenu chiffré par DRM de l'objet NetStream à l'origine de l'événement. Ajoutez ce gestionnaire d'événement à un objet NetStream qui pointe vers le contenu chiffré par DRM. function drmStatusEventHandler(event:DRMStatusEvent):void { trace(event); } function drmStatusEventHandler(event:DRMStatusEvent):void { trace(event); } Utilisation de la classe DRMAuthenticateEvent L'objet DRMAuthenticateEvent est distribué lorsqu'un objet NetStream tente de lire un contenu chiffré par DRM qui nécessite la saisie d'informations d'identification pour authentifier l'utilisateur avant de démarrer la lecture. Le gestionnaire DRMAuthenticateEvent est chargé de collecter les informations d'identification requises (nom d'utilisateur, mot de passe et type) et de les transmettre à la méthode NetStream.setDRMAuthenticationCredentials() pour qu'elles soient validées. Chaque application AIR doit intégrer un mécanisme de collecte des informations d'identification des utilisateurs. L'application pourrait par exemple proposer à l'utilisateur une interface simple permettant d'entrer son nom d'utilisateur et son mot de passe, ainsi que, le cas échéant, le type requis. L'application AIR devrait également fournir un mécanisme de gestion et de restriction des tentatives d'authentification. Propriétés DRMAuthenticateEvent La classe DRMAuthenticateEvent comprend les propriétés suivantes : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 291 Utilisation de la gestion des droits d'auteur numériques (DRM) Propriété Description authenticationType Indique si les informations d'identification fournies sont destinées à une authentification auprès de FMRMS (« drm ») ou d'un serveur proxy (« proxy »). Par exemple, l'option « proxy »permet à l'application de s'authentifier auprès d'un serveur proxy si une entreprise impose une étape de ce type avant que l'utilisateur ne puisse accéder à Internet. A moins que l'authentification anonyme ne soit utilisée, au terme de l'authentification proxy, l'utilisateur doit néanmoins s'authentifier auprès de FMRMS pour obtenir le voucher et lire le contenu. Vous pouvez utiliser setDRMAuthenticationcredentials() une seconde fois avec l'option « drm » pour procéder à une authentification auprès de FMRMS. header En-tête du fichier de contenu chiffré fourni par le serveur. Il contient des informations relatives au contexte du contenu chiffré. netstream Objet NetStream à l'origine de cet événement. passwordPrompt Invite associée au mot de passe, fournie par le serveur. La chaîne peut comporter des instructions relatives au type de mot de passe requis. urlPrompt Invite associée à une chaîne URL, fournie par le serveur. La chaîne peut indiquer l'emplacement où sont envoyés le nom d'utilisateur et le mot de passe. usernamePrompt Invite associée au nom d'utilisateur, fournie par le serveur. La chaîne peut comporter des instructions relatives au type de nom d'utilisateur requis. Un fournisseur de contenu peut, par exemple, stipuler que le nom d'utilisateur soit exprimé sous forme d'adresse électronique. Création d'un gestionnaire DRMAuthenticateEvent L'exemple suivant crée un gestionnaire d'événement qui transmet un jeu d'informations d'authentification codées en dur à l'objet NetStream à l'origine de l'événement. (Ce chapitre ne contient pas le code permettant de lire la vidéo et de s'assurer qu'une connexion au flux vidéo a abouti.) 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"); } Création d'une interface de collecte des informations d'identification des utilisateurs Si le contenu DRM nécessite l'authentification de l'utilisateur, l'application AIR doit généralement collecter les informations d'identification correspondantes par le biais d'une interface utilisateur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 292 Utilisation de la gestion des droits d'auteur numériques (DRM) Utilisation de la classe DRMErrorEvent AIR distribue un objet DRMErrorEvent lorsqu'un objet NetStream qui tente de lire un fichier chiffré par une solution de gestion des droits numériques (DRM) rencontre une erreur DRM. Si les informations d'identification de l'utilisateur ne sont pas valides, l'objet DRMAuthenticateEvent gère l'erreur par le biais d'une distribution répétée jusqu'à ce que l'utilisateur entre des informations d'identification valides ou que l'application AIR interdise toute nouvelle tentative. L'application doit écouter tout autre événement d'erreur DRM pour détecter, identifier et gérer les erreurs DRM. Si un utilisateur entre des informations d'identification valides, il risque néanmoins de ne pas être autorisé à visionner le contenu chiffré, selon les termes du voucher DRM. Ce cas de figure se produit par exemple si l'utilisateur tente de visionner le contenu dans une application non autorisée (en d'autres termes, une application non validée par l'éditeur du contenu chiffré). Dans ce cas, un objet DRMErrorEvent est distribué. Les événements d'erreur peuvent également être déclenchés si le contenu est endommagé ou si la version de l'application ne correspond pas aux données stipulées par le voucher. L'application doit intégrer un mécanisme de gestion des erreurs approprié. Propriétés DRMErrorEvent Le tableau suivant recense les erreurs signalées par l'objet DRMErrorEvent : Code d'erreur majeure Code d'erreur mineure Informations relatives à l'erreur 1001 non utilisé L'authentification de l'utilisateur a échoué. 1002 non utilisé FMRMS (Flash Media Rights Management Server) ne gère pas SSL (Secure Sockets Layer). 1003 non utilisé Le contenu a expiré et ne peut plus être visionné. 1004 non utilisé L'autorisation de l'utilisateur a échoué. Ce cas de figure se produit par exemple lorsque l'utilisateur n'a pas réglé le contenu et ne dispose de ce fait pas des droits requis pour le visionner. 1005 non utilisé 1006 non utilisé Une mise à jour du client est nécessaire. En d'autres termes, Flash Media Rights Management Server (FMRMS) requiert un nouveau moteur de gestion des droits numériques (DRM). 1007 non utilisé Echec interne générique. 1008 Code d'erreur de chiffrement détaillé Clé de licence incorrecte. 1009 non utilisé Contenu FLV endommagé. 1010 non utilisé 1011 non utilisé Server URL publisherID:applicationID Description Connexion au serveur impossible. L'ID d'application de visualisation ne correspond pas à un ID valide géré par l'éditeur de contenu. La version de l'application ne correspond pas à la valeur indiquée dans les régulations. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 293 Utilisation de la gestion des droits d'auteur numériques (DRM) Code d'erreur majeure Code d'erreur mineure Informations relatives à l'erreur 1012 non utilisé La vérification du voucher associé au contenu chiffré a échoué, ce qui indique que ce dernier risque d'être endommagé. 1013 non utilisé Il s'est avéré impossible d'enregistrer le voucher associé au contenu chiffré. 1014 non utilisé La vérification de l'intégrité de l'en-tête du fichier FLV a échoué, ce qui indique que le contenu risque d'être endommagé. Code d'erreur majeure Code d'erreur mineure 3300 Code d'erreur Adobe Policy Server L'application a détecté un voucher non valide associé au contenu. 3301 non utilisé L'authentification de l'utilisateur a échoué. 3302 non utilisé SSL (Secure Sockets Layer) n'est pas pris en charge par FMRMS (Flash Media Rights Management Server). 3303 non utilisé Le contenu a expiré et ne peut plus être visionné. 3304 non utilisé L'autorisation de l'utilisateur a échoué. Ce cas de figure se produit même si l'utilisateur est authentifié (s'il n'a pas réglé les droits de visionnement du contenu, par exemple). 3305 non utilisé 3306 non utilisé Une mise à jour du client est nécessaire. En d'autres termes, FMRMS (Flash Media Rights Management Server) requiert un nouveau moteur client de gestion des droits numériques. 3307 non utilisé Echec générique interne de gestion des droits numériques. 3308 Code d'erreur de chiffrement détaillé Clé de licence incorrecte. 3309 non utilisé Le contenu vidéo Flash est endommagé. 3310 non utilisé publisherID:applicationID L'ID d'application de visualisation ne correspond pas à un ID valide géré par l'éditeur de contenu. En d'autres termes, l'application de visualisation n'est pas prise en charge par le fournisseur de contenu. 3311 non utilisé min=x:max=y La version de l'application ne correspond pas à la valeur indiquée par le voucher. 3312 non utilisé La vérification du voucher associé au contenu chiffré a échoué, ce qui indique que le contenu risque d'être endommagé. 3313 non utilisé Il s'est avéré impossible d'enregistrer dans Microsafe le voucher associé au contenu chiffré. Informations relatives à l'erreur Server URL Description Description Connexion au serveur impossible. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 294 Utilisation de la gestion des droits d'auteur numériques (DRM) Code d'erreur majeure Code d'erreur mineure Informations relatives à l'erreur Description 3314 non utilisé La vérification de l'intégrité de l'en-tête du fichier FLV a échoué, ce qui indique que le contenu risque d'être endommagé. 3315 non utilisé La lecture à distance du contenu protégé par la solution DRM n'est pas autorisée. 3316 non utilisé Module AdobeCP manquant. 3317 non utilisé Échec du chargement du module AdobeCP. 3318 non utilisé Version AdobeCP incompatible détectée. 3319 non utilisé Point d'entrée d'API AdobeCP manquant. 3320 non utilisé Le module AdobeCP n'est pas authentifié. Création d'un gestionnaire DRMErrorEvent L'exemple suivant crée un gestionnaire d'événement associé à l'objet NetStream à l'origine de l'événement. Il est appelé si l'objet NetStream rencontre une erreur lors d'une tentative de lecture du contenu chiffré par DRM. En temps normal, lorsqu'une application rencontre une erreur, elle exécute diverses tâches de nettoyage, avertit l'utilisateur de l'erreur et propose des options permettant de résoudre le problème. private function drmErrorEventHandler(event:DRMErrorEvent):void { trace(event.toString()); } Utilisation de la classe DRMManager Utilisez la classe DRMManager pour gérer les vouchers et les sessions de gestion des droits d'auteur dans une application AIR. La classe DRMManager est disponible dans AIR version 1.5 ou ultérieure. Gestion des vouchers Lorsqu'un utilisateur lit un fichier multimédia protégé par DRM en ligne, AIR obtient et met en cache le voucher de licence requis pour afficher le contenu. Si l'application enregistre le fichier localement et que le voucher autorise une lecture hors ligne, l'utilisateur peut afficher le contenu même si la connexion au serveur de gestion des droits d'auteur n'est pas disponible. La méthode DRMManager et NetStream preloadEmbeddedMetadata() vous permet de mettre préalablement en cache le voucher de sorte que l'application n'ait pas besoin de lancer la lecture pour obtenir la licence nécessaire à l'affichage du contenu. Par exemple, votre application peut télécharger le fichier multimédia, puis obtenir le voucher pendant que l'utilisateur est encore en ligne. Pour précharger un voucher, utilisez la méthode NetStream preloadEmbeddedMetadata() pour obtenir un objet DRMContentData. L'objet DRMContentData contient l'URL et le domaine du serveur de gestion des droits d'auteur pouvant fournir la licence et indique si l'authentification de l'utilisateur est requise. Avec ces informations, vous pouvez appeler la méthode DRMManager loadVoucher() pour obtenir le voucher et le mettre en cache. Le flux de travail du préchargement des vouchers est décrit plus en détails à la section « Préchargement de vouchers pour une lecture hors ligne » à la page 285. Gestion des sessions DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 295 Utilisation de la gestion des droits d'auteur numériques (DRM) Vous pouvez également utiliser DRMManager pour authentifier l'utilisateur auprès d'un serveur de gestion des droits d'auteur et pour gérer les sessions persistantes. Appelez la méthode DRMManager authenticate() pour établir une session auprès du serveur de gestion des droits d'auteur. Une fois l'authentification réussie, le DRMManager distribue un objet DRMAuthenticationCompleteEvent qui contient un jeton de session. Vous pouvez enregistrer ce jeton pour établir les sessions futures de sorte que l'utilisateur n'ait plus besoin de fournir les informations d'identification de son compte. Transmettez le jeton à la méthode setAuthenticationToken() pour établir une nouvelle session authentifiée. (L'expiration du jeton, et d'autres attributs, sont déterminés par les paramètres du serveur qui génère le jeton. La structure des données du jeton n'est pas destinée à être interprétée par le code de l'application AIR et est susceptible d'être modifiée dans les futures mises à jour AIR.) Les jetons d'authentification peuvent être transférés vers d'autres ordinateurs. Pour les protéger, vous pouvez les stocker dans le magasin local chiffré d'AIR. Pour plus d'informations, consultez la section « Stockage des données chiffrées » à la page 219. Evénements DRMStatus Le DRMManager distribue un objet DRMStatusEvent lorsqu'un appel à la méthode loadVoucher() se termine avec succès. Si un voucher a été obtenu, la propriété detail de l'objet événement prend la valeur : « DRM.voucherObtained » et la propriété voucher contient l'objet DRMVoucher. Si le voucher n'a pas été obtenu, la propriété detail conserve la valeur : « DRM.voucherObtained » ; toutefois, la propriété voucher est null. Un voucher peut ne pas être obtenu si, par exemple, vous utilisez le LoadVoucherSetting de localOnly et qu'aucun voucher n'a été mis en cache localement. Si l'appel à la méthode loadVoucher() échoue, par exemple du fait d'une erreur de communication ou d'authentification, le DRMManager renvoie à la place un objet DRMErrorEvent. Evénements DRMAuthenticationComplete Le DRMManager distribue un objet DRMAuthenticationCompleteEvent lorsque l'utilisateur est bien authentifié via un appel à la méthode authenticate(). Dans AIR 1.5, l'objet DRMAuthenticationCompleteEvent contient un jeton réutilisable qui permet de faire persister l'authentification de l'utilisateur tout au long des sessions de l'application. Transmettez ce jeton à la méthode setAuthenticationToken() du DRMManager pour rétablir la session. (Les attributs du jeton, tels que l'expiration, sont définis par le créateur de ce jeton. AIR ne fournit pas d'API capable d'examiner les attributs du jeton.) Evénements DRMAuthenticationError Le DRMManager distribue un objet DRMAuthenticationErrorEvent lorsqu'un utilisateur n'a pas pu s'authentifier via un appel aux méthodes authenticate() ou setAuthenticationToken(). Utilisation de la classe DRMContentData L'objet DRMContentData contient les propriétés de métadonnées du fichier multimédia protégé par DRM. Les propriétés DRMContentData contiennent les informations nécessaires à l'obtention du voucher de licence permettant d'afficher le contenu. 296 Chapitre 26 : Lancement d'applications et options de fermeture Cette section traite des choix et points à prendre en compte concernant le lancement d'une application Adobe® AIR™ installée et la fermeture d'une application en cours d'exécution. Appel d'une application Une application AIR est appelée lorsque l'utilisateur (ou le système d'exploitation) exécute l'une des actions suivantes : • Il lance l'application à partir du shell de poste de travail. • Il utilise l'application comme une commande sur un shell de ligne de commande. • Il ouvre un type de fichier pour lequel cette application correspond à l'application d'ouverture définie par défaut. • (Mac OS X) Il clique sur l'icône de l'application sur la barre des tâches du Dock (que l'application soit en cours d'exécution ou non). • Il choisit de lancer l'application à partir du programme d'installation (à la fin d'un nouveau processus d'installation ou après un double-clic sur le fichier AIR d'une application déjà installée). • Il commence une mise à jour d'une application AIR alors que la version installée l'informe qu'elle est déjà en train de traiter des mises à jour (par l'inclusion de la déclaration <customUpdateUI>true</customUpdateUI> dans le fichier descripteur d'application). • Il consulte une page Web hébergeant une application ou un badge Flash appelant la méthode com.adobe.air.AIR launchApplication() qui spécifie les informations d'identification relatives à l'application AIR. (Le descripteur d'application doit également comprendre une déclaration <allowBrowserInvocation>true</allowBrowserInvocation> afin que les appels au navigateur aboutissent.) Consultez la section « Lancement d'une application AIR installée à partir du navigateur » à la page 326. Dès qu'une application AIR est appelée, AIR distribue un objet InvokeEvent de type invoke par le biais de l'objet NativeApplication Singleton. Afin de laisser à une application le temps de s'initialiser et d'enregistrer un écouteur d'événement, les événements invoke sont placés en file d'attente au lieu d'être ignorés. Dès qu'un écouteur est enregistré, tous les événements placés en file d'attente sont livrés. Remarque : lorsqu'une application est appelée au moyen de la fonction d'appel du navigateur, l'objet NativeApplication distribue un événement invoke uniquement si l'application n'est pas en cours d'exécution. Consultez la section « Lancement d'une application AIR installée à partir du navigateur » à la page 326. Pour recevoir des événements invoke, appelez la méthode addEventListener() de l'objet NativeApplication (NativeApplication.nativeApplication). Lorsqu'un écouteur d'événement s'enregistre pour un événement invoke, il reçoit également tous les événements invoke survenus avant l'enregistrement. Les événements invoke placés en file d'attente sont distribués un par un dans un court laps de temps après le renvoi de l'appel à addEventListener(). Si un nouvel événement invoke se produit au cours de ce processus, il peut être distribué avant un ou plusieurs des événements placés en file d'attente. Ce placement des événements en file d'attente vous permet de gérer tous les événements invoke survenus avant l'exécution de votre code d'initialisation. Sachez que si, plus tard dans l'exécution (après l'initialisation de l'application), vous ajoutez un écouteur d'événement, celui-ci recevra toujours tous les événements invoke survenus depuis le lancement de l'application. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 297 Lancement d'applications et options de fermeture Une seule occurrence d'une application AIR est lancée. Lorsqu'une application en cours d'exécution est à nouveau appelée, AIR distribue un nouvel événement invoke vers elle. C'est l'application AIR qui est chargée de répondre à un événement invoke et de prendre les mesures appropriées (comme l'ouverture d'une nouvelle fenêtre de document). Un objet InvokeEvent contient tous les arguments transmis à l'application, de même qu'un répertoire à partir duquel l'application a été appelée. Si l'application a été appelée via une association de type de fichier, le chemin d'accès complet au fichier est alors inclus dans les arguments de ligne de commande. De la même manière, si l'application a été appelée via une mise à jour, le chemin d'accès complet au fichier AIR de mise à jour est fourni. Lorsque plusieurs fichiers sont ouverts simultanément, un seul objet InvokeEvent est distribué sous Mac OS X. Chaque fichier est inclus dans le tableau arguments. Sous Windows et Linux, un objet InvokeEvent distinct est distribué pour chaque fichier. Votre application gère les événements invoke en enregistrant un écouteur avec son objet NativeApplication : NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvokeEvent); air.NativeApplication.nativeApplication.addEventListener(air.InvokeEvent.INVOKE, onInvokeEvent); Et en définissant un écouteur d'événement : var arguments:Array; var currentDir:File; public function onInvokeEvent(invocation:InvokeEvent):void { arguments = invocation.arguments; currentDir = invocation.currentDirectory; } Capture des arguments de ligne de commande Les arguments de ligne de commande associés à l'appel d'une application AIR sont livrés dans l'événement invoke distribué par l'objet NativeApplication. La propriété InvokeEvent.arguments contient un tableau des arguments transmis par le système d'exploitation suite à l'appel d'une application AIR. Si les arguments contiennent des chemins de fichiers relatifs, il est généralement possible de résoudre les chemins à l'aide de la propriété currentDirectory. Les arguments transmis à un programme AIR sont traités sous forme de chaînes délimitées par des espaces, à moins d'être placés entre guillemets doubles : Arguments Tableau tick tock {tick,tock} tick "tick tock" {tick,tick tock} "tick" “tock” {tick,tock} \"tick\" \"tock\" {"tick","tock"} La propriété InvokeEvent.currentDirectory contient un objet File représentant le répertoire à partir duquel l'application a été lancée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 298 Lancement d'applications et options de fermeture Lorsqu'une application est appelée suite à l'ouverture d'un fichier dont le type est enregistré par l'application, le chemin d'accès natif au fichier est compris dans les arguments de ligne de commande sous forme de chaîne. (Votre application est chargée d'ouvrir le fichier ou d'effectuer l'opération attendue.) De la même manière, lorsqu'une application est programmée pour se mettre à jour automatiquement (plutôt que de dépendre de l'interface utilisateur de mise à jour d'AIR standard), le chemin d'accès natif au fichier AIR est inclus si un utilisateur double-clique sur un fichier AIR contenant une application dotée de l'ID d'application correspondant. Vous pouvez accéder au fichier à l'aide de la méthode resolve() de l'objet File currentDirectory : if((invokeEvent.currentDirectory != null)&&(invokeEvent.arguments.length > 0)){ dir = invokeEvent.currentDirectory; fileToOpen = dir.resolvePath(invokeEvent.arguments[0]); } Il est également recommandé de vérifier qu'un argument correspond effectivement à un chemin d'accès à un fichier. Exemple : journal des événements d'appel L'exemple suivant explique comment enregistrer des écouteurs pour l'événement invoke et comment gérer ce type d'événement. Dans cet exemple, tous les événements d'appel reçus sont consignés dans un journal et le répertoire actif ainsi que les arguments de ligne de commande sont affichés. Remarque : pour créer l'exemple suivant avec Adobe® Flash® CS3 Professional ou Adobe® Flash® CS4 Professional, commencez par créer un fichier Flash (Adobe AIR). Dans le panneau Paramètres d'ActionScript 3.0 (Fichier > Paramètres de publication > bouton Paramètres), saisissez le nom InvokeEventLogExample dans le champ Classe du document. Enregistrez le fichier FLA sous le nom InvokeEventLogExample.fla. Créez ensuite un fichier ActionScript dans le même dossier. Saisissez le code suivant dans le fichier ActionScript, puis enregistrez le fichier sous le nom 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 { DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 299 Lancement d'applications et options de fermeture var now:String = new Date().toTimeString(); 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); } } } Lancement lors de la connexion Il est possible de configurer le lancement automatique d'une application AIR au moment de la connexion de l'utilisateur actif en définissant NativeApplication.nativeApplication.startAtLogin=true. Une fois ce paramètre défini, l'application est lancée automatiquement chaque fois que l'utilisateur se connecte. Elle suit ce comportement de lancement tant que le paramètre n'est pas défini sur false. Soit ce changement est effectué manuellement par l'utilisateur via le système d'exploitation, soit il survient suite à la désinstallation de l'application. Le lancement au moment de la connexion est un paramètre d'exécution. Remarque : l'application n'est pas lancée au démarrage du système informatique. Elle s'ouvre lorsque l'utilisateur se connecte. Le paramètre s'applique uniquement à l'utilisateur actif. En outre, l'application doit être installée afin que la propriété startAtLogin soit définie correctement sur true. Une erreur est renvoyée si la propriété est définie alors que l'application n'est pas installée (suite à un lancement à l'aide d'ADL, par exemple). Appel du navigateur La fonction d'appel du navigateur permet à un site Web de lancer une application AIR installée à partir du navigateur. L'appel du navigateur est uniquement autorisé si le fichier descripteur d'application définit allowBrowserInvocation sur true: <allowBrowserInvocation>true</allowBrowserInvocation> DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 300 Lancement d'applications et options de fermeture Pour plus d'informations sur le fichier descripteur d'application, consultez la section « Définition des propriétés d'une application AIR » à la page 46. Lorsque l'application est appelée par le biais du navigateur, l'objet NativeApplication de l'application distribue un objet BrowserInvokeEvent. Pour recevoir des événements BrowserInvokeEvent, appelez la méthode addEventListener() de l'objet NativeApplication (NativeApplication.nativeApplication) dans l'application AIR. Lorsqu'un écouteur d'événement s'enregistre pour un événement BrowserInvokeEvent, il reçoit également tous les événements BrowserInvokeEvent survenus avant l'enregistrement. Ces événements sont distribués après le renvoi de l'appel à addEventListener(), mais pas nécessairement avant d'autres événements BrowserInvokeEvent susceptibles d'être reçus après l'enregistrement. Cela vous permet de gérer les événements BrowserInvokeEvent survenus avant l'exécution de votre code d'initialisation (comme, par exemple, lorsque l'application a été appelée au départ depuis le navigateur). Sachez que si, plus tard dans l'exécution (après l'initialisation de l'application), vous ajoutez un écouteur d'événement, celui-ci recevra toujours tous les événements BrowserInvokeEvent survenus depuis le lancement de l'application. L'objet BrowserInvokeEvent comprend les propriétés suivantes : Propriété Description arguments Tableau d'arguments (de chaînes) à transmettre à l'application. isHTTPS Indique si le contenu du navigateur utilise le modèle d'URL https (true) ou pas (false). isUserEvent Indique si l'appel du navigateur a entraîné un événement utilisateur (tel qu'un clic de souris). Dans AIR 1.0, cette propriété est toujours définie sur true ; AIR requiert un événement utilisateur pour la fonction d'appel du navigateur. sandboxType Type de sandbox relatif au contenu du navigateur. Les valeurs valides sont identiques à celles qui sont admises pour la propriété Security.sandboxType. Il peut s'agir de l'une des valeurs suivantes : • • Security.APPLICATION : le contenu se trouve dans le sandbox de sécurité de l'application. Security.LOCAL_TRUSTED : le contenu se trouve dans le sandbox de sécurité local avec système de fichiers. • Security.LOCAL_WITH_FILE : le contenu se trouve dans le sandbox de sécurité local avec système de fichiers. • Security.LOCAL_WITH_NETWORK : le contenu se trouve dans le sandbox de sécurité local avec accès au réseau. • securityDomain Security.REMOTE : le contenu se trouve dans un domaine (réseau) distant. Correspond au domaine de sécurité du contenu du navigateur, tel www.adobe.com ou www.example.org. Cette propriété est uniquement définie pour le contenu du sandbox de sécurité distant (pour le contenu d'un domaine réseau). Elle n'est pas définie pour un contenu figurant dans un sandbox de sécurité d'application ou local. Si vous utilisez la fonction d'appel du navigateur, tenez compte des implications sous-jacentes au niveau de la sécurité. Lorsqu'un site Web lance une application AIR, il peut envoyer les données par le biais de la propriété arguments de l'objet BrowserInvokeEvent. Utilisez ces données avec précaution dans toute opération délicate, telle que des API de chargement de code ou de fichier. Le niveau de risque varie en fonction de l'usage que l'application réserve aux données. Si seul un site Web spécifique doit appeler l'application, cette-ci devrait vérifier la propriété securityDomain de l'objet BrowserInvokeEvent. Vous pouvez également exiger de la part du site Web appelant l'application qu'il utilise le protocole HTTPS, ce que vous pouvez contrôler en vérifiant la propriété isHTTPS de l'objet BrowserInvokeEvent. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 301 Lancement d'applications et options de fermeture L'application devrait valider les données transmises. Si, par exemple, une application s'attend à recevoir des URL pointant vers un domaine spécifique, elle devrait vérifier que les URL pointent réellement vers le domaine attendu. Cette procédure peut empêcher un pirate de tromper l'application en lui demandant de lui envoyer des données sensibles. Aucune application ne devrait utiliser d'arguments BrowserInvokeEvent susceptibles de pointer vers des ressources locales. Ainsi, il est vivement déconseillé de concevoir une application qui crée des objets File à partir d'un chemin transmis depuis le navigateur. Si le navigateur peut transmettre des chemins distants, l'application devrait vérifier que ces derniers n'utilisent pas le protocole file:// à la place d'un protocole distant. Pour plus d'informations sur l'appel d'une application à partir du navigateur, consultez la section « Lancement d'une application AIR installée à partir du navigateur » à la page 326. Fermeture d'une application Le moyen le plus rapide pour interrompre une application consiste à appeler NativeApplication.nativeApplication.exit(). Cette méthode fonctionne parfaitement lorsque l'application ne comporte pas de données à enregistrer ni de ressources externes à nettoyer. L'appel de la méthode exit() entraîne la fermeture de toutes les fenêtres, puis celle de l'application. Toutefois, pour permettre aux fenêtres ou à d'autres composants de l'application d'interrompre le processus de fermeture, afin d'enregistrer des données cruciales par exemple, distribuez les événements d'avertissement pertinents avant d'appeler exit(). Un autre point à prendre en compte dans le cadre de l'arrêt progressif d'une application est l'utilisation d'un seul chemin d'exécution, quelle que soit la manière dont le processus d'arrêt commence. L'utilisateur (ou le système d'exploitation) peut déclencher la fermeture de l'application de l'une des manières suivantes : • En fermant la dernière fenêtre de l'application lorsque la méthode NativeApplication.nativeApplication.autoExit est définie sur true. • En sélectionnant la commande de fermeture d'application à partir du système d'exploitation comme, par exemple, lorsque l'utilisateur choisit la commande Quitter de l'application dans le menu par défaut. Cela se produit uniquement sous Mac OS, car Windows et Linux ne fournissent pas de commande de fermeture d'application via le chrome système. • En arrêtant l'ordinateur. Lorsqu'une commande de fermeture est traitée par le biais du système d'exploitation selon l'une de ces méthodes, NativeApplication distribue un événement exiting. Si aucun écouteur n'annule l'événement exiting, toutes les fenêtres qui étaient ouvertes se ferment. Chaque fenêtre distribue un événement closing suivi d'un événement close. Si l'une des fenêtres annule l'événement closing, le processus d'arrêt est interrompu. Si l'ordre de fermeture des fenêtres présente un problème pour votre application, écoutez l'événement exiting de NativeApplication et fermez manuellement les fenêtres dans l'ordre approprié. Cela peut se produire si, par exemple, vous disposez d'une fenêtre de document affichant des palettes d'outils. Il peut s'avérer peu pratique (voire pire) que le système ferme les palettes alors que l'utilisateur a choisi d'annuler la commande de fermeture afin d'enregistrer des données. Sous Windows, vous obtiendrez uniquement l'événement exiting après la fermeture de la dernière fenêtre (lorsque la propriété autoExit de l'objet NativeApplication est définie sur true). Pour adopter un comportement homogène sur toutes les plates-formes, que la séquence de fermeture soit lancée via l'arrière-plan du système d'exploitation, les commandes de menu ou la logique de l'application, suivez les recommandations ci-après pour fermer l'application : 1 Distribuez toujours un événement exiting par le biais de l'objet NativeApplication avant d'appeler exit() dans le code de l'application et vérifiez qu'aucun autre composant de l'application n'annule l'événement. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 302 Lancement d'applications et options de fermeture public function applicationExit():void { var exitingEvent:Event = new Event(Event.EXITING, false, true); NativeApplication.nativeApplication.dispatchEvent(exitingEvent); if (!exitingEvent.isDefaultPrevented()) { NativeApplication.nativeApplication.exit(); } } 2 Ecoutez l'événement exiting de l'application à partir de l'objet NativeApplication.nativeApplication et, dans le gestionnaire, fermez toutes les fenêtres ouvertes (en distribuant d'abord un événement closing). Effectuez les éventuelles tâches de nettoyage nécessaires (enregistrement des données de l'application, suppression des fichiers temporaires, etc.) une fois toutes les fenêtres fermées. Faites exclusivement appel à des méthodes synchrones lors du nettoyage afin de vous assurer qu'elles sont bien terminées avant la fermeture de l'application. Si l'ordre de fermeture des fenêtres est sans importance, vous pouvez analyser en boucle le tableau NativeApplication.nativeApplication.openedWindows et fermer chaque fenêtre une après l'autre. Si l'ordre de fermeture compte, élaborez un moyen de l'appliquer aux fenêtres. 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 Les fenêtres devraient toujours gérer leur propre nettoyage en écoutant les événements closing qui les concernent. 4 Utilisez un seul écouteur exiting dans l'application, car les gestionnaires appelés auparavant ignorent si des gestionnaires ultérieurs annuleront l'événement exiting (sans compter qu'il serait déraisonnable de se fier à l'ordre d'exécution). Voir aussi « Définition des propriétés d'une application AIR » à la page 46 « Présentation d'une interface utilisateur personnalisée pour la mise à jour d'applications » à la page 337 303 Chapitre 27 : Lecture des paramètres de l'application Lors de l'exécution, vous pouvez lire à la fois les propriétés du fichier descripteur d'application et l'ID d'éditeur d'une application. Ceux-ci sont spécifiées dans les propriétés applicationDescriptor et publisherID de l'objet NativeApplication. Lecture du fichier descripteur d'application Vous pouvez lire le fichier descripteur d'application de l'application en cours d'exécution, sous la forme d'un objet XML, en lisant la propriété applicationDescriptor de l'objet NativeApplication, comme le montre l'exemple cidessous : var appXml:XML = NativeApplication.nativeApplication.applicationDescriptor; Vous pouvez alors accéder aux données du descripteur d'applications en tant qu'objet XML (E4X), comme le montre l'exemple suivant : 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; Pour plus d'informations, consultez la section « Structure du fichier descripteur d'application » à la page 46. Lecture des identifiants d'application et d'éditeur Les ID d'application et d'éditeur identifient ensemble de manière unique une application AIR. Vous spécifiez l'ID d'application dans l'élément <id> du descripteur d'application. L'ID d'éditeur est issu du certificat utilisé pour authentifier le package d'installation AIR. L'ID d'application peut être lu dans la propriété id de l'objet NativeApplication, comme l'illustre le code ci-dessous : trace(NativeApplication.nativeApplication.applicationID); L'ID d'éditeur peut être lu dans la propriété publisherID de l'objet NativeApplication. trace(NativeApplication.nativeApplication.publisherID); Remarque : lorsqu'une application AIR est exécutée avec ADL, elle ne comporte pas d'ID d'éditeur à moins qu'on lui en ait affecté un à l'aide de l'indicateur -pubID sur la ligne de commande ADL. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 304 Lecture des paramètres de l'application On peut également trouver l'ID d'éditeur pour une application installée dans le fichier META-INF/AIR/publisherid au sein du répertoire d'installation de l'application. Pour plus d'informations, consultez la section « A propos des identifiants d'éditeur AIR » à la page 329. 305 Chapitre 28 : Utilisation des informations sur le moteur d'exécution et les systèmes d'exploitation La présente section décrit comment une application AIR peut gérer des associations de fichiers de systèmes d'exploitation, constater les activités des utilisateurs et lire des informations sur le moteur d'exploitation Adobe® AIR™. Gestion des associations de fichiers Les associations entre votre application et un type de fichier doivent être déclarées dans le descripteur d'application. Au cours du processus d'installation, le programme d'installation de l'application AIR spécifie celle-ci comme application de démarrage par défaut pour chacun des types de fichiers déclarés, à moins qu'une autre application ne le soit déjà par défaut. Le processus d'installation de l'application AIR n'écrase pas une association de types de fichiers existants. Pour remplacer l'association par une autre application, appelez la méthode NativeApplication.setAsDefaultApplication() lors de l'exécution. Il est recommandé de s'assurer que les associations de fichiers prévues sont en place lorsque votre application démarre. Ceci, parce que le programme d'installation de l'application AIR n'annule pas les associations de fichiers existantes et que ces associations sur un système d'utilisateur peuvent changer à tout moment. Lorsqu'une autre application dispose de l'association de fichiers actuelle, il est recommandé par courtoisie de demander une autorisation à l'utilisateur avant de prendre le contrôle de l'association en cours. Les méthodes suivantes de la classe NativeApplication permettent à une application de gérer des associations de fichiers. Chacune des méthodes prend l'extension du type de fichier comme paramètre. Méthode Description isSetAsDefaultApplication() Renvoie true si l'application AIR est actuellement associée au type de fichier spécifié. setAsDefaultApplication() Crée l'association entre l'application AIR et l'opération d'ouverture du type de fichier. removeAsDefaultApplication() Annule l'association entre l'application AIR et le type de fichier. getDefaultApplication() Signale le chemin de l'application qui est actuellement associée au type de fichier. AIR ne peut gérer des associations que pour des types de fichiers déclarés à l'origine dans le descripteur d'application. Il n'est pas possible de lire des informations sur les associations d'un type de fichier non déclaré, même si un utilisateur a créé manuellement l'association entre ce type de fichier et votre application. L'appel de toute méthode de gestion d'association de fichiers avec l'extension, pour un type de fichier non déclaré dans le descripteur d'application, provoque le renvoi d'une exception d'exécution par l'application Pour des informations sur la déclaration des types de fichiers dans le descripteur d'application, consultez la section « Déclaration des associations de type de fichier » à la page 55. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 306 Utilisation des informations sur le moteur d'exécution et les systèmes d'exploitation Lecture de la version du moteur d'exécution et du correctif L' objet NativeApplication possède une propriété runtimeVersion, qui correspond à la version du moteur d'exécution dans lequel l'application est exécutée (une chaîne telle que "1.0.5"). L'objet NativeApplication possède également une propriété runtimePatchLevel qui est un niveau du correctif pour le moteur d'exécution, un nombre tel que 2960. Le code ci-dessous utilise ces propriétés : trace(NativeApplication.nativeApplication.runtimeVersion); trace(NativeApplication.nativeApplication.runtimePatchLevel); Détection des capacités d'AIR Pour un fichier regroupé avec l'application Adobe AIR, la propriété Security.sandboxType est définie sur la valeur spécifiée par la constante Security.APPLICATION. Vous pouvez charger le contenu, qui peut contenir ou non des interfaces de programmation spécifiques à AIR, selon qu'un fichier se trouve ou non dans le sandbox de sécurité d'Adobe Air, comme le montre le code ci-dessous : if (Security.sandboxType == Security.APPLICATION) { // Load SWF that contains AIR APIs } else { // Load SWF that does not contain AIR APIs } Toutes les ressources qui ne sont pas installées avec l'application AIR sont affectées aux mêmes sandbox de sécurité que ceux qu'Adobe® Flash® Player auraient affecté dans un navigateur Web. Les ressources distantes sont placées dans des sandbox selon leurs domaines d'origine tandis que les ressources locales le sont dans un sandbox local avec accès au réseau, local avec système de fichiers ou approuvé localement. Vous pouvez contrôler si la propriété statique Capabilities.playerType est définie sur "Desktop" pour voir si le contenu est exécuté dans le moteur d'exécution (et non pas dans Flash Player qui, lui, est exécuté dans un navigateur). Pour plus d'informations, consultez le chapitre « Sécurité AIR » à la page 24. Suivi de la présence des utilisateurs L'objet NativeApplication distribue deux événements qui vous aident à détecter à quel moment un utilisateur est actif sur son ordinateur. Si aucune activité de souris ou de clavier n'est détectée dans l'intervalle fixé par par la propriété NativeApplication.idleThreshold, la NativeApplication distribue un événement userIdle. Lorsque survient l'entrée suivante par le clavier ou par la souris, l'objet NativeApplication distribue un événement userPresent. L'intervalle idleThreshold est mesuré en secondes et il a une valeur par défaut de 300, soit cinq minutes. Vous pouvez également lire le nombre de secondes depuis la dernière saisie de l'utilisateur grâce à la propriété NativeApplication.nativeApplication.lastUserInput. Les lignes de code ci-dessous définissent le délai d'inactivité sur deux minutes et elles sont à l'écoute des deux événements userIdle et userPresent : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 307 Utilisation des informations sur le moteur d'exécution et les systèmes d'exploitation 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"); }); Remarque : il n'y a qu'un seul événement userIdle distribué entre deux événements userPresent quels qu'ils soient. 308 Chapitre 29 : Surveillance de la connectivité réseau Adobe® AIR™ permet de vérifier les changements apportés à la connectivité réseau de l'ordinateur sur lequel est installée une application AIR. Ces informations sont utiles si une application utilise des données transmises via le réseau. Par ailleurs, une application peut vérifier la disponibilité d'un service réseau. Détection des changements apportés à la connectivité réseau Votre application AIR peut s'exécuter dans des environnements caractérisés par une connectivité réseau non déterminée et en évolution constante. Pour aider une application à gérer les connexions aux ressources en ligne, Adobe AIR envoie un événement de changement réseau à chaque fois qu'une connexion réseau est disponible ou non disponible. L'objet NativeApplication de l'application distribue l'événement de changement réseau. Pour répondre à cet événement, ajoutez un écouteur : NativeApplication.nativeApplication.addEventListener(Event.NETWORK_CHANGE, onNetworkChange); Définissez également une fonction de gestionnaire d'événement : function onNetworkChange(event:Event) { //Check resource availability } L'événement Event.NETWORK_CHANGE n'indique pas un changement de la connectivité réseau globale. Il se contente de signaler qu'une connexion réseau a changé. AIR ne tente pas d'interpréter la signification du changement réseau. Un ordinateur connecté au réseau étant susceptible de disposer d'un nombre élevé de connexions réelles et virtuelles, perdre une connexion ne signifie pas nécessairement perdre une ressource. A l'inverse, une nouvelle connexion n'est pas non plus synonyme de disponibilité accrue des ressources. Il arrive qu'une nouvelle connexion bloque l'accès à des ressources précédemment disponibles (lors d'une connexion à un VPN, par exemple). En règle générale, l'unique façon de déterminer si une application peut se connecter à une ressource distante consiste à en faire l'essai. A cet effet, les structures de surveillance des services du package air.net proposent aux applications AIR un moyen orienté événement de répondre aux changements de la connectivité réseau vers un hôte déterminé. Remarque : la structure de surveillance des services détecte si un serveur répond de manière acceptable à une requête. Cette méthode ne garantit pas une connectivité totale. Les services Web évolutifs proposent souvent des dispositifs de mise en cache et d'équilibrage de charge destinés à réorienter le trafic vers un groupe de serveurs Web. Dans ce cas de figure, les prestataires de services n'assurent qu'un diagnostic partiel de la connectivité réseau. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 309 Surveillance de la connectivité réseau Principes de base de la surveillance des services La structure de surveillance des services, distincte de la structure AIR, réside dans le fichier servicemonitor.swc. Pour pouvoir utiliser la structure, le fichier servicemonitor.swc doit être inclus dans votre processus de compilation. Important : pour utiliser ces classes dans Adobe® Flash® CS3 Professional, faites glisser le composant ServiceMonitorShim du panneau Composants vers la Bibliothèque, puis ajoutez l'instruction import suivante dans votre code ActionScript 3.0 : import air.net.*; Pour utiliser ces classes dans Adobe® Flash® CS4 Professional : 1 Choisissez Fichier > Paramètres de publication. 2 Cliquez sur le bouton Paramètres pour ActionScript 3.0. Sélectionnez Chemin de la bibliothèque. 3 Cliquez sur le bouton Localiser le fichier SWC, puis localisez Adobe Flash CS4/AIK1.1/frameworks/libs/air/servicemoniter.swc. 4 Cliquez sur le bouton OK. 5 Ajoutez l'instruction d'importation suivante dans votre code ActionScript 3.0 : import air.net.*; La classe ServiceMonitor met en œuvre la structure de surveillance des services réseau et propose des fonctionnalités de base aux utilitaires de surveillance des services. Par défaut, une occurrence de la classe ServiceMonitor distribue des événements relatifs à la connectivité réseau. L'objet ServiceMonitor distribue ces événements lors de la création de l'occurrence et lorsqu'un changement réseau est détecté par Adobe AIR. Par ailleurs, vous pouvez définir la propriété pollInterval d'une occurrence de ServiceMonitor de sorte à vérifier la connectivité à fréquence déterminée exprimée en millisecondes, sans tenir compte des événements de connectivité réseau généraux. Un objet ServiceMonitor ne vérifie pas la connectivité réseau tant que la méthode start() n'a pas été appelée. La classe URLMonitor, une sous-classe de la classe ServiceMonitor, détecte les changements de connectivité HTTP associés à une requête URLRequest déterminée. La classe SocketMonitor, également une sous-classe de la classe ServiceMonitor, détecte les changements de connectivité vers un hôte déterminé sur un port donné. Détection de la connectivité HTTP La classe URLMonitor détermine s'il est possible d'envoyer des requêtes HTTP à une adresse déterminée sur le port 80 (qui est généralement utilisé par les communications HTTP). Le code suivant utilise une occurrence de la classe URLMonitor pour détecter les changements de connectivité vers le site Web d'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); } DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 310 Surveillance de la connectivité réseau Détection de la connectivité des sockets Les applications AIR peuvent également utiliser les connexions de socket pour assurer la connectivité de type « push ». Pour raisons de sécurité, les pare-feu et routeurs réseau interdisent généralement les communications réseau sur les ports non autorisés. Les développeurs doivent de ce fait tenir compte du fait que les utilisateurs risquent de ne pas pouvoir établir des connexions de socket. Similaire à l'exemple URLMonitor, le code suivant utilise une occurrence de la classe SocketMonitor pour détecter les changements de connectivité associés à une connexion de socket sur le port 6667, fréquemment utilisé par 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); } 311 Chapitre 30 : Requêtes d'URL et mise en réseau La nouvelle fonctionnalité d'AIR permettant de spécifier les requêtes d'URL n'est pas disponible pour le contenu SWF s'exécutant dans un navigateur. Cette fonctionnalité n'est disponible que pour le contenu du sandbox de sécurité de l'application. Cette section décrit les fonctions URLRequest du moteur d'exécution et aborde les changements de l'API de mise en réseau dans du contenu AIR. Pour plus d'informations sur l'utilisation des capacités de mise en réseau et de communication d'Adobe® ActionScript® 3.0, consultez le document Programmation avec Adobe ActionScript 3.0. Utilisation de la classe URLRequest La classe URLRequest ne vous permet pas seulement de définir la chaîne URL. AIR ajoute de nouvelles propriétés à la classe URLRequest, uniquement disponibles pour le contenu AIR s'exécutant dans le sandbox de sécurité de l'application. Le contenu du moteur d'exécution peut définir des URL à l'aide des nouveaux modèles d'URL (outre les modèles standard tels que file et http). Propriétés de la classe URLRequest La classe URLRequest comprend les propriétés suivantes, disponibles uniquement dans le sandbox de sécurité de l'application AIR : Propriété Description followRedirects Indique si des redirections sont utilisées (true, valeur par défaut) ou non (false). Cette propriété est prise en charge uniquement dans le moteur d'exécution. manageCookies Indique si la pile du protocole HTTP doit gérer les cookies (true, valeur par défaut) ou non (false) pour cette requête. Cette propriété est prise en charge uniquement dans le moteur d'exécution. authenticate Indique si les requêtes d'authentification doivent être traitées (true) pour cette requête. Cette propriété est prise en charge uniquement dans le moteur d'exécution. Par défaut, les requêtes sont authentifiées ; il est par conséquent possible qu'une boîte de dialogue d'authentification s'affiche si le serveur requiert l'affichage des informations d'identification. Vous pouvez en outre définir le nom d'utilisateur et le mot de passe. Consultez la section « Définition des paramètres par défaut de la classe URLRequest » à la page 312. cacheResponse Indique si les données de réponse satisfaisantes doivent être mises en mémoire cache pour cette requête. Cette propriété est prise en charge uniquement dans le moteur d'exécution. Par défaut, la réponse est mise en mémoire cache (true). useCache Indique si le cache local doit être consulté avant que la classe URLRequest récupère les données. Cette propriété est prise en charge uniquement dans le moteur d'exécution. Par défaut, le cache local doit être utilisé, s'il est disponible (true). userAgent Indique la chaîne agent utilisateur à utiliser dans la requête HTTP. Les propriétés suivantes d'un objet URLRequest peuvent être définies selon le contenu dans n'importe quel sandbox (et pas uniquement dans le sandbox de sécurité de l'application AIR) : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 312 Requêtes d'URL et mise en réseau Propriété Description contentType Type de contenu MIME des données envoyées avec la requête d'URL. data Objet contenant des données à transmettre avec la demande d'URL. digest « Digest » sécurisé sur un fichier mis en cache pour suivre le cache d'Adobe® Flash® Player. method Contrôle la méthode de requête HTTP, comme les opérations GET et POST. (Le contenu s'exécutant dans le domaine de sécurité de l'application AIR peut spécifier des chaînes autres que "GET" ou "POST" comme propriété method. Tous les verbes HTTP sont autorisés et "GET" est la méthode par défaut. Consultez le chapitre « Sécurité AIR » à la page 24.) requestHeaders Tableau d'en-tête de requête HTTP à ajouter à la fin de la requête HTTP. url Spécifie l'URL qui fait l'objet de la requête. Remarque : la classe HTMLLoader possède des propriétés associées pour les paramètres appartenant au contenu chargé par un objet HTMLLoader. Pour plus de détails, consultez la section « A propos de la classe HTMLLoader » à la page 237. Définition des paramètres par défaut de la classe URLRequest La classe URLRequestDefaults vous permet de définir les paramètres par défaut des objets URLRequest. Par exemple, le code suivant définit les valeurs par défaut des propriétés manageCookies et useCache : URLRequestDefaults.manageCookies = false; URLRequestDefaults.useCache = false; air.URLRequestDefaults.manageCookies = false; air.URLRequestDefaults.useCache = false; La classe URLRequestDefaults inclut une méthode setLoginCredentialsForHost() qui vous permet de spécifier un nom d'utilisateur et un mot de passe par défaut pour un hôte spécifique. L'hôte, défini dans le paramètre hostname de la méthode, peut être un domaine, tel que "www.example.com", ou un domaine et un numéro de port, par exemple "www.example.com:80". Notez que "example.com", "www.example.com" et "sales.example.com" sont considérés comme hôtes uniques. Ces informations d'identification ne sont utilisées que lorsque le serveur les demande. Si l'utilisateur s'est déjà authentifié (notamment via la boîte de dialogue d'authentification), vous ne pouvez pas modifier l'utilisateur authentifié en appelant la méthode setLoginCredentialsForHost(). Par exemple, le code suivant définit le nom d'utilisateur et le mot de passe par défaut devant être utilisés pour accéder à www.example.com : URLRequestDefaults.setLoginCredentialsForHost("www.example.com", "Ada", "love1816$X"); air.URLRequestDefaults.setLoginCredentialsForHost("www.example.com", "Ada", "love1816$X"); Chaque propriété des paramètres URLRequestDefaults s'applique uniquement au domaine d'application du contenu définissant la propriété. En revanche, la méthode setLoginCredentialsForHost() s'applique au contenu de tous les domaines d'application d'une application AIR. De cette manière, une application peut se connecter à un hôte et connecter tout le contenu de l'application avec les informations d'identification spécifiées. Pour plus d'informations, consultez la classe URLRequestDefaults dans le Guide de référence du langage et des composants ActionScript 3.0 (http://www.adobe.com/go/learn_air_aslr_fr). Utilisation des modèles d'URL AIR dans les URL Les modèles d'URL standard, notamment ceux cités ci-dessous, sont disponibles lors de la définition d'URL dans le sandbox de sécurité d'une application AIR : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 313 Requêtes d'URL et mise en réseau http: et https: Utilisez-les de la même manière que dans un navigateur Web. file: Utilisez ce modèle pour spécifier un chemin relatif à la racine du système de fichiers. Exemple : file:///c:/AIR Test/test.txt Vous pouvez également utiliser les modèles suivants lorsque vous définissez l'URL d'un contenu s'exécutant dans le sandbox de sécurité de l'application : app: Utilisez ce modèle pour spécifier un chemin relatif au répertoire racine de l'application installée (répertoire contenant le fichier descripteur d'application installée). Par exemple, le chemin suivant pointe vers un sous-répertoire de ressources du répertoire de l'application installée : app:/resources Lorsque vous exécutez l'application de débogage du lanceur AIR (ADL), le répertoire de ressources de l'application est défini sur le répertoire contenant le fichier descripteur d'application. app-storage: Utilisez ce chemin pour spécifier un chemin relatif au répertoire de stockage de l'application. Pour chaque application installée, AIR définit un répertoire de stockage unique pour chaque utilisateur, qui est l'emplacement idéal pour stocker les données spécifiques à l'application correspondante. Par exemple, le chemin suivant pointe vers un fichier prefs.xml dans un sous-répertoire de paramètres du répertoire de stockage de l'application : app-storage:/settings/prefs.xml L'emplacement du répertoire de stockage de l'application dépend du nom d'utilisateur, de l'ID d'application et de l'ID d'éditeur : • Sous Mac OS, dans : /Utilisateurs/nom d'utilisateur/Bibliothèque/Preferences/ID d'application.ID d'éditeur/Local Store/ Exemple : /Users/babbage/Library/Preferences/com.example.TestApp.02D88EEED35F84C264A183921344EEA353 A629FD.1/Local Store • Sous Windows, dans le répertoire Documents and Settings, dans : nom d'utilisateur/Application Data/ID d'application.ID d'éditeur/Local Store/ Exemple : C:\Documents and Settings\babbage\Application Data\com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Local Store • Sous Linux, dans : /home/nom d'utilisateur/.appdata/applicationID.ID d'éditeur/Local Store/ Exemple : /home/babbage/.appdata/com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Loc al Store DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 314 Requêtes d'URL et mise en réseau L'URL (et la propriété url) d'un objet File créé avec File.applicationStorageDirectory utilise le modèle d'URL app-storage, comme suit : 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 : Vous pouvez utiliser le modèle mailto dans les objets URLRequest transmis à la fonction navigateToURL(). Voir « Ouverture d'une URL dans le navigateur Web par défaut du système » à la page 314. Utilisation des modèles d'URL dans AIR Vous pouvez utiliser un objet URLRequest qui utilise l'un de ces modèles d'URL pour définir la requête d'URL d'un certain nombre d'objets différents, tels qu'un objet FileStream ou Sound. Vous pouvez par ailleurs utiliser ces modèles dans le contenu HTML s'exécutant dans AIR ; par exemple, vous pouvez les utiliser dans l'attribut src d'une balise img. Néanmoins, vous pouvez utiliser ces modèles d'URL spécifiques à AIR (app: et app-storage:) uniquement dans le contenu du sandbox de sécurité de l'application. Pour plus d'informations, consultez le chapitre « Sécurité AIR » à la page 24. Modèles d'URL non autorisés Certaines API vous permettent de lancer le contenu dans un navigateur Web. Pour des raisons de sécurité, certains modèles d'URL sont interdits lors de l'utilisation de ces API dans AIR. La liste des modèles non autorisés dépend du sandbox de sécurité du code utilisant l'API. Pour plus d'informations, consultez la section « Ouverture d'une URL dans le navigateur Web par défaut du système » à la page 314. Modifications de la classe URLStream La classe URLStream offre un accès de bas niveau pour le téléchargement de données à partir d'URL. Dans le moteur d'exécution, la classe URLStream comprend un nouvel événement : httpResponseStatus. Contrairement à l'événement httpStatus, l'événement httpResponseStatus est renvoyé avant toute donnée de réponse. L'événement httpResponseStatus (défini dans la classe HTTPStatusEvent) inclut une propriété responseURL, qui correspond à l'URL que la réponse a renvoyée, ainsi qu'une propriété responseHeaders, qui est un tableau d'objets URLRequestHeader représentant les en-têtes de réponse que la réponse a renvoyés. Ouverture d'une URL dans le navigateur Web par défaut du système Vous pouvez utiliser la fonction navigateToURL() pour ouvrir une URL dans le navigateur Web par défaut du système. Pour l'objet URLRequest que vous transmettez comme paramètre request de cette fonction, seule la propriété url est utilisée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 315 Requêtes d'URL et mise en réseau var url = "http://www.adobe.com"; var urlReq = new air.URLRequest(url); air.navigateToURL(urlReq); Remarque : lorsque vous utilisez la fonction navigateToURL(), le moteur d'exécution traite un objet URLRequest qui utilise la méthode POST (celui dont la propriété method est définie sur URLRequestMethod.POST) comme la méthode GET. Lors de l'utilisation de la fonction navigateToURL(), les modèles d'URL sont permis en fonction du sandbox de sécurité du code appelant la fonction navigateToURL(). Certaines API vous permettent de lancer le contenu dans un navigateur Web. Pour des raisons de sécurité, certains modèles d'URL sont interdits lors de l'utilisation de ces API dans AIR. La liste des modèles non autorisés dépend du sandbox de sécurité du code utilisant l'API. (Pour plus d'informations sur les sandbox de sécurité, consultez le chapitre « Sécurité AIR » à la page 24.) Sandbox de l'application Les modèles suivants sont autorisés. Utilisez-les de la même manière que dans un navigateur Web. • http: • https: • file: • mailto: AIR dirige ces requêtes à l'application de messagerie système enregistrée • app: • app-storage: Tous les autres modèles d'URL ne sont pas autorisés. Sandbox distant Les modèles suivants sont autorisés. Utilisez-les de la même manière que dans un navigateur Web. • http: • https: • mailto: AIR dirige ces requêtes à l'application de messagerie système enregistrée Tous les autres modèles d'URL ne sont pas autorisés. Sandbox local avec fichiers Les modèles suivants sont autorisés. Utilisez-les de la même manière que dans un navigateur Web. • file: • mailto: AIR dirige ces requêtes à l'application de messagerie système enregistrée Tous les autres modèles d'URL ne sont pas autorisés. Sandbox local avec accès au réseau Les modèles suivants sont autorisés. Utilisez-les de la même manière que dans un navigateur Web. • http: • https: • mailto: AIR dirige ces requêtes à l'application de messagerie système enregistrée Tous les autres modèles d'URL ne sont pas autorisés. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 316 Requêtes d'URL et mise en réseau Sandbox approuvé localement Les modèles suivants sont autorisés. Utilisez-les de la même manière que dans un navigateur Web. • file: • http: • https: • mailto: AIR dirige ces requêtes à l'application de messagerie système enregistrée Tous les autres modèles d'URL ne sont pas autorisés. 317 Chapitre 31 : Communication interapplications La classe LocalConnection active les communications entre les applications Adobe® AIR™AIR d'une part et, d'autre part, entre applications AIR et contenu SWF qui s'exécutent dans le navigateur. La méthode connect() de la classe LocalConnection utilise un paramètre connectionName pour identifier les applications. Dans un contenu qui s'exécute dans le sandbox de sécurité de l'application AIR (un contenu installé avec l'application AIR), AIR utilise la chaîne app# suivie de l'ID d'application, lui-même suivi d'un caractère point (.), suivi encore de l'ID d'éditeur pour l'application AIR (défini dans le fichier descripteur d'application) au lieu du domaine utilisé par le contenu SWF qui tourne dans le navigateur. Par exemple, un connectionName pour une application avec l'ID d'application com.example.air.MyApp, le connectionName et l'ID d'éditeur B146A943FBD637B68C334022D304CEA226D129B4 correspond à "app#com.example.air.MyApp.B146A943FBD637B68C334022D304CEA226D129B4:connectionName". Pour plus d'informations, consultez les sections Spécifications des informations de base de l'application et « Lecture des identifiants d'application et d'éditeur » à la page 303. Lorsque vous autorisez une autre application AIR à communiquer avec votre application par la connexion locale, vous devez appeler le allowDomain() de l'objet LocalConnection en transmettant le nom du domaine de la connexion locale. Pour une application AIR, ce nom de domaine est formé à partir des ID d'application et d'éditeur, de la même façon que la chaîne de connexion. Par exemple, si l'application AIR d'envoi a pour ID d'application com.example.air.FriendlyApp et pour ID d'éditeur 214649436BD677B62C33D02233043EA236D13934, la chaîne de domaine que vous utiliseriez pour autoriser cette application à se connecter est : app#com.example.air.FriendlyApp.214649436BD677B62C33D02233043EA236D13934. Remarque : lorsque vous exécutez votre application avec ADL, ou encore avec un outil de développement tel que Flash CS3, Flex Builder ou Dreamweaver, l'ID d'éditeur est "null" et doit être omis de la chaîne du domaine. Lorsque vous installez et exécutez votre application, l'ID d'éditeur doit être incluse dans la chaîne du domaine. Il est possible d'affecter un ID d'éditeur temporaire à l'aide d'arguments de lignes de commande ADL : Utilisez un ID d'éditeur temporaire pour vous assurer que la chaîne de connexion et le nom du domaine sont correctement formatés. 318 Chapitre 32 : Distribution, installation et exécution d'applications AIR La distribution d'une application AIR s'effectue par l'intermédiaire d'un fichier d'installation AIR unique contenant le code de l'application et tous les actifs. Vous pouvez distribuer ce fichier selon les moyens habituels : téléchargement, courrier électronique ou support physique comme le CD-ROM. Les utilisateurs peuvent installer l'application en double-cliquant sur le fichier AIR. Vous pouvez utiliser la fonctionnalité d'installation transparente pour permettre aux utilisateurs d'installer votre application AIR (et au besoin Adobe® AIR™) en cliquant sur un lien unique dans une page Web. Avant sa distribution, le fichier d'installation AIR doit être mis en package et signé au moyen d'un certificat de signature de code et d'une clé privée. Le fait de signer numériquement ce fichier offre la garantie qu'aucune modification n'a été apportée à votre application depuis l'apposition de la signature. En outre, si une autorité de certification approuvée a émis le certificat numérique, vos utilisateurs peuvent avoir la confirmation de votre identité en tant qu'éditeur et signataire. Le fichier AIR est signé au moment de la création du package de l'application, à l'aide de l'outil ADT (AIR Developer Tool). Pour plus d'informations sur la mise en package d'une application dans un fichier AIR par le biais de la mise à jour AIR pour Flash, consultez la section « Création d'une application AIR et de ses fichiers d'installation » à la page 16. Pour plus d'informations sur la mise en package d'une application dans un fichier AIR en utilisant le SDK (kit de développement logiciel) Adobe® AIR™, consultez la section « Création d'un package de fichier d'installation AIR à l'aide de l'outil ADT » à la page 365. Installation et exécution d'une application AIR à partir du Bureau Il vous suffit d'envoyer le fichier AIR au destinataire. Vous pouvez par exemple l'envoyer sous forme de pièce jointe dans un courrier électronique, ou sous forme de lien dans une page Web. Une fois que l'utilisateur a téléchargé l'application AIR, il suit les instructions suivantes pour l'installer : 1 Double-cliquez sur le fichier AIR. Le logiciel Adobe AIR doit être déjà installé sur l'ordinateur. 2 Dans la fenêtre d'installation, conservez les paramètres par défaut sélectionnés, puis cliquez sur Continuer. Sous Windows, l'environnement d'exécution AIR effectue les opérations suivantes : • installation de l'application dans le répertoire Program Files ; • création d'un raccourci sur le Bureau pour ouvrir l'application ; • création d'un raccourci dans le menu Démarrer ; • ajout d'une entrée dans Ajout/Suppression de programmes du Panneau de configuration. Sous Mac OS, l'application est automatiquement ajoutée dans le répertoire Applications. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 319 Distribution, installation et exécution d'applications AIR Si l'application existe déjà, le programme d'installation donne à l'utilisateur le choix d'ouvrir la version existante de l'application ou de mettre celle-ci à jour grâce au fichier AIR téléchargé. Le programme d'installation identifie l'application au moyen de l'ID d'application et de l'ID d'éditeur qui sont contenus dans le fichier AIR. 3 Une fois que vous avez terminé l'installation, cliquez sur Terminer. S'il utilise Mac OS, l'utilisateur a besoin des privilèges système appropriés pour installer une version de mise à jour d'une application dans le répertoire de l'application. S'il utilise Windows ou Linux, l'utilisateur doit disposer de privilèges d'administrateur. Une application peut également installer une nouvelle version via ActionScript ou JavaScript. Pour plus d'informations, consultez la section « Mise à jour des applications AIR » à la page 335. Une fois l'application AIR installée, l'utilisateur se contente de double-cliquer sur l'icône de l'application pour l'exécuter, exactement comme n'importe quelle application de poste de travail. • Sous Windows, double-cliquez sur l'icône de l'application (installée sur le Bureau ou dans un dossier) ou sélectionnez l'application à partir du menu Démarrer. • Sous Linux, double-cliquez sur l'icône de l'application (installée sur le Bureau ou dans un dossier) ou sélectionnez l'application dans le menu. • Sous Mac OS, double-cliquez sur l'application dans le dossier où elle a été installée. Le répertoire d'installation par défaut est /Applications. La fonctionnalité d'installation transparente d'AIR permet à un utilisateur d'installer une application AIR en cliquant sur un lien dans une page Web. La fonctionnalité d'appel du navigateur d'AIR permet à un utilisateur d'exécuter une application AIR installée en cliquant sur un lien dans une page Web. Ces fonctionnalités sont décrites dans la section suivante. Installation et exécution d'applications AIR à partir d'une page Web La fonctionnalité d'installation transparente offre la possibilité d'incorporer un fichier SWF dans une page Web, ce qui permet ensuite à l'utilisateur d'installer une application AIR à partir du navigateur. Si le moteur d'exécution n'est pas installé, la fonctionnalité d'installation transparente procède à son installation. Cette fonctionnalité permet aux utilisateurs d'installer l'application AIR sans enregistrer le fichier AIR sur le disque dur de leur ordinateur. Le fichier badge.swf, inclus dans le SDK AIR, est fourni pour vous faciliter l'utilisation de la fonctionnalité d'installation transparente. Pour plus d'informations, consultez la section « Utilisation du fichier badge.swf pour installer une application AIR » à la page 320. Une démonstration de l'utilisation de la fonctionnalité d'installation est disponible dans l'article de démarrage rapide Distribution d'une application AIR via le Web (http://www.adobe.com/go/learn_air_qs_seamless_install_fr). A propos de la personnalisation du fichier badge.swf de l'installation transparente Outre l'utilisation du fichier badge.swf fourni dans le SDK (kit de développement logiciel), vous avez également la possibilité de créer votre propre fichier SWF pour l'utiliser dans une page de navigateur. Le fichier SWF que vous avez personnalisé peut interagir avec le moteur d'exécution de différentes façons : • Il peut installer une application AIR. Consultez la section « Installation d'une application AIR à partir du navigateur » à la page 325. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 320 Distribution, installation et exécution d'applications AIR • Il peut vérifier si une application AIR particulière est installée. Consultez la section « Vérification à partir d'une page Web de la présence d'une application AIR installée » à la page 325. • Il peut vérifier si le moteur d'exécution est installé. Consultez la section « Vérification de la présence du moteur d'exécution » à la page 324. • Il peut lancer une application AIR installée sur le système d'un utilisateur. Consultez la section « Lancement d'une application AIR installée à partir du navigateur » à la page 326. Ces possibilités sont toutes fournies en appelant des API dans un fichier SWF, nommé air.swf, et hébergé sur adobe.com. air.swf. Cette section explique comment utiliser et personnaliser le fichier badge.swf, et comment appeler les API du fichier air.swf à partir de votre propre fichier SWF. En outre, un fichier SWF s'exécutant dans le navigateur peut communiquer avec une application AIR en cours d'exécution grâce à l'utilisation de la classe LocalConnection. Pour plus d'informations, consultez la section « Communication inter-applications » à la page 317. Important : les fonctionnalités décrites dans cette section (et les API dans le fichier air.swf) impliquent l'installation préalable d'Adobe® Flash® Player 9 Mise à jour 3 par l'utilisateur final dans le navigateur Web sous Windows ou Mac OS. Sous Linux, la fonction d'installation transparente requiert Flash Player 10 (version 10,0,12,36 ou ultérieure). Vous pouvez écrire du code pour vérifier la version installée de Flash Player et fournir une autre interface à l'utilisateur si la version requise de Flash Player n'est pas installée. Par exemple, si une ancienne version de Flash Player est installée, vous avez la possibilité de fournir un lien vers la version à télécharger du fichier AIR (plutôt que d'utiliser le fichier badge.swf ou l'API du fichier air.swf pour installer une application). Utilisation du fichier badge.swf pour installer une application AIR Le fichier badge.swf, inclus dans le SDK AIR, est donné pour vous faciliter l'utilisation de la fonctionnalité d'installation transparente. Ce fichier peut installer le moteur d'exécution et une application AIR à partir d'un lien dans une page Web. Le fichier badge.swf et son code source vous sont fournis pour que vous puissiez assurer la distribution sur vos différentes pages Web. Les instructions contenues dans cette section regroupent des informations sur la définition des paramètres du fichier badge.swf fourni par Adobe. Nous mettons également à votre disposition le code source pour le fichier badge.swf, ce qui vous permet de le personnaliser. Intégration du fichier badge.swf dans une page Web 1 Repérez les fichiers suivants qui sont stockés dans le répertoire samples/badge du SDK AIR et ajoutez-les à votre serveur Web. • badge.swf • default_badge.html • AC_RunActiveContent.js 2 Ouvrez la page default_badge.html dans un éditeur de texte. 3 Dans la page default_badge.html, au niveau de la fonction JavaScript AC_FL_RunContent(), ajustez le paramétrage FlashVars pour les paramètres suivants : Paramètre Description appname Nom de l'application, affiché par le fichier SWF lorsque le moteur d'exécution n'est pas installé. appurl (Obligatoire). URL du fichier AIR à télécharger. Vous devez utiliser une URL absolue, et non relative. airversion (Obligatoire). Pour la version 1.0 du moteur d'exécution, définissez ce paramètre sur 1.0. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 321 Distribution, installation et exécution d'applications AIR Paramètre Description imageurl URL de l'image (facultative) à afficher dans le badge. buttoncolor Couleur du bouton Télécharger (spécifiée sous forme de valeur hexadécimale, telle que FFCC00). messagecolor Couleur du message textuel affiché sous le bouton lorsque le moteur d'exécution n'est pas installé (spécifiée sous la forme d'une valeur hexadécimale, telle que FFCC00). 4 La taille minimale du fichier badge.swf est de 217 pixels de large sur 180 de haut. Ajustez les valeurs des paramètres width et height de la fonction AC_FL_RunContent() à votre convenance. 5 Renommez le fichier default_badge.html et ajustez son code (ou englobez-le dans une autre page HTML) selon vos besoins. Vous pouvez également modifier et recompiler le fichier badge.swf. Pour plus d'informations, consultez la section « Modification du fichier badge.swf » à la page 322. Installation de l'application AIR à partir d'un lien d'installation transparente proposé dans une page Web Une fois que vous avez ajouté le lien de l'installation transparente à une page, l'utilisateur peut installer l'application AIR en cliquant sur le lien dans le fichier SWF. 1 Naviguez jusqu'à la page HTML dans un navigateur Web sur lequel Flash Player (version 9 mise à jour 3 ou ultérieure sous Windows et Mac OS, ou version 10 sous Linux) est installé. 2 Dans cette page Web, cliquez sur le lien contenu dans le fichier badge.swf. • Si le moteur d'exécution est installé, passez à l'étape suivante. • Si le moteur d'exécution n'est pas installé, une boîte de dialogue s'affiche pour vous proposer de l'installer. Installez le moteur d'exécution (consultez le chapitre « Installation d'Adobe AIR » à la page 1), puis passez à l'étape suivante. 3 Dans la fenêtre d'installation, conservez les paramètres par défaut sélectionnés, puis cliquez sur Continuer. Sous Windows, l'environnement d'exécution AIR effectue les opérations suivantes : • installation de l'application dans c:\Program Files\ ; • création d'un raccourci sur le Bureau pour ouvrir l'application ; • création d'un raccourci dans le menu Démarrer ; • ajout d'une entrée dans Ajout/Suppression de programmes du Panneau de configuration. Sous Mac OS, le programme d'installation ajoute l'application au répertoire Applications (par exemple, dans le répertoire \Applications pour Mac OS). Sur un ordinateur Linux, AIR effectue automatiquement les opérations suivantes : • installation de l'application dans /opt ; • création d'un raccourci sur le Bureau pour ouvrir l'application ; • création d'un raccourci dans le menu Démarrer ; • ajout d'une entrée dans le gestionnaire de package du système. 4 Sélectionnez les options qui vous intéressent, puis cliquez sur le bouton Installer. 5 Une fois que vous avez terminé l'installation, cliquez sur Terminer. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 322 Distribution, installation et exécution d'applications AIR Modification du fichier badge.swf Le kit SDK AIR fournit les fichiers source pour le fichier badge.swf. Ces fichiers sont situés dans le dossier samples/badge du kit SDK : Fichiers source Description badge.fla Fichier Flash source, utilisé pour compiler le fichier badge.swf. Le fichier badge.fla est compilé dans un fichier SWF 9 (pouvant être chargé dans Flash Player). AIRBadge.as Classe ActionScript 3.0 définissant la classe de base utilisée dans le fichier basdge.fla. Vous pouvez utiliser Flash CS3 ou CS4 pour modifier la conception de l’interface visuelle du fichier badge.fla. La fonction constructeur AIRBadge(), définie dans la classe AIRBadge, charge le fichier air.swf hébergé à l'adresse suivante http://airdownload.adobe.com/air/browserapi/air.swf. Le fichier air.swf contient le code pour l'utilisation de la fonctionnalité d'installation transparente. La méthode onInit() (dans la classe AIRBadge) est appelée lorsque le chargement du fichier air.swf s'est correctement déroulé : 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; } } Le code définit la variable _air globale sur la classe principale du fichier air.swf chargé. Cette classe comprend les méthodes publiques suivantes auxquelles le fichier badge.swf accède pour appeler la fonctionnalité d'installation transparente : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 323 Distribution, installation et exécution d'applications AIR Méthode Description getStatus() Détermine si le moteur d'exécution est installé (ou s'il peut être installé) sur l'ordinateur. Pour plus d'informations, consultez la section « Vérification de la présence du moteur d'exécution » à la page 324. installApplication() Installe l'application spécifiée sur l'ordinateur de l'utilisateur. Pour plus d'informations, consultez la section « Installation d'une application AIR à partir du navigateur » à la page 325. • url – Chaîne définissant l'URL. Vous devez utiliser un chemin d'URL absolu, et non relatif. • runtimeVersion – Chaîne précisant la version du moteur d'exécution (par exemple « 1.0.M6 ») qui est requise par l'application à installer. • arguments – Arguments à transmettre à l'application si elle est lancée au moment de l'installation. L'application est lancée à l'installation si l'élément allowBrowserInvocation est défini sur true dans le fichier descripteur de l'application. (Pour plus d'informations sur le fichier descripteur de l'application, consultez la section « Définition des propriétés d'une application AIR » à la page 46.) Si l'application est lancée lors d'une installation transparente depuis le navigateur (l'utilisateur ayant choisi le lancement à l'installation), l'objet NativeApplication de l'application ne distribue d'objet BrowserInvokeEvent que si des arguments sont transmis. Tenez compte des conséquences au niveau de la sécurité qu'une transmission de données à l'application peut entraîner. Pour plus d'informations, consultez la section « Lancement d'une application AIR installée à partir du navigateur » à la page 326. Les paramètres pour url et runtimeVersion sont transmis dans le fichier SWF via les paramètres FlashVars dans la page HTML servant de conteneur. Si l'application démarre automatiquement à l'installation, vous pouvez utiliser la communication LocalConnection pour que l'application installée contacte le fichier badge.swf au moment de l'appel. Pour plus d'informations, consultez la section « Communication inter-applications » à la page 317. Vous pouvez également appeler la méthode getApplicationVersion() du fichier air.swf pour vérifier qu'une application est déjà installée. Vous avez le choix d'appeler cette méthode avant que la procédure d'installation de l'application débute, ou après le démarrage de l'installation. Pour plus d'informations, consultez la section « Vérification à partir d'une page Web de la présence d'une application AIR installée » à la page 325. Chargement du fichier air.swf Vous pouvez créer votre propre fichier SWF, il sert à utiliser les API dans le fichier air.swf pour interagir avec le moteur d'exécution et les applications AIR depuis une page Web affichée dans un navigateur. Le fichier air.swf est hébergé à l'adresse suivante http://airdownload.adobe.com/air/browserapi/air.swf. Pour référencer les API du fichier air.swf à partir de votre fichier SWF, chargez le fichier air.swf dans le même domaine d'application que celui de votre fichier SWF. Le code suivant illustre un exemple de chargement du fichier air.swf dans le domaine d'application du fichier SWF chargeant. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 324 Distribution, installation et exécution d'applications AIR 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; } Une fois le fichier air.swf chargé (lorsque l'objet contentLoaderInfo de l'objet chargeur Loader distribue l'événement init), vous pouvez appeler n'importe quelle API du fichier air.swf. Ces API sont décrites dans les sections suivantes : • « Vérification de la présence du moteur d'exécution » à la page 324 • « Vérification à partir d'une page Web de la présence d'une application AIR installée » à la page 325 • « Installation d'une application AIR à partir du navigateur » à la page 325 • « Lancement d'une application AIR installée à partir du navigateur » à la page 326 Remarque : le fichier badge.swf, fourni avec le SDK AIR, charge automatiquement le fichier air.swf. Consultez la section « Utilisation du fichier badge.swf pour installer une application AIR » à la page 320. Les instructions détaillées dans cette section se rapportent à la création de votre propre fichier SWF qui charge le fichier air.swf. Vérification de la présence du moteur d'exécution Un fichier SWF peut vérifier si le moteur d'exécution est installé en appelant la méthode getStatus() dans le fichier air.swf chargé à partir de http://airdownload.adobe.com/air/browserapi/air.swf. Pour plus d'informations, consultez la section « Chargement du fichier air.swf » à la page 323. Une fois le fichier air.swf chargé, le fichier SWF peut appeler la méthode getStatus() du fichier air.swf, comme suit : var status:String = airSWF.getStatus(); La méthode getStatus() renvoie une des valeurs de chaîne suivantes en fonction de l'état du moteur d'exécution sur l'ordinateur : Valeur de chaîne Description "available" Il est possible d'installer le moteur d'exécution sur cet ordinateur, mais il n'y est pas installé actuellement. "unavailable" Il est impossible d'installer le moteur d'exécution sur cet ordinateur. "installed" Le moteur d'exécution est installé sur cet ordinateur. La méthode getStatus() renvoie une erreur si la version requise de Flash Player (version 9 mise à jour 3 ou ultérieure sous Windows et Mac OS, ou version 10 sous Linux) n'est pas installée dans le navigateur. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 325 Distribution, installation et exécution d'applications AIR Vérification à partir d'une page Web de la présence d'une application AIR installée Un fichier SWF peut vérifier si une application AIR (avec un ID d'application et un ID d'éditeur correspondants) est installée en appelant la méthode getApplicationVersion() dans le fichier air.swf chargé à partir de http://airdownload.adobe.com/air/browserapi/air.swf. Pour plus d'informations, consultez la section « Chargement du fichier air.swf » à la page 323. Une fois le fichier air.swf chargé, le fichier SWF peut appeler la méthode getApplicationVersion() du fichier air.swf comme suit : 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. } } La méthode getApplicationVersiom() possède les paramètres suivants : Paramètres Description appID ID d'application pour l'application. Pour plus d'informations, consultez la section « Définition de l'identité de l'application » à la page 49. pubID ID d'éditeur de l'application. Pour plus d'informations, consultez la section « A propos des identifiants d'éditeur AIR » à la page 329. callback Fonction de rappel pour servir comme fonction de gestionnaire. La méthode getApplicationVersion() fonctionne de façon asynchrone et c'est lorsque la présence (ou l'absence) de la version est détectée que cette méthode de rappel est invoquée. La définition de la méthode de rappel doit inclure un paramètre, une chaîne, qui est défini sur la chaîne de version de l'application installée. Si l'application n'est pas installée, une valeur « null » est transmise à la fonction, comme illustré dans l'exemple de code précédent. La méthode getApplicationVersion() renvoie une erreur si la version requise de Flash Player (version 9 mise à jour 3 ou ultérieure sous Windows et Mac OS, ou version 10 sous Linux) n'est pas installée dans le navigateur. Installation d'une application AIR à partir du navigateur Un fichier SWF peut installer une application AIR en appelant la méthode installApplication() dans le fichier air.swf chargé à partir de http://airdownload.adobe.com/air/browserapi/air.swf. Pour plus d'informations, consultez la section « Chargement du fichier air.swf » à la page 323. Une fois le fichier air.swf chargé, le fichier SWF peut appeler la méthode installApplication() du fichier air.swf comme suit : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 326 Distribution, installation et exécution d'applications AIR var url:String = "http://www.example.com/myApplication.air"; var runtimeVersion:String = "1.0"; var arguments:Array = ["launchFromBrowser"]; // Optional airSWF.installApplication(url, runtimeVersion, arguments); La méthode installApplication() installe l'application spécifiée sur l'ordinateur de l'utilisateur. Cette méthode est dotée des paramètres suivants : Paramètre Description url Chaîne définissant l'URL du fichier AIR à installer. Vous devez utiliser un chemin d'URL absolu, et non relatif. runtimeVersion Chaîne précisant la version du moteur d'exécution (par exemple « 1.0 ») qui est requise par l'application à installer. arguments Tableau d'arguments à transmettre à l'application si elle est lancée au moment de l'installation. Seuls les caractères alphanumériques sont reconnus dans les arguments. Pour transmettre d'autres valeurs, pensez à utiliser un schéma de codage. L'application est lancée à l'installation si l'élément allowBrowserInvocation est défini sur true dans le fichier descripteur de l'application. (Pour plus d'informations sur le fichier descripteur de l'application, consultez la section « Définition des propriétés d'une application AIR » à la page 46.) Si l'application est lancée lors d'une installation transparente depuis le navigateur (l'utilisateur ayant choisi le lancement à l'installation), l'objet NativeApplication de l'application ne distribue d'objet BrowserInvokeEvent que si des arguments ont été transmis. Pour plus d'informations, consultez la section « Lancement d'une application AIR installée à partir du navigateur » à la page 326. La méthode installApplication() ne peut fonctionner que lorsqu'elle est appelée dans le gestionnaire d'événement pour un événement utilisateur, tel qu'un clic de souris. La méthode installApplication() renvoie une erreur si la version requise de Flash Player (version 9 mise à jour 3 ou ultérieure sous Windows et Mac OS, ou version 10 sous Linux) n'est pas installée dans le navigateur. Sous Mac OS, l'utilisateur doit détenir les droits système appropriés lui permettant d'installer une version de mise à jour d'une application dans le répertoire de cette application (et de privilèges d'administration si l'application met à jour le moteur d'exécution). S'il utilise Windows, l'utilisateur doit détenir des privilèges d'administration. Vous pouvez également appeler la méthode getApplicationVersion() du fichier air.swf pour vérifier si une application est déjà installée. Vous avez le choix d'appeler cette méthode avant que la procédure d'installation de l'application débute, ou après le démarrage de l'installation. Pour plus d'informations, consultez la section « Vérification à partir d'une page Web de la présence d'une application AIR installée » à la page 325. Dès qu'elle est exécutée, l'application peut communiquer avec le contenu SWF dans le navigateur en utilisant la classe LocalConnection. Pour plus d'informations, consultez la section « Communication inter-applications » à la page 317. Lancement d'une application AIR installée à partir du navigateur Pour utiliser la fonctionnalité d'appel du navigateur (lui permettant d'être lancé à partir du navigateur), le fichier descripteur d'application de l'application cible doit comporter le paramètre suivant : <allowBrowserInvocation>true</allowBrowserInvocation> Pour plus d'informations sur le fichier descripteur de l'application, consultez la section « Définition des propriétés d'une application AIR » à la page 46. Un fichier SWF présent dans le navigateur peut lancer une application AIR en appelant la méthode launchApplication() dans le fichier air.swf chargé à partir de http://airdownload.adobe.com/air/browserapi/air.swf. Pour plus d'informations, consultez la section « Chargement du fichier air.swf » à la page 323. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 327 Distribution, installation et exécution d'applications AIR Une fois le fichier air.swf chargé, le fichier SWF peut appeler la méthode launchApplication() du fichier air.swf comme suit : var appID:String = "com.example.air.myTestApplication"; var pubID:String = "02D88EEED35F84C264A183921344EEA353A629FD.1"; var arguments:Array = ["launchFromBrowser"]; // Optional airSWF.launchApplication(appID, pubID, arguments); La méthode launchApplication() est définie au niveau supérieur du fichier air.swf (qui est chargé dans le domaine d'application du fichier SWF de l'interface utilisateur). Le fait d'appeler cette méthode déclenche le lancement de l'application spécifiée par AIR (si cette application est installée et si l'appel du navigateur est autorisé, par le biais du paramètre allowBrowserInvocation dans le fichier descripteur de l'application). Cette méthode est dotée des paramètres suivants : Paramètre Description appID ID d'application pour l'application à lancer. Pour plus d'informations, consultez la section « Définition de l'identité de l'application » à la page 49. pubID ID d'éditeur de l'application à lancer. Pour plus d'informations, consultez la section « A propos des identifiants d'éditeur AIR » à la page 329. arguments Tableau d'arguments à transmettre à l'application. L'objet NativeApplication de l'application distribue un événement BrowserInvokeEvent dont une propriété arguments est définie sur ce tableau. Seuls les caractères alphanumériques sont reconnus dans les arguments. Pour transmettre d'autres valeurs, pensez à utiliser un schéma de codage. La méthode launchApplication() ne peut fonctionner que lorsqu'elle est appelée dans le gestionnaire d'événement pour un événement utilisateur, tel qu'un clic de souris. La méthode launchApplication() renvoie une erreur si la version requise de Flash Player (version 9 mise à jour 3 ou ultérieure sous Windows et Mac OS, ou version 10 sous Linux) n'est pas installée dans le navigateur. Si l'élément allowBrowserInvocation est défini sur false dans le fichier descripteur de l'application, l'appel de la méthode launchApplication() n'a aucune incidence. Avant de présenter l'interface utilisateur pour lancer l'application, il est peut-être préférable d'appeler la méthode getApplicationVersion() dans le fichier air.swf. Pour plus d'informations, consultez la section « Vérification à partir d'une page Web de la présence d'une application AIR installée » à la page 325. Lorsque l'application est invoquée par le biais de la fonctionnalité d'appel du navigateur, l'objet NativeApplication de l'application distribue un objet BrowserInvokeEvent. Pour plus d'informations, consultez la section « Appel du navigateur » à la page 299. Si vous utilisez la fonctionnalité d'appel du navigateur, assurez-vous d'avoir envisagé les conséquences au niveau de la sécurité qui sont décrites à la section « Appel du navigateur » à la page 299. Dès qu'elle est exécutée, l'application peut communiquer avec le contenu SWF dans le navigateur en utilisant la classe LocalConnection. Pour plus d'informations, consultez la section « Communication inter-applications » à la page 317. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 328 Distribution, installation et exécution d'applications AIR Déploiement dans l'entreprise Les administrateurs peuvent installer le moteur d'exécution d'Adobe AIR et les applications AIR en toute transparence à l'aide d'outils de déploiement de postes de travail standard. Ces administrateurs peuvent exécuter les tâches suivantes : • Installation en mode silencieux du moteur d'exécution d'Adobe AIR à l'aide d'outils tels que Microsoft SMS, Tivoli d'IBM ou de tout autre outil de déploiement permettant des installations automatiques au moyen d'un programme d'amorçage • Installation en mode silencieux de l'application AIR à l'aide des mêmes outils utilisés pour déployer le moteur d'exécution Pour plus d'informations, consultez le Guide de l'administrateur Adobe AIR (http://www.adobe.com/go/learn_air_admin_guide_fr). Signature numérique d'un fichier AIR Le fait de signer numériquement vos fichiers d'installation AIR à l'aide d'un certificat délivré par une autorité de certification reconnue rassure pleinement vos utilisateurs sur l'état de l'application qu'ils installent : cette signature garantit que l'application n'a pas été modifiée accidentellement, ou intentionnellement dans le but de nuire, et vous identifie en tant signataire (éditeur). L'environnement AIR affiche le nom de l'éditeur pendant l'installation lorsque l'application AIR est signée à l'aide d'un certificat approuvé ou lié par une chaîne de certificats à un certificat approuvé sur l'ordinateur de l'installation. Sinon, le nom de l'éditeur est indiqué comme étant « Inconnu ». Important : des personnes mal intentionnées peuvent falsifier un fichier AIR en usurpant votre identité si elles obtiennent le fichier magasin de signatures ou découvrent votre clé privé. Informations concernant les certificats de signature de code Les obligations légales, restrictions et garanties de sécurité impliquant l'utilisation de certificats de signature de code sont brièvement exposées dans les déclarations des pratiques de certification – ou déclarations CPS (Certificate Practice Statements) – et les contrats d'abonnés publiés par l'autorité de certification émettrice. Pour plus d'informations sur les contrats des autorités de certification publiant actuellement des certificats de signature de code AIR, consultez les documents suivants : 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) Déclaration CPS de Thawte (http://www.thawte.com/cps/index.html) en anglais Contrat de signature de code pour développeur de Thawte (http://www.thawte.com/ssl-digital-certificates/freeguides-whitepapers/pdf/develcertsign.pdf) en anglais Enoncé des pratiques de certification de VeriSign (EPC)4 (http://www.verisign.com/repository/CPS/) Contrat d'abonnement de VeriSign (https://www.verisign.fr/repository/index.html) DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 329 Distribution, installation et exécution d'applications AIR A propos de la signature de code AIR Lorsqu'un fichier AIR est signé, une signature numérique est ajoutée dans le fichier d'installation. La signature comprend un résumé du package, utilisé pour vérifier que le fichier AIR n'a pas été modifié depuis qu'il a été signé, et englobe des informations sur le certificat de signature qui permettent de vérifier l'identité de l'éditeur. L'environnement AIR utilise l'infrastructure de clé publique (PKI) qui est prise en charge par le biais du magasin de certificats du système d'exploitation afin de déterminer la fiabilité d'un certificat. Pour que les informations de l'éditeur soient contrôlées, l'ordinateur sur lequel une application AIR est installée doit faire confiance directement au certificat utilisé pour signer l'application AIR, ou faire confiance à une chaîne de certificats liant ce certificat à une autorité de certification approuvée. Si un fichier AIR est signé à l'aide d'un certificat n'appartenant pas à une chaîne le rattachant à l'un des certificats racines approuvés (et en règle générale ceci englobe tous les certificats auto-signés), les informations de l'éditeur ne peuvent pas être vérifiées. Si l'environnement AIR peut déterminer que le package AIR n'a pas été modifié depuis qu'il a été signé, il n'y a par contre aucun moyen de savoir qui est l'auteur et le signataire de ce fichier. Remarque : un utilisateur peut choisir de faire confiance à un certificat auto-signé, dans ce cas toute application AIR signée à l'aide de ce certificat affiche le nom de l'éditeur en guise de valeur du champ de nom commun dans le certificat. L'environnement AIR ne fournit aucune possibilité à l'utilisateur de désigner un certificat comme étant approuvé. Le certificat (sans la clé privée) doit être fourni séparément à l'utilisateur et celui-ci doit utiliser l'un des moyens proposés par le système d'exploitation, ou tout autre outil approprié, pour importer le certificat à l'emplacement approprié dans le magasin de certificats du système. A propos des identifiants d'éditeur AIR Au cours de la procédure d'élaboration d'un fichier AIR, l'outil ADT génère un ID d'éditeur. Il s'agit d'un identifiant unique pour le certificat utilisé lors de la préparation du fichier AIR. Si vous réutilisez le même certificat pour plusieurs applications AIR, celles-ci seront dotées du même ID d'éditeur. L'ID d'éditeur sert à identifier l'application AIR dans la communication LocalConnection (consultez la section « Communication inter-applications » à la page 317). Vous pouvez identifier l'ID d'éditeur d'une application installée en lisant la propriété NativeApplication.nativeApplication.publisherID. Les champs suivants sont utilisés pour former l'ID d'éditeur : 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 et NameAtBirth. Si vous renouvelez un certificat émis par une autorité de certification ou générez de nouveau un certificat auto-signé, ces champs doivent demeurer identiques pour que l'ID d'éditeur reste le même. En outre, le certificat racine d'un certificat émis par une autorité de certification et la clé publique d'un certificat auto-signé doivent être identiques. A propos des formats de certificats Les outils de signature AIR acceptent tous les magasins de clés accessibles par l'intermédiaire de l'architecture de chiffrement Java, ou architecture JCA (Java Cryptography Architecture). Ceci englobe les fichiers de magasins de clés, comme les fichiers au format PKCS12 (utilisant généralement une extension de fichier .pfx ou p12), les fichiers .keystore de Java, les magasins de clés matériels PKCS11 et les magasins de clés système. Les formats de magasins de clés auxquels l'outil ADT peut accéder dépendent de la version et de la configuration du moteur d'exécution Java qui est utilisé pour exécuter cet outil. L'accès à certains types de magasins de clés, comme les jetons (périphériques de sécurité) matériels PKCS11, peut nécessiter l'installation et la configuration de pilotes logiciels et de plug-ins JCA supplémentaires. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 330 Distribution, installation et exécution d'applications AIR Pour signer des fichiers AIR, vous pouvez utiliser la plupart des certificats de signature de code existants ou en obtenir un nouveau publié expressément pour la signature des applications AIR. Vous pouvez par exemple utiliser l'un des types de certificats suivants publiés par VeriSign, Thawte, GlobalSign ou ChosenSecurity : • ChosenSecurity • ID d'éditeur TC pour Adobe AIR • GlobalSign • Certificat de signature de code ObjectSign • Thawte : • Certificat de développeur AIR • Certificat de développeur Apple • Certificat de développeur JavaSoft • Certificat Microsoft Authenticode • VeriSign : • ID numérique Adobe AIR • ID numérique Microsoft Authenticode • ID numérique Sun Java Signing Remarque : le certificat doit être créé pour la signature de code. Vous ne pouvez pas utiliser de certificat SSL ou d'autres types de certificats pour signer des fichiers AIR. Horodatages Lorsque vous signez un fichier AIR, l'outil de création de packages fait une demande auprès du serveur d'une autorité d'horodatage en vue d'obtenir une date et une heure de signature pouvant être vérifiées indépendamment. L'horodatage obtenu est incorporé au fichier AIR. Tant que le certificat utilisé pour la signature est valable au moment de cette signature, il est toujours possible d'installer le fichier AIR, même après l'expiration du certificat. Par contre, si aucun horodatage n'est obtenu, le fichier AIR perd toute possibilité d'installation lorsque le certificat expire ou est révoqué. Par défaut, les outils de création de packages AIR obtiennent un horodatage. Cependant, afin de permettre la mise en package des applications malgré une indisponibilité du service d'horodatage, vous pouvez désactiver l'option d'horodatage. Adobe recommande la présence d'un horodatage dans tout fichier AIR distribué publiquement. L'autorité d'horodatage par défaut qui est utilisée par les outils de création de package AIR est GeoTrust. Obtention d'un certificat Pour obtenir un certificat, il suffit généralement de se rendre sur le site Web de l'autorité de certification et de suivre la procédure d'acquisition indiquée par la société. Les outils utilisés pour élaborer le fichier de magasin de clés nécessaire aux outils AIR dépendent du type de certificat acheté, de la façon dont le certificat est stocké sur l'ordinateur receveur et, dans certains cas, du navigateur utilisé pour obtenir ce certificat. Par exemple, pour obtenir et exporter un certificat Adobe Developer publié par Thawte, vous devez utiliser Mozilla Firefox. Le certificat peut ensuite être exporté directement sous forme de fichier .p12 ou .pfx à partir de l'interface utilisateur de Firefox. Vous pouvez générer un certificat auto-signé par le biais de l'outil ADT utilisé pour la mise en package des fichiers d'installation AIR. Il est également possible d'utiliser d'autres outils tiers. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 331 Distribution, installation et exécution d'applications AIR Pour connaître la procédure de création automatique d'un certificat auto-signé, et les instructions concernant la signature d'un fichier AIR, consultez la section « Création d'un package de fichier d'installation AIR à l'aide de l'outil ADT » à la page 365. Vous pouvez également exporter et signer des fichiers AIR par l'intermédiaire de Flex Builder, Dreamweaver et de la mise à jour AIR pour Flash. L'exemple suivant décrit la procédure d'obtention d'un certificat de développeur AIR auprès de l'autorité de certification Thawte, et sa préparation pour l'utiliser avec l'outil ADT. Exemple : obtention d'un certificat de développeur AIR auprès de l'autorité Thawte Remarque : cet exemple n'est qu'une illustration parmi les nombreuses possibilités disponibles pour acquérir et préparer un certificat de signature de code. Chaque autorité de certification possède ses propres stratégies et procédures. Pour acquérir un certificat de développeur AIR, le site Web de Thawte nécessite l'utilisation du navigateur Firefox de Mozilla. La clé privée pour le certificat est stockée dans le magasin de clés du navigateur. Assurez-vous que le magasin de clés de Firefox est sécurisé à l'aide d'un mot de passe principal et que l'ordinateur lui-même est installé dans un endroit sûr et protégé. (Vous pouvez exporter et supprimer le certificat et la clé privée depuis le magasin de clés du navigateur une fois la procédure d'acquisition achevée.) Au cours de la procédure d'inscription du certificat, une paire de clé privée/publique est générée. La clé privée est automatiquement stockée dans le magasin de clés Firefox. Vous devez utiliser le même navigateur sur le même ordinateur pour faire la demande d'un certificat sur le site Web de Thawte et procéder à sa récupération. 1 Visitez le site Web de Thawte et affichez la Page Produits – Certificats développeur (signature de code). 2 A partir de la liste des certificats proposés, sélectionnez le certificat du développeur Adobe® Air™. 3 Suivez les trois étapes de la procédure d'inscription. Vous devez fournir des informations sur votre organisation et les coordonnées de la personne à contacter. Thawte procède ensuite à l'opération du contrôle d'identité, ce qui peut faire l'objet d'une demande de renseignements complémentaires. Cette vérification achevée, un courrier électronique vous est adressé, il contient des instructions sur la procédure de récupération du certificat. Remarque : vous trouverez des informations supplémentaires sur la nature des documents à fournir en suivant ce lien : https://www.thawte.com/ssl-digital-certificates/free-guides-whitepapers/pdf/enroll_codesign_eng.pdf. 4 Récupérez le certificat émis depuis le site Thawte. Le certificat est automatiquement enregistré dans le magasin de clés Firefox. 5 Exportez un fichier de magasin de clés contenant la clé privée et le certificat à partir du magasin de clés Firefox en procédant comme suit : Remarque : lorsqu'ils sont exportés à partir de Firefox, la clé privée et le certificat sont transmis dans un format p12 (pfx) exploitable par l'outil ADT, Flex, Flash et Dreamweaver. a Ouvrez la boîte de dialogue Gestionnaire de certificats : b Sous Windows : ouvrez Outils > Options > Avancé > Chiffrement > Afficher les certificats. c Sous Mac OS : ouvrez Firefox > Préférences > Avancé > Chiffrement > Afficher les certificats. d Sous Linux : ouvrez Edition > Préférences > Avancé > Chiffrement > Afficher les certificats. e Sélectionnez le certificat de signature de code Adobe Air à partir de la liste des certificats et cliquez sur le bouton Sauvegarder. f Entrez un nom de fichier et indiquez l'emplacement vers lequel exporter le fichier de magasin de clés, puis cliquez sur Enregistrer. g Si vous utilisez la fonction de mot de passe principal de Firefox et que vous voulez exporter le fichier, vous êtes invité à préciser votre mot de passe pour le dispositif logiciel de sécurité. (Ce mot de passe n'est utilisé que par Firefox.) DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 332 Distribution, installation et exécution d'applications AIR h Dans la boîte de dialogue Choisir un mot de passe de sauvegarde du certificat, créez un mot de passe pour le fichier de magasin de clés. Important : ce mot de passe protège le fichier de magasin de clés et il est requis lorsque le fichier est utilisé pour signer des applications AIR. Votre choix devrait se porter de préférence sur un mot de passe sécurisé. i Cliquez sur OK. Vous devriez recevoir un message de sauvegarde du mot de passe vous informant que l'opération a réussi. Le fichier de magasin de clés, qui contient la clé privée et le certificat, est sauvegardé au moyen d'une extension de fichier .p12 (au format PKCS12). 6 Utilisez le fichier de magasin de clés exporté avec l'outil ADT, Flex Builder ou Dreamweaver. Le mot de passe créé pour le fichier est demandé chaque fois qu'une application AIR est signée. Important : la clé privée et le certificat demeurent stockés dans le magasin de clés Firefox. Si cette procédure vous permet d'exporter un exemplaire supplémentaire du fichier de certificat, vous obtenez également un autre point d'accès qu'il faut absolument protéger pour préserver la sécurité de votre certificat et de votre clé privée. Changement de certificats Vous pouvez être amené dans certains cas à changer le certificat que vous utilisez pour signer votre application AIR. Entre autres, dans les circonstances suivantes : • Mise à niveau à partir d'un certificat auto-signé vers un certificat émis par une autorité de certification • Changement d'un certificat auto-signé sur le point d'expirer • Changement d'un certificat commercial, par exemple lorsque les informations relatives à l'identité de votre société sont modifiées Etant donné que le certificat de signature fait partie des éléments déterminant l'identité d'une application AIR, vous ne pouvez pas vous contenter de signer une mise à jour pour votre application au moyen d'un autre certificat. Pour que l'environnement AIR reconnaisse un fichier AIR comme mise à jour, vous devez signer les deux fichiers, l'original et celui qui est mis à jour, avec le même certificat. Sinon, AIR installe le nouveau fichier AIR en tant qu'application distincte au lieu de mettre l'application existante à jour. Depuis AIR 1.1, vous pouvez changer le certificat de signature d'une application au moyen d'une signature de migration. Ce type de signature constitue une deuxième signature appliquée au fichier AIR de mise à jour. La signature de migration utilise le certificat original attestant que le signataire est bien l'éditeur d'origine de l'application. Important : le certificat doit être changé avant que le certificat original expire ou soit révoqué. Si vous ne créez aucune mise à jour à l'aide d'une signature de migration avant l'expiration de votre certificat, les utilisateurs devront désinstaller leur version existante de votre application avant d'installer des mises à jour. Il est généralement possible de renouveler les certificats commerciaux afin d'éviter leur expiration. Les certificats auto-signés ne sont pas renouvelables. Pour changer de certificats : 1 Créez une mise à jour pour votre application. 2 Procédez à la création du package et à la signature du fichier AIR de mise à jour à l'aide du nouveau certificat. 3 Signez le fichier AIR de nouveau au moyen du certificat original (grâce à la commande -migrate de l'outil ADT). La procédure d'application d'une signature de migration est décrite dans la section « Modification du certificat d'une application à l'aide d'une signature de fichier AIR » à la page 375. Lorsque le fichier AIR de mise à jour est installé, l'identité de l'application change. Ce changement d'identité entraîne les répercussions suivantes : • L'ID d'éditeur de l'application change pour correspondre au nouveau certificat. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 333 Distribution, installation et exécution d'applications AIR • La nouvelle version de l'application ne peut pas accéder aux données contenues dans le magasin local chiffré existant. • L'emplacement du répertoire de stockage de l'application change. Les données situées à l'ancien emplacement ne sont pas copiées dans le nouveau répertoire. (Par contre, la nouvelle application peut localiser le répertoire d'origine en fonction de l'ancien ID d'éditeur). • L'application ne peut plus ouvrir une seule connexion locale au moyen de l'ancien ID d'éditeur. • Si un utilisateur réinstalle un fichier AIR de pré-migration, l'environnement d'exécution AIR l'installe comme une application distincte à l'aide de l'ID d'éditeur original. C'est à votre application que revient la tâche de faire migrer les données entre la version originale de l'application et la nouvelle version. Pour faire migrer des données du magasin local chiffré, vous devez les exporter avant que le changement de certificats n'ait lieu. La nouvelle version de votre application n'est pas en mesure de lire le magasin de l'ancienne version. (Il est souvent plus facile de recréer tout simplement les données plutôt que de procéder à leur migration.) Il est préférable de continuer à appliquer la signature de migration à autant de mises à jour ultérieures que possible. Sinon, les utilisateurs qui n'ont pas encore procédé à la mise à niveau de leur version d'origine devront soit installer une version de migration intermédiaire, soit désinstaller leur version actuelle avant de pouvoir installer votre mise à jour la plus récente. Bien sûr, le certificat original finira par expirer et vous ne serez plus en mesure d'appliquer la moindre signature de migration. (Toutefois, à moins de désactiver l'option d'horodatage, les fichiers AIR précédemment signés au moyen d'une signature de migration demeureront valides. La signature de migration est horodatée pour permettre à l'environnement AIR d'accepter la signature même après l'expiration du certificat.) Un fichier AIR doté d'une signature de migration est, à d'autres égards, un fichier AIR tout à fait normal. Si l'application est installée sur un système vierge de toute version originale, l'environnement AIR installe la nouvelle version de la façon habituelle. Remarque : en règle générale, il n'est pas nécessaire de faire migrer le certificat lorsque vous renouvelez un certificat commercial. Un certificat renouvelé conserve la même identité d'éditeur que celle de l'original à moins que le nom unique ait changé. Pour obtenir une liste complète des attributs de certificat utilisés dans la détermination du nom unique, consultez la section « A propos des identifiants d'éditeur AIR » à la page 329. Terminologie Cette section propose un glossaire des termes essentiels à votre compréhension lorsque vous décidez de signer une application pour la distribuer publiquement. Terme Description Autorité de certification Entité dans un réseau à infrastructure de clé publique qui sert de tiers de confiance et qui, en définitive, atteste de l'identité du propriétaire d'une clé publique. Normalement, une autorité de certification émet des certificats numériques, signés par sa propre clé privée, pour attester qu'elle a effectivement contrôlé l'identité du détenteur du certificat. Déclaration des pratiques de certification (Déclaration CPS) Présente les différentes pratiques et stratégies de l'autorité de certification dans l'émission et la vérification des certificats. La déclaration des pratiques de certification, ou déclaration CPS (Certification Practice Statement), fait partie intégrante du contrat qui lie l'autorité de certification avec ses abonnés et parties de confiance. Elle décrit également dans les grandes lignes les stratégies élaborées pour la vérification d'identité et le niveau des garanties offertes par les certificats fournis. Liste de révocation de certificats Liste des certificats émis qui ont été révoqués et qui ne devraient plus être considérés comme dignes de confiance. L'environnement d'exécution AIR vérifie la liste de révocation des certificats à la signature d'une application AIR et, si aucun horodatage n'est présent, renouvelle l'opération lorsque l'application est installée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 334 Distribution, installation et exécution d'applications AIR Terme Description Chaîne de certificats Une chaîne de certificats est une séquence de certificats dans laquelle chaque certificat présent a été signé par le certificat qui lui succède. Certificat numérique Document numérique contenant des informations sur l'identité du propriétaire, la clé publique du propriétaire et l'identité du certificat lui-même. Un certificat émis par une autorité de certification est lui-même signé par un certificat appartenant à l'autorité de certification émettrice. Signature numérique Résumé ou message chiffré ne pouvant être déchiffré qu'à l'aide de la paire clé publique et moitié de la clé publique-privée. Dans une infrastructure de clé publique (PKI), une signature numérique contient un ou plusieurs certificats numériques qui, en bout de chaîne, remontent jusqu'à l'autorité de certification. Une signature numérique peut servir à garantir qu'un message (ou un fichier informatique) n'a subi aucune modification depuis sa signature (dans les limites de la garantie fournie par l'algorithme de chiffrement utilisé) et, en admettant que l'autorité de certification émettrice soit jugée digne de confiance, à attester de l'identité du signataire. Magasin de clés Base de données contenant des certificats numériques et, dans certains cas, les clés privées associées. Architecture de chiffrement Java, ou architecture JCA Architecture extensible propre à la gestion et à l'accès des magasins de clés. Pour plus d'informations, consultez le Guide de référence de l'architecture JCA. PKCS #11 Norme de chiffrement d'interface pour jeton élaborée par RSA Laboratories. Un magasin de clés sur jeton (périphérique de sécurité) matériel. PKCS #12 Norme décrivant la syntaxe des échanges d'informations personnelles élaborée par RSA Laboratories. Fichier de magasin de clés ; il contient habituellement une clé privée et son certificat numérique associé. Clé privée Système de chiffrement asymétrique de la moitié privée de la clé à deux composants public-privé. La clé privée doit être conservée dans un endroit secret et ne devrait jamais être transmise via un réseau. Les messages signés numériquement sont chiffrés par le signataire au moyen de la clé privée. Clé publique Système de chiffrement asymétrique de la moitié publique de la clé à deux composants publicprivé. La clé publique est disponible sans réserve : elle sert à déchiffrer des messages chiffrés à l'aide de la clé privée. Infrastructure de clé publique (PKI) Système basé sur l'approbation dans lequel les autorités de certification garantissent l'identité des propriétaires de clés publiques. Les clients du réseau font confiance aux certificats numériques émis par une autorité de certification approuvée pour vérifier l'identité du signataire d'un message numérique (ou d'un fichier). Horodatage Donnée signée numériquement qui contient la date et l'heure auxquelles un événement est survenu. L'outil ADT peut englober un horodatage à partir d'un serveur de temps RFC 3161 (en anglais) dans un package AIR. Lorsqu'il est présent, l'environnement AIR utilise l'horodatage pour établir la validité d'un certificat au moment de la signature. Ceci permet l'installation d'une application AIR après l'expiration du certificat de signature. Autorité d'horodatage Organisation ayant autorité pour émettre des horodatages. Pour être reconnu par l'environnement AIR, l'horodatage doit être conforme au protocole RFC 3161 et la signature de cet horodatage doit être liée par une chaîne de certificats à un certificat racine de confiance sur l'ordinateur d'installation. 335 Chapitre 33 : Mise à jour des applications AIR Les utilisateurs peuvent installer ou mettre à jour une application AIR en double-cliquant sur un fichier AIR sur leur ordinateur ou dans un navigateur (à l'aide de la fonction d'installation transparente). Le programme d'installation d'Adobe® AIR™ gère l'installation et avertit les utilisateurs s'ils mettent à jour une application existante. (Consultez le chapitre « Distribution, installation et exécution d'applications AIR » à la page 318.) Par ailleurs, la classe Updater permet à une application installée de se mettre automatiquement à niveau vers une nouvelle version. (Il est possible qu'une application installée détecte qu'une nouvelle version peut être téléchargée et installée.) La classe Updater inclut une méthode update() qui vous permet de pointer vers un fichier AIR sur l'ordinateur de l'utilisateur et d'effectuer la mise à jour vers cette version. L'ID d'application et l'ID d'éditeur d'un fichier AIR de mise à jour doivent correspondre à l'application à mettre à jour. L'ID d'éditeur est issu du certificat de signature, ce qui signifie que la mise à jour et l'application à mettre à jour doivent être signées avec le même certificat. Depuis AIR 1.1, vous pouvez effectuer la migration d'une application pour utiliser un nouveau certificat de signature de code. La migration d'une application pour utiliser une nouvelle signature implique la signature du fichier AIR de mise à jour avec l'ancien et le nouveau certificat. La migration de certificats est un processus unidirectionnel. Après la migration, seuls les fichiers AIR signés avec le nouveau certificat (ou avec les deux certificats) sont reconnus comme étant des mises à jour d'une installation existante. La gestion des mises à jour des applications peut se révéler complexe. AIR 1.5 comprend la nouvelle structure de mise à jour pour applications Adobe® AIR™. Cette structure fournit des API qui aident les développeurs à doter les applications AIR de bonnes capacités de mise à jour. Vous pouvez utiliser la migration de certificats pour passer d'un certificat auto-signé à un certificat de signature de code commercial, ou d'un certificat auto-signé ou commercial à un autre. Si vous n'effectuer pas la migration du certificat, les utilisateurs existants doivent supprimer la version actuelle de votre application avant d'installer la nouvelle. Pour plus d'informations, consultez la section « Changement de certificats » à la page 332. A propos de la mise à jour des applications La classe Updater (dans le package flash.desktop) comprend une méthode, update(), que vous pouvez utiliser pour mettre à jour l'application en cours d'exécution vers une nouvelle version. Par exemple, si l'utilisateur dispose d'une version du fichier AIR ("Sample_App_v2.air") située dans le poste de travail, le code suivant met à jour l'application : var updater:Updater = new Updater(); var airFile:File = File.desktopDirectory.resolvePath("Sample_App_v2.air"); var version:String = "2.01"; updater.update(airFile, version); Pour que l'application puisse utiliser la classe Updater, l'utilisateur ou l'application doit télécharger la version mise à jour du fichier AIR sur l'ordinateur. Pour plus d'informations, consultez la section « Téléchargement d'un fichier AIR sur l'ordinateur de l'utilisateur » à la page 337. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 336 Mise à jour des applications AIR Résultats de l'appel à la méthode Updater.update() Lorsqu'une application du moteur d'exécution appelle la méthode update(), le moteur d'exécution ferme l'application, puis tente d'installer la nouvelle version à partir du fichier AIR. Le moteur d'exécution vérifie que l'ID d'application et l'ID d'éditeur spécifiés dans le fichier AIR correspondent à ceux de l'application qui appellent la méthode update(). (Pour plus d'informations sur l'ID d'application et l'ID d'éditeur, consultez le chapitre « Définition des propriétés d'une application AIR » à la page 46.) Il vérifie également que la chaîne de version correspond à la chaîne version transmise à la méthode update(). Si l'installation réussit, le moteur d'exécution ouvre la nouvelle version de l'application. Dans le cas contraire (si l'installation échoue), il ouvre à nouveau la version existante (pré-installée) de l'application. Pour installer la version mise à jour d'une application sous Mac OS, l'utilisateur doit disposer des privilèges système adéquats sur le répertoire de l'application. S'il utilise Windows ou Linux, l'utilisateur doit disposer de privilèges d'administrateur. Si la version mise à jour de l'application requiert une mise à jour du moteur d'exécution, la nouvelle version du moteur est installée. Pour mettre à jour le moteur d'exécution, l'utilisateur doit disposer de privilèges d'administration sur l'ordinateur. Lors du test d'une application avec l'application de débogage du lanceur AIR (ADL), l'appel de la méthode update() provoque une exception d'exécution. A propos de la chaîne de version La chaîne spécifiée comme paramètre version de la méthode update() doit correspondre à la chaîne dans l'attribut version de l'élément application principal du fichier descripteur d'application pour le fichier AIR à installer. Par mesure de sécurité, la définition du paramètre version est obligatoire. Obliger l'application à vérifier le numéro de version dans le fichier AIR l'empêche d'installer par inadvertance une version plus ancienne pouvant éventuellement contenir une faille de sécurité corrigée dans l'application actuellement installée. L'application doit également vérifier la chaîne de version du fichier AIR avec la chaîne de version de l'application installée afin d'éviter les tentatives d'attaque pour rétrograder l'application. Sélectionnez le format de la chaîne de version de votre choix. Par exemple, il peut s'agir de « 2.01 » ou de « version 2 ». En tant que développeur de l'application, vous devez décider du format de cette chaîne. Le moteur d'exécution ne valide pas la chaîne de version ; c'est au code de l'application de s'en charger, avant la mise à jour de l'application. Si une application Adobe AIR télécharge un fichier AIR via Internet, il est conseillé de disposer d'un mécanisme permettant au service Web d'informer l'application Adobe AIR de la version en cours de téléchargement. L'application peut ainsi utiliser cette chaîne comme paramètre version de la méthode update(). Si le fichier AIR est obtenu par un autre moyen, dans lequel la version du fichier AIR est inconnue, l'application AIR peut examiner le fichier AIR afin de déterminer les informations de version. (Un fichier AIR est une archive compressée et le fichier descripteur d'application correspond au deuxième enregistrement dans l'archive.) Pour plus d'informations sur le fichier descripteur d'application, consultez le chapitre « Définition des propriétés d'une application AIR » à la page 46. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 337 Mise à jour des applications AIR Présentation d'une interface utilisateur personnalisée pour la mise à jour d'applications AIR inclut une interface de mise à jour par défaut : Cette interface est toujours utilisée la première fois qu'un utilisateur installe une version d'une application sur une machine. Vous pouvez cependant définir votre propre interface en vue de l'utiliser dans les occurrences suivantes. Si votre application définit une interface de mise à jour personnalisée, spécifiez un élément customUpdateUI dans le fichier descripteur d'application pour l'application actuellement installée : <customUpdateUI>true</customUpdateUI> Après avoir installé l'application et une fois que l'utilisateur a ouvert un fichier AIR avec un ID d'application et un ID d'éditeur correspondant à l'application installée, c'est le moteur d'exécution qui ouvre l'application et non le programme d'installation par défaut de l'application AIR. Pour plus d'informations, consultez la section « Définition d'une interface utilisateur personnalisée pour les mises à jour d'une application » à la page 54. Lors de son exécution (c'est-à-dire lorsque l'objet NativeApplication.nativeApplication distribue un événement load), l'application peut décider de mettre ou non l'application à jour (à l'aide de la classe Updater). Si elle décide d'effectuer la mise à jour, elle peut présenter à l'utilisateur sa propre interface d'installation (qui diffère de l'interface d'exécution standard). Téléchargement d'un fichier AIR sur l'ordinateur de l'utilisateur Pour utiliser la classe Updater, l'utilisateur ou l'application doit tout d'abord enregistrer un fichier AIR localement sur l'ordinateur de l'utilisateur. Remarque : AIR 1.5 comprend une structure de mise à jour qui aide les développeurs à doter les applications AIR de bonnes capacités de mise à jour. L'utilisation de cette structure peut être bien plus simple que l'utilisation directe de la méthode update() de la classe Update. Pour plus d'informations, consultez la section « Utilisation de la structure de mise à jour » à la page 339. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 338 Mise à jour des applications AIR Le code suivant lit un fichier AIR à partir d'une URL (http://example.com/air/updates/Sample_App_v2.air) et enregistre le fichier AIR dans le répertoire de stockage de l'application : 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."); } Pour plus d'informations, consultez la section « Flux de travail pour la lecture et l'écriture de fichiers » à la page 123. Vérifications permettant de savoir si l'application est exécutée pour la première fois Après avoir mis à jour une application, vous pouvez afficher un message de bienvenue ou de mise en route destiné à l'utilisateur. Au démarrage, l'application vérifie si elle est exécutée pour la première fois afin d'afficher ou non ce message. Remarque : AIR 1.5 comprend une structure de mise à jour qui aide les développeurs à doter les applications AIR de bonnes capacités de mise à jour. Cette structure fournit des méthodes simples qui permettent de vérifier si la version de l'application est exécutée pour la première fois. Pour plus d'informations, consultez la section « Utilisation de la structure de mise à jour » à la page 339. Pour cela, vous devez enregistrer un fichier dans le répertoire de stockage de l'application lors de l'initialisation de l'application. Chaque fois que l'application démarre, elle vérifie l'existence de ce fichier. Si le fichier n'existe pas, l'application est exécutée pour la première fois pour l'utilisateur actuel. Si le fichier existe, l'application a déjà été exécutée au moins une fois. Si le fichier existe et contient un numéro de version antérieur au numéro de version actuel, vous savez que l'utilisateur exécute la nouvelle version pour la première fois. Si votre application enregistre les données localement (par exemple, dans le répertoire de stockage de l'application), vous pouvez vérifier toutes les données préalablement enregistrées (de versions antérieures) lors de la première exécution. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 339 Mise à jour des applications AIR Utilisation de la structure de mise à jour La gestion des mises à jour des applications peut se révéler complexe. La structure de mise à jour pour applications Adobe®AIR fournit des API qui aident les développeurs à doter les applications AIR de bonnes capacités de mise à jour. Les fonctionnalités de la structure de mise à jour AIR aident les développeurs dans les opérations suivantes : • Vérifications régulières de la présence de mise à jour, en fonction d'un intervalle ou à la demande de l'utilisateur • Téléchargement des fichiers AIR (mises à jour) depuis une source Web • Alerte de l'utilisateur lors de la première exécution de la version nouvellement installée • Confirmation de la part de l'utilisateur que celui-ci souhaite vérifier la présence de mises à jour • Affichage des informations relatives à la nouvelle version • Affichage pour l'utilisateur de la progression du téléchargement et d'informations d'erreurs La structure de mise à jour AIR propose un exemple d'interface utilisateur dont votre application peut se servir. Cette interface présente des informations de base à l'utilisateur et les options associées aux mises à jour de l'application. Votre application peut également définir sa propre interface utilisateur personnalisée à utiliser avec la structure de mise à jour. La structure de mise à jour AIR vous permet de stocker les informations relatives à la version mise à jour d'une application AIR dans de simples fichiers de configuration XML. Pour la plupart des applications, la configuration de ces fichiers de configuration et l'inclusion d'une partie du code de base fournissent à l'utilisateur final de bonnes fonctionnalités de mise à jour. Outre l'utilisation de la structure de mise à jour, Adobe AIR comprend également une classe Updater que les applications AIR peuvent utiliser pour effectuer la mise à jour vers de nouvelles versions. Cette classe permet à l'application de procéder à une mise à jour vers la version contenue dans un fichier AIR situé sur l'ordinateur de l'utilisateur. Toutefois, la gestion des mises à jour peut se révéler plus complexe que la simple mise à jour d'une application à partir d'un fichier AIR stocké localement. Fichiers de la structure de mise à jour AIR La structure de mise à jour AIR comprend les répertoires suivants : • doc : documentation (que vous êtes en train de lire) de la structure de mise à jour AIR. • frameworks : ce répertoire comprend les fichiers SWC, pour le développement Flex, et les fichiers SWF, pour le développement HTML. Pour plus d'informations, consultez les sections suivantes (qui suivent immédiatement cette section) : • « Configuration de votre environnement de développement Flex » à la page 340 • « Intégration des fichiers de la structure dans une application AIR de type HTML » à la page 340 • samples : ce répertoire comprend les modèles Flex et HTML qui décrivent l'utilisation de la structure de mise à jour des applications. Compilez et testez ces fichiers comme vous le feriez pour n'importe quelle application AIR. • templates : ce répertoire contient des exemples de fichiers descripteur de mise à jour (simples et localisés) et les fichiers de configuration. (Pour plus d'informations sur ces fichiers, consultez les sections Configuration de votre environnement de développement Flex et « Exemple de base : utilisation de la version ApplicationUpdaterUI » à la page 340.) DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 340 Mise à jour des applications AIR Configuration de votre environnement de développement Flex Le répertoire frameworks/flex de la structure de mise à jour contient les fichiers suivants : • ApplicationUpdater.swc : définit les fonctionnalités de base de la bibliothèque de mise à jour, sans interface utilisateur. • ApplicationUpdater_UI.swc : définit les fonctionnalités de base de la bibliothèque de mise à jour, avec une interface utilisateur dont votre application peut se servir pour afficher les options de la mise à jour. Les fichiers SWC définissent les classes que vous pouvez utiliser dans un développement Flex. Pour utiliser la structure de mise à jour lors d'une compilation avec le kit SDK Flex, intégrez le fichier ApplicationUpdater.swc ou ApplicationUpdater_UI.swc dans l'appel au compilateur amxmlc. Dans l'exemple suivant, le compilateur charge le fichier ApplicationUpdater.swc dans le sous-répertoire lib du répertoire SDK Flex : amxmlc -library-path+=lib/ApplicationUpdater.swc -- myApp.mxml Dans l'exemple suivant, le compilateur charge le fichier ApplicationUpdater_UI.swc dans le sous-répertoire lib du répertoire SDK Flex : amxmlc -library-path+=lib/ApplicationUpdater_UI.swc -- myApp.mxml Lors d'un développement avec Flex Builder, ajoutez le fichier SWC dans l'onglet Chemin de la bibliothèque des paramètres du chemin de création Flex de la boîte de dialogue Propriétés. Assurez-vous de copier les fichiers SWC dans le répertoire que vous référencerez dans le compilateur amxmlc (avec SDK Flex) ou Flex Builder. Intégration des fichiers de la structure dans une application AIR de type HTML Le répertoire frameworks/html de la structure de mise à jour contient les fichiers SWF suivants : • ApplicationUpdater.swf : définit les fonctionnalités de base de la bibliothèque de mise à jour, sans interface utilisateur. • ApplicationUpdater_UI.swf : définit les fonctionnalités de base de la bibliothèque de mise à jour, avec une interface utilisateur que votre application peut utiliser pour afficher les options de la mise à jour. Le code JavaScript des applications AIR peut utiliser les classes définies dans les fichiers SWF. Pour utiliser la structure de mise à jour, intégrez le fichier ApplicationUpdater.swf ou ApplicationUpdater_UI.swf dans le répertoire de votre application (ou dans un sous-répertoire). Ensuite, dans le fichier HTML qui utilisera la structure (dans le code JavaScript), insérez une balise script chargeant le fichier : <script src="applicationUpdater.swf" type="application/x-shockwave-flash"/> Vous pouvez également utiliser cette balise script pour charger le fichier ApplicationUpdater_UI.swf : <script src="ApplicationUpdater_UI.swf" type="application/x-shockwave-flash"/> L'API définie dans ces deux fichiers est décrite dans la suite de ce document. Exemple de base : utilisation de la version ApplicationUpdaterUI La version ApplicationUpdaterUI de la structure de mise à jour offre une interface de base que vous pouvez facilement utiliser dans votre application. Voici un exemple de base. D'abord, créez une application AIR qui appelle la structure de mise à jour : 1 S'il s'agit d'une application AIR de type HTML, chargez le fichier ApplicationUpdaterUI.js : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 341 Mise à jour des applications AIR <script src="ApplicationUpdater_UI.swf" type="application/x-shockwave-flash"/> 2 Dans la logique du programme de votre application AIR, instanciez un objet ApplicationUpdaterUI. Dans ActionScript, utilisez le code suivant : var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI(); Dans JavaScript, utilisez le code suivant : var appUpdater = new runtime.air.update.ApplicationUpdaterUI(); Vous pouvez ajouter ce code dans une fonction d'initialisation qui s'exécute après le chargement de l'application. 3 Créez un fichier texte nommé updateConfig.xml et ajoutez-lui les éléments suivants : <?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> Modifiez l'élément URL du fichier updateConfig.xml pour qu'il corresponde à l'emplacement final du fichier descripteur de la mise à jour sur votre serveur Web (voir la procédure suivante). L'élément delay définit le nombre de jours devant s'écouler avant que l'application ne vérifie la présence de nouvelles mises à jour. 4 Ajoutez le fichier updateConfig.xml dans le répertoire de projet de votre application AIR. 5 Faites en sorte que l'objet updater fasse référence au fichier updateConfig.xml, et appelez la méthode initialize() de l'objet. Dans ActionScript, utilisez le code suivant : appUpdater.configurationFile = new File("app:/updateConfig.xml"); appUpdater.initialize(); Dans JavaScript, utilisez le code suivant : appUpdater.configurationFile = new air.File("app:/updateConfig.xml"); appUpdater.initialize(); 6 Créez une seconde version de l'application AIR dont la version diffère de la première application. (La version est spécifiée dans le fichier descripteur de l'application, dans l'élément version.) Ajoutez ensuite la mise à jour de votre application AIR sur votre serveur Web : 1 Placez la version mise à jour du fichier AIR sur votre serveur Web. 2 Créez un fichier texte nommé updateDescriptor.xml et ajoutez-lui le contenu suivant : <?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> Modifiez les éléments version, URL et description du fichier updateDescriptor.xml pour qu'ils correspondent à votre fichier AIR de mise à jour. 3 Ajoutez le fichier updateDescriptor.xml dans le répertoire du serveur Web qui contient déjà le fichier AIR de mise à jour. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 342 Mise à jour des applications AIR Il s'agit là d'un exemple de base, mais il fournit des fonctionnalités de mise à jour suffisantes pour la plupart des applications. La suite de ce document décrit l'utilisation de la structure de mise à jour en fonction de vos besoins. Pour obtenir un autre exemple d'utilisation de la structure de mise à jour, consultez l'exemple d'application suivant dans le centre des développeurs Adobe AIR : Structure de mise à jour dans une application de type Flash(http://www.adobe.com/go/learn_air_qs_update_framework_flash_fr). Définition du fichier descripteur de mise à jour et ajout du fichier AIR dans votre serveur Web Lorsque vous utilisez la structure de mise à jour AIR, vous définissez les informations de base relatives à la mise à jour disponible dans un fichier descripteur de mise à jour, stocké sur votre serveur Web. Ce fichier descripteur de mise à jour est un simple fichier XML. La structure de mise à jour incluse dans l'application examine ce fichier pour savoir si une nouvelle version a été chargée. Le fichier descripteur de mise à jour contient les données suivantes : • version : nouvelle version de l'application AIR. Cette chaîne doit correspondre à celle qui est utilisée en tant que version dans le fichier descripteur de la nouvelle application AIR. Si la version indiquée dans le fichier descripteur de mise à jour ne correspond pas à celle du fichier AIR de mise à jour, la structure de mise à jour renvoie une exception. • url : emplacement du fichier AIR de mise à jour. Ce fichier contient la version mise à jour de l'application AIR. • description : détails de la nouvelle version. Ces informations peuvent s'afficher pour l'utilisateur pendant le processus de mise à jour. Les éléments version et url sont obligatoires. L'élément description est facultatif. Voici un exemple de fichier descripteur de mise à jour : <?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> Pour définir la balise description avec plusieurs langues, utilisez plusieurs éléments text définissant un attribut 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> Placez le fichier descripteur de mise à jour et le fichier AIR de mise à jour sur votre serveur Web. Le répertoire templates inclus avec le descripteur de mise à jour comprend des exemples de fichiers descripteur de mise à jour. Ces derniers comprennent des versions de langage unique et des versions multilingues. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 343 Mise à jour des applications AIR Instanciation d'un objet updater Après le chargement de la structure de mise à jour AIR dans votre code (voir « Configuration de votre environnement de développement Flex » à la page 340 et « Intégration des fichiers de la structure dans une application AIR de type HTML » à la page 340), vous devez instancier un objet updater, comme dans l'exemple suivant : var appUpdater:ApplicationUpdater = new ApplicationUpdater(); Le code précédent utilise la classe ApplicationUpdater (qui ne fournit pas d'interface utilisateur). Pour utiliser la classe ApplicationUpdaterUI (qui fournit une interface utilisateur), utilisez le code suivant : var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI(); Les autres exemples de code de ce document supposent que vous avez instancié un objet updater nommé appUpdater. Configuration des paramètres de la mise à jour Les classes ApplicationUpdater et ApplicationUpdaterUI peuvent être configurées par l'intermédiaire d'un fichier de configuration fourni avec l'application ou par le code ActionScript ou JavaScript de l'application. Définition des paramètres de la mise à jour dans un fichier de configuration XML Ce fichier de configuration de la mise à jour est un fichier XML. Il peut contenir les éléments suivants : • updateURL : chaîne représentant l'emplacement du descripteur de la mise à jour sur le serveur distant. Tout emplacement URLRequest valide est autorisé. Vous devez définir la propriété updateURL, par l'intermédiaire du fichier de configuration ou du script (voir « Définition du fichier descripteur de mise à jour et ajout du fichier AIR dans votre serveur Web » à la page 342). Vous devez définir cette propriété avant d'utiliser l'objet updater (avant d'appeler la méthode initialize() de l'objet updater, décrite à la section « Initialisation de la structure de mise à jour » à la page 346). • delay : nombre représentant un intervalle de jours donné (des valeurs comme 0.25 sont autorisées) correspondant à la fréquence de vérification de la présence de mises à jour. Une valeur 0 (définie par défaut) spécifie que l'objet updater ne vérifie pas automatiquement la présence de mise à jour. Le fichier de configuration d'ApplicationUpdaterUI peut contenir l'élément suivant en plus des éléments updateURL et delay : • defaultUI : liste des éléments dialog. Chaque élément dialog possède un attribut name correspondant à une boîte de dialogue de l'interface utilisateur. Chaque élément dialog possède un attribut visible qui spécifie si la boîte de dialogue est visible. La valeur par défaut est true. Les valeurs possibles de l'attribut name sont les suivantes : • "checkForUpdate" : correspondant aux boîtes de dialogue Rechercher une mise à jour, Aucune mise à jour et Erreur de mise à jour. • "downloadUpdate" : correspondant à la boîte de dialogue Télécharger la mise à jour. • "downloadProgress" : correspondant aux boîtes de dialogue Progression du téléchargement et Erreur de téléchargement. • • "installUpdate" : correspondant à la boîte de dialogue Installer la mise à jour. • "fileUpdate" : correspondant aux boîtes de dialogue Mise à jour des fichiers, Aucune mise à jour de fichiers et Erreur de fichier. "unexpectedError" : correspondant à la boîte de dialogue Erreur imprévue. Lorsque l'attribut est défini sur false, la boîte de dialogue correspondante ne s'affiche pas dans le cadre de la procédure de mise à jour. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 344 Mise à jour des applications AIR Voici un exemple de fichier de configuration pour la structure 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> Voici un exemple de fichier de configuration pour la structure ApplicationUpdaterUI, comprenant une définition de l'élément 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> Pointez la propriété configurationFile sur l'emplacement de ce fichier, comme dans le code suivant : • ActionScript : appUpdater.configurationFile = new File("app:/cfg/updateConfig.xml"); • JavaScript : appUpdater.configurationFile = new air.File("app:/cfg/updateConfig.xml"); Le répertoire templates de la structure de mise à jour comprend un exemple de fichier de configuration, configtemplate.xml. Définition des paramètres de mise à jour dans le code ActionScript ou JavaScript Ces paramètres de configuration peuvent également être définis dans le code de l'application, comme dans le code suivant : appUpdater.updateURL = " http://example.com/updates/update.xml"; appUpdater.delay = 1; Les propriétés de l'objet updater sont updateURL et delay. Ces propriétés définissent les mêmes paramètres que les éléments updateURL et delay dans le fichier de configuration : l'URL du fichier descripteur de mise à jour et l'intervalle de vérification des mises à jour. Si vous spécifiez un fichier de configuration et des paramètres dans le code, toutes les propriétés définies à l'aide du code sont prioritaires sur les paramètres correspondants dans le fichier de configuration. Vous devez définir la propriété updateURL, par l'intermédiaire du fichier de configuration ou du script (voir « Définition du fichier descripteur de mise à jour et ajout du fichier AIR dans votre serveur Web » à la page 342), avant d'utiliser l'objet updater (avant d'appeler la méthode initialize() de l'objet updater, décrite à la section « Initialisation de la structure de mise à jour » à la page 346). La structure ApplicationUpdaterUI définit les propriétés supplémentaires suivantes de l'objet updater : • isCheckForUpdateVisible : correspondant aux boîtes de dialogue Rechercher une mise à jour, Aucune mise à jour et Erreur de mise à jour. • isDownloadUpdateVisible : correspondant à la boîte de dialogue Télécharger une mise à jour. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 345 Mise à jour des applications AIR • isDownloadProgressVisible : correspondant aux boîtes de dialogue Progression du téléchargement et Erreur de téléchargement. • isInstallUpdateVisible : correspondant à la boîte de dialogue Installer la mise à jour. • isFileUpdateVisible : correspondant aux boîtes de dialogue Mise à jour des fichiers, Aucune mise à jour de fichiers et Erreur de fichier. • isUnexpectedErrorVisible : correspondant à la boîte de dialogue Erreur imprévue. Chaque propriété correspond à une ou plusieurs boîtes de dialogue de l'interface utilisateur ApplicationUpdaterUI. Chaque propriété est une valeur booléenne, dont la valeur par défaut est true. Lorsqu'elle est définie sur false, les boîtes de dialogue correspondantes ne s'affichent pas lors de la procédure de mise à jour. Les propriétés de ces boîtes de dialogue remplacent les paramètres du fichier de configuration de mise à jour. Processus de mise à jour La structure de mise à jour AIR complète le processus de mise à jour selon la procédure suivante : 1 L'initialisation du programme de mise à jour contrôle si une vérification de mise à jour a été effectuée au cours de l'intervalle défini (voir « Configuration des paramètres de la mise à jour » à la page 343). Si une vérification de mise à jour doit être effectuée, le processus se poursuit. 2 Le programme de mise à jour télécharge et interprète le fichier descripteur de mise à jour. 3 Le programme de mise à jour télécharge le fichier AIR de mise à jour. 4 Le programme de mise à jour installe la version mise à jour de l'application. L'objet updater distribue des événements à la fin de chacune de ces étapes. Dans la version ApplicationUpdater, vous pouvez annuler les événements qui indiquent le succès d'une étape du processus. Si vous annulez l'un de ces événements, l'étape suivante du processus est annulée. Dans la version ApplicationUpdaterUI, le programme de mise à jour affiche une boîte de dialogue qui permet à l'utilisateur d'annuler ou de continuer à chaque étape du processus. Si vous annulez l'événement, vous pouvez appeler les méthodes de l'objet updater pour reprendre le processus. Au fur et à mesure que la version ApplicationUpdater du programme de mise à jour poursuit le processus, l'état en cours est enregistré dans une propriété currentState. Cette propriété est définie sur une chaîne qui peut prendre les valeurs suivantes : • "UNINITIALIZED" : le programme de mise à jour n'a pas été initialisé. • "INITIALIZING" : le programme de mise à jour est en cours d'initialisation. • "READY" : le programme de mise à jour a été initialisé. • "BEFORE_CHECKING" : le programme de mise à jour n'a pas encore vérifié la présence du fichier descripteur de mise à jour. • "CHECKING" : le programme de mise à jour recherche un fichier descripteur de mise à jour. • "AVAILABLE" : le fichier descripteur de mise à jour est disponible. • "DOWNLOADING" : le programme de mise à jour télécharge le fichier AIR. • "DOWNLOADED" : le programme de mise à jour a téléchargé le fichier AIR. • "INSTALLING" : le programme de mise à jour installe le fichier AIR. • "PENDING_INSTALLING" : le programme de mise à jour a été initialisé et des mises à jour sont en attente. Certaines méthodes de l'objet updater ne s'exécutent que si le programme de mise à jour est dans un certain état. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 346 Mise à jour des applications AIR Initialisation de la structure de mise à jour Après la définition des propriétés de configuration (voir « Exemple de base : utilisation de la version ApplicationUpdaterUI » à la page 340), appelez la méthode initialize() pour initialiser la mise à jour : appUpdater.initialize(); Cette méthode effectue les opérations suivantes : • Elle initialise la structure de mise à jour, en installant silencieusement et de façon synchrone les mises à jour en attente. Il est obligatoire d'appeler cette méthode au démarrage de l'application car elle peut redémarrer l'application lorsqu'elle est appelée. • Elle vérifie la présence éventuelle d'une mise à jour reportée et l'installe. • Si une erreur se produit pendant le processus de mise à jour, elle efface le fichier de mise à jour et les informations de version dans l'emplacement de stockage de l'application. • Si le délai est arrivé à expiration, elle démarre le processus de mise à jour. Sinon, elle réinitialise le minuteur. L'appel à cette méthode peut entraîner la distribution des événements suivants par l'objet updater : • UpdateEvent.INITIALIZED : distribué lorsque l'initialisation est terminée. • ErrorEvent.ERROR : distribué lorsqu'une erreur se produit pendant l'initialisation. Lors de la distribution de l'événement UpdateEvent.INITIALIZED, le processus de mise à jour est terminé. Lorsque vous appelez la méthode initialize(), le programme de mise à jour démarre le processus et effectue toutes les étapes, en fonction du paramètre de délai du minuteur. Toutefois, vous pouvez également démarrer le processus de mise à jour à tout moment en appelant la méthode checkNow() de l'objet updater : appUpdater.checkNow(); Cette méthode n'a aucune incidence si le processus de mise à jour est déjà en cours d'exécution. Sinon, elle démarre le processus de mise à jour. L'objet updater peut distribuer l'événement suivant après un appel à la méthode checkNow() : • L'événement UpdateEvent.CHECK_FOR_UPDATE juste avant la tentative de téléchargement du fichier descripteur de mise à jour. Si vous annulez l'événement checkForUpdate, vous pouvez appeler la méthode checkForUpdate() de l'objet updater. (Voir la section suivante.) Si vous n'annulez pas l'événement, le processus de mise jour recherche le fichier descripteur de mise à jour. Gestion du processus de mise à jour dans la version ApplicationUpdaterUI Dans la version ApplicationUpdaterUI, l'utilisateur peut annuler le processus via les boutons Annuler des boîtes de dialogue de l'interface utilisateur. De même, vous pouvez annuler par programmation le processus de mise à jour en appelant la méthode cancelUpdate() de l'objet ApplicationUpdaterUI. Vous pouvez définir les propriétés de l'objet ApplicationUpdaterUI ou définir les éléments du fichier de configuration de mise à jour pour spécifier les confirmations de boîtes de dialogue devant être affichées par le programme de mise à jour. Pour plus d'informations, consultez la section « Configuration des paramètres de la mise à jour » à la page 343. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 347 Mise à jour des applications AIR Gestion du processus de mise à jour dans la version ApplicationUpdater Vous pouvez appeler la méthode preventDefault() des objets d'événements distribués par l'objet ApplicationUpdater pour annuler des étapes du processus de mise à jour (voir « Processus de mise à jour » à la page 345). L'annulation du comportement par défaut permet à votre application d'afficher un message à l'utilisateur pour lui demander s'il souhaite continuer. Les sections suivantes montrent comment poursuivre le processus de mise à jour lorsqu'une étape du processus a été annulée. Téléchargement et interprétation du fichier descripteur de mise à jour L'objet ApplicationUpdater distribue l'événement checkForUpdate avant le début du processus de mise à jour, juste avant que le programme de mise à jour ne tente de télécharger le fichier descripteur de mise à jour. Si vous annulez le comportement par défaut de l'événement checkForUpdate, le programme de mise à jour ne télécharge pas le fichier descripteur de mise à jour. Pour reprendre le processus de mise à jour, vous pouvez appeler la méthode checkForUpdate() : appUpdater.checkForUpdate(); L'appel à la méthode checkForUpdate() oblige le programme de mise à jour à effectuer un téléchargement asynchrone et à interpréter le fichier descripteur de mise à jour. À la suite d'un appel à la méthode checkForUpdate(), l'objet updater peut distribuer les événements suivants : • StatusUpdateEvent.UPDATE_STATUS : le programme de mise à jour à bien téléchargé et interprété le fichier descripteur de mise à jour. Les propriétés de cet événement sont les suivantes : • available : valeur booléenne. Définie sur true si une version différente de l'application en cours est disponible ; false dans le cas contraire (la version est la même). • version : chaîne. La version indiquée dans le fichier descripteur d'application du fichier de mise à jour. • details : tableau. S'il n'y a pas de versions localisées de la description, ce tableau renvoie une chaîne vide ("") en tant que premier élément et la description en tant que second élément. S'il existe plusieurs versions de la description (dans le fichier descripteur de mise à jour), le tableau contient plusieurs sous-tableaux. Chaque tableau comprend deux éléments : le premier étant le code de langue (par exemple "en"), et le second la description correspondante (une chaîne) dans cette langue. Voir « Définition du fichier descripteur de mise à jour et ajout du fichier AIR dans votre serveur Web » à la page 342. • StatusUpdateErrorEvent.UPDATE_ERROR : une erreur s'est produite et le programme de mise à jour n'a pas pu télécharger ou interpréter le fichier descripteur de mise à jour. Téléchargement du fichier AIR de mise à jour L'objet ApplicationUpdater distribue l'événement updateStatus dès que le programme de mise à jour à bien téléchargé et interprété le fichier descripteur de mise à jour. Le comportement par défaut consiste à démarrer le téléchargement du fichier de mise à jour lorsque ce dernier est disponible. Si vous annulez le comportement par défaut, vous pouvez reprendre le processus en appelant la méthode downloadUpdate() : appUpdater.downloadUpdate(); L'appel à cette méthode oblige le programme de mise à jour à effectuer un téléchargement asynchrone de la mise à jour du fichier AIR. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 348 Mise à jour des applications AIR La méthode downloadUpdate() peut distribuer les événements suivants : • UpdateEvent.DOWNLOAD_START : la connexion au serveur a été établie. Lorsque la bibliothèque ApplicationUpdaterUI est utilisée, cet événement affiche une boîte de dialogue dans laquelle une barre de progression permet de suivre l'avancée du téléchargement. • ProgressEvent.PROGRESS : distribué régulièrement au fur et à mesure de la progression du téléchargement du fichier. • DownloadErrorEvent.DOWNLOAD_ERROR : distribué lorsqu'une erreur se produit pendant la connexion ou le téléchargement du fichier de mise à jour. Cet événement est également distribué pour les états HTTP non valides (par exemple « 404 - Fichier introuvable »). Cet événement a une propriété errorID, un nombre entier qui définit d'autres informations d'erreur. Une autre propriété subErrorID peut contenir d'autres informations d'erreur. • UpdateEvent.DOWNLOAD_COMPLETE : le programme de mise à jour à bien téléchargé et interprété le fichier descripteur de mise à jour. Si vous n'annulez pas cet événement, la version ApplicationUpdater procède à l'installation de la mise à jour. Dans la version ApplicationUpdaterUI, une boîte de dialogue est présentée à l'utilisateur pour lui proposer de continuer. Mise à jour de l'application L'objet ApplicationUpdater déclenche l'événement downloadComplete lorsque le téléchargement du fichier de mise à jour est terminé. Si vous annulez le comportement par défaut, vous pouvez reprendre le processus en appelant la méthode installUpdate() : appUpdater.installUpdate(file); Un appel à cette méthode oblige le programme de mise à jour à installer la mise à jour du fichier AIR. La méthode comprend un paramètre, file, correspondant à un objet File qui fait référence au fichier AIR à utiliser en tant que mise à jour. L'objet ApplicationUpdater peut distribuer l'événement beforeInstall à la suite d'un appel à la méthode installUpdate() : • UpdateEvent.BEFORE_INSTALL : distribué juste avant l'installation de la mise à jour. Il est parfois utile d'empêcher l'installation de la mise à jour à ce stade de sorte que l'utilisateur puisse terminer son travail en cours avant de lancer l'installation. L'appel à la méthode preventDefault() de l'objet Event reporte l'installation jusqu'au prochain démarrage et empêche le lancement de tout processus de mise à jour supplémentaire. (Cela comprend les mises à jour résultant d'un appel à la méthode checkNow() ou liées à une vérification périodique.) Installation à partir d'un fichier AIR arbitraire Vous pouvez appeler la méthode installFromAIRFile() pour installer la mise à jour à partir d'un fichier AIR situé sur l'ordinateur de l'utilisateur : appUpdater.installFromAIRFile(); Cette méthode oblige le programme de mise à jour à installer la mise à jour de l'application à partir du fichier AIR. La méthode installFromAIRFile() peut distribuer les événements suivants : • StatusFileUpdateEvent.FILE_UPDATE_STATUS : distribué lorsque ApplicationUpdater a bien validé le fichier envoyé par la méthode installFromAIRFile(). Les propriétés de cet événement sont les suivantes : • available : définie sur true si une version différente de l'application actuelle est disponible ; false, dans le cas contraire (les versions sont identiques). • version : chaîne représentant la nouvelle version disponible. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 349 Mise à jour des applications AIR • path : représente le chemin natif du fichier de mise à jour. Vous pouvez annuler cet événement si la propriété available de l'objet StatusFileUpdateEvent est définie sur true. L'annulation de l'événement annule également le processus de mise à jour. Pour poursuivre le processus de mise à jour, appelez la méthode installUpdate(). • StatusFileUpdateErrorEvent.FILE_UPDATE_ERROR : une erreur s'est produite et le programme de mise à jour n'a pas pu installer l'application AIR. Annulation du processus de mise à jour Pour annuler le processus de mise à jour, vous pouvez appeler la méthode cancelUpdate() : appUpdater.cancelUpdate(); Cette méthode annule tous les téléchargements en attente, en supprimant tous les fichiers partiellement téléchargés, et réinitialise le minuteur de vérification périodique. Cette méthode n'a aucune incidence si le programme de mise à jour est initialisé. Localisation de l'interface ApplicationUpdaterUI La classe ApplicationUpdaterUI fournit une interface utilisateur par défaut pour le processus de mise à jour. Celle-ci comprend des boîtes de dialogue qui permettent à l'utilisateur de démarrer le processus, de l'annuler et d'effectuer d'autres actions associées. L'élément description du fichier descripteur de mise à jour vous permet de définir la description de l'application en plusieurs langues. Utilisez plusieurs éléments text définissant des attributs lang, comme dans l'exemple suivant : <?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> La structure de mise à jour utilise la description correspondant le mieux au chaînage de localisation de l'utilisateur final. Pour plus d'informations, consultez la section Définition du fichier descripteur de mise à jour et ajout du fichier AIR dans votre serveur Web. Les développeurs Flex peuvent ajouter directement une nouvelle langue dans le regroupement "ApplicationUpdaterDialogs". Les développeurs JavaScript peuvent appeler la méthode addResources() de l'objet updater. Cette méthode ajoute dynamiquement un nouveau regroupement de ressources pour une langue. Le regroupement de ressources définit les chaînes localisées d'une langue. Ces chaînes sont utilisées dans les champs de texte des différentes boîtes de dialogue. Les développeurs JavaScript peuvent utiliser la propriété localeChain de la classe ApplicationUpdaterUI pour définir la chaîne de paramètres régionaux utilisée par l'interface utilisateur. En général, seuls les développeurs JavaScript (HTML) utilisent cette propriété. Les développeurs Flex peuvent utiliser ResourceManager pour gérer la chaîne de paramètres régionaux. Par exemple, le code JavaScript suivant définit des regroupements de ressources pour le roumain et le hongrois : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 350 Mise à jour des applications 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; Pour plus d'informations, consultez la description de la méthode addResources() de la classe ApplicationUpdaterUI dans le guide de référence du langage. 351 Chapitre 34 : Localisation d'applications AIR Adobe® AIR™ 1.1 prend en charge plusieurs langues. Introduction à la localisation La localisation consiste à inclure des actifs prenant en charge plusieurs jeux de paramètres régionaux. Un jeu de paramètres régionaux correspond à une langue et un code de pays. Par exemple, en_US fait référence à l'anglais tel qu'il est parlé aux Etats-Unis et fr_FR, au français utilisé en France. Pour localiser une application en fonction de ces paramètres régionaux, vous proposeriez deux jeux d'actifs : un pour les paramètres en_US et l'autre pour les paramètres fr_FR. Les paramètres régionaux peuvent partager des langues. Ainsi, en_US et en_GB (Grande Bretagne) sont des jeux de paramètres régionaux différents. Dans ce cas, les deux jeux de paramètres régionaux correspondent à l'anglais mais le code de pays indiquent qu'ils sont différents et n'utilisent donc pas nécessairement les mêmes actifs. Par exemple, une application utilisant le jeu de paramètres régionaux en_US comprendra peut-être le mot « color » alors que ce mot sera épelé « colour » dans le jeu de paramètres régionaux en_GB. Par ailleurs, les devises correspondraient aux dollars ou aux livres Sterling, selon le jeu de paramètres régionaux, et les formats de date et d'heure seraient peut-être aussi différents. Vous pouvez également fournir un jeu d'actifs pour une langue sans spécifier de code de pays. Ainsi, vous pouvez fournir des actifs en pour l'anglais et des actifs supplémentaires pour les paramètres régionaux en_US, qui sont spécifiques à l'anglais américain. Le SDK d'AIR propose une structure de localisation HTML (qui figure dans un fichier AIRLocalizer.js). Cette structure comprend des API qui simplifient l'utilisation de plusieurs jeux de paramètres régionaux. Pour plus d'informations, consultez la section « Localisation de contenu HTML » à la page 353. La localisation ne consiste pas seulement à traduire les chaînes utilisées dans votre application. Elle peut également comprendre tout type d'actif, fichiers audio, des images, des vidéos, etc. Localisation du nom et de la description de l'application dans son programme d'installation Vous pouvez spécifier plusieurs langues pour les éléments name et description du fichier descripteur d'application. Par exemple, le code suivant définit le nom de l'application en trois langues (anglais, français et allemand) : <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> L'attribut xml:lang de chaque élément text définit un code de langue, comme indiqué dans la norme RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 352 Localisation d'applications AIR L'élément name définit le nom de l'application qu'affiche le programme d'installation de l'application AIR. Ce programme utilise la valeur localisée qui correspond le mieux aux langues d'interface utilisateur définies par les paramètres du système d'exploitation. De même, vous pouvez spécifier des versions en plusieurs langues de l'élément description dans le fichier descripteur d'application. Cet élément définit le texte descriptif qu'affiche le programme d'installation de l'application AIR. Ces paramètres s'appliquent uniquement aux langues disponibles dans le programme d'installation de l'application AIR. Ils ne définissent pas les jeux de paramètres régionaux disponibles pour l'application installée lorsqu'elle s'exécute. L'interface utilisateur des applications AIR peut prendre en charge plusieurs langues, y compris, entre autres, celles gérées par le programme d'installation de l'application AIR. Pour plus d'informations, consultez la section « Définition des propriétés dans le fichier descripteur d'application » à la page 47. Choix d'un jeu de paramètres régionaux Pour déterminer les jeux de paramètres régionaux qu'utilise votre application, vous pouvez procéder comme suit, au choix : • Invite utilisateur : vous pouvez démarrer l'application avec un jeu de paramètres régionaux par défaut et inviter l'utilisateur à choisir le jeu qu'il préfère. • Capabilities.languages : la propriété Capabilities.languages présente un tableau de langues disponibles dans les langues préférées de l'utilisateur, telles que définies par le biais du système d'exploitation. Les chaînes contiennent des balises de langue (ainsi que des informations de script et de région, le cas échéant) définies par la norme RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Elles utilisent des tirets comme délimiteurs (par exemple, "en-US" ou "ja-JP"). La première entrée du tableau renvoyé possède le même identifiant de langue principale que la propriété language. Par exemple, si languages[0] est défini sur "en-US", la propriété language est définie sur "en". Cependant, si la propriété language est définie sur "xu" (qui représente une langue inconnue), le premier élément du tableau languages est différent. • Capabilities.language : la propriété Capabilities.language indique le code de langue de l'interface utilisateur du système d'exploitation. Cette propriété est toutefois limitée à 20 langues connues. Sur les systèmes anglais, elle renvoie uniquement le code de langue et non le code du pays. C'est pourquoi il est préférable d'utiliser le premier élément du tableau Capabilities.languages. Localisation du contenu Flash Flash CS3 et Flash CS4 comprennent une classe Locale dans les composants ActionScript 3.0. La classe Locale vous permet de contrôler l'affichage de texte multilingue dans un fichier SWF. Le panneau Chaînes de Flash vous permet d'utiliser des ID de chaîne au lieu de littéraux de chaîne dans les champs de texte dynamique. Vous pouvez ainsi créer un fichier SWF affichant du texte chargé à partir d'un fichier XML spécifique à une langue. Pour plus d'information sur l'utilisation de la classe Locale, consultez le Guide de référence du langage et des composants ActionScript 3.0 de Flash. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 353 Localisation d'applications AIR Localisation de contenu HTML Le SDK d'AIR 1.1 comprend une structure de localisation HTML, que définit le fichier JavaScript AIRLocalizer.js. Ce fichier réside dans le répertoire frameworks du SDK d'AIR. Il contient une classe air.Localizer, qui propose des fonctionnalités facilitant la création d'applications prenant en charge plusieurs versions localisées. Chargement du code de la structure de localisation HTML d'AIR Pour utiliser la structure de localisation, copiez le fichier AIRLocalizer.js dans votre projet. Incluez-le ensuite dans le fichier HTML principal de l'application, à l'aide d'une balise script : <script src="AIRLocalizer.js" type="text/javascript" charset="utf-8"></script> Vous pouvez ensuite appeler l'objet air.Localizer.localizer par le biais de code JavaScript : <script> var localizer = air.Localizer.localizer; </script> L'objet air.Localizer.localizer est un objet singleton qui définit des méthodes et des propriétés relatives à l'utilisation et à la gestion des ressources localisées. La classe Localizer comprend les méthodes suivantes : Méthode Description getFile() Extrait le texte d'un regroupement de ressources spécifié pour un jeu de paramètres régionaux spécifique. Consultez la section « Extraction de ressources d'un jeu de paramètres régionaux spécifique » à la page 359. getLocaleChain() Renvoie les langues qui figurent dans le chaînage de jeux de paramètres régionaux. Consultez la section « Définition du chaînage de jeux de paramètres régionaux » à la page 358. getResourceBundle() Renvoie les clés du regroupement et les valeurs correspondantes sous forme d'objet. Consultez la section « Extraction de ressources d'un jeu de paramètres régionaux spécifique » à la page 359. getString() Extrait la chaîne définie pour une ressource. Consultez la section « Extraction de ressources d'un jeu de paramètres régionaux spécifique » à la page 359. setBundlesDirectory( ) Définit l'emplacement du répertoire de regroupements. Consultez la section « Personnalisation des paramètres de la structure de localisation HTML d'AIR » à la page 357. setLocalAttributePre fix() Définit le préfixe utilisé par les attributs de localisation utilisés dans des éléments DOM HTML. Consultez la section « Personnalisation des paramètres de la structure de localisation HTML d'AIR » à la page 357. setLocaleChain() Définit l'ordre des langues dans le chaînage de jeux de paramètres régionaux. Consultez la section « Définition du chaînage de jeux de paramètres régionaux » à la page 358. sortLanguagesByPrefe rence() Trie les jeux de paramètres régionaux du chaînage de jeux de paramètres régionaux en fonction des paramètres du système d'exploitation. Consultez la section « Définition du chaînage de jeux de paramètres régionaux » à la page 358. update() Met à jour le DOM HTML (ou un élément DOM) avec les chaînes localisées du chaînage de jeux de paramètres régionaux en cours. Pour plus d'informations sur les chaînages de jeux de paramètres régionaux, consultez la section « Gestion des chaînages de jeux de paramètres régionaux » à la page 355. Pour plus d'informations sur la méthode update(), consultez la section « Mise à jour d'éléments DOM afin qu'ils utilisent le jeu de paramètres régionaux en cours » à la page 356. La classe Localizer comprend les propriétés statiques suivantes : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 354 Localisation d'applications AIR Propriété Description localizer Renvoie une référence à l'objet singleton Localizer de l'application. ultimateFallbackLocale Jeu de paramètres régionaux utilisé lorsque l'application ne prend en charge aucune préférence utilisateur. Consultez la section « Définition du chaînage de jeux de paramètres régionaux » à la page 358. Définition de regroupements de ressources La structure de localisation HTML lit les versions localisées des chaînes dans des fichiers de localisation. Un fichier de localisation est un ensemble de valeurs basées sur des clés, sérialisées dans un fichier de texte. Ce type de fichier est parfois appelé un regroupement. Créez dans le répertoire de projet de votre application un sous-répertoire que vous nommerez locale. (Vous pouvez utiliser un autre nom ; consultez la section « Personnalisation des paramètres de la structure de localisation HTML d'AIR » à la page 357.) Ce répertoire contient les fichiers de localisation et est appelé le répertoire de regroupements. Créez un sous-répertoire dans le répertoire de regroupements pour chaque jeu de paramètres régionaux pris en charge par votre application. Attribuez à chaque sous-répertoire un nom correspondant au code du jeu de paramètres régionaux. Par exemple, nommez le répertoire français « fr » et le répertoire anglais « en ». Vous pouvez utiliser un trait de soulignement (_) pour définir un jeu de paramètres régionaux constitué d'une langue et d'un code de pays. Par exemple, nommez le répertoire anglais américain « en_us ». Vous pouvez éventuellement remplacer le trait de soulignement par un tiret (« en-us », par exemple). La structure de localisation HTML prend ces deux formats en charge. Libre à vous d'ajouter tout nombre de fichiers de ressources à un sous-répertoire de jeu de paramètres régionaux. En règle générale, vous créez un fichier de localisation par langue (et le placez dans le répertoire correspondant à celle-ci). La structure de localisation HTML comprend une méthode getFile() qui vous permet de lire le contenu d'un fichier (consultez la section « Extraction de ressources d'un jeu de paramètres régionaux spécifique » à la page 359). Les fichiers dotés de l'extension .properties constituent des fichiers de propriétés de localisation. Ils permettent de définir les paires clé-valeur d'un jeu de paramètres régionaux. Un fichier de propriétés définit une valeur chaîne sur chaque ligne. Ainsi, l'exemple suivant attribue la valeur chaîne « Hello in English. » à une clé nommée greeting : greeting=Hello in English. Un fichier de propriétés contenant le texte suivant définit six paires clé-valeur : title=Sample Application greeting=Hello in English. exitMessage=Thank you for using the application. color1=Red color2=Green color3=Blue Cet exemple illustre une version anglaise du fichier de propriétés, à stocker dans le répertoire en. Une version française de ce fichier de propriétés est placée dans le répertoire fr : title=Application Example greeting=Bonjour en français. exitMessage=Merci d'avoir utilisé cette application. color1=Rouge color2=Vert color3=Bleu DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 355 Localisation d'applications AIR Vous pouvez définir plusieurs fichiers de ressources pour différents types d'information. Imaginons un fichier nommé legal.properties, qui contient un modèle de texte juridique (tel un avis de copyright). Vous souhaiterez peut-être le réutiliser dans plusieurs applications. De même, vous pourriez créer plusieurs fichiers définissant du contenu localisé pour différentes parties de l'interface utilisateur. Utilisez le codage UTF-8 pour ces fichiers afin de prendre en charge plusieurs langues. Gestion des chaînages de jeux de paramètres régionaux Lorsque votre application charge le fichier AIRLocalizer.js, il examine les jeux de paramètres régionaux définis dans celle-ci. Ces jeux correspondent aux sous-répertoires du répertoire de regroupements (consultez la section « Définition de regroupements de ressources » à la page 354). La liste des jeux de paramètres régionaux disponibles est appelée chaînage de jeux de paramètres régionaux. Le fichier AIRLocalizer.js trie automatiquement le chaînage de jeux de paramètres régionaux en fonction de l'ordre de préférence défini par les paramètres du système d'exploitation. (La propriété Capabilities.languages trie les langues d'interface utilisateur du système d'exploitation dans l'ordre de préférence.) Par conséquent, si une application définit des ressources pour "en", "en_US" et "en_UK", la structure de localisation HTML d'AIR trie le chaînage de jeux de paramètres régionaux de manière appropriée. Lorsqu'une application démarre sur un système qui indique que le jeu de paramètres régionaux principal correspond à "en", le chaînage est trié de la façon suivante : ["en", "en_US", "en_UK"]. Dans ce cas, l'application recherche des ressources dans le regroupement « en » en premier, puis dans le regroupement "en_US". Cependant, si le système indique que le jeu de paramètres régionaux principal correspond à "en_US", le tri devient ["en_US", "en", en_UK"]. Dans ce cas, l'application recherche des ressources dans le regroupement "en_US" en premier, puis dans le regroupement "en". Par défaut, l'application définit le premier jeu de paramètres régionaux du chaînage en tant que jeu à utiliser par défaut. Vous pouvez inviter l'utilisateur à sélectionner un jeu de paramètres régionaux lors de la première exécution de l'application. Vous pouvez ensuite choisir de stocker la sélection dans un fichier de préférences et utiliser ce jeu de paramètres régionaux lors de démarrages suivants. Votre application peut utiliser des chaînes de ressource de tout jeu de paramètres régionaux du chaînage. Si un jeu de paramètres régionaux spécifique ne définit pas une chaîne de ressource, l'application utilise la chaîne de ressource correspondante suivante d'autres jeux de paramètres régionaux du chaînage. Vous pouvez personnaliser le chaînage de jeux de paramètres régionaux en appelant la méthode setLocaleChain() de l'objet Localizer. Consultez la section « Définition du chaînage de jeux de paramètres régionaux » à la page 358 Mise à jour d'éléments DOM avec du contenu localisé Un élément de l'application peut référencer une valeur de clé dans un fichier de propriétés de localisation. Ainsi, l'élément title de l'exemple ci-dessous spécifie un attribut local_innerHTML. La structure de localisation utilise cet attribut pour rechercher une valeur localisée. Par défaut, la structure recherche des attributs dont le nom commence par « local_ ». Elle met à jour les attributs portant un nom correspondant au texte suivant « local_ ». Dans ce cas, elle définit l'attribut innerHTML de l'élément title. L'attribut innerHTML utilise la valeur définie pour la clé mainWindowTitle dans le fichier de propriétés par défaut (default.properties) : <title local_innerHTML="default.mainWindowTitle"/> Si le jeu de paramètres régionaux en cours ne définit pas de valeur correspondante, la structure de localisation examine le reste du chaînage de jeux. Elle utilise le jeu suivant du chaînage pour lequel une valeur est définie. Dans l'exemple suivant, le texte (attribut innerHTML) de l'élément p utilise la valeur de la clé greeting définie dans le fichier de propriétés par défaut : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 356 Localisation d'applications AIR <p local_innerHTML="default.greeting" /> Dans l'exemple suivant, l'attribut value (et le texte affiché) de l'élément input utilise la valeur de la clé btnBlue définie dans le fichier de propriétés par défaut : <input type="button" local_value="default.btnBlue" /> Pour mettre à jour le DOM HTML afin qu'il utilise les chaînes définies dans le chaînage de jeu de paramètres régionaux en cours, appelez la méthode update() de l'objet Localizer. L'appel de la méthode update() force l'objet Localizer à analyser le DOM et à appliquer des manipulations lorsqu'il détecte des attributs de localisation (« local_... ») : air.Localizer.localizer.update(); Vous pouvez définir des valeurs pour un attribut (tel que « innerHTML ») et pour l'attribut de localisation correspondant (tel que « local_innerHTML »). Dans ce cas, la structure de localisation ne remplace la valeur de l'attribut que si elle détecte une valeur correspondante dans le chaînage de localisation. Par exemple, l'élément suivant définit les attributs value et local_value : <input type="text" value="Blue" local_value="default.btnBlue"/> Vous pouvez aussi vous contenter de mettre à jour un élément DOM spécifique. Pour plus d'informations, consultez la section suivante, « Mise à jour d'éléments DOM afin qu'ils utilisent le jeu de paramètres régionaux en cours » à la page 356 Par défaut, la structure de localisation HTML d'AIR applique le préfixe « local_ » aux attributs définissant des paramètres de localisation pour un élément. Ainsi, un attribut local_innerHTML définit par défaut le regroupement et le nom de ressource utilisés pour la valeur innerHTML d'un élément. De même, un attribut local_value définit par défaut le regroupement et le nom de ressource utilisés pour l'attribut value d'un élément. Vous pouvez configurer la structure de localisation de sorte à utiliser un préfixe autre que « local_ ». Consultez la section « Personnalisation des paramètres de la structure de localisation HTML d'AIR » à la page 357. Mise à jour d'éléments DOM afin qu'ils utilisent le jeu de paramètres régionaux en cours Lorsque l'objet Localizer met à jour le DOM HTML, les éléments marqués doivent utiliser des valeurs d'attribut basées sur des chaînes définies dans le chaînage de jeux de paramètres régionaux en cours. Pour que la structure de localisation HTML mette à jour le DOM HTML, appelez la méthode update() de l'objet Localizer : air.Localizer.localizer.update(); Pour mettre à jour un élément DOM spécifique seulement, transmettez-le en tant que paramètre à la méthode update(). La méthode update() possède un seul paramètre, parentNode, qui est facultatif. Lorsqu'il est spécifié, le paramètre parentNode définit l'élément DOM à localiser. L'appel de la méthode update() en incluant le paramètre parentNode définit des valeurs localisées pour tous les éléments enfant qui spécifient des attributs de localisation. Soit, par exemple, l'élément div ci-dessous : <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> Pour mettre cet élément à jour afin qu'il utilise les chaînes localisées définies dans le chaînage de jeu de paramètres régionaux en cours, utilisez le code JavaScript suivant : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 357 Localisation d'applications AIR var divElement = window.document.getElementById("colorsDiv"); air.Localizer.localizer.update(divElement); Si le chaînage de jeux de paramètres régionaux ne contient pas de valeur de clé, la structure de localisation définit la valeur de l'attribut sur la valeur de l'attribut « local_ ». Ainsi, imaginons que dans l'exemple précédent, la structure de localisation n'a pas trouvé de valeur pour la clé lblColors (dans aucun des fichiers default.properties du chaînage de jeux de paramètres régionaux). Dans ce cas, elle attribue la valeur "default.lblColors" à l'attribut innerHTML. L'utilisation de cette valeur indique une absence de ressources (au développeur). La méthode update() distribue un événement resourceNotFound lorsqu'une ressource est introuvable dans le chaînage de jeux de paramètres régionaux. La constante air.Localizer.RESOURCE_NOT_FOUND définit la chaîne "resourceNotFound". L'événement possède trois propriétés : bundleName, resourceName et locale. La propriété bundleName représente le nom du regroupement dans lequel la ressource est introuvable. La propriété resourceName représente le nom de la ressource introuvable. La propriété locale représente le nom du jeu de paramètres régionaux dans lequel la ressource est introuvable. La méthode update() distribue un événement bundleNotFound lorsque le regroupement spécifié est introuvable. La constante air.Localizer.BUNDLE_NOT_FOUND définit la chaîne "bundleNotFound". L'événement possède deux propriétés : bundleName et locale. La propriété bundleName représente le nom du regroupement introuvable. La propriété locale représente le nom du jeu de paramètres régionaux dans lequel la ressource est introuvable. La propriété update() s'exécute en mode asynchrone (et distribue des événements resourceNotFound et bundleNotFound de manière asynchrone). Le code suivant définit des écouteurs pour les événements resourceNotFound et 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); } Personnalisation des paramètres de la structure de localisation HTML d'AIR La méthode setBundlesDirectory() de l'objet Localizer vous permet de personnaliser le chemin d'accès au répertoire de regroupements. La méthode setLocalAttributePrefix() de l'objet Localizer vous permet de personnaliser le chemin d'accès au répertoire de regroupements et la valeur d'attribut utilisée par l'objet. Le répertoire de regroupements par défaut correspond au sous-répertoire de jeux de paramètres régionaux du répertoire d'application. Vous pouvez spécifier un autre répertoire en appelant la méthode setBundlesDirectory() de l'objet Localizer. Cette méthode gère un paramètre unique, path, qui représente sous forme de chaîne le chemin d'accès au répertoire de regroupements souhaité. Le paramètre path prend en charge les valeurs suivantes : • Une chaîne définissant un chemin relatif au répertoire d'application, telle que "locales" • Une chaîne définissant une URL valide utilisant le modèle d'URL app, app-storage ou file, telle que "app://languages" (n'utilisez pas le modèle d'URL http) • Un objet File Pour plus d'informations sur les URL et les chemins de répertoire, consultez la section « Chemin des objets File » à la page 110. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 358 Localisation d'applications AIR Par exemple, le code suivant définit le répertoire de regroupements sur le sous-répertoire languages du répertoire de stockage de l'application (répertoire d'application) : air.Localizer.localizer.setBundlesDirectory("languages"); Définissez le paramètre path sur un chemin valide. Sinon, la méthode renvoie une exception BundlePathNotFoundError. « BundlePathNotFoundError » correspond à la propriété name de cette erreur, dont la propriété message spécifie le chemin non valide. Par défaut, la structure de localisation HTML d'AIR applique le préfixe « local_ » aux attributs définissant des paramètres de localisation pour un élément. Par exemple, l'attribut local_innerHTML définit le regroupement et le nom de ressource utilisés pour la valeur innerHTML de l'élément input suivant : <p local_innerHTML="default.greeting" /> La méthode setLocalAttributePrefix() de l'objet Localizer vous permet d'utiliser un préfixe d'attribut autre que « local_ ». Cette méthode statique gère un paramètre unique, qui correspond à la chaîne à utiliser comme préfixe d'attribut. Par exemple, le code suivant force la structure de localisation à utiliser « loc_ » comme préfixe d'attribut : air.Localizer.localizer.setLocalAttributePrefix("loc_"); Vous pouvez personnaliser le préfixe d'attribut utilisé par la structure de localisation. Vous souhaiterez peut-être personnaliser le préfixe si la valeur par défaut (« local_ ») est en conflit avec le nom d'un autre attribut utilisé par votre code. Lorsque vous appelez cette méthode, veillez à utiliser des caractères valides pour les attributs HTML. (La valeur ne doit pas contenir d'espaces, par exemple.) Pour plus d'informations sur l'utilisation d'attributs de localisation dans des éléments HTML, consultez la section « Mise à jour d'éléments DOM avec du contenu localisé » à la page 355. Les paramètres relatifs au répertoire de regroupements et au préfixe d'attribut ne sont pas persistants d'une session d'application à une autre. Si vous utilisez des paramètres personnalisés, veillez donc à les définir à chaque initiation de l'application. Définition du chaînage de jeux de paramètres régionaux Lorsque vous chargez le code AIRLocalizer.js, il définit automatiquement le chaînage de jeux de paramètres régionaux par défaut. Les jeux de paramètres régionaux disponibles dans le répertoire de regroupements et les paramètres de langue du système d'exploitation définissent ce chaînage (consultez la section « Gestion des chaînages de jeux de paramètres régionaux » à la page 355). Vous pouvez modifier le chaînage de jeux de paramètres régionaux en appelant la méthode statique setLocaleChain() de l'objet Localizer. Ainsi, vous souhaiterez peut-être appeler cette méthode si l'utilisateur indique qu'il préfère utiliser une langue spécifique. La méthode setLocaleChain() gère un paramètre unique, chain, qui correspond à un tableau de jeux de paramètres régionaux, tel que ["fr_FR","fr","fr_CA"]. L'ordre des jeux dans le tableau détermine l'ordre dans lequel la structure recherche ultérieurement des ressources. Si une ressource est absente du premier jeu du chaînage, la structure continue la recherche dans les autres jeux. Si l'argument chain est absent, n'est pas un tableau ou est un tableau vide, la fonction échoue et renvoie une exception IllegalArgumentsError. La méthode statique getLocaleChain() de l'objet Localizer renvoie un tableau répertoriant les jeux de paramètres régionaux du chaînage en cours. Le code suivant lit le chaînage en cours et ajoute deux jeux de paramètres régionaux français au début : var currentChain = air.Localizer.localizer.getLocaleChain(); newLocales = ["fr_FR", "fr"]; air.Localizer.localizer.setLocaleChain(newLocales.concat(currentChain)); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 359 Localisation d'applications AIR La méthode setLocaleChain() distribue un événement « change » lorsqu'elle met à jour le chaînage de jeux de paramètres régionaux. La constante air.Localizer.LOCALE_CHANGE définit la chaîne « change ». L'événement possède une propriété unique, localeChain, un tableau des codes de jeux de paramètres régionaux que comprend le nouveau chaînage. Le code suivant définit un écouteur pour cet événement : 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 propriété statique air.Localizer.ultimateFallbackLocale représente le jeu de paramètres régionaux utilisé lorsque l'application ne prend pas en charge de préférences utilisateur. La valeur par défaut est "en". Vous pouvez définir un autre jeu de paramètres régionaux, comme illustré ci-dessous : air.Localizer.ultimateFallbackLocale = "fr"; Extraction de ressources d'un jeu de paramètres régionaux spécifique La méthode getString() de l'objet Localizer renvoie la chaîne définie pour une ressource dans un jeu de paramètres régionaux spécifique. Lors de l'appel de la méthode, il est inutile de spécifier une valeur locale. Dans ce cas, la méthode examine la totalité du chaînage de jeux de paramètres régionaux et renvoie la chaîne du premier jeu contenant le nom de ressource concerné. Cette méthode prend en charge les paramètres suivants : Paramètre Description bundleName Regroupement contenant la ressource. Il s'agit du nom du fichier de propriétés sans l'extension .properties. Par exemple, si ce paramètre est défini sur "alerts", le code Localizer examine les fichiers de localisation appelés alerts.properties. resourceName Nom de la ressource. templateArgs Facultatif. Tableau de chaînes servant à remplacer les balises numérotées dans la chaîne de remplacement. Par exemple, soit un appel à la fonction dans lequel le paramètre templateArgs est défini sur ["Raúl", "4"] et la chaîne de ressource correspondante est "Hello, {0}. You have {1} new messages.". Dans ce cas, la fonction renvoie "Hello, Raúl. You have 4 new messages.". Pour ne pas tenir compte de ce paramètre, transmettez la valeur null. locale Facultatif. Code du jeu de paramètres régionaux (tel que "en", "en_us" ou "fr") à utiliser. Si un jeu de paramètres régionaux est indiqué et qu'aucune valeur correspondante n'est trouvée, la méthode ne recherche pas de valeurs dans les autres jeux du chaînage. Si aucun code de jeu de paramètres régionaux n'est spécifié, la fonction renvoie la chaîne du premier jeu du chaînage qui contient une valeur pour le nom de ressource donné. La structure de localisation peut mettre à jour des attributs DOM HTML marqués. Vous pouvez cependant utiliser les chaînes localisées autrement. Ainsi, vous pouvez utiliser une chaîne dans du contenu HTML généré dynamiquement ou en tant que valeur de paramètre dans un appel de fonction. Par exemple, le code suivant appelle la fonction alert() avec la chaîne définie dans la ressource error114 du fichier de propriété par défaut du jeu de paramètres régionaux fr_FR : alert(air.Localizer.localizer.getString("default", "error114", null, "fr_FR")); DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 360 Localisation d'applications AIR La méthode getString() distribue un événement resourceNotFound si la ressource est introuvable dans le regroupement spécifié. La constante air.Localizer.RESOURCE_NOT_FOUND définit la chaîne "resourceNotFound". L'événement possède trois propriétés : bundleName, resourceName et locale. La propriété bundleName représente le nom du regroupement dans lequel la ressource est introuvable. La propriété resourceName représente le nom de la ressource introuvable. La propriété locale représente le nom du jeu de paramètres régionaux dans lequel la ressource est introuvable. La méthode getString() distribue un événement bundleNotFound lorsque le regroupement spécifié est introuvable. La constante air.Localizer.BUNDLE_NOT_FOUND définit la chaîne "bundleNotFound". L'événement possède deux propriétés : bundleName et locale. La propriété bundleName représente le nom du regroupement introuvable. La propriété locale représente le nom du jeu de paramètres régionaux dans lequel la ressource est introuvable. La méthode getString() s'exécute en mode asynchrone (et distribue les événements resourceNotFound et resourceNotFound de manière asynchrone). Le code suivant définit des écouteurs pour les événements resourceNotFound et 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); } La méthode getResourceBundle() de l'objet Localizer renvoie le regroupement spécifié pour un jeu de paramètres régionaux donné. La valeur renvoyée de la méthode est un objet dont les propriétés correspondent aux clés du regroupement. (Si l'application ne trouve pas le regroupement spécifié, la méthode renvoie null.) La méthode reconnaît deux paramètres : locale et bundleName. Paramètre Description locale Jeu de paramètres régionaux (par exemple « fr »). bundleName Nom du regroupement. Par exemple, le code suivant appelle la méthode document.write() pour charger le regroupement par défaut pour le jeu de paramètres régionaux fr. Il appelle ensuite la méthode document.write() pour écrire les valeurs des clés str1 et str2 dans ce regroupement : 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/>"); La méthode getResourceBundle() distribue un événement bundleNotFound lorsque le regroupement spécifié est introuvable. La constante air.Localizer.BUNDLE_NOT_FOUND définit la chaîne "bundleNotFound". L'événement possède deux propriétés : bundleName et locale. La propriété bundleName représente le nom du regroupement introuvable. La propriété locale représente le nom du jeu de paramètres régionaux dans lequel la ressource est introuvable. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 361 Localisation d'applications AIR La méthode getFile() de l'objet Localizer renvoie le contenu d'un regroupement, sous forme de chaîne, pour un jeu de paramètres régionaux donné. Le fichier de regroupement est lu au format UTF-8. La méthode prend en charge les paramètres suivants : Paramètre Description resourceFileName Nom du fichier de ressource ("about.html", par exemple). templateArgs Facultatif. Tableau de chaînes servant à remplacer les balises numérotées dans la chaîne de remplacement. Par exemple, soit un appel à la fonction dans lequel le paramètre templateArgs est défini sur ["Raúl", "4"] et le fichier de ressource correspondant contient deux lignes : <html> <body>Hello, {0}. You have {1} new messages.</body> </html> Dans ce cas, la fonction renvoie une chaîne de deux lignes : <html> <body>Hello, Raúl. You have 4 new messages. </body> </html> locale Code de jeu de paramètres régionaux à utiliser, tel que "en_GB". Si un jeu de paramètres régionaux est indiqué et qu'aucun fichier correspondant n'est trouvé, la méthode n'examine pas les autres jeux du chaînage. Si aucun code de jeu de paramètres régionaux n'est spécifié, la fonction renvoie le texte du premier jeu du chaînage comportant un fichier qui correspond à resourceFileName. Par exemple, le code suivant appelle la méthode document.write() à l'aide du contenu du fichier about.html du jeu de paramètres régionaux fr : var aboutWin = window.open(); var aboutHtml = localizer.getFile("about.html", null, "fr"); aboutWin.document.close(); aboutWin.document.write(aboutHtml); La méthode getFile() distribue un événement fileNotFound lorsqu'une ressource est introuvable dans le chaînage de jeux de paramètres régionaux. La constante air.Localizer.FILE_NOT_FOUND définit la chaîne "fileNotFound". La méthode getFile() s'exécute en mode asynchrone (et distribue l'événement fileNotFound de manière asynchrone). L'événement possède deux propriétés : fileName et locale. La propriété fileName représente le nom du fichier introuvable. La propriété locale représente le nom du jeu de paramètres régionaux dans lequel la ressource est introuvable. Le code suivant définit un écouteur pour cet événement : 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); } Localisation des dates, heures et devises L'affichage des dates, heures et devises dans les applications varie grandement en fonction du jeu de paramètres régionaux. Aux Etats-Unis, par exemple, la date est représentée sous la forme mois/jour/année alors qu'en Europe, la norme consiste à utiliser jour/mois/année. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 362 Localisation d'applications AIR Vous pouvez écrire du code pour formater les dates, heures et devises. Par exemple, le code suivant convertit un objet Date du format mois/jour/année au format jour/mois/année. Si la variable locale (qui représente le jeu de paramètres régionaux) est définie sur "en_US", la fonction renvoie le format mois/jour/année. L'exemple convertit un objet Date au format jour/mois/année pour tous les autres jeux de paramètres régionaux : function convertDate(date) { if (locale == "en_US") { return (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear(); } else { return date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear(); } } 363 Chapitre 35 : Création d'une application AIR à l'aide des outils de ligne de commande Les outils de ligne de commande d'Adobe® AIR™ vous permettent de tester et de mettre en package les applications Adobe AIR. Ces outils s'utilisent également dans les processus de développement automatisés. Les outils de ligne de commande d'AIR sont fournis dans le kit SDK d'AIR (http://www.adobe.com/go/learn_air_download_AIRSDK_fr). Utilisation de l'application de débogage du lanceur AIR (ADL) L'application de débogage du lanceur AIR (ADL) permet d'exécuter à la fois des applications SWF et HTML lors de la phase de développement. Grâce à ADL, vous pouvez exécuter une application sans la mettre en package et l'installer au préalable. Par défaut, ADL utilise un moteur d'exécution fourni avec le kit SDK. Autrement dit, il est inutile d'installer le moteur d'exécution séparément pour se servir d'ADL. ADL imprime les instructions trace et les erreurs d'exécution au format de sortie standard, mais ne prend pas en charge les points d'arrêt ou d'autres fonctions de débogage. Si vous développez une application SWF, utilisez Flash Debugger (ou Flash CS) pour résoudre les problèmes de débogage complexes. Pour vous connecter à Flash Debugger, lancez le programme de débogage avant d'exécuter votre application avec ADL. Lancement d'une application à l'aide d'ADL Utilisez la syntaxe suivante : adl [-runtime runtime-directory] [-pubid publisher-id] [-nodebug] application.xml [rootdirectory] [-- arguments] -runtime runtime-directory Indique le répertoire contenant le moteur d'exécution à utiliser. Si vous ne le précisez pas, le répertoire du moteur d'exécution situé dans le même kit SDK que le programme ADL est utilisé. Si vous déplacez ADL hors de son dossier SDK, vous devez spécifier le répertoire du moteur d'exécution. Sous Windows et Linux, indiquez le répertoire contenant le dossier Adobe AIR. Sous Mac OS X, spécifiez le répertoire contenant Adobe AIR.framework. -pubid publisher-id Affecte la valeur indiquée comme ID d'éditeur de l'application AIR pour cette exécution. L'utilisation d'un ID d'éditeur temporaire vous permet de tester les fonctions d'une application AIR (telles que la communication via une connexion locale) nécessitant ce type d'identifiant afin d'identifier une application de manière unique. L'ID d'éditeur final est déterminé par le certificat numérique servant à signer le fichier d'installation AIR. -nodebug Désactive la prise en charge du débogage. Si cette option est utilisée, le processus de l'application ne peut pas se connecter au programme Flash Debugger et les boîtes de dialogue relatives aux exceptions non gérées sont masquées. (Toutefois, les instructions trace sont toujours imprimées dans la fenêtre de la console.) La désactivation de la fonction de débogage permet d'accélérer l'exécution de votre application et d'émuler plus étroitement le mode d'exécution d'une application installée. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 364 Création d'une application AIR à l'aide des outils de ligne de commande application.xml Fichier descripteur d'application. Consultez la section « Définition des propriétés d'une application AIR » à la page 46. root-directory Indique le répertoire racine de l'application à exécuter. S'il n'est pas spécifié, c'est le répertoire contenant le fichier descripteur d'application qui est utilisé. -- arguments Toutes les chaînes de caractères figurant après « -- » sont transmises à l'application sous forme d'arguments de ligne de commande. Remarque : lorsque vous lancez une application AIR déjà en cours d'exécution, aucune nouvelle occurrence de l'application n'est ouverte. Au lieu de cela, un événement invoke est distribué à l'occurrence en cours d'exécution. Impression d'instructions trace Pour imprimer des instructions trace sur la console utilisée pour exécuter ADL, ajoutez des instructions trace au code à l'aide de la fonction trace() : trace("debug message"); air.trace("debug message"); Exemples ADL Exécutez une application dans le répertoire actif : adl myApp-app.xml Exécutez une application dans un sous-répertoire du répertoire actif : adl source/myApp-app.xml release Exécutez une application et transmettez deux arguments de ligne de commande, tick et tock : adl myApp-app.xml -- tick tock Exécutez une application à l'aide d'un moteur d'exécution spécifique : adl -runtime /AIRSDK/runtime myApp-app.xml Exécutez une application sans prise en charge du débogage : adl myApp-app.xml -nodebug Connexion au programme Flash Debugger (FDB) Pour déboguer une application AIR SWF à l'aide de Flash Debugger, ouvrez une session FDB, puis lancez une version de débogage de l'application. Une application AIR qui contient une version de débogage d'un fichier SWF se connecte automatiquement à une session FDB qui écoute. Remarque : dans la version de débogage d'une application AIR, le fichier SWF est compilé avec l'indicateur -debug. 1 Lancez le programme FDB. Le programme FDB est disponible dans le répertoire bin du kit SDK Flex. La console affiche l'invite de FDB : <fdb> 2 Exécutez la commande run : <fdb>run [Entrée]. 3 Dans une console de shell ou de commande différente, lancez une version de débogage de l'application : adl myApp.xml 4 A l'aide des commandes de FDB, définissez les points d'arrêt souhaités. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 365 Création d'une application AIR à l'aide des outils de ligne de commande 5 Saisissez : continue [Entrée] Si l'application AIR est de type SWF, le débogueur ne contrôle que l'exécution du code ActionScript. Si l'application AIR est de type HTML, le débogueur ne contrôle que l'exécution du code JavaScript. Pour exécuter ADL sans vous connecter au débogueur, ajoutez l'option -nodebug : adl myApp.xml -nodebug Pour obtenir des informations de base sur les commandes FDB, exécutez la commande help : <fdb>help [Enter] Pour plus d'informations sur les commandes FDB, consultez la section Utilisation des commandes du débogueur de ligne de commande dans la documentation Flex. Codes d'erreur et de sortie d'ADL Le tableau suivant décrit les codes de sortie imprimés par ADL : Code de sortie Description 0 Lancement réussi. ADL se ferme après la fermeture de l'application AIR. 1 Appel réussi d'une application AIR déjà exécutée. Fermeture immédiate d'ADL. 2 Erreur d'utilisation. Les arguments transmis à ADL sont incorrects. 3 Moteur d'exécution introuvable. 4 Impossible de démarrer le moteur d'exécution. En général, cela se produit lorsque la version ou le niveau du correctif spécifiés dans l'application ne correspondent pas à ceux du moteur d'exécution. 5 Une erreur d'origine inconnue s'est produite. 6 Fichier descripteur d'application introuvable. 7 Le contenu du descripteur de l'application est incorrect. Cette erreur indique généralement que le fichier XML n'est pas bien constitué. 8 Le fichier de contenu principal de l'application (spécifié dans l'élément <content> du fichier descripteur d'application) est introuvable. 9 Le fichier du contenu principal de l'application n'est pas un fichier SWF ou HTML valide. Création d'un package de fichier d'installation AIR à l'aide de l'outil ADT L'outil AIR Developer Tool (ADT) vous permet de créer un fichier d'installation AIR à la fois pour les applications AIR SWF et HTML. (Si vous utilisez Adobe Flash CS3 pour développer une application, vous pouvez également vous servir de la commande Créer un fichier AIR du menu Commandes afin de créer un package AIR. Pour plus d'informations, consultez la section « Mise à jour Adobe AIR pour Flash CS3 Professional » à la page 13. Pour plus d'informations sur la création d'applications AIR avec Flash CS4, consultez la section Publication dans Adobe AIR de Utilisation de Flash). ADT est un programme Java que vous pouvez exécuter à partir de la ligne de commande ou à l'aide d'un outil de développement tel qu'Ant. Les kits SDK d'AIR et de Flex comprennent des scripts de ligne de commande chargés d'exécuter le programme Java à votre place. DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 366 Création d'une application AIR à l'aide des outils de ligne de commande Création d'un package de fichier d'installation AIR Chaque application AIR doit disposer d'au moins un fichier descripteur d'application et d'un fichier SWF ou HTML principal. Toutes les autres ressources d'application installées doivent également être incluses dans le package de fichier AIR. Tous les fichiers du programme d'installation AIR doivent être signés à l'aide d'un certificat numérique. Le programme d'installation AIR fait appel à la signature pour vérifier que le fichier de l'application n'a pas été modifié depuis que vous y avez apposé votre signature. Vous pouvez utiliser un certificat de signature de code provenant d'une autorité de certification ou un certificat auto-signé. Un certificat émis par une autorité de certification approuvée offre aux utilisateurs de l'application une certaine garantie de votre identité en tant qu'éditeur. Un certificat auto-signé ne permet pas de vérifier votre identité en tant que signataire. Cet inconvénient ne garantit pas non plus totalement que le package n'a pas subi de modifications, car il est tout à fait possible qu'un fichier d'installation légitime soit remplacé par un faux avant d'atteindre l'utilisateur). Vous pouvez créer et signer un package de fichier AIR au cours de la même opération grâce à la commande -package d'ADT. Vous avez également la possibilité de créer un package non signé intermédiaire à l'aide de la commande prepare. Vous pouvez ensuite signer ce package intermédiaire au cours d'une étape distincte en utilisant la commande -sign. Lors de la signature du package d'installation, l'outil ADT contacte automatiquement un serveur d'autorité d'horodatage chargé de vérifier l'heure. Les informations d'horodatage sont incluses dans le fichier AIR. Un fichier AIR comprenant un horodatage vérifié peut être installé à tout moment par la suite. Si l'outil ADT ne parvient pas à se connecter au serveur d'horodatage, la création du package est annulée. Vous pouvez ignorer l'option d'horodatage, mais sans horodatage, il devient impossible d'installer une application AIR une fois que le certificat utilisé pour signer le fichier d'installation est arrivé à expiration. Si vous créez un package permettant de mettre à jour une application AIR existante, vous devez le signer au moyen du même certificat que l'application d'origine ou d'un certificat doté de la même identité. Pour que deux certificats disposent de la même identité, ils doivent posséder le même nom unique (tous les champs d'informations doivent concorder) et la même chaîne de certificat associée au certificat racine. Par conséquent, vous pouvez utiliser un certificat renouvelé émis par une autorité de certification du moment que vous ne modifiez pas les informations d'identification qu'il contient. Depuis la version 1.1 d'AIR, vous avez la possibilité de migrer une application afin qu'elle utilise un nouveau certificat. Pour ce faire, saisissez la commande -migrate. La migration d'un certificat nécessite la signature du fichier AIR au moyen des deux certificats (l'ancien et le nouveau). Cette opération vous permet de passer d'un certificat auto-signé à un certificat de signature de code commercial ou d'un certificat auto-signé ou commercial à un autre. Si vous migrez un certificat, les utilisateurs existants de votre application n'ont pas besoin de désinstaller leur application avant d'installer la nouvelle version. Les signatures de migration sont horodatées par défaut. Remarque : les paramètres du fichier descripteur d'application déterminent l'identité d'une application AIR et son chemin d'installation par défaut. Consultez la section « Structure du fichier descripteur d'application » à la page 46. Pour créer et signer un package de fichier AIR en une seule étape ❖ Utilisez la commande -package en respectant la syntaxe suivante (sur une seule ligne de commande) : adt -package SIGNING_OPTIONS air_file app_xml [file_or_dir | -C dir file_or_dir | -e file dir ...] ... SIGNING_OPTIONS Les options de signature permettent d'identifier le keystore (magasin de clés) contenant la clé privée et le certificat utilisés pour signer le fichier AIR. Pour signer une application AIR à l'aide d'un certificat auto-signé généré par l'outil ADT, les options à utiliser sont les suivantes : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 367 Création d'une application AIR à l'aide des outils de ligne de commande -storetype pkcs12 -keystore certificate.p12 Dans cet exemple, certificate.p12 désigne le fichier keystore. (ADT vous invite à saisir votre mot de passe, car celuici ne s'affiche pas automatiquement sur la ligne de commande.) Les options de signature sont décrites en détail à la section « Options de signature disponibles sur la ligne de commande de l'outil ADT » à la page 371. air_file Nom du fichier AIR créé. app_xml Chemin d'accès au fichier descripteur d'application. Il est possible de spécifier un chemin relatif (défini par rapport au répertoire actif) ou un chemin absolu. (Le fichier descripteur d'application est renommé application.xml dans le fichier AIR.) file_or_dir Fichiers et répertoires à inclure dans le package de fichier AIR. Le nombre de fichiers et de répertoires spécifié n'est pas limité, mais les noms doivent être séparés par un espace. Si vous indiquez un répertoire, tous les fichiers et sous-répertoires qu'il contient, à l'exception des fichiers masqués, sont ajoutés au package. (En outre, si le fichier descripteur d'application est spécifié, soit directement soit via le développement de caractères génériques ou de répertoires, il est ignoré et exclu du package la seconde fois.) Les fichiers et répertoires spécifiés doivent se trouver dans le répertoire actif ou l'un de ses sous-répertoires. Utilisez l'option -C pour changer de répertoire actif. Important : les caractères génériques ne sont pas admis dans les arguments file_or_dir suivant l'option –C. (Les shells de commande développent les caractères génériques avant de transmettre les arguments à l'outil ADT, ce qui incite ce dernier à rechercher des fichiers à un emplacement erroné.) Vous pouvez néanmoins continuer à utiliser le caractère point (.) pour indiquer le répertoire actif. Par exemple, « -C assets . » copie le contenu intégral du répertoire des ressources, sous répertoires compris, au niveau racine du package de l'application. -C dir Change le répertoire de travail sur la valeur de dir avant de traiter les fichiers et répertoires ultérieurs ajoutés au package de l'application. Les fichiers ou les répertoires sont ajoutés à la racine du package de l'application. Il est possible d'utiliser l'option –C de manière illimitée afin d'inclure des fichiers provenant de divers emplacements du système de fichiers. Si un chemin relatif est défini pour dir, il est toujours résolu à partir du répertoire de travail initial. Comme l'outil ADT traite les fichiers et répertoires inclus dans le package, les chemins relatifs définis entre le répertoire actif et les fichiers cible sont stockés. Ces chemins sont développés dans la structure de répertoires de l'application au moment de l'installation du package. Par conséquent, en indiquant -C release/bin lib/feature.swf, vous placez le fichier release/bin/lib/feature.swf dans le sous-répertoire lib du dossier racine de l'application. -e file dir Place le fichier spécifié dans le répertoire indiqué du package. Remarque : l'élément <content> du fichier descripteur d'application doit indiquer l'emplacement final du fichier principal de l'application au sein de l'arborescence de répertoires du package de l'application. Exemples ADT Création d'un package de fichiers d'application spécifiques dans le répertoire actuel : adt –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf components.swc Création d'un package de tous les fichiers et sous-répertoires inclus dans le répertoire de travail actif : adt –package -storetype pkcs12 -keystore ../cert.p12 myApp.air myApp.xml . Remarque : le fichier keystore contient la clé privée utilisée pour signer votre application. Veillez à ne jamais inclure le certificat de signature dans le package AIR. Si vous utilisez des caractères génériques dans la commande ADT, déplacez le fichier keystore afin qu'il ne soit pas inclus dans le package. Dans cet exemple, le fichier keystore (cert.p12) réside dans le répertoire parent. Création d'un package contenant uniquement les fichiers principaux et un sous-répertoire d'images : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 368 Création d'une application AIR à l'aide des outils de ligne de commande adt –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf images Création d'un package du fichier application.xml et du fichier SWF principal se trouvant dans un répertoire de travail (release/bin) : adt –package -storetype pkcs12 -keystore cert.p12 myApp.air release/bin/myApp.xml –C release/bin myApp.swf Création d'un package des ressources provenant de plusieurs emplacements du système de fichiers de développement. Dans cet exemple, les ressources de l'application se trouvent dans les dossiers suivants avant la création du package : /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 Exécution de la commande ADT suivante à partir du répertoire /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 Résultats dans la structure de package suivante : /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 Exécution de l'outil ADT en tant que programme Java (sans définir le chemin de classe) : DÉVELOPPEMENT D'APPLICATIONS ADOBE AIR 1.5 AVEC ADOBE FLASH CS4 PROFESSIONAL 369 Création d'une application AIR à l'aide des outils de ligne de commande java –jar {AIRSDK}/lib/ADT.jar –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf Exécution de l'outil ADT en tant que programme Java (le chemin de classe Java étant défini pour inclure le package ADT.jar) : java com.adobe.air.ADT –package -storetype pkcs12 -keystore cert.p12 myApp.air myApp.xml myApp.swf Messages d'erreur du programme ADT Les tableaux suivants présentent la liste des erreurs pouvant être signalées par le programme ADT et leurs causes probables : Erreurs de validation du fichier descripteur d'application Code d'erreur Description Remarques 100 Le fichier descripteur d'application ne peut Recherchez les erreurs de syntaxe XML pas être analysé. éventuelles dans le fichier descripteur d'application, par exemple des balises non fermées. 101 Espace de nom manquant Ajoutez l'espace de nom nécessaire. 102 Espace de nom non valide Vérifiez l'orthographe de l'espace de nom. 103 Elément ou attribut inattendu Supprimez les éléments ou les attributs fautifs. Les valeurs personnalisées ne sont pas autorisées dans le fichier descripteur. Vérifiez l'orthographe du nom des éléments ou des attributs. Assurez-vous que ces éléments soient placés dans l'élément parent approprié et que les attributs soient utilisés avec les éléments corrects. 104 Elément ou attribut manquant Ajoutez l'élément ou l'attribut requis. 105 L'élément ou l'attribut contient une valeur non valide. Corrigez la valeur fautive. 106 Combinaison d'attributs de fenêtre non valide Certains paramètres de fenêtre, tels que transparency = true et systemChrome = standard ne peuvent pas être utilisés simultanément. Modifiez l'un des paramètres incompatibles. 107 La taille minimale de la fenêtre e