Ontwikkeling van ADOBE AIR 1.1-toepassingen met ADOBE FLASH CS4 PROFESSIONAL ®
®
®
™
© 2008 Adobe Systems Incorporated. Alle rechten voorbehouden. Copyright
Ontwikkeling van Adobe® AIR™ 1.1-toepassingen met Adobe® Flash® CS4 Professional Indien deze handleiding wordt gedistribueerd met software die een gebruiksrechtovereenkomst bevat, valt deze handleiding, samen met de hierin beschreven software, onder een licentie en mag deze alleen worden gebruikt of gekopieerd in overeenstemming met de voorwaarden van een dergelijke licentie. Tenzij dit wordt toegestaan door een dergelijke licentie, mag geen enkel deel van deze handleiding worden gereproduceerd, opgeslagen in een ophaalsysteem of worden verzonden in enige vorm of op enige wijze, elektronisch, mechanisch, opname of anderszins, zonder voorafgaande schriftelijke toestemming van Adobe Systems Incorporated. De inhoud van deze handleiding wordt auteursrechtelijk beschermd, ook als deze niet wordt gedistribueerd met sofware die een gebruiksrechtovereenkomst bevat. De inhoud van deze handleiding dient alleen ter informatie en kan zonder voorafgaande berichtgeving worden gewijzigd en kan niet worden geïnterpreteerd als een verplichting van de zijde van Adobe Systems Incorporated. Adobe Systems Incorporated aanvaardt geen verantwoordelijkheid of aansprakelijkheid voor eventuele fouten in de inhoud van deze handleiding. Bestaande illustraties of afbeeldingen die u in uw project wilt invoegen, kunnen auteursrechtelijk zijn beschermd. Bij het onrechtmatig invoegen van dergelijk materiaal in uw werk wordt het auteursrecht van de copyright-eigenaar geschonden. Zorg dat u toestemming hebt van de copyright-eigenaar als u dit materiaal gebruikt. Eventuele bedrijfsnamen of namen van personen in voorbeeldsjablonen dienen slechts om het gebruik van het product te illustreren en zijn fictief. 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 trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries. All other trademarks are the property of their respective owners. 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. 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
Inhoud Hoofdstuk 1: Adobe AIR installeren Systeemvereisten voor Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Adobe AIR installeren
.................................................................................................. 2
Adobe AIR verwijderen
................................................................................................ 2
AIR-voorbeeldtoepassingen installeren en uitvoeren
................................................................... 2
Hoofdstuk 2: De Adobe AIR Update voor Flash CS3 instellen Systeemvereisten voor de Adobe AIR-update voor Flash CS3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Installatie van de Adobe AIR-update voor Flash CS3 ongedaan maken Installatie van de Adobe AIR-update voor Flash CS3 Adobe AIR-uitbreidingen van Flash CS3
.................................................. 4
.................................................................... 5
................................................................................ 5
Hoofdstuk 3: Inleiding tot Adobe AIR Hoofdstuk 4: AIR-bronnen zoeken Hoofdstuk 5: Uw eerste AIR-applicatie maken in Flash CS3 of CS4 De Hello World-toepassing in Flash maken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 De toepassing testen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Een Flash-toepassing converteren naar een Adobe AIR-toepassing
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Hoofdstuk 6: Adobe AIR-update voor Flash CS3 Professional Een Adobe AIR-bestand aanmaken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Adobe AIR-publicatie-instellingen installeren Voorbeeld van een Adobe AIR-toepassing
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Het debuggen van een Adobe AIR-toepassing
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
AIR-toepassings- en installerbestanden aanmaken
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Een aangepast descriptor-bestand van de toepassing aanmaken Uw toepassing ondertekenen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Hoofdstuk 7: Beveiliging in AIR Basisbeginselen van beveiliging in AIR Installatie en updates Sandboxen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Beveiliging in HTML
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Scripting tussen de inhoud van verschillende domeinen Naar schijf schrijven
Veilig werken met niet-vertrouwde inhoud
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Aanbevolen beveiligingsprocedures voor ontwikkelaars Codeondertekening
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Hoofdstuk 8: Eigenschappen van AIR-toepassingen instellen De structuur van het descriptorbestand van de toepassing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Eigenschappen definiëren in het descriptorbestand van de toepassing
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL iv Inhoud
Hoofdstuk 9: Nieuwe functionaliteit in Adobe AIR Nieuwe runtimeklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Runtimeklassen met nieuwe functionaliteit
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Klassen voor het framework voor servicecontrole
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Hoofdstuk 10: Werken met native vensters Aanvullende online informatie over native vensters Basisinformatie over AIR-vensters Vensters maken Vensters beheren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Luisteren naar venstergebeurtenissen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Schermvullende vensters weergeven
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Hoofdstuk 11: Schermen Aanvullende online informatie over schermen Basisinformatie over schermen Schermen opsommen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Hoofdstuk 12: Werken met native menu's Aanvullende online informatie over native menu's Basisinformatie over AIR-menu's Native menu's maken
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Informatie over contextmenu's
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Informatie over contextmenu's in HTML Native menu's declaratief definiëren Pop-upmenu's weergeven
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Menugebeurtenissen afhandelen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Voorbeeld: venstermenu en toepassingsmenu
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Hoofdstuk 13: Taakbalkpictogrammen Aanvullende online informatie over taakbalkpictogrammen Informatie over taakbalkpictogrammen Dock-pictogrammen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Systeemvakpictogrammen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Taakbalkpictogrammen en -knoppen voor vensters
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Hoofdstuk 14: Werken met het bestandssysteem Aanvullende online informatie over de AIR API voor het bestandssysteem Basisinformatie over AIR-bestanden Werken met File-objecten
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Informatie over het bestandssysteem ophalen Werken met mappen Werken met bestanden
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Lezen van en schrijven naar bestanden
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Hoofdstuk 15: Slepen en neerzetten Aanvullende online informatie over slepen en neerzetten Basisinformatie over slepen en neerzetten
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL v Inhoud
Ondersteuning voor de uitsleepbeweging
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Ondersteuning voor de insleepbeweging
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
HTML slepen en neerzetten
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Hoofdstuk 16: kopiëren en plakken Aanvullende online informatie over kopiëren en plakken Basisbeginselen van kopiëren en plakken
Lezen van en schrijven naar het systeemklembord HTML kopiëren en plakken
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Menuopdrachten en toetsaanslagen voor kopiëren en plakken Klembordgegevensindelingen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Hoofdstuk 17: Werken met bytearrays Bytearrays lezen en schrijven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 Voorbeeld van een bytearray: een ZIP-bestand lezen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Hoofdstuk 18: Werken met lokale SQL-databases Aanvullende online informatie over lokale SQL-databases Informatie over lokale SQL-databases Databases creëren en wijzigen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Werken met SQL-databasegegevens
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Synchrone en asynchrone databasebewerkingen gebruiken Strategieën voor het werken met SQL-databases
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Hoofdstuk 19: Gecodeerde gegevens opslaan Hoofdstuk 20: Informatie over de HTML-omgeving Overzicht van de HTML-omgeving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 AIR- en Webkit-extensies
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Hoofdstuk 21: Programmeren in HTML en JavaScript Informatie over de klasse HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 JavaScript-beveiligingsfouten voorkomen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
API-klassen van AIR oproepen vanuit JavaScript Informatie over URL's in AIR
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
ActionScript-objecten beschikbaar maken voor JavaScript
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
HTML DOM- en JavaScript-objecten oproepen vanuit ActionScript SWF-inhoud insluiten in HTML
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
ActionScript-bibliotheken in een HTML-pagina gebruiken Date- en RegExp-objecten converteren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
HTML-opmaakmodellen bewerken vanuit ActionScript
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
Cross-scripting van inhoud in verschillende beveiligingssandboxen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Hoofdstuk 22: HTML-gerelateerde gebeurtenissen afhandelen HTMLLoader-gebeurtenissen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 DOM-gebeurtenissen afhandelen met ActionScript
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
Reageren op niet-onderschepte JavaScript-uitzonderingen Runtimegebeurtenissen afhandelen met JavaScript
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL vi Inhoud
Hoofdstuk 23: Scripts schrijven voor de HTML-container Eigenschappen van HTMLLoader-objecten weergeven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 HTML-inhoud schuiven
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Historisch overzicht van HTML openen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Gebruikersagent voor het laden van HTML-inhoud instellen Tekencodering voor HTML-inhoud instellen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
Gebruikersinterfaces van het type browser definiëren voor HTML-inhoud Subklassen van de klasse HTMLLoader maken
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Hoofdstuk 24: PDF-inhoud toevoegen PDF-mogelijkheden detecteren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 PDF-inhoud laden
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Scripting van PDF-inhoud
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Bekende beperkingen voor PDF-inhoud in AIR
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
Hoofdstuk 25: Digitaal rechtenbeheer gebruiken Aanvullende online informatie over digitaal rechtenbeheer Gecodeerde FLV-workflows begrijpen Wijzigingen in de klasse NetStream
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
De klasse DRMStatusEvent gebruiken
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
De klasse DRMAuthenticateEvent gebruiken De klasse DRMErrorEvent gebruiken
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
Hoofdstuk 26: Opties voor het starten en sluiten van toepassingen Toepassingen oproepen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Opdrachtregelargumenten vastleggen Starten bij aanmelden
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Oproepen vanuit browser
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Toepassingen beëindigen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Hoofdstuk 27: Toepassingsinstellingen lezen Het descriptorbestand van de toepassing lezen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Toepassings- en uitgevers-id's ophalen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Hoofdstuk 28: Werken met runtime- en besturingssysteeminformatie Bestandskoppelingen beheren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 De runtimeversie en het patchniveau ophalen AIR-mogelijkheden detecteren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Gebruikersaanwezigheid bijhouden
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Hoofdstuk 29: Netwerkconnectiviteit bewaken Wijzigingen in de netwerkconnectiviteit detecteren Basisbeginselen van servicebewaking
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
HTTP-connectiviteit detecteren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Socketconnectiviteit detecteren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL vii Inhoud
Hoofdstuk 30: URL-aanvragen en netwerken De klasse URLRequest gebruiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 Wijzigingen in de klasse URLStream
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
URL's openen in de standaard webbrowser van het systeem
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Hoofdstuk 31: AIR-toepassingen distribueren, installeren en uitvoeren AIR-toepassingen vanaf de desktop installeren en uitvoeren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 AIR-toepassingen installeren en uitvoeren vanaf een webpagina Implementatie in ondernemingen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
AIR-bestanden digitaal ondertekenen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
Hoofdstuk 32: AIR-toepassingen updaten Informatie over het updaten van toepassingen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Aangepaste gebruikersinterfaces voor toepassingsupdates presenteren AIR-bestanden naar de computer van de gebruiker downloaden
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
Controleren of een toepassing voor de eerste keer wordt uitgevoerd
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
Hoofdstuk 33: AIR-toepassingen lokaliseren Inleiding tot lokalisatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 De toepassingsnaam en -beschrijving lokaliseren in het installatieprogramma van de toepassing
. . . . . . . . . . . . . . . . . . . . . . 316
Een landinstelling kiezen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
Flash-inhoud lokaliseren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
HTML-inhoud lokaliseren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
Datums, tijden en valuta's lokaliseren
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
Hoofdstuk 34: AIR-toepassingen maken met behulp van opdrachtregelprogramma's ADL (AIR Debug Launcher) gebruiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 AIR-installatiebestanden in een pakket plaatsen met ADT (AIR Developer Tool) AIR-bestanden ondertekenen om het toepassingscertificaat te wijzigen Zelfondertekende certificaten maken met ADT
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
Apache Ant gebruiken met de hulpprogramma's van de SDK Index
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
1
Hoofdstuk 1: Adobe AIR installeren Adobe® AIR™ stelt u in staat AIR-toepassingen uit te voeren op de desktop. U kunt de runtime op de volgende manieren installeren:
• U kunt de runtime afzonderlijk installeren (zonder ook een AIR-toepassing te installeren). • U kunt voor de eerste keer een AIR-toepassing installeren (u wordt dan ook gevraagd de runtime te installeren). • U kunt een AIR-ontwikkelomgeving instellen zoals de AIR SDK, Adobe® Flex™ Builder™ 3 of de Adobe Flex™ 3 SDK (die de AIR-opdrachtregelhulpprogramma’s bevat). De runtime hoeft op iedere computer maar eenmaal te worden geïnstalleerd.
Systeemvereisten voor Adobe AIR De systeemvereisten voor de uitvoering van Adobe AIR zijn:
• Voor basistoepassingen van Adobe AIR:
Processor
Windows
Macintosh
Intel® Pentium® 1,0 GHz-processor of sneller
PowerPC® G3 1,0 GHz-processor of sneller, of Intel Core™ Duo 1,83 GHz-processor of sneller
Geheugen
256 MB RAM
256 MB RAM
OS
Windows 2000 Service Pack 4
Mac OS X 10.4.10 of 10.5.x (PowerPC)
Windows XP SP2
Mac OS X 10.4.x of 10.5.x (Intel)
Vista
• Voor Adobe AIR-toepassingen die gebruikmaken van video op het volledige scherm met hardware scaling:
Processor
Windows
Macintosh
Intel® Pentium® 2,0 GHz-processor of sneller
PowerPC® G4 1,8 GHz-processor of sneller, of Intel Core™ Duo 1,33 GHz-processor of sneller
Geheugen
512 MB RAM; 32 MB video-RAM
256 MB RAM; 32 MB video-RAM
OS
Windows 2000 Service Pack 4
Mac OS X v.10.4.10 of v.10.5 (Intel of PowerPC)
Windows XP SP2 Vista
OPMERKING: voor de codec die wordt gebruikt om H.264-video weer te geven, is een Intelprocessor vereist.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 2 Adobe AIR installeren
Adobe AIR installeren Houd u aan de volgende instructies voor het downloaden en installeren van de Windows®- en Mac OS X-versies van AIR. Voor het updaten van de runtime moet de gebruiker over beheerdersrechten voor de computer beschikken. De runtime installeren op een Windows-computer 1 Download het runtime-installatiebestand. 2 Dubbelklik op het runtime-installatiebestand. 3 Volg in het installatievenster de aanwijzingen om de installatie te voltooien.
De runtime installeren op een Mac-computer 1 Download het runtime-installatiebestand. 2 Dubbelklik op het runtime-installatiebestand. 3 Volg in het installatievenster de aanwijzingen om de installatie te voltooien. 4 Als het installatieprogramma een verificatievenster weergeeft, geeft u uw gebruikersnaam en wachtwoord voor Mac
OS op.
Adobe AIR verwijderen Als u de runtime hebt geïnstalleerd, kunt u deze verwijderen aan de hand van de volgende procedures. De runtime verwijderen op een Windows-computer 1 Klik in het menu Start van Windows op Instellingen > Configuratiescherm. 2 Selecteer het onderdeel Software. 3 Selecteer “Adobe AIR” om de runtime te verwijderen. 4 Klik op de knop Wijzigen/Verwijderen.
De runtime verwijderen op een Mac-computer • Dubbelklik op “Adobe AIR Uninstaller” in de map /Applications (Programma’s).
AIR-voorbeeldtoepassingen installeren en uitvoeren Er zijn een paar voorbeeldtoepassingen beschikbaar waarin functies van AIR worden gedemonstreerd. U kunt deze als volgt openen en installeren: 1 Download de AIR-voorbeeldtoepassingen en voer ze uit. Zowel de gecompileerde toepassingen als de broncode zijn
beschikbaar. 2 Als u een voorbeeldtoepassing wilt downloaden en uitvoeren, klikt u op de knop Install Now van de
voorbeeldtoepassing. U wordt gevraagd de toepassing te installeren en uit te voeren.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 3 Adobe AIR installeren
3 Als u voorbeeldtoepassingen wilt downloaden en later wilt uitvoeren, selecteert u de downloadkoppelingen. U kunt
AIR-toepassingen op elk gewenst moment uitvoeren:
• In Windows dubbelklikt u op het toepassingspictogram op het bureaublad of selecteert u de toepassing in het menu Start van Windows.
• In Mac OS dubbelklikt u op het toepassingspictogram dat standaard is geïnstalleerd in de map Applications (Programma’s) van de gebruikersdirectory (bijvoorbeeld in Macintosh HD/Users/Gebruiker/Applications/). Opmerking: Updates van de AIR-releasenotes vindt u in http://www.adobe.com/go/learn_air_relnotes_nl.
4
Hoofdstuk 2: De Adobe AIR Update voor Flash CS3 instellen De Adobe® AIR™-update voor Adobe® Flash® CS3 Professional breidt de Flash-ontwikkelingsomgeving uit met elementen waarmee u AIR-toepassingen met behulp van Flash kunt bouwen. U kunt er AIR-toepassingsbestanden in Flash mee maken, testen en debuggen. Adobe® Flash® CS4 Professional heeft ingebouwde ondersteuning voor het maken van AIR-applicaties. Zie Publishing for Adobe AIRin Using Flash voor meer informatie.
Systeemvereisten voor de Adobe AIR-update voor Flash CS3 Om Flash CS3 te gebruiken voor de ontwikkeling en uitvoering van AIR-toepassingen, moet de volgende software geïnstalleerd zijn:
• Flash CS3 Professional Indien u geen exemplaar hebt van Flash CS3 Professional kunt u dit aankopen op de Adobe-website: http://www.adobe.com/products/flash/
• Adobe AIR Raadpleeg “Adobe AIR installeren” op pagina 1 voor meer informatie over het installeren van Adobe AIR.
• Adobe AIR-update voor Flash CS3 Indien u al een versie van de Adobe AIR-update voor Flash CS3 hebt geïnstalleerd, moet u deze installatie eerst ongedaan maken door de procedure te volgen in Installatie van de Adobe AIR-update voor Flash CS3 ongedaan maken. Als u de Adobe AIR-update voor Flash CS3 nog niet eerder hebt geïnstalleerd, gaat u naar de sectie “Installatie van de Adobe AIR-update voor Flash CS3” op pagina 5.
Installatie van de Adobe AIR-update voor Flash CS3 ongedaan maken Indien u de Adobe AIR-update voor Flash CS3 reeds hebt geïnstalleerd, voert u volgende stappen uit om de installatie ongedaan te maken alvorens een nieuwe Adobe AIR-update voor Flash CS3 te installeren. 1 Verwijder volgende map:
(Windows) HD:\Program Files\Adobe\Adobe Flash CS3\AIK (Mac) HD:/Applications/Adobe Flash CS3/AIK 2 Zoek volgende locatie:
(Windows) HD:\Program Files\Adobe\Adobe Flash CS3\
\First Run\Commands\ (Mac) HD:/Applications/Adobe Flash CS3/First Run/Commands
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 5 De Adobe AIR Update voor Flash CS3 instellen
en verwijder de volgende bestanden/mappen:
• AIR-map • AIR - Application and Installer Settings.jsfl • AIR - Create AIR File.jsfl 3 Verwijder volgend bestand:
(Windows) HD:\Program Files\Adobe\Adobe Flash CS3\\Configuration\External Libraries\FLAir.dll (Mac) HD:/Applications/Adobe Flash CS3/Configuration/External Libraries/FLAir.bundle. 4 Verwijder het volgende bestand:
(Windows) HD:\Program Files\Adobe\Adobe Flash CS3\\Configuration\Players\AdobeAIR1_0.xml (Mac) HD:/Applications/Adobe Flash CS3/Configuration/Players/ AdobeAIR1_0.xml 5 Zoek de volgende locatie:
(Windows) HD:\Document and Settings\<username>\Local Settings\Application Data\Adobe\Flash CS3\\Configuration\Commands\ (Mac) HD:/Users/<username>/Library/Application Support/Adobe/Flash CS3//Configuration/Commands/ en verwijder de volgende bestanden/mappen:
• AIR-map • AIR - Application and Installer Settings.jsfl • AIR - Create AIR File.jsfl Opmerking: Als u de opgegeven locatie niet vindt in Windows schakelt u "Verborgen bestanden/mappen weergeven" in de mapopties in.
Installatie van de Adobe AIR-update voor Flash CS3 Voordat u de Adobe AIR-update voor Flash CS3 installeert, sluit u Flash af en ook alle browsers die u mogelijk hebt geopend.
• Download de Adobe AIR-update voor Flash CS3. • Nadat u de update hebt gedownload, dubbelklikt u op het update patch-bestand om het te installeren.
Adobe AIR-uitbreidingen van Flash CS3 Na het installeren van de Adobe AIR-update kunt u volgende wijzigingen zien in Flash:
• In het dialoogvenster Publicatie-instellingen (Bestand -> Publicatie-instellingen), op het tabblad Flash, is er een nieuwe ingang in het menu Versie voor Adobe AIR 1.0
• Een bijgewerkt welkomscherm dat een ingang bevat voor het aanmaken van een Flash-bestand (Adobe AIR) (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\en\FirstRun\StartPage (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\en\FirstRun\StartPage\resources
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 6 De Adobe AIR Update voor Flash CS3 instellen
Opmerking: Op een MacIntosh-computer, verwijdert u de volgende map als het Flash-bestand (Adobe AIR) niet wordt weergegeven in het welkomscherm en start u Flash opnieuw op: HD:/Users/<username>/Libraries/Application Support/Adobe/Flash CS3//Configuration/StartPage
• Nieuw playerglobal.swc-bestand dat alle ActionScript 3.0 API's en Adobe AIR API's omvat in de map ActionScript 3.0/Classes (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\en\Configuration\ActionScript 3.0 Classes (Mac) HD:/Applications/Adobe Flash CS3/Configuration/ActionScript 3.0/Classes/
• Nieuwe jsfl-bestanden (AIR - Application and Installer Settings.jsfl, AIR - Publish AIR File.jsfl) (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\en\FirstRun\Commands (Mac) HD:/Applications/Adobe Flash CS3/First Run/Commands/
• Adobe AIR Software Development Kit (AIK) (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\AIK
• Externe bibliotheek (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\en\Configuration\External Libraries (Mac) HD:/Applications/Adobe Flash CS3/Configuration/External Libraries/
• Doelbestand voor configuratie (Windows) HD:\Program Files\Adobe\Adobe Flash CS3\en\Configuration\Players\ (Mac) HD:/Applications/Adobe Flash CS3/Configuration/Players
7
Hoofdstuk 3: Inleiding tot Adobe AIR Adobe® AIR™ is een runtime die voor meerdere besturingssystemen kan worden gebruikt en u in staat stelt gebruik te blijven maken van uw kennis op het gebied van webontwikkeling (Adobe® Flash® CS3 Professional, Adobe® Flex™, HTML, JavaScript®, Ajax) voor de ontwikkeling en implementatie van RIA's (Rich Internet Applications) voor de desktop. AIR stelt u in staat te werken in bekende omgevingen, gebruik te blijven maken van de hulpmiddelen en benaderingen die u goed kent en zo, mede dankzij de ondersteuning van Flash, Flex, HTML, JavaScript en Ajax, toepassingen te bouwen die optimaal aansluiten bij uw behoeften. U kunt bijvoorbeeld toepassingen ontwikkelen met behulp van een van de volgende technologieën of een combinatie daarvan:
• Flash / Flex / ActionScript • HTML / JavaScript / CSS / Ajax • PDF kan worden gebruikt met iedere toepassing. AIR-toepassingen kunnen daarom worden gebaseerd op:
• Flash of Flex: toepassingen waarvan de basisinhoud bestaat uit Flash/Flex (SWF); • Flash of Flex met HTML of PDF: toepassingen waarvan de basisinhoud bestaat uit Flash/Flex (SWF) met HTML(HTML, JS, CSS) of PDF-inhoud;
• HTML: toepassingen waarvan de basisinhoud bestaat uit HTML, JS, CSS; • HTML met Flash/Flex of PDF: toepassingen waarvan de basisinhoud bestaat uit HTML met Flash/Flex- (SWF) of PDF-inhoud. Gebruikers gebruiken AIR-toepassingen op dezelfde manier als native desktoptoepassingen. De runtime wordt éénmaal op de computer van de gebruiker geïnstalleerd, en daarna worden AIR-toepassingen geïnstalleerd en uitgevoerd net als elke andere desktoptoepassing. De runtime biedt een consistent platform voor meerdere besturingssystemen en een kader voor de implementatie van toepassingen waarbij de functionaliteit op verschillende desktops gegarandeerd constant is, zodat deze niet voor elke browser hoeft te worden getest. U richt zich bij de ontwikkeling op de runtime, niet op een specifiek besturingssysteem. Dit heeft de volgende voordelen:
• Toepassingen die zijn ontwikkeld voor AIR kunnen in meerdere besturingssystemen worden uitgevoerd zonder dat u extra werk hoeft te verrichten. De runtime garandeert een consistente en voorspelbare presentatie en interacties voor alle besturingssystemen die worden ondersteund door AIR.
• U kunt veel sneller toepassingen bouwen doordat u in staat bent gebruik te maken van bestaande webtechnologieën en ontwerppatronen, en doordat u uw webgebaseerde toepassingen kunt uitbreiden naar de desktop zonder dat u de traditionele technologieën voor desktopontwikkeling hoeft te leren of zich bezig hoeft te houden met de complexiteit van native code.
• Bij de ontwikkeling van toepassingen hoeft u geen gebruik te maken van laag-niveautalen zoals C of C++. U hoeft niet de complexe laag-niveau-API's te beheren die specifiek zijn voor ieder besturingssysteem. Bij de ontwikkeling van toepassingen voor AIR kunt u gebruikmaken van een zeer uitgebreide set bestaande frameworks en API's:
• API's die specifiek zijn voor AIR en die worden geleverd door de runtime en het AIR-framework
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 8 Inleiding tot Adobe AIR
• ActionScript-API's die worden gebruikt in SWF-bestanden en Flex-frameworks (evenals andere ActionScriptgebaseerde bibliotheken en frameworks)
• HTML, CSS en JavaScript • De meeste Ajax-frameworks AIR zorgt voor een enorme verandering in de manier waarop toepassingen kunnen worden gemaakt, geïmplementeerd en ervaren. U krijgt meer creatieve controle en kunt uw Flash-, Flex-, HTML- en Ajax-gebaseerde toepassingen uitbreiden naar de desktop zonder dat u de traditionele desktopontwikkeltechnologieën hoeft te leren.
9
Hoofdstuk 4: AIR-bronnen zoeken Raadpleeg de volgende bronnen voor meer informatie over het ontwikkelen van Adobe® AIR™-toepassingen: Bron
Locatie
ActionScript 3.0 programmeren
http://www.adobe.com/go/learn_fl_cs4_programmingAS3_en
ActionScript 3.0 Language and Components Reference (bevat AIR)
http://www.adobe.com/go/learn_flashcs4_langref_en
Adobe AIR-snelstarthandleidingen voor Flash
http://www.adobe.com/go/learn_air_flash_qs_nl
Flash gebruiken
http://www.adobe.com/go/learn_fl_cs4_using_en
ActionScript 3.0-componenten gebruiken
http://www.adobe.com/go/learn_fl_cs4_as3components_en
Artikelen, voorbeelden en presentaties door Adobe en community-specialisten kunt u vinden in Adobe AIR Developer Connection op http://www.adobe.com/devnet/air/. Hier kunt u ook Adobe AIR en verwante software downloaden. Een sectie speciaal voor Flash-ontwikkelaars kunt u vinden op http://www.adobe.com/devnet/air/flash/. Bezoek de Adobe-ondersteuningssite op http://www.adobe.com/support/ om problemen met uw product op te lossen en alles te leren over gratis en betaalde technische ondersteuningsmogelijkheden. Volg de koppeling Training voor toegang tot boeken van Adobe Press, uiteenlopende opleidingsbronnen, certificeringsprogramma's voor Adobesoftware en nog veel meer.
10
Hoofdstuk 5: Uw eerste AIR-applicatie maken in Flash CS3 of CS4 Voor een snelle, praktische demonstratie van de werking van Adobe® AIR™ volgt u de aanwijzingen in dit onderwerp om een eenvoudige “Hello World” AIR-toepassing te maken en te comprimeren. Download en installeer de Adobe AIR-update voor Flash CS3 mocht u dit nog niet hebben gedaan. Voor meer informatie over de installatie van Adobe AIR voor Flash CS3, kunt u “De Adobe AIR Update voor Flash CS3 instellen” op pagina 4 raadplegen. Als u Flash CS4 gebruikt, is ondersteuning voor Adobe AIR al ingebouwd, zodat u niets hoeft te installeren om aan de slag te gaan.
De Hello World-toepassing in Flash maken Een Adobe AIR-toepassing in Flash maken, is vergelijkbaar met het maken van iedere andere Flash-toepassing. In dit geval begint u echter met het maken van een Flash-bestand (Adobe AIR) vanuit het welkomscherm en u eindigt met het aanmaken van de toepassings- en installer-instellingen, en het installeren van uw AIR-toepassing. De volgende procedure leidt u door het proces voor het creëren van een eenvoudige Hello World-toepassing. De Hello World-toepassing aanmaken 1 Start Flash. 2 In het welkomscherm klikt u op Flash-bestand (Adobe AIR) om een leeg FLA-bestand aan te maken met Adobe
AIR-publicatie-instellingen. 3 Klik op OK om te reageren op het overzichtsdialoogvenster, Ontwerpomgeving voor Adobe AIR met Flash CS3.
Het duurt de eerste keer een paar minuten voordat dit dialoogvenster verschijnt. (Dit dialoogvenster wordt niet weergegeven in Flash CS4.) 4 Selecteer Tekstgereedschap in het venster Gereedschappen en maak een statisch tekstveld (standaard) in het
midden van de stage. Maak het breed genoeg zodat het 15 -20 tekens kan bevatten. 5 Typ de tekst “Hello World” in het tekstveld. 6 Sla het bestand op met een naam (bijvoorbeeld, helloAIR).
De toepassing testen 1 Druk op Ctrl + Enter of selecteer Control ->Test Movie om de toepassing te testen in Adobe AIR. 2 Om de functie Debug Movie te gebruiken, voegt u eerst de ActionScript-code toe aan de toepassing. U kunt dit snel
proberen door als volgt een trace statement toe te voegen: trace("Running AIR application using Debug Movie");
3 Druk op Ctrl + Shift + Enter, of selecteer Control->Debug Movie om de toepassing met Debug Movie uit te voeren.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 11 Uw eerste AIR-applicatie maken in Flash CS3 of CS4
4 Selecteer Opdrachten > AIR - toepassingen en het menu-item Installer-instellingen om het dialoogvenster AIR -
Toepassing & Installer-instellingen te openen. In Flash CS4 kunt u dit dialoogvenster openen door Bestand > AIRinstellingen te kiezen.
5 Onderteken het Adobe AIR-pakket met een zelfondertekend digitaal certificaat: a Klik op de knop Instellen voor de prompt Digitale handtekening om het dialoogvenster Digitale handtekening
te openen. b Klik op de knop Maken om het dialoogvenster Zelfondertekend digitaal certificaat maken te openen c Vul de volgende velden in: Naam uitgever, Afdeling organisatie, Naam organisatie, E-mail, Land, Wachtwoord,
en Wachtwoord bevestigen. d Geef het soort certificaat op. Het soort certificaat houdt verband met het niveau van beveiliging: 1024-RSA
gebruikt een 1024-bit-code (minder veilig), en 2048-RSA gebruikt een 2048-bit-code (veiliger). e Sla de gegevens op in een certificaatbestand via Opslaan als, of door te klikken op de knop Bladeren... om naar
een maplocatie te gaan. (Bijvoorbeeld, C:/Temp/mycert.pfx). Klik als u klaar bent op OK. f
Flash leidt u terug naar het dialoogvenster Digitale handtekening. Het pad en de bestandsnaam van het zelfondertekende certificaat dat u hebt gemaakt, verschijnt in het tekstvak Certificaat. Indien dit niet het geval is, voert u het pad en de bestandsnaam in of klikt u op de knop Bladeren om het te zoeken en te selecteren.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 12 Uw eerste AIR-applicatie maken in Flash CS3 of CS4
g Typ hetzelfde wachtwoord als in stap c in het tekstveld Wachtwoord van het dialoogvenster Digitale
handtekening en klik op OK. Voor meer informatie over het ondertekenen van uw Adobe AIR-toepassingen raadpleegt u “Uw toepassing ondertekenen” op pagina 21. 6 Klik op de knop AIR-bestand publiceren om het toepassings- en installerbestand te creëren. U moet Test Movie of
Debug Movie uitvoeren om de SWF- en application.xml-bestanden aan te maken voordat u het AIR-bestand creëert. 7 Om de toepassing te installeren, dubbelklikt u op het AIR-bestand (toepassing.air) in dezelfde map waarin u uw
toepassing hebt opgeslagen. 8 Klik op de knop Installeren in het dialoogvenster Toepassing installeren. 9 Controleer de installatievoorkeuren en de locatie-instellingen en zorg dat het vakje ‘Toepassing opstarten na
installatie’ is aangevinkt. Klik vervolgens op Doorgaan. 10 Als het bericht Installatie voltooid verschijnt, klikt u op Afsluiten.
De toepassing Hello World ziet er als volgt uit:
Een Flash-toepassing converteren naar een Adobe AIRtoepassing U kunt een bestaande Flash-toepassing ook converteren naar een AIR-toepassing. Zie “Adobe AIR-publicatieinstellingen installeren” op pagina 13 voor informatie over hoe u dit in Flash CS3 kunt doen. Als u Flash CS4 gebruikt, zie dan Publishing for Adobe AIRin Using Flash voor meer informatie.
13
Hoofdstuk 6: Adobe AIR-update voor Flash CS3 Professional De Adobe® AIR™-update voor Adobe® Flash® CS3 Professional vult de ontwerpomgeving aan waardoor u Adobe AIRtoepassingen met Flash kunt aanmaken, debuggen en comprimeren. De procedure voor het aanmaken van een Adobe AIR-toepassing bestaat uit het creëren van een Adobe AIR FLA-bestand, het installeren van de juiste publicatieinstellingen, het ontwikkelen van de toepassing, en het aanmaken van de toepassings- en installer-bestanden zodat u met de bestanden kunt werken. Als u Adobe® Flash® CS4 Professional gebruikt, kunt u naar Publishing for Adobe AIRin Using Flash gaan voor meer informatie over AIR-toepassingen. Voor informatie over de Adobe AIR ActionScript™ API's die u kunt gebruiken in uw toepassing, raadpleegt u op de verwijzing ActionScript 3.0 Taal en Componenten. Voor een lijst met Adobe AIR ActionScript API's raadpleegt u “Nieuwe functionaliteit in Adobe AIR” op pagina 54. Opmerking: Om gebruik te maken van klassen in het air.net-pakket, sleept u eerst het ServiceMonitorShim -component vanuit het venster Componenten naar het venster Bibliotheek en voegt u vervolgens de volgende import-verklaring toe aan uw ActionScript 3.0-code: import air.net.*;
Een Adobe AIR-bestand aanmaken U kunt Flash-bestanddocumenten (Adobe AIR) aanmaken met behulp van het Flash-welkomscherm of een Flashbestand aanmaken (ActionScript™ 3.0) en dit converteren naar een Adobe AIR-bestand via het dialoogvenster Publicatie-instellingen. U kunt echter geen Adobe AIR-bestand aanmaken met het dialoogvenster Nieuw document (Bestand > Nieuw). Voor informatie over het converteren van een Flash-bestand naar een Adobe AIR-bestand, raadpleegt u “Adobe AIR-publicatie-instellingen installeren” op pagina 13. 1 Start Flash of, indien Flash reeds opgestart is, sluit u alle openstaande documenten om terug te keren naar het
welkomscherm. Opmerking: Als u het Flash-welkomscherm hebt uitgeschakeld, kunt u het opnieuw weergeven door Bewerken > Voorkeuren selecteren en Welkomscherm kiezen in het pop-upmenu On Launch van de rubriek Algemeen. 2 In het welkomscherm klikt u op Flash-bestand (Adobe AIR).
Er verschijnt een waarschuwingsvenster waarin wordt gemeld hoe u de Adobe AIR-toepassingsinstellingen en de Help-documentatie kunt openen. U kunt deze waarschuwing overslaan in de toekomst door Niet meer weergeven te selecteren, maar dan kan het nooit meer worden weergegeven achteraf.
Adobe AIR-publicatie-instellingen installeren Gebruik de Flash-publicatie-instellingen om de instellingen voor een AIR-bestand te onderzoeken en te wijzigen en om een Flash-bestandsdocument (ActionScript 3.0) naar een Flash-bestandsdocument (Adobe AIR) te converteren.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 14 Adobe AIR-update voor Flash CS3 Professional
Adobe AIR-publicatie-instellingen weergeven 1 Open vanuit het Flash-welkomscherm een Flash-bestandsdocument (Adobe AIR). 2 Selecteer Bestand > Publicatie-instellingen en klik op het tabblad Flash om de Adobe AIR-publicatie-instellingen
weer te geven. Adobe AIR 1.0 wordt automatisch geselecteerd in het menu Versie wanneer u een Adobe AIR-document opent. De ActionScript™-versie wordt automatisch ingesteld op ActionScript 3.0. De veiligheidsinstelling Local playback wordt uitgeschakeld omdat deze niet relevant is voor een AIR SWF-bestand. Als u een Flash FLA-bestand heeft geopend, kunt u dit converteren naar een Flash AIR-bestand door de publicatieinstellingen te wijzigen. Een Flash FLA-bestand converteren naar een Flash AIR-bestand met behulp van het dialoogvenster Publicatieinstellingen 1 Ga als volgt te werk:
• Een bestaand Flash-bestand openen. • Gebruik het welkomscherm of selecteer Bestand > Nieuw om een nieuw Flash-bestand aan te maken. 2 Selecteer Bestand > Publicatie-instellingen. 3 Op het tabblad Flash selecteert u in het pop-upmenu Versie Adobe AIR 1.0.
De versie ActionScript is uitgeschakeld omdat ActionScript 3.0 de enige optie is voor een AIR-bestand. De resterende standaardopties zijn gelijk voor zowel een Flash-bestand als een Adobe AIR-bestand. 4 Klik op de knop Publiceren, en klik vervolgens op OK om het dialoogvenster Publicatie-instellingen af te sluiten.
De Property inspector geeft nu aan dat Adobe AIR 1 de Player target is als het gereedschap Selectie is geselecteerd. Opmerking: Wanneer u het Adobe AIR 1.0-profiel kiest, voegt Flash automatisch de locatie van het AIR playerglobal.swc-bestand toe aan de Classpath-omgevingsvariabele. Het AIR playerglobal.swc-bestand biedt u de mogelijkheid om de ActionScript AIR API's te gebruiken. Als u overschakelt van Adobe AIR 1 naar Adobe® Flash® Player 9 wordt Flash echter niet automatisch in het standaardprofiel ingesteld, of wordt de Classpath-instelling niet gewijzigd om de playerglobal.swc voor Flash Player 9 te gebruiken. Als u de publicatie-instellingen van Adobe AIR 1 naar Flash Player 9 wijzigt, moet u het publicatieprofiel instellen als standaard. Voor meer informatie over het dialoogvenster Publicatie-instellingen, raadpleegt u Flash gebruiken op www.adobe.com/go/learn_fl_using. Een Flash FLA-bestand converteren naar een Flash AIR-toepassing met behulp van het menu Opdrachten 1 Open uw Flash FLA-bestand. 2 Als u een nieuw Flash-bestand (ActionScript 3.0) opent, moet u het opslaan. Als u het niet opslaat, verschijnt er een
waarschuwing bij de volgende stap. 3 Selecteer Opdrachten > AIR - Toepassings- en Installer-instellingen.
Er verschijnt een waarschuwingsvenster waarin u wordt gevraagd of u het bestand wilt converteren naar Adobe AIR-publicatie-instellingen. 4 Klik op OK om het FLA-bestand te converteren naar Adobe AIR-publicatie-instellingen. Het dialoogvenster AIR -
Toepassings- en Installer-instellingen wordt weergegeven. Voor informatie over het dialoogvenster AIR - Toepassings- en Installer-instellingen raadpleegt u “AIRtoepassings- en installerbestanden aanmaken” op pagina 16.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 15 Adobe AIR-update voor Flash CS3 Professional
U kunt gebruikmaken van de opdrachten Film testen, Film debuggen, en AIR-bestand aanmaken op het geconverteerde AIR FLA-bestand.
Voorbeeld van een Adobe AIR-toepassing U kunt een voorbeeld bekijken van een Flash AIR SWF-bestand zoals het zal worden weergegeven in het AIRtoepassingsvenster. Een voorbeeld is nuttig wanneer u wilt zien hoe de zichtbare aspecten van de toepassing eruitzien zonder de toepassing te comprimeren en te installeren. 1 Zorg dat u de publicatie-instellingen hebt ingesteld voor een Adobe AIR-toepassing. Voor meer informatie
raadpleegt u “Adobe AIR-publicatie-instellingen installeren” op pagina 13. 2 Selecteer Beheer > Film testen of druk op Control+Enter.
Als u de toepassingsinstellingen niet hebt ingesteld via het dialoogvenster AIR - Toepassings- en Installerinstellingen genereert Flash voor u een descriptor-bestand in de standaardtoepassing (swfname-app.xml) in dezelfde map als de map waarin het SWF-bestand is geschreven. Als u de toepassingsinstellingen hebt ingesteld via het dialoogvenster AIR - Toepassings- en Installer-instellingen, geeft het descriptor-bestand van de toepassing die instellingen weer.
Het debuggen van een Adobe AIR-toepassing Het Adobe AIR SWF-bestand kan op dezelfde wijze worden gedebugged als een Flash Player 9 ActionScript 3.0 SWFbestand, behalve voor debuggen op afstand. 1 Zorg dat u de Adobe AIR-publicatie-instellingen hebt ingesteld. 2 Voeg de ActionScript-code toe aan het venster Acties (Window > Acties). Voor testing kunt u gewoon een trace()
statement zoals deze in het venster Acties toevoegen op het eerste frame van de Tijdslijn: trace("My application is running");
3 Selecteer Debuggen > Film debuggen of druk op Control+Shift+Enter.
Flash opent de ActionScript-debugger en exporteert het SWF-bestand met de debug-gegevens. Als u de toepassingsinstellingen niet hebt ingesteld via het dialoogvenster AIR - Toepassings- en Installerinstellingen genereert Flash voor u een descriptor-bestand in de standaardtoepassing (swfname-app.xml) in dezelfde map als de map waarin het SWF-bestand is geschreven. Als u de toepassingsinstellingen hebt ingesteld via het dialoogvenster AIR - Toepassings- en Installer-instellingen, geeft het descriptor-bestand van de toepassing die instellingen weer. Wanneer u Debuggen > Film debuggen selecteert of u drukt op Control+Shift+Enter om uw toepassing te debuggen, geeft Flash een waarschuwing weer als uw toepassing geen ActionScript-code heeft ingevoegd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 16 Adobe AIR-update voor Flash CS3 Professional
AIR-toepassings- en installerbestanden aanmaken Nadat u uw toepassing hebt voltooid, maakt u de AIR-toepassing en de installer-bestanden aan om deze te gebruiken. Adobe AIR voegt twee nieuwe menu's toe aan het Flash-opdrachtenmenu: AIR - Toepassings- en Installer-instellingen en AIR - AIR-bestand aanmaken. Nadat u de AIR-toepassing en installer-instellingen hebt aangemaakt, kunt u gebruikmaken van het item AIR-AIR-bestand aanmaken om het AIR-bestand (.air) opnieuw aan te maken met de bestaande instellingen. De Adobe AIR-toepassings- en installer-betanden aanmaken 1 In Flash opent u de pagina's of groep van pagina's die uw Adobe AIR-toepassing vormen. 2 Sla het Adobe AIR FLA-bestand op voordat u het dialoogvenster AIR - Toepassings- en Installer-instellingen opent. 3 Selecteer Opdrachten > AIR - Toepassings- en Installer-instellingen. 4 Vul het dialoogvenster AIR - Toepassings- en Installer-instellingen in, en klik vervolgens op AIR-bestand
publiceren. Als u klikt op de knop AIR-bestand publiceren worden de volgende bestanden gecomprimeerd: het FLA-bestand, het SWF-bestand, het descriptor-bestand van de toepassing, de bestanden van het toepassingspictogram, en de bestanden die worden weergegeven in het tekstvak Toegevoegde bestanden. Als u nog geen digitaal certificaat hebt aangemaakt, geeft Flash het dialoogvenster Digitale handtekening weer wanneer u op de knop AIR-bestand publiceren, klikt. Het dialoogvenster AIR - Toepassings en Installer-instellingen bestaat uit twee onderdelen: Toepassingsinstellingen en Installer-instellingen. Zie de volgende secties voor meer informatie over deze instellingen.
Toepassingsinstellingen De sectie toepassingsinstellingen van het dialoogvenster AIR - Toepassings- en Installer-instellingen heeft de volgende opties: Bestandsnaam De naam van het hoofdbestand van de toepassing. Standaardinstellingen voor de naam van het SWF-
bestand. Naam De naam die wordt gebruikt door de installer voor het genereren van de bestandsnaam van de toepassing en de
toepassingsmap. De naam mag enkel geldige tekens voor bestandsnamen of namen van mappen bevatten. Standaardinstellingen voor de naam van het SWF-bestand. Versie Optioneel. Geeft het versienummer op voor uw toepassing. Standaardinstelling is leeg. Id Identificeert uw toepassing met een unieke id. U kunt de standaard-id wijzigen als u dit wenst. Gebruik geen spaties of speciale tekens in de id. De enige geldige tekens zijn 0-9, a-z, A-Z, . (punt), en - (koppelteken), van 1 tot 212 tekens lang. Is standaard ingesteld op com.adobe.voorbeeld.toepassing_naam. Beschrijving Optioneel. Hiermee kunt u een beschrijving invoeren van de toepassing die wordt weergegeven wanneer de gebruiker de toepassing installeert. Standaardinstelling is leeg. Copyright Optioneel. Hiermee kunt u een copyright-melding invoeren die wordt weergegeven wanneer de gebruiker
de toepassing installeert. Vensterstijl Geeft aan welke vensterstijl (of chroom) u moet gebruiken voor de gebruikersinterface wanneer de gebruikers de toepassing uitvoeren op hun computer. U kunt Systeemchroom opgeven. Dit verwijst naar de visuele stijl die wordt gebruikt door het besturingssysteem. U kunt ook Aangepaste chroom (ondoorzichtig) of Aangepaste chroom (transparant) opgeven. Om uw toepassing zonder de systeemchroom weer te geven, selecteert u Geen. Systeemchroom omringt de toepassing met het standaard vensterbeheer van het besturingssysteem. Aangepaste
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 17 Adobe AIR-update voor Flash CS3 Professional
chroom (ondoorzichtig) elimineert de chroom van het standaardsysteem en laat u een eigen chroom creëren voor de toepassing. (U bouwt de aangepaste chroom rechtstreeks in het FLA-bestand.) Aangepaste chroom (transparant) is als Aangepaste chroom (ondoorzichtig), behalve dat het transparante capaciteiten toevoegt aan de randen van de pagina. Deze capaciteiten laten toepassingsvensters toe die niet vierkant of rechthoekig zijn. Pictogram Optioneel. Hiermee kunt u een pictogram voor de toepassing specificeren. Het pictogram wordt weergegeven nadat u de toepassing hebt geïinstalleerd en uitgevoerd in Adobe AIR. U kunt vier verschillende groottes opgeven voor het pictogram (128, 48, 32, en 16 pixels) om de verschillende weergaven waarin het pictogram verschijnt mogelijk te maken. Bijvoorbeeld, het pictogram kan worden weergegeven in de bestandsbrowser als thumbnail, gedetailleerd en naast elkaar. Het kan ook als bureaubladpictogram worden weergegeven, en in de titel van het AIRtoepassingsvenster, alsook op andere plaatsen.
De pictogramafbeelding is standaard ingesteld als een voorbeeld van een AIR-toepassingspictogram als er geen andere pictogrambestanden zijn opgegeven. Om een pictogram op te geven, klikt u op de knop Pictogramafbeeldingen selecteren in het To specify an icon, click the Select Icon Images button in het dialoogvenster AIR - Toepassings- en Installer-instellingen. In het dialoogvenster van de pictogramafbeeldingen dat wordt weergegeven, klikt u op de map voor elke pictogramgrootte en selecteert u het pictogrambestand dat moet worden gebruikt. De bestanden moeten in PNG-formaat (Portable Network Graphics) zijn. Volgende illustraties geven het dialoogvenster weer van de pictogramafbeeldingen met de standaard Adobe AIRtoepassingspictogrammen.
Verschillende groottes van de pictogramafbeeldingen van de toepassing opgeven
Als u een afbeelding opgeeft, moet het de exacte grootte hebben (128x128, 48x48, 32x32, of 16x16). Als u geen afbeelding opgeeft voor een bepaalde pictogramgrootte, past Adobe AIR een van de meegeleverde afbeeldingen aan om de ontbrekende pictogramafbeelding aan te maken.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 18 Adobe AIR-update voor Flash CS3 Professional
Geavanceerde instellingen Met de knop Instellingen in het dialoogvenster AIR - Toepassings- en Installer-instellingen kunt u geavanceerde instellingen opgeven voor het descriptor-bestand van de toepassing. Wanneer u op de knop Instellingen klikt, wordt het dialoogvenster Geavanceerde instellingen weergegeven. Met het dialoogvenster Geavanceerde instellingen kunt u geassocieerde bestandtypes opgeven die de toepassing moet behandelen. Bijvoorbeeld, als u wilt dat uw toepassing de hoofdtoepassing wordt voor het behandelen van HTMLbestanden, moet u dit opgeven in het tekstvak Geassocieerde bestandstypes. U kunt ook instellingen opgeven voor de volgende aspecten van de toepassing:
• De grootte en plaatsing van het initiële venster • De map waarin de toepassing is geïnstalleerd • De map met het Programmamenu waarin de toepassing moet worden geplaatst Het dialoogvenster heeft de volgende opties: Geassocieerde bestandstypes Hiermee kunt u de geassocieerde bestandstypes opgeven die de AIR-toepassing zal
behandelen. Klik op de knop Plus (+) om een nieuw bestandstype toe te voegen aan het tekstvak. Wanneer u op de Plus-knop drukt wordt het dialoogvenster Instellingen van bestandstype weergegeven. Wanneer u klikt op de knop Min (-) wordt een item dat is geselecteerd in het tekstvak verwijderd. Wanneer u klikt op de knop Potlood wordt het dialoogvenster Instellingen van bestandstype weergegeven en kunt u een item dat u hebt geselecteerd in het tekstvak bewerken. De knoppen Min (-) en Potlood zijn standaard uitgeschakeld. Door een item te selecteren in het tekstvak kunt u de knoppen Min (-) en Potlood inschakelen waardoor u het item kunt verwijderen of bewerken. De standaardwaarde in het tekstvak is Geen. Raadpleeg “Instellingen bestandstypen” op pagina 19 voor meer informatie over de instellingen van de bestandstypen voor geassocieerde bestanden. Initiële vensterinstellingen Hiermee kunt u de instellingen voor grootte en plaatsing van het initiële
toepassingsvenster opgeven.
• Breedte: Geeft de initiële breedte aan van het venster in pixels. De waarde is standaard leeg. • Hoogte: Geeft de initiële hoogte aan van het venster in pixels. De waarde is standaard leeg. • X: Geeft de initiële horizontale positie aan van het venster in pixels. De waarde is standaard leeg. • Y: Geeft de initiële verticale positie aan van het venster in pixels. De waarde is standaard leeg. • Maximumbreedte en maximunhoogte: Geven de maximumgrootte aan van het venster in pixels. Deze waarden zijn standaard leeg.
• Minimumbreedte en minimumhoogte: Geven de minimumgrootte aan van het venster in pixels. Deze waarden zijn standaard leeg.
• Vergrootbaar: Hiermee kunt u aangeven of de gebruiker het venster kan vergroten. Deze optie is standaard (of echt) geselecteerd.
• Verkleinbaar: Hiermee kunt u aangeven of de gebruiker het venster kan verkleinen. Deze optie is standaard (of echt) geselecteerd.
• Afmetingen wijzigen: Hiermee kunt u aangeven of de gebruiker de afmetingen van het venster kan wijzigen. Als deze optie niet is geselecteerd, zijn Maximumbreedte, Maximumhoogte, Minimumbreedte, en Minimumhoogte uitgeschakeld. Deze optie is standaard (of echt) geselecteerd.
• Zichtbaar: Hiermee geeft u aan of het toepassingsvenster initieel zichtbaar is. De optie is standaard (of echt) geselecteerd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 19 Adobe AIR-update voor Flash CS3 Professional
Andere instellingen Hiermee geeft u de volgende bijkomende gegevens aan in verband met de installatie:
• Installatiemap: Geeft de map aan waarin de toepassing is geïnstalleerd. • Map met programmamenu: Geeft de naam aan van de map met het programmamenu voor de toepassing. • Aangepaste update UI: Geeft aan wat er gebeurt wanneer een gebruiker een AIR-bestand opent voor een toepassing die reeds is geïnstalleerd. Standaard geeft AIR een dialoogvenster weer waarmee de gebruiker de geïnstalleerde versie kan bijwerken met de versie in het AIR-bestand. Als u niet wilt dat de gebruiker een dergelijke beslissing neemt en dat de toepassing het volledige beheer heeft over zijn updates, dan selecteert u deze optie. Wanneer u deze optie selecteert wordt het standaardgedrag overschreven en krijgt de toepassing het beheer over zijn eigen updates. Raadpleeg “AIR-toepassingen updaten” op pagina 312 voor meer informatie over het programmatisch updaten van een AIR-toepassing.
Instellingen bestandstypen Flash geeft het dialoogvenster Instellingen van bestandstype weer als u klikt op de knop Plus (+) of de knop Potlood in het dialoogvenster met geavanceerde instellingen zodat geassocieerde bestandstypes van de toepassing kunnen worden toegevoegd of bewerkt. De enige twee verplichte velden in dit dialoogvenster zijn Naam en Extensie. Als u klikt op OK en een van beide velden is leeg, geeft Flash een dialoogvenster met een foutmelding weer. U kunt volgende instellingen opgeven voor een geassocieerd bestandstype: Naam De naam van het bestandstype (bijvoorbeeld, Hypertext Markup Language, Tekstbestand, of Voorbeeld). Extensie De extensie van de bestandsnaam (bijvoorbeeld, html, txt, of xmpl), tot 39 alfanumerieke basistekens, (A-Zaz0-9), en zonder een voorafgaande periode. Beschrijving Optioneel. Een beschrijving van het bestandstype (bijvoorbeeld, Adobe videobestand). inhoudstype Optioneel. Specificeert het MIME-type voor het bestand. Instellingen van het bestandstype-pictogram Optioneel. Hiermee kunt u een pictogram opgeven dat is gekoppeld aan
het bestandstype. U kunt vier verschillende groottes opgeven voor het pictogram (128x128, 48x48, 32x32, en 16x16 pixels) om de verschillende weergaven waarin het pictogram verschijnt mogelijk te maken. Bijvoorbeeld, het pictogram kan worden weergegeven in de bestandsbrowser als thumbnail, gedetailleerd en naast elkaar. Als u een afbeelding opgeeft, moet het de grootte hebben die u specificeert. Als u geen bestand opgeeft voor een bepaalde grootte gebruikt AIR de afbeelding van vergelijkbare grootte en past het de afmetingen aan wat is opgegeven aan. Om een pictogram op te geven, klikt u ofwel op de map voor de pictogramgrootte en selecteert u een pictogrambestand dat u wilt gebruiken, of u voert het pad en de bestandsnaam in voor het pictogrambestand in het tekstvak naast de prompt. Het pictogrambestand moet in PNG-formaat zijn. Nadat een nieuw bestandstype is aangemaakt, wordt dit weergegeven in het lijstvak Bestandstype in het dialoogvenster van de geavanceerde instellingen.
Instellingen van descriptor-bestand van toepassing De toepassinginstellingen die u opgeeft worden opgeslagen in het bestand toepassing_naam-app.xml. U hebt echter de keuze om in Flash aan te geven dat u een aangepast descriptor-bestand van de toepassing wilt gebruiken. Een aangepast descriptor-bestand van de toepassing gebruiken Hiermee kunt u bladeren naar een aangepast descriptor-bestand van de toepassing. Als u Aangepast descriptor-bestand van de toepassing gebruiken selecteert, wordt in het dialoogvenster de sectie met toepassingsinstellingen uitgeschakeld. Om de locatie op te geven van het aangepast descriptor-bestand van de toepassing, voert u het ofwel in in onderstaand tekstveld Aangepast descriptorbestand van de toepassing gebruiken, of klikt u op het mappictogram en gaat u naar de locatie. Raadpleeg “Een
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 20 Adobe AIR-update voor Flash CS3 Professional
aangepast descriptor-bestand van de toepassing aanmaken” op pagina 21 voor meer informatie over het descriptorbestand van de toepassing.
Installer-instellingen Het tweede deel van het dialoogvenster AIR - Toepassings- en Installer-instellingen bevat instellingen die betrekking hebben op de installatie van de toepassing. Digitale handtekening Alle Adobe AIR-toepassingen moeten worden ondertekend om te kunnen worden geïnstalleerd in een ander systeem. Raadpleeg “Uw toepassing ondertekenen” op pagina 21 voor meer informatie over het toewijzen van een digitale handtekening aan een Flash Adobe AIR-toepassing. Bestemming Geeft aan waar het AIR-bestand moet worden opgeslagen. De standaardlocatie is de directory waarin u
het FLA-bestand hebt opgeslagen. Klik op het pictogram van de map om een andere locatie te selecteren. De standaardnaam van het pakket is de toepassingsnaam met de extensie .air. Bijgevoegde bestanden/mappen Geeft aan welke bijkomende bestanden en mappen bij uw toepassing moeten
worden gevoegd. Klik op de knop Plus (+) om bestanden toe te voegen en op de knop van de map om mappen toe te voegen. Om een bestand of map te verwijderen uit uw lijst selecteert u het bestand of de map en klikt u op de knop Min (-). Standaard worden het descriptor-bestand van de toepassing en het hoofd SWF-bestand automatisch toegevoegd aan de pakketlijst. De pakketlijst toont deze bestanden zelfs wanneer u het Adobe AIR FLA-bestand nog niet hebt gepubliceerd. De pakketlijst geeft de bestanden en mappen weer in een vlakke structuur. Bestanden in een map worden niet weergegeven, en volledige padnamen naar bestanden worden weergegeven maar kunnen indien nodig worden ingekort. Pictogrambestanden zijn niet opgenomen in de lijst. Wanneer Flash de bestanden comprimeert, worden de pictogrambestanden naar een tijdelijke map gekopieerd die gekoppeld is aan de locatie van het SWF-bestand. Flash wist de map nadat het comprimeren is voltooid.
Aanmaak van toepassings- en installer-bestanden mislukt De toepassings- en installer-bestanden worden in volgende gevallen niet aangemaakt:
• De toepassings-id-string heeft een onjuiste lengte of bevat ongeldige tekens. De toepassings-id-string mag 1 tot 212 tekens hebben en mag volgende tekens omvatten: 0-9, a-z, A-Z, . (punt), - (koppelteken).
• Bestanden in de installer-lijst bestaan niet. • De groottes van de aangepaste pictogrambestanden zijn niet correct. • De AIR-bestemmingsmap heeft geen schrijfrechten. • U hebt de toepassing niet getekend of u hebt niet opgegeven dat het een Adobe AIRI-toepassing betreft die later zal worden ondertekend.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 21 Adobe AIR-update voor Flash CS3 Professional
Een aangepast descriptor-bestand van de toepassing aanmaken Het descriptor-bestand van de toepassing is een XML-bestand dat u kunt bewerken met een tekstbewerker. Om een aangepast descriptor-bestand van de toepassing aan te maken, bewerkt u de waarden om aan te geven welke waarden u wenst. De standaardwaarden worden hier weergegeven:
• id = com.adobe.voorbeeld.swfname • fileName = swfname • name = swfname • versie = 1.0 • beschrijving = leeg • copyright = leeg • initialWindow • titel= naam • inhoud = swfname.swf • systemChrome = standaard, type = normaal • transparant = fout • zichtbaar = juist • pictogram • image128x128 = icons/AIRApp_128.png • image48x48 = icons/AIRApp_48.png • image32x32 = icons/AIRApp_32.png • image16x16 = icons/AIRApp_16.png • customUpdateUI = fout • allowBrowserInvocation = fout Raadpleeg “Eigenschappen van AIR-toepassingen instellen” op pagina 45 voor meer informatie over het descriptor-bestand van de toepassing.
Uw toepassing ondertekenen Alle Adobe AIR-toepassingen moeten worden ondertekend om te kunnen worden geïnstalleerd in een ander systeem. Flash biedt echter de mogelijkheid om niet ondertekende Adobe AIR-installer-bestanden aan te maken zodat de toepassing later kan worden ondertekend. Deze niet ondertekende Adobe AIR-installer-bestanden worden een AIRIpakket genoemd. Deze mogelijkheid wordt gebruikt in gevallen waarbij het certificaat zich op een ander toestel bevindt, of wanneer ondertekenen niet samen met de toepassingsontwikkeling wordt behandeld.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 22 Adobe AIR-update voor Flash CS3 Professional
Onderteken een Adobe AIR-toepassing met een vooraf aangekocht digitaal certificaat van een basis certificaatautoriteit 1 Klik op de knop Digitale handtekening instellen in het dialoogvenster AIR - Toepassings en Installer-instellingen. Het dialoogvenster Digitale handtekening wordt geopend. Dit dialoogvenster heeft twee radioknoppen waarmee u uw Adobe AIR-toepassing kunt ondertekenen met een digitaal certificaat of waarmee u een AIRI-pakket kunt voorbereiden. Als u uw AIR-toepassing ondertekent, kunt u ofwel een digitaal certificaat gebruiken dat werd toegewezen door een basiscertificaatautoriteit, of u kunt een zelfondertekend certificaat aanmaken. Een zelfondertekend certificaat is eenvoudig te maken, maar is niet zo veilig als een certificaat dat werd toegekend door een basiscertificaatautoriteit.
Dialoogvenster voor digitale handtekening voor het ondertekenen van een AIR-toepassing
2 Selecteer een certificaatbestand in het pop-upmenu of klik op de knop Bladeren om een certificaatbestand te
zoeken. 3 Selecteer het certificaat. 4 Voer een wachtwoord in. 5 Klik op OK.
Raadpleeg “AIR-bestanden digitaal ondertekenen” op pagina 305 voor meer informatie over het ondertekenen van uw AIR-toepassing. Een zelfondertekend digitaal certificaat maken 1 Klik op de knop Aanmaken. Het dialoogvenster Zelfondertekend digitaal certificaat maken, wordt geopend. 2 Vul volgende velden in: Naam uitgever, Afdeling organisatie, Naam organisatie, Land, Wachtwoord, en
Wachtwoord bevestigen. 3 Geef het soort certificaat op.
Het soort certificaat houdt verband met het niveau van beveiliging van het certificaat: 1024-RSA gebruikt een 1024bit-code (minder veilig), en 2048-RSA gebruikt een 2048-bit-code (veiliger). 4 Sla de gegevens op in een certificaatbestand via Opslaan als, of door te klikken op de knop Bladeren om naar een
maplocatie te gaan. 5 Klik op OK. 6 In het dialoogvenster Digitale handtekening voert u het wachtwoord in dat u hebt toegekend in de tweede stap van
deze procedure en klikt u op OK.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 23 Adobe AIR-update voor Flash CS3 Professional
Nadat u het digitale certificaat hebt ingesteld, wordt de knop Instellen veranderd in de knop Wijzigen. Om ervoor te zorgen dat Flash het wachtwoord dat u voor deze sessie heeft gebruikt onthoudt, klikt u op Wachtwoord onthouden voor deze sessie. Als de optie Tijdstempel niet geselecteerd is wanneer u op OK klikt, waarschuwt een dialoogvenster u dat de toepassing niet zal worden geïinstalleerd wanneer het digitale certificaat is verlopen. Als u op Ja klikt als antwoord op de waarschuwing, dan wordt de tijdstempel uitgeschakeld. Als u op Nee klikt, wordt de optie Tijdstempel automatisch geselecteerd en ingeschakeld. Raadpleeg “AIR-bestanden digitaal ondertekenen” op pagina 305 voor meer informatie over het maken van een zelfondertekend certificaat. U kunt ook een AIR Intermediate-toepassing (AIRI) aanmaken zonder een digitale handtekening. Een gebruiker kan de toepassing echter niet op een bureaublad installeren zolang u geen digitale handtekening hebt toegevoegd. Een AIRI-pakket voorbereiden dat later zal worden ondertekend ❖ In het dialoogvenster Digitale handtekening selecteert u Een AIRI-pakket voorbereiden dat later zal worden ondertekend, en vervolgens klikt u op OK. De status van de digitale handtekening wordt gewijzigd om aan te geven dat u ervoor hebt gekozen een AIRI-pakket voor te bereiden dat later zal worden ondertekend; en de knop Instellen verandert in de knop Wijzigen.
24
Hoofdstuk 7: Beveiliging in AIR In dit onderwerp worden beveiligingsproblemen besproken die u in acht moet nemen bij het ontwikkelen van een AIR-toepassing.
Basisbeginselen van beveiliging in AIR AIR-toepassingen worden met dezelfde gebruikersrechten als native toepassingen uitgevoerd. Over het algemeen bieden deze toegangsrechten brede toegang tot functies van het besturingssysteem, zoals het lezen en schrijven van bestanden, het starten van toepassingen, het tekenen op het scherm en het communiceren met het netwerk. Beperkingen van het besturingssysteem die gelden voor native toepassingen, zoals gebruikersspecifieke rechten, gelden ook voor AIR-toepassingen. Het beveiligingsmodel van Adobe® AIR™ is weliswaar een evolutie van het beveiligingsmodel van Adobe® Flash® Player maar het beveiligingscontract verschilt van het contract dat op inhoud in een browser wordt toegepast. Dit contract biedt ontwikkelaars een veilige manier om te beschikken over een bredere functionaliteit voor interessante ervaringen, met een vrijheid die niet geschikt is voor browsertoepassingen. AIR-toepassingen worden geschreven in gecompileerde bytecode (SWF-inhoud) of met geïnterpreteerde scripts (JavaScript, HTML), zodat de runtime geheugenbeheer biedt. Dit beperkt de kwetsbaarheid van AIR-toepassingen voor geheugenbeheerproblemen zoals buffer overflow en gegevensbeschadiging. Hieronder ziet u een aantal van de meest voorkomende problemen bij desktoptoepassingen die in native code zijn geschreven.
Installatie en updates AIR-toepassingen worden gedistribueerd via AIR-installatiebestanden met de extensie air. Wanneer Adobe AIR wordt geïnstalleerd en een AIR-installatiebestand wordt geopend, beheert de runtime de installatiemethode. Opmerking: Ontwikkelaars kunnen een versie, toepassingsnaam en uitgeversbron opgeven maar de initiële workflow zelf van de toepassingsinstallatie kan niet worden gewijzigd. Deze beperking is nuttig voor de gebruiker omdat hierdoor alle AIR-toepassingen dezelfde veilige, gestroomlijnde en consistente installatiemethode hebben, die door de runtime wordt beheerd. Als een toepassing moet worden aangepast, kan dit plaatsvinden wanneer de toepassing de eerste keer wordt gestart.
Installatielocatie van runtime Voor AIR-toepassingen moet eerst de runtime op de computer van de gebruiker worden geïnstalleerd, zoals voor SWF-bestanden eerst de Flash Player plug-in voor de browser moet worden geïnstalleerd. De runtime wordt op de volgende locatie op de computer van de gebruiker geïnstalleerd:
• Mac OS: /Library/Frameworks/ • Windows: C:\Program
Files\Common Files\Adobe AI
Als een gebruiker in Mac OS een recentere versie van een toepassing wil installeren, moet de gebruiker over voldoende toegangsrechten beschikken om te installeren in de toepassingsmap. In Windows moet de gebruiker over beheerdersrechten beschikken.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 25 Beveiliging in AIR
De runtime kan op twee manieren worden geïnstalleerd: met behulp van de naadloze installatiefunctie (installatie rechtstreeks vanuit een webbrowser) of via een handmatige installatie. Zie “AIR-toepassingen distribueren, installeren en uitvoeren” op pagina 296voor meer informatie.
Naadloze installatie (runtime en toepassing) De naadloze installatiefunctie biedt ontwikkelaars een gestroomlijnde installatiemethode voor gebruikers die Adobe AIR nog niet hebben geïnstalleerd. Bij de naadloze installatiemethode maakt de ontwikkelaar een SWF-bestand dat de te installeren toepassing opgeeft. Wanneer de gebruiker op het SWF-bestand klikt om de toepassing te installeren, probeert het SWF-bestand de runtime te detecteren. Als de runtime niet kan worden gedetecteerd, wordt deze geïnstalleerd en onmiddellijk gestart met de installatiemethode voor de toepassing van de ontwikkelaar.
Handmatige installatie De gebruiker kan echter ook de runtime handmatig downloaden en installeren vooraleer een AIR-bestand te openen. In dat geval beschikt de ontwikkelaar over verschillende manieren om een AIR-bestand te distribueren (bijvoorbeeld via e-mail of een HTML-koppeling op een website). Nadat het AIR-bestand is geopend, begint de runtime de toepassing te installeren. Zie “AIR-toepassingen distribueren, installeren en uitvoeren” op pagina 296voor meer informatie over deze methode.
Installatieflow van toepassing Het beveiligingsmodel van AIR biedt de gebruiker de keuze om een AIR-toepassing al dan niet te installeren. De installatiemethode van AIR biedt meerdere voordelen ten opzichte van native installatietechnologieën voor toepassingen, wat het maken van dit vertrouwensbesluit vergemakkelijkt voor de gebruiker:
• De runtime biedt een consistente installatiemethode in alle besturingssystemen, zelfs als een AIR-toepassing via een koppeling in een webbrowser wordt geïnstalleerd. De meeste native installatiemethoden voor toepassingen zijn afhankelijk van de browser of een andere toepassing voor het leveren van beveiligingsinformatie en in sommige gevallen wordt zelfs helemaal geen beveiligingsinformatie geleverd.
• De AIR-installatiemethode voor toepassingen identificeert de bron van de toepassing en informatie over de toegangsrechten van de toepassing (mits de gebruiker de installatie laat plaatsvinden).
• De runtime beheert de installatiemethode van een AIR-toepassing. Een AIR-toepassing heeft geen controle over de installatiemethode die door de runtime wordt gebruikt. De gebruiker wordt doorgaans niet aangeraden desktoptoepassingen te installeren die afkomstig zijn van een nietvertrouwde bron of een bron die niet kan worden gecontroleerd. De bewijslast op het gebied van veiligheid bij native toepassingen geldt ook voor AIR-toepassing en andere installeerbare toepassingen.
Doellocatie van toepassing De installatiedirectory kan worden ingesteld met een van de volgende twee opties: 1 De gebruiker kiest de doellocatie tijdens de installatie. De toepassing wordt geïnstalleerd op de locatie die door de
gebruiker is opgegeven. 2 Als de gebruiker de standaard installatielocatie niet wijzigt, wordt de toepassing geïnstalleerd volgens het
standaardpad dat door de runtime wordt bepaald:
• Mac OS: ~/Applications/ • Windows XP en oudere versies: C:\Program
Files\
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 26 Beveiliging in AIR
• Windows Vista: ~/Apps/ Als de ontwikkelaar in het descriptorbestand van de toepassing een waarde opgeeft voor installFolder, wordt de toepassing geïnstalleerd in een subpad van deze directory.
Bestandssysteem van AIR Tijdens de installatie van een AIR-toepassing worden alle bestanden die de ontwikkelaar in het installatiebestand van de AIR-toepassing heeft opgenomen, gekopieerd naar de lokale computer van de gebruiker. De geïnstalleerde toepassing bestaat uit:
• Windows: een directory met alle bestanden die in het installatiebestand van de AIR-toepassing zijn opgenomen. Tijdens de installatie van de AIR-toepassing maakt de runtime ook een EXE-bestand.
• Mac OS: een APP-bestand met de volledige inhoud van het installatiebestand van de AIR-toepassing. Dit kan worden geïnspecteerd met de opdracht Toon pakketinhoud in Finder. Tijdens de installatie van de AIR-toepassing maakt de runtime dit APP-bestand. AIR-toepassingen worden als volgt gestart:
• Windows: voer het bestand met de extensie .exe in de installatiemap of een snelkoppeling naar dit bestand uit (bijvoorbeeld in het menu Start of op het bureaublad).
• Mac OS: voer het bestand met de extensie .app of een alias van dit bestand uit. Het bestandssysteem van de toepassing bevat ook subdirectory's betreffende de functie van de toepassing. Bijvoorbeeld: informatie die naar een gecodeerde lokale opslaglocatie wordt geschreven, wordt opgeslagen in een subdirectory in een directory met de naam van de toepassingsidentificatie.
Opslag van AIR-toepassing AIR-toepassingen hebben de vereiste rechten om te schrijven naar een willekeurige locatie op de vaste schijf van de gebruiker. Ontwikkelaars wordt echter aangeraden om het pad app-storage:/ voor lokale opslag van hun toepassing te gebruiken. Bestanden die vanuit een toepassing naar app-storage:/ worden geschreven, bevinden zich op een standaardlocatie die afhankelijk is van het besturingssysteem van de gebruiker:
• In Mac OS: de opslagdirectory van een toepassing is //Local
Store/, waarbij de voorkeursmap van de gebruiker is (doorgaans /Users//Library/Preferences).
• In Windows: de opslagdirectory van een toepassing is \\Local
Store\, waarbij
de CSIDL_APPDATA 'speciale map' van de gebruiker is (doorgaans C:\Documents and Settings\\Application Data). U hebt toegang tot de opslagdirectory voor toepassingen via de eigenschap air.File.applicationStorageDirectory. U kunt de inhoud ervan bekijken via de methode resolvePath() van
de klasse File. Zie “Werken met het bestandssysteem” op pagina 105 voor meer informatie.
Adobe AIR updaten Wanneer de gebruiker een AIR-toepassing installeert waarvoor een recentere runtime is vereist, installeert de runtime automatisch de vereiste update. Voor het updaten van de runtime moet de gebruiker over beheerdersrechten voor de computer beschikken.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 27 Beveiliging in AIR
AIR-toepassingen updaten De ontwikkeling en distributie van software-updates is een van de grootste beveiligingsproblemen bij toepassingen in native code. De API van AIR biedt een mechanisme om dit risico te beperken: bij het starten kan de methode Updater.update() worden opgeroepen om een AIR-bestand te zoeken in een externe locatie. Als een update wordt gevonden, wordt het AIR-bestand gedownload en geïnstalleerd, en wordt de toepassing opnieuw gestart. Ontwikkelaars kunnen deze klasse niet alleen voor nieuwe functionaliteit gebruiken maar ook voor het bieden van oplossingen voor mogelijke beveiligingsproblemen. Opmerking: Ontwikkelaars kunnen de versie van een toepassing opgeven door de eigenschap version van het descriptorbestand van de toepassing in te stellen. AIR interpreteert de tekenreeks voor de versie helemaal niet. Met andere woorden, versie '3.0' wordt niet als recenter dan versie '2.0' beschouwd. De ontwikkelaar moet zorgen voor een correct versiebeheer. Zie “Eigenschappen definiëren in het descriptorbestand van de toepassing” op pagina 46voor meer informatie.
AIR-toepassingen verwijderen AIR-toepassingen worden als volgt verwijderd:
• In Windows: via het onderdeel Software van het Configuratiescherm. • In Mac OS: door het bestand met de extensie .app uit de installatiedirectory te verwijderen. Bij het verwijderen van een AIR-toepassing worden alle bestanden uit de toepassingsmap verwijderd. Eventuele bestanden die de toepassing buiten de toepassingsmap heeft gemaakt, worden echter niet verwijderd. Bij het verwijderen van een AIR-toepassing worden eventuele wijzigingen die de AIR-toepassing heeft aangebracht in bestanden buiten de toepassingsmap, niet ongedaan gemaakt.
Adobe AIR verwijderen AIR wordt als volgt verwijderd:
• In Windows: door het onderdeel Software van het Configuratiescherm te openen, Adobe AIR te selecteren en op de knop Verwijderen te klikken.
• In Mac OS: door de toepassing Adobe AIR Uninstaller in de directory Applications uit te voeren.
Windows-registerinstellingen voor beheerders In Windows kunnen beheerders een computer zo configureren dat de installatie van AIR-toepassingen en het uitvoeren van runtime-updates (niet) is toegestaan. Deze instellingen staan in het Windows-register onder de sleutel HKLM\Software\Policies\Adobe\AIR. De instellingen zijn onder andere: Registerinstelling
Beschrijving
AppInstallDisabled
Geeft aan of het installeren en verwijderen van AIR-toepassingen is toegestaan. Zet op 0 voor 'toegestaan' of op 1 voor 'niet toegestaan'.
UntrustedAppInstallDisabled
Geeft aan of de installatie van niet-vertrouwde AIR-toepassingen (toepassingen die geen vertrouwd certificaat bevatten) is toegestaan (zie “AIR-bestanden digitaal ondertekenen” op pagina 305). Zet op 0 voor 'toegestaan' of op 1 voor 'niet toegestaan'.
UpdateDisabled
Geeft aan of het updaten van de runtime is toegestaan, als achtergrondtaak of als deel van een expliciete installatie. Zet op 0 voor 'toegestaan' of op 1 voor 'niet toegestaan'.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 28 Beveiliging in AIR
Sandboxen AIR biedt een uitgebreide beveiligingsarchitectuur die rechten definieert voor elk bestand van een AIR-toepassing, zowel intern als extern. De rechten worden aan bestanden toegekend op basis van hun oorsprong en zijn verdeeld in logische beveiligingsgroepen die sandboxen worden genoemd.
Informatie over AIR-toepassingssandboxen Het runtime-beveiligingsmodel van sandboxen bestaat uit het beveiligingsmodel van Flash Player, waaraan de toepassingssandbox is toegevoegd. Voor bestanden die zich niet in de toepassingssandbox bevinden, gelden beveiligingsbeperkingen vergelijkbaar met de beperkingen uit het beveiligingsmodel van Flash Player. De runtime gebruikt deze beveiligingssandboxen om het gegevensbereik te definiëren waartoe code toegang heeft en de bewerkingen die door code mogen worden uitgevoerd. De lokale veiligheid blijft gegarandeerd doordat de bestanden in elke sandbox gescheiden zijn van de bestanden van andere sandboxen. Bijvoorbeeld: een SWF-bestand dat vanaf een externe internet-URL is geladen in een AIR-toepassing, wordt in een externe sandbox geplaatst en heeft standaard niet de vereiste toegangsrechten om scriptcode te schrijven in bestanden in de toepassingsmap, die zijn toegewezen aan de toepassingssandbox. De volgende tabel beschrijft de verschillende sandboxtypen: Sandbox
Beschrijving
toepassing
Het bestand bevindt zich in de toepassingsmap en heeft alle AIR-toegangsrechten.
extern
Het bestand is afkomstig van een internet-URL en werkt met domeingebaseerde sandboxregels vergelijkbaar met de regels die gelden voor externe bestanden in Flash Player. (Er zijn aparte externe sandboxen voor elk netwerkdomein, zoals http://www.voorbeeld.com en https://foo.voorbeeld.org.)
lokaal-vertrouwd
Het bestand is een lokaal bestand en de gebruiker heeft het als vertrouwd gemarkeerd via Instellingsbeheer of met een Flash Player-vertrouwensconfiguratiebestand. Het bestand kan zowel van lokale gegevensbronnen lezen als met internet communiceren maar heeft niet alle AIRtoegangsrechten.
lokaal-met-netwerk
Het bestand is een lokaal SWF-bestand dat met een netwerktoewijzing is gepubliceerd maar niet expliciet door de gebruiker wordt vertrouwd. Het bestand kan met internet communiceren maar kan niet van lokale gegevensbronnen lezen. Deze sandbox is alleen beschikbaar voor SWF-inhoud.
lokaal-met-bestandssysteem
Het bestand is een lokaal scriptbestand dat niet met een netwerktoewijzing is gepubliceerd en niet expliciet door de gebruiker wordt vertrouwd. Dit geldt onder andere voor niet-vertrouwde JavaScriptbestanden. Het bestand kan van lokale gegevensbronnen lezen maar kan niet met internet communiceren.
Dit onderwerp is hoofdzakelijk gebaseerd op de toepassingssandbox en zijn relatie met andere sandboxen in de AIRtoepassing. Ontwikkelaars die inhoud gebruiken die is toegewezen aan andere sandboxen, wordt aangeraden aanvullende documentatie te lezen over het beveiligingsmodel van Flash Player. Zie het hoofdstuk “Flash Player Security” in de documentatie ActionScript 3.0 programmeren (http://www.adobe.com/go/flashCS3_progAS3_security_nl) en de white paper Flash Player 9 Security (http://www.adobe.com/go/fp9_0_security_nl).
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 29 Beveiliging in AIR
Toepassingssandbox Bij de installatie van een toepassing worden alle bestanden in het AIR-installatiebestand geïnstalleerd in een toepassingsmap op de computer van de gebruiker. Ontwikkelaars kunnen in de programmacode naar deze map verwijzen via het URL-schema app:/ (zie “URL-schema's van AIR gebruiken in URL's” op pagina 292). Alle bestanden in de toepassingsmapstructuur worden bij het starten van de toepassing aan de toepassingssandbox toegewezen. De inhoud van de toepassingssandbox heeft alle toegangsrechten die beschikbaar zijn voor een AIRtoepassing, zoals interactie met het lokale bestandssysteem. Vele AIR-toepassingen gebruiken alleen deze lokaal geïnstalleerde bestanden om de toepassing uit te voeren. AIRtoepassingen zijn echter niet beperkt tot de bestanden in de toepassingsmap; ze kunnen een willekeurig type bestand van een willekeurige bron laden. Dit geldt onder andere voor lokale bestanden op de computer van de gebruiker en bestanden op beschikbare externe bronnen, zoals op een lokaal netwerk of internet. Het type van de bestanden heeft geen invloed op de beveiligingsbeperkingen: geladen HTML-bestanden hebben dezelfde beveiligingsrechten als geladen SWF-bestanden van dezelfde bron. De inhoud van de toepassingsbeveiligingssandbox heeft toegang tot AIR API's die niet kunnen worden gebruikt door de inhoud van andere sandboxen. Voorbeeld: de eigenschap air.NativeApplication.nativeApplication.applicationDescriptor, die de inhoud van het descriptorbestand van de toepassing weergeeft, is beperkt tot de inhoud van de toepassingsbeveiligingssandbox. Een ander voorbeeld van een beperkte API is de klasse FileStream, die methoden voor het lezen van en schrijven naar het lokale bestandssysteem bevat. ActionScript API's die alleen beschikbaar zijn voor de inhoud van de toepassingsbeveiligingssandbox, zijn in de ActionScript 3.0 Language Reference for Adobe AIR gemarkeerd met het AIR-logo. Als deze API's in andere sandboxen worden gebruikt, genereert de runtime een SecurityError-fout. Bij HTML-inhoud (in een HTMLLoader-object) zijn alle AIR JavaScript API's (de API's die beschikbaar zijn via de eigenschap window.runtime, of via het object air bij het gebruik van het bestand AIRAliases.js) beschikbaar voor inhoud van de toepassingsbeveiligingssandbox. De HTML-inhoud van andere sandboxen heeft geen toegang tot de eigenschap window.runtime, zodat deze inhoud geen toegang heeft tot de AIR API's.
Beperkingen van JavaScript en HTML Voor de HTML-inhoud van de toepassingsbeveiligingssandbox zijn er beperkingen betreffende het gebruik van API's die tekenreeksen dynamisch in programmacode kunnen omzetten nadat de code is geladen. Hierdoor wordt voorkomen dat de toepassing onbedoeld code van niet-toepassingsbronnen (zoals mogelijk onveilige netwerkdomeinen) opneemt (en uitvoert). Een voorbeeld hiervan is het gebruik van de functie eval(). Zie “Codebeperkingen voor de inhoud van verschillende sandboxen” op pagina 33voor meer informatie.
Beperkingen betreffende img-tags in de inhoud van ActionScript-tekstvelden Om mogelijke phishingaanvallen te blokkeren worden img -tags in de HTML-inhoud van ActionScript TextFieldobjecten genegeerd in de SWF-inhoud van de toepassingsbeveiligingssandbox.
Beperkingen betreffende asfunction De inhoud van de toepassingssandbox kan geen gebruik maken van het protocol asfunction in de HTML-inhoud van ActionScript 2.0-tekstvelden.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 30 Beveiliging in AIR
Geen toegang tot niet-vluchtige cross-domain cache De SWF-inhoud van de toepassingssandbox kan geen gebruik maken van de cross-domain cache, een nieuwe functie vanaf Flash Player 9 Update 3. Met deze functie kan Flash Player de inhoud van componenten van het Adobe-platform opslaan in een niet-vluchtige cache en vervolgens op aanvraag opnieuw gebruiken in geladen SWF-inhoud (zodat de inhoud niet meerdere keren opnieuw hoeft te worden geladen).
Rechten van inhoud van niet-toepassingssandboxen Bestanden die vanaf een netwerk- of internetlocatie zijn geladen, worden toegewezen aan de externe remote sandbox. Bestanden die vanaf een locatie buiten de toepassingsmap zijn geladen, worden toegewezen aan de lokaalmet-bestandssysteem, lokaal-met-netwerk of lokaal-vertrouwde sandbox, afhankelijk van de manier waarop het bestand is aangemaakt en of de gebruiker het bestand als vertrouwd heeft gemarkeerd via de Global Settings Manager van Flash Player. Zie http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager.html voor meer informatie.
Beperkingen van JavaScript en HTML In tegenstelling tot de inhoud van de toepassingsbeveiligingssandbox kan JavaScript-inhoud van een niettoepassingsbeveiligingssandbox wel de functie eval() oproepen om op elk gewenst moment dynamisch gegenereerde code uit te voeren. Er gelden echter beperkingen voor JavaScript in een niettoepassingsbeveiligingssandbox. Onder andere:
• JavaScript-code in een niet-toepassingssandbox heeft geen toegang tot het object window.runtime, zodat deze code geen AIR API's kan uitvoeren.
• De inhoud van een niet-toepassingsbeveiligingssandbox kan standaard geen XMLHttpRequest-oproepen gebruiken om gegevens te laden van andere domeinen dan het domein waarvan de aanvraag afkomstig is. Toepassingscode kan niet-toepassingsinhoud hiervoor echter toestemming geven door een kenmerk allowCrossdomainXHR in te stellen in het containerframe of iframe. Zie “Scripting tussen de inhoud van verschillende domeinen” op pagina 36voor meer informatie.
• Er zijn beperkingen betreffende het oproepen van de JavaScript-methode window.open(). Zie “Beperkingen betreffende het oproepen van de JavaScript-methode window.open()” op pagina 36voor meer informatie. Zie “Codebeperkingen voor de inhoud van verschillende sandboxen” op pagina 33voor meer informatie.
Beperkingen betreffende het laden van CSS-, frame-, iframe- en img-elementen De HTML-inhoud van externe (netwerk-) beveiligingssandboxen kan alleen inhoud van het type CSS, frame, iframe of img vanaf externe domeinen (netwerk-URL's) laden. De HTML-inhoud van lokaal-met-bestandssysteem, lokaal-met-netwerk of lokaal-vertrouwde sandboxen kan alleen inhoud van het type CSS, frame, iframe of img uit lokale sandboxen (niet van toepassings- of netwerk-URL's) laden.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 31 Beveiliging in AIR
Beveiliging in HTML De runtime past regels toe en biedt mechanismen voor het verhelpen van mogelijke beveiligingsproblemen in HTML en JavaScript. Hierbij worden altijd dezelfde regels toegepast, ongeacht of uw toepassing hoofdzakelijk in JavaScript is geschreven of dat u de HTML- en JavaScript-inhoud in een SWF-toepassing laadt. De inhoud van de toepassingssandbox en de inhoud van de niet-toepassingsbeveiligingssandbox (zie “Sandboxen” op pagina 28) hebben verschillende rechten. Wanneer inhoud in een iframe of frame wordt geladen, biedt de runtime een veilig sandboxbridge-mechanisme, waardoor de inhoud van het frame of iframe veilig kan communiceren met de inhoud van de toepassingsbeveiligingssandbox. In dit onderwerp wordt de AIR HTML-beveiligingsarchitectuur besproken, evenals het gebruik van iframes, frames en de sandboxbridge voor het configureren van uw toepassing. Zie “JavaScript-beveiligingsfouten voorkomen” op pagina 222voor meer informatie.
Overzicht van het configureren van uw HTML-toepassing Frames en iframes bieden een handige structuur voor het indelen van HTML-inhoud in AIR. Met frames kunt u zowel gegevens persistent houden als veilig werken met externe inhoud. Aangezien HTML in AIR zijn normale, op pagina's gebaseerde indeling behoudt, wordt de HTML-omgeving volledig vernieuwd als het bovenste frame van de HTML-inhoud naar een andere pagina 'navigeert'. U kunt frames en iframes gebruiken om gegevenspersistentie in AIR te behouden, ongeveer op dezelfde manier als voor een webtoepassing in een browser. Als u de belangrijkste toepassingsobjecten in het bovenste frame plaatst, persisteren ze tot u het frame naar een nieuwe pagina laat navigeren. Gebruik subframes of -iframes om de overgangsdelen van de toepassing te laden en weer te geven. (Er zijn verschillende manieren om voor gegevenspersistentie te zorgen als aanvulling op of in plaats van frames. Bijvoorbeeld cookies, lokale gedeelde objecten, lokale bestandsopslag, gecodeerde bestandsopslag en lokale databaseopslag.) HTML behoudt in AIR zijn normale, vage lijn tussen programmacode en gegevens. Daarom plaatst AIR de inhoud van het bovenste frame van de HTML-omgeving in de toepassingssandbox, en beperkt het eventuele bewerkingen, zoals eval(), die een teksttekenreeks kunnen omzetten in een uitvoerbaar object. Deze beperking wordt altijd toegepast, zelfs als een toepassing geen externe inhoud laadt. Als u in AIR veilig wilt werken met externe HTML-inhoud, moet u frames of iframes gebruiken. Zelfs als u geen externe inhoudt laadt, kan het handiger zijn om de inhoud uit te voeren in een subframe met sandbox zodat de inhoud kan worden uitgevoerd zonder beperkingen betreffende eval(). (Mogelijk is het gebruik van sandboxen vereist bij het gebruik van bepaalde JavaScript-toepassingsframeworks.) Zie “Codebeperkingen voor de inhoud van verschillende sandboxen” op pagina 33voor de volledige lijst van JavaScriptbeperkingen in de toepassingssandbox. Aangezien HTML in AIR de mogelijkheid behoudt om externe, mogelijk onveilige inhoud te laden, past AIR een 'beleid van zelfde oorsprong' toe om de voorkomen dat de inhoud van een bepaald domein in contact komt met de inhoud van een ander domein. Als u contact tussen de inhoud van de toepassing en de inhoud van een ander domein wilt toestaan, kunt u een bridge creëren die fungeert als interface tussen een hoofd- en een subframe.
Relatie tussen hoofd- en subsandbox creëren AIR voegt de kenmerken sandboxRoot en documentRoot toe aan de HTML frame- en iframe-elementen. Met deze kenmerken kunt u de toepassingsinhoud behandelen alsof deze van een ander domein afkomstig is:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 32 Beveiliging in AIR
Attribuut
Beschrijving
sandboxRoot
De URL waarmee de sandbox en het domein worden bepaald waarin de frame-inhoud wordt geplaatst. Het URLschema file:, http: of https: moet worden gebruikt.
documentRoot
De URL waarvan de frame-inhoud moet worden geladen. Het URL-schema file:, app: of app-storage: moet worden gebruikt.
In het volgende voorbeeld wordt de inhoud van de sandboxsubdirectory van de toepassing zo geconfigureerd dat deze wordt uitgevoerd in de externe sandbox en het domein www.example.com: <iframe src="ui.html" sandboxRoot="http://www.example.com/local/" documentRoot="app:/sandbox/">
Bridge tussen hoofd- en een subframes in verschillende sandboxen of domeinen instellen AIR voegt de eigenschappen childSandboxBridge en parentSandboxBridge toe aan het window-object van een willekeurig subframe. Met deze eigenschappen kunt u bridges definiëren als interfaces tussen een hoofd- en een subframe. Elke bridge gaat in één richting: childSandboxBridge - met de eigenschap childSandboxBridge kan het subframe een interface toegankelijk maken voor de inhoud van het hoofdframe. Als u een interface toegankelijk wilt maken, stelt u de eigenschap childSandbox in op een functie of object in het subframe. Vervolgens hebt u toegang tot het object of de functie vanuit de inhoud van het hoofdframe. In het volgende voorbeeld ziet u hoe een script dat in een subframe wordt uitgevoerd, een object dat een functie en een eigenschap bevat, toegankelijk kan maken voor het hoofdframe: var interface = {}; interface.calculatePrice = function(){ return .45 + 1.20; } interface.storeID = "abc" window.childSandboxBridge = interface;
Als deze onderliggende inhoud zich bevindt in een iframe waaraan de id"child" is toegewezen, hebt u vanuit de bovenliggende inhoud toegang tot de interface door de eigenschap childSandboxBridge van het frame te lezen: var childInterface = document.getElementById("child").childSandboxBridge; air.trace(childInterface.calculatePrice()); //traces "1.65" air.trace(childInterface.storeID)); //traces "abc" parentSandboxBridge - met de eigenschap parentSandboxBridge kan het bovenliggende frame een interface toegankelijk maken voor de inhoud van het subframe. Als u een interface toegankelijk wilt maken, stelt u de eigenschap parentSandbox van het onderliggende frame in op een functie of object in het bovenliggende frame. Vervolgens hebt u toegang tot het object of de functie vanuit de inhoud van het onderliggende frame. In het volgende voorbeeld ziet u hoe een script dat in het bovenliggende frame wordt uitgevoerd, een object dat de functie Save bevat, toegankelijk kan maken voor een onderliggend frame: var interface = {}; interface.save = function(text){ var saveFile = air.File("app-storage:/save.txt"); //write text to file } document.getElementById("child").parentSandboxBridge = interface;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 33 Beveiliging in AIR
Via deze interface kan de inhoud van het onderliggende frame bijvoorbeeld tekst opslaan in een bestand met de naam save.txt. De inhoud heeft echter geen andere toegang tot het bestandssysteem. Normaliter moet de toepassingsinhoud de kleinst mogelijke interface toegankelijk maken voor andere sandboxen. De onderliggende inhoud kan bijvoorbeeld de functie Save als volgt oproepen: var textToSave = "A string."; window.parentSandboxBridge.save(textToSave);
Als onderliggende inhoud een eigenschap van het object parentSandboxBridge probeert in te stellen, genereert de runtime een SecurityError-fout. Als bovenliggende inhoud een eigenschap van het object childSandboxBridge probeert in te stellen, genereert de runtime een SecurityError-fout.
Codebeperkingen voor de inhoud van verschillende sandboxen Zoals in de inleiding tot dit onderwerp, “Beveiliging in HTML” op pagina 31, is besproken, past de runtime regels toe en biedt deze mechanismen voor het verhelpen van mogelijke beveiligingsproblemen in HTML en JavaScript. De desbetreffende beperkingen staan in dit onderwerp. Als code deze beperkte API's probeert op te roepen, geeft de runtime de foutmelding weer dat er in de runtime van Adobe AIR een beveiligingsfout betreffende JavaScript-code in de toepassingsbeveiligingssandbox is opgetreden. Zie “JavaScript-beveiligingsfouten voorkomen” op pagina 222voor meer informatie.
Beperkingen betreffende het gebruik van de JavaScript-functie eval() en soortgelijke technieken Voor de HTML-inhoud van de toepassingsbeveiligingssandbox zijn er beperkingen betreffende het gebruik van API's die tekenreeksen dynamisch in programmacode kunnen omzetten nadat de code is geladen (nadat de gebeurtenis onload van het element body is verzonden en de handlerfunctie onload is voltooid). Hierdoor wordt voorkomen dat de toepassing onbedoeld code van niet-toepassingsbronnen (zoals mogelijk onveilige netwerkdomeinen) opneemt (en uitvoert). Als uw toepassing bijvoorbeeld tekenreeksgegevens van een externe bron gebruikt om naar de eigenschap innerHTML van een DOM-element te schrijven, bevat de tekenreeks mogelijk (JavaScript-) programmacode die onveilige bewerkingen kan uitvoeren. Tijdens het laden van de inhoud is er echter geen risico dat externe tekenreeksen in het DOM-element worden ingevoegd. Eén beperking betreft het gebruik van de JavaScript-functie eval(). Nadat code in de toepassingssandbox is geladen en de gebeurtenishandler onload is verwerkt, kunt u de functie eval() slechts met bepaalde beperkingen gebruiken. De volgende regels gelden voor het gebruik van de functie eval()nadat code is geladen uit de toepassingsbeveiligingssandbox:
• Expressies met literalen zijn toegestaan. Bijvoorbeeld: eval("null"); eval("3 + .14"); eval("'foo'");
• Objectliteralen zijn toegestaan, zoals in de volgende situatie: { prop1: val1, prop2: val2 }
• Setter/getters met objectliteralen zijn niet toegestaan, zoals in de volgende situatie: { get prop1() { ... }, set prop1(v) { ... } }
• Arrayliteralen zijn toegestaan, zoals in de volgende situatie: [ val1, val2, val3 ]
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 34 Beveiliging in AIR
• Expressies met het lezen van eigenschappen zijn niet toegestaan, zoals in de volgende situatie: a.b.c
• Het oproepen van functies is niet toegestaan. • Functiedefinities zijn niet toegestaan. • Het instellen van eigenschappen is niet toegestaan. • Functieliteralen zijn niet toegestaan. Tijdens het laden van de code, vóór de gebeurtenis onload, en tijdens de uitvoering van de gebeurtenishandlerfunctie onload gelden deze beperkingen echter niet voor de inhoud van de toepassingsbeveiligingssandbox. Bij de volgende code bijvoorbeeld treedt een fout op nadat code is geladen: eval("alert(44)"); eval("myFunction(44)"); eval("NativeApplication.applicationID");
Dynamisch gegenereerde code, zoals bij het oproepen van de functie eval(), zou een veiligheidsrisico zijn als deze toegang kreeg tot de toepassingssandbox. Een toepassing kan bijvoorbeeld onbedoeld een tekenreeks uitvoeren die is geladen vanaf een netwerkdomein en schadelijke code bevat. De code kan bijvoorbeeld bestanden op de computer van de gebruiker verwijderen of wijzigen. Of de inhoud van een lokaal bestand doorsturen naar een niet-vertrouwd netwerkdomein. Dynamische code kan op de volgende manieren worden gegenereerd:
• door het oproepen van de functie eval(); • door eigenschappen van het type innerHTML of DOM-functies te gebruiken om scripttags in te voegen die een script buiten de toepassingsmap laden;
• door eigenschappen van het type innerHTML of DOM-functies te gebruiken om scripttags in te voegen die inline code bevatten (in plaats van een script te laden via het kenmerk src);
• door het kenmerk src voor script tags zo in te stellen dat een JavaScript-bestand wordt geladen dat zich buiten de toepassingsmap bevindt;
• door het URL-schema javascript te gebruiken (zoals in href="javascript:alert('Test')"); • door de functie setInterval() of setTimeout() te gebruiken, waarbij de eerste parameter (die de functie asynchroon laat uitvoeren) een (te evalueren) tekenreeks en geen functienaam is (zoals in setTimeout('x = 4', 1000));
• door document.write() of document.writeln() op te roepen. Code in de toepassingsbeveiligingssandbox kan tijdens het laden van inhoud alleen deze methoden gebruiken. Deze beperkingen blokkeren het gebruik van eval() met JSON-objectliteralen niet. Hierdoor kan de inhoud van uw toepassing met de JSON JavaScript-bibliotheek werken. U kunt echter geen overbelaste JSON-code (met gebeurtenishandlers) gebruiken. Voor andere Ajax-frameworks en JavaScript-codebibliotheken moet u controleren of de code in het framework of de bibliotheek binnen deze beperkingen betreffende dynamisch gegenereerde code werkt. Als dat niet het geval is, neemt u alle inhoud die gebruikmaakt van het framework of de bibliotheek op in een niet-toepassingsbeveiligingssandbox. Zie “Rechten van inhoud van niet-toepassingssandboxen” op pagina 30en “Scripting tussen toepassings- en niettoepassingsinhoud” op pagina 41voor meer informatie. Adobe houdt een lijst bij van Ajax-frameworks waarvan bekend is dat ze de toepassingsbeveiligingssandbox ondersteunen. Ga hiervoor naar http://www.adobe.com/products/air/develop/ajax/features/.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 35 Beveiliging in AIR
In tegenstelling tot de inhoud van de toepassingsbeveiligingssandbox kan JavaScript-inhoud van een niettoepassingsbeveiligingssandbox wel de functie eval() oproepen om op elk gewenst moment dynamisch gegenereerde code uit te voeren.
Beperkingen betreffende de toegang tot AIR API's (voor niet-toepassingssandboxen) JavaScript-code in een niet-toepassingssandbox heeft geen toegang tot het object window.runtime, zodat deze code geen AIR API's kan uitvoeren. Als de inhoud van een niet-toepassingsbeveiligingssandbox de volgende code oproept, treedt een TypeError-fout op: try { window.runtime.flash.system.NativeApplication.nativeApplication.exit(); } catch (e) { alert(e); }
Het fouttype is TypeError (niet-gedefinieerde waarde) omdat de inhoud van de niet-toepassingssandbox het object window.runtime niet herkent en het als een niet-gedefinieerde waarde beschouwt. Als u runtime-functionaliteit toegankelijk wilt maken voor de inhoud van een niet-toepassingssandbox, gebruikt u een scriptbridge. Zie “Scripting tussen toepassings- en niet-toepassingsinhoud” op pagina 41voor meer informatie.
Beperkingen betreffende het gebruik van XMLHttpRequest-oproepen De HTML-inhoud van een toepassingsbeveiligingssandbox kan geen synchrone XMLHttpRequest-methoden gebruiken om gegevens van buiten de toepassingssandbox te laden tijdens het laden van de HTML-inhoud en tijdens de gebeurtenis onLoad. De HTML-inhoud van niet-toepassingsbeveiligingssandboxen kan standaard geen JavaScript XMLHttpRequestobject gebruiken om gegevens te laden van andere domeinen dan het domein waarvan de aanvraag afkomstig is. Een tag van het type frame of iframe kan een kenmerk van het type allowcrosscomainxhr bevatten. Als u dit kenmerk instelt op een waarde die niet leeg is, kan de inhoud van het frame of iframe het Javascript XMLHttpRequest-object gebruiken om gegevens te laden van andere domeinen dan het domein van de code waarvan de aanvraag afkomstig is: <iframe id="UI" src="http://example.com/ui.html" sandboxRoot="http://example.com/" allowcrossDomainxhr="true" documentRoot="app:/">
Zie “Scripting tussen de inhoud van verschillende domeinen” op pagina 36voor meer informatie.
Beperkingen betreffende het laden van CSS-, frame-, iframe- en img-elementen (voor de inhoud van niet-toepassingssandboxen) De HTML-inhoud van externe (netwerk-) beveiligingssandboxen kan alleen inhoud van het type CSS, frame, iframe of img uit externe sandboxen (netwerk-URL's) laden. De HTML-inhoud van lokaal-met-bestandssysteem, lokaal-met-netwerk of lokaal-vertrouwde sandboxen kan alleen inhoud van het type CSS, frame, iframe of img uit lokale sandboxen (niet van toepassings- of externe sandboxen) laden.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 36 Beveiliging in AIR
Beperkingen betreffende het oproepen van de JavaScript-methode window.open() Als een venster dat door het oproepen van de JavaScript-methode window.open() is gemaakt, de inhoud van een niet-toepassingsbeveiligingssandbox weergeeft, begint de titel van het venster met de titel van het hoofdvenster (vanwaaruit het nieuwe venster is geopend), gevolgd door een dubbele punt. U kunt geen code gebruiken om dat deel van de venstertitel buiten het scherm te verplaatsen. De inhoud van niet-toepassingsbeveiligingssandboxen kan de JavaScript-methode window.open() alleen oproepen als reactie op een gebeurtenis die is gestart door een klik met de muisknop of een druk op een toets van het toetsenbord. Hierdoor wordt voorkomen dat niet-toepassingsinhoud vensters creëert die voor bedrog kunnen worden gebruikt (bijvoorbeeld voor phishingaanvallen). Ook kan de gebeurtenishandler voor de muis- of toetsenbordgebeurtenis de methode window.open() niet zo instellen dat deze na een vertraging wordt uitgevoerd (bijvoorbeeld door de functie setTimeout() op te roepen). De inhoud van externe (netwerk-) sandboxen kan de methode window.open() alleen gebruiken om de inhoud van externe netwerksandboxen te openen. Deze inhoud kan de methode window.open() niet gebruiken om de inhoud van de toepassingssandbox of van lokale sandboxen te openen. De inhoud van lokaal-met-bestandssysteem, lokaal-met-netwerk of lokaal-vertrouwde sandboxen (zie “Sandboxen” op pagina 28) kan de methode window.open() alleen gebruiken om de inhoud van lokale sandboxen te openen. Deze inhoud kan window.open() niet gebruiken om de inhoud van de toepassingssandbox of van externe sandboxen te openen.
Fouten bij het oproepen van beperkte code Als u code oproept die niet in een sandbox kan worden gebruikt vanwege deze beveiligingsbeperkingen, geeft de runtime de foutmelding weer dat er in de runtime van Adobe AIR een beveiligingsfout betreffende JavaScript-code in de toepassingsbeveiligingssandbox is opgetreden. Zie “JavaScript-beveiligingsfouten voorkomen” op pagina 222voor meer informatie.
Scripting tussen de inhoud van verschillende domeinen Bij de installatie van AIR-toepassingen worden hieraan speciale rechten toegewezen. Het is van groot belang dat deze rechten niet aan andere inhoud worden doorgegeven, zoals externe bestanden en lokale bestanden die geen deel uitmaken van de toepassing.
Informatie over de AIR-sandboxbridge Inhoud van andere domeinen kan normaal gesproken geen scripts in andere domeinen oproepen. Om AIRtoepassingen te beschermen tegen onbedoelde lekkage van informatie of besturingselementen waarvoor speciale toegangsrechten gelden, gelden de volgende beperkingen voor de inhoud van de beveiligingssandbox application (inhoud die met de toepassing is geïnstalleerd):
• Code in de toepassingsbeveiligingssandbox mag geen toegang bieden tot andere sandboxen door de methode Security.allowDomain() op te roepen. Het oproepen van deze methode vanuit de toepassingsbeveiligingssandbox heeft geen effect.
• Het importeren van niet-toepassingsinhoud in de toepassingssandbox door de eigenschap LoaderContext.securityDomain of LoaderContext.applicationDomain te activeren, wordt verhinderd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 37 Beveiliging in AIR
Er zijn echter situaties waarin de AIR-hoofdtoepassing inhoud van een extern domein nodig heeft voor gecontroleerde toegang tot scripts in de AIR-hoofdtoepassing, of omgekeerd. Hiervoor biedt de runtime het mechanisme sandboxbridge, dat als gateway tussen beide sandboxen fungeert. Een sandboxbridge kan expliciete interactie tussen externe en toepassingsbeveiligingssandboxen bieden. De sandboxbridge maakt twee objecten toegankelijk, waartoe zowel geladen als ladende scripts toegang hebben:
• Het object parentSandboxBridge staat ladende inhoud toe om eigenschappen en functies toegankelijk te maken voor scripts in de geladen inhoud.
• Het object childSandboxBridge staat geladen inhoud toe om eigenschappen en functies toegankelijk te maken voor scripts in de ladende inhoud. Objecten die via de sandboxbridge toegankelijk worden gemaakt, worden doorgegeven op basis van waarde en niet op basis van referentie. Alle gegevens zijn geserialiseerd. Dit betekent dat de objecten die door de ene kant van de bridge toegankelijk zijn gemaakt, niet door de andere kant kunnen worden ingesteld, en dat alle toegankelijke objecten geen specifiek type hebben. Bovendien kunt u alleen eenvoudige objecten en functies toegankelijk maken, geen complexe objecten. Als onderliggende inhoud een eigenschap van het object parentSandboxBridge probeert in te stellen, genereert de runtime een SecurityError-fout. Evenzo genereert de runtime een SecurityError-fout als bovenliggende inhoud een eigenschap van het object childSandboxBridge probeert in te stellen.
Voorbeeld van sandboxbridge (SWF) Dit voorbeeld is gebaseerd op een AIR-toepassing voor een muziekwinkel. De toepassing wil externe SWF-bestanden toestaan om de prijs van albums toegankelijk te maken maar wil niet dat het externe SWF-bestand aangeeft of de prijs een opruimingsprijs is. Hiervoor biedt de klasse StoreAPI een methode die de prijs opvraagt maar de opruimingsprijs verbergt. Vervolgens wordt een instantie van deze StoreAPI-klasse toegewezen aan de eigenschap parentSandboxBridge van het LoaderInfo-object van het Loader-object dat het externe SWF-bestand laadt. Dit is de code voor de AIR-muziekwinkel:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 38 Beveiliging in AIR
<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:UIComponent id="container" />
Het StoreAPI-object roept de hoofdtoepassing op om de normale albumprijs op te vragen maar geeft “Not available” (Niet beschikbaar) weer wanneer de methode getSaleAlbumPrice() wordt opgeroepen. De volgende code definieert de klasse StoreAPI:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 39 Beveiliging in AIR
public class StoreAPI { private static var musicStore:Object; public function StoreAPI(musicStore:Object) { this.musicStore = musicStore; } public function getRegularAlbumPrice():String { return musicStore.getRegularAlbumPrice(); } public function getSaleAlbumPrice():String { return "Not available"; } public function getAlbumPrice():String { return musicStore.getRegularAlbumPrice(); } }
De volgende code is een voorbeeld van het SWF-bestand PriceQuoter (Prijsofferte), dat de verkoopprijs van de winkel weergeeft maar de opruimingsprijs niet kan weergeven: 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()); } } }
Voorbeeld van sandboxbridge (HTML) Bij HTML-inhoud worden de eigenschappen parentSandboxBridge en childSandboxBridge toegevoegd aan het JavaScript window-object van een subdocument. Zie “Sandboxbridge-interface instellen” op pagina 237voor een voorbeeld van hoe u bridgefuncties definieert in HTML-inhoud.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 40 Beveiliging in AIR
API-toegankelijkheid beperken Bij het toegankelijk maken van sandboxbridges is het belangrijk dat u API's toegankelijk maakt die van een hoog niveau zijn en de mate beperken waarin ze kunnen worden misbruikt. Vergeet niet dat de inhoud die uw bridgeimplementatie oproept, door een kwaadwillige persoon kan zijn gewijzigd (bijvoorbeeld via een code-injectie). Dit betekent bijvoorbeeld dat een methode readFile(path:String) (die de inhoud van een willekeurig bestand leest) die via een bridge toegankelijk wordt gemaakt, kan worden misbruikt. Het is aan te raden een API readApplicationSetting() toegankelijk te maken die geen specifiek pad volgt en een specifiek bestand leest. De meer semantische methode beperkt de schade die een toepassing kan aanbrengen als een deel ervan door een kwaadwillige persoon is gewijzigd.
Zie ook “Cross-scripting van inhoud in verschillende beveiligingssandboxen” op pagina 235 “Toepassingssandbox” op pagina 29 “Rechten van inhoud van niet-toepassingssandboxen” op pagina 30
Naar schijf schrijven Toepassingen die in een webbrowser worden uitgevoerd, hebben slechts beperkte interactie met het lokale bestandssysteem van de gebruiker. Webbrowsers passen beveiligingsmaatregelen toe die zorgen dat de computer van de gebruiker niet in gevaar kan worden gebracht door het laden van webinhoud. Bijvoorbeeld: SWF-bestanden die via Flash Player in een browser worden uitgevoerd, kunnen niet rechtstreeks interageren met bestanden die al op de computer van de gebruiker staan. Gedeelde objecten en cookies kunnen naar de computer van de gebruiker worden geschreven voor het bijhouden van gebruikersvoorkeuren en andere gegevens, maar meer niet. Aangezien AIRtoepassingen in het besturingssysteem worden geïnstalleerd, gebruiken ze een ander beveiligingscontract, dat onder andere de mogelijkheid biedt om te lezen van en te schrijven naar het lokale bestandssysteem. Deze vrijheid gaat gepaard met een grote verantwoordelijkheid voor de ontwikkelaars. Toevallige kwetsbaarheden van toepassingen brengen niet alleen de functionaliteit van de toepassing in gevaar, maar ook de integriteit van de computer van de gebruiker. Daarom wordt ontwikkelaars aangeraden “Aanbevolen beveiligingsprocedures voor ontwikkelaars” op pagina 42te lezen. AIR-ontwikkelaars kunnen bestanden in het lokale bestandssysteem via verschillende URL-schemaconventies lezen/schrijven: URL-schema
Beschrijving
app:/
Een alias voor de toepassingsmap. Bestanden die via dit pad worden benaderd, worden toegewezen aan de toepassingssandbox en beschikken over alle toegangsrechten die door de runtime worden verleend.
app-storage:/
Een alias voor de lokale opslagdirectory, gestandaardiseerd door de runtime. Bestanden die via dit pad worden benaderd, worden toegewezen aan een niet-toepassingssandbox.
file:///
Een alias die de hoofddirectory van de vaste schijf van de gebruiker vertegenwoordigt. Aan een bestand dat via dit pad wordt benaderd, wordt een toepassingssandbox toegewezen als het bestand in de toepassingsmap bestaat. Als dat niet het geval is, wordt een niet-toepassingssandbox toegewezen.
Opmerking: AIR-toepassingen kunnen geen inhoud wijzigen via het URL-schema app:. Bovendien is de toepassingsmap mogelijk alleen-lezen, afhankelijk van de beheerdersinstellingen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 41 Beveiliging in AIR
Als er geen beheerdersrechten voor de computer van de gebruiker vereist zijn, mogen AIR-toepassingen naar een willekeurige locatie op de vaste schijf van de gebruiker schrijven. Ontwikkelaars wordt aangeraden het pad appstorage:/ te gebruiken voor lokale opslag betreffende hun toepassing. Bestanden die vanuit een toepassing naar app-storage:/ worden geschreven, worden in een standaardlocatie geplaatst:
• In Mac OS: de opslagdirectory van een toepassing is //Local
Store/, waarbij de voorkeursmap van de gebruiker is. Dit is doorgaans /Users//Library/Preferences.
• In Windows: de opslagdirectory van een toepassing is \\Local
Store\, waarbij de CSIDL_APPDATA 'speciale map' van de gebruiker is. Dit is doorgaans C:\Documents and Settings\\Application Data.
Als een toepassing is ontworpen om te interageren met bestaande bestanden in het bestandssysteem van de gebruiker, moet u “Aanbevolen beveiligingsprocedures voor ontwikkelaars” op pagina 42lezen.
Veilig werken met niet-vertrouwde inhoud Inhoud die niet aan de toepassingssandbox is toegewezen, kan uw toepassing aanvullende scriptfunctionaliteit bieden, maar alleen als wordt voldaan aan de beveiligingscriteria van de runtime. In dit onderwerp wordt het AIRbeveiligingscontract met niet-toepassingsinhoud besproken.
Security.allowDomain() AIR-toepassingen beperken de toegang van scripts voor niet-toepassingsinhoud in hogere mate dan de Flash Player 9 plug-in voor de browser de toegang van scripts voor niet-vertrouwde inhoud. Bijvoorbeeld: wanneer in Flash Player in de browser een SWF-bestand dat is toegewezen aan de lokaal-vertrouwde sandbox, de methode System.allowDomain() oproept, wordt scripttoegang verleend voor een willekeurig SWF-bestand dat vanaf het opgegeven domein wordt geladen, waarbij de toewijzing van dit externe bestand wordt verplaatst van de externe naar de lokaal-vertrouwde sandbox. Deze benadering is niet toegestaan voor toepassingsinhoud in AIRtoepassingen omdat hierdoor onredelijke toegang tot het niet-toepassingsbestand in het bestandssysteem van de gebruiker zou worden verleend. Externe bestanden hebben nooit rechtstreekse toegang tot de toepassingssandbox, ongeacht de aanwezigheid van oproepen van de methode Security.allowDomain().
Scripting tussen toepassings- en niet-toepassingsinhoud Voor AIR-toepassingen die scripts gebruiken tussen toepassings- en niet-toepassingsinhoud, gelden complexere beveiligingsmaatregelen. Bestanden die zich niet in de toepassingssandbox bevinden, hebben alleen via een sandboxbridge toegang tot de eigenschappen en methoden van bestanden in de toepassingssandbox. Een sandboxbridge is een gateway tussen toepassings- en niet-toepassingsinhoud, en maakt expliciete interactie tussen de twee bestanden mogelijk. Wanneer een sandboxbridges correct wordt gebruikt, biedt deze een extra beveiligingslaag door te zorgen dat niet-toepassingsinhoud geen toegang heeft tot objectverwijzingen die deel uitmaken van toepassingsinhoud. Het voordeel van sandboxbridges wordt het best met een voorbeeld geïllustreerd. Dit voorbeeld is gebaseerd op een AIR-toepassing voor een muziekwinkel. De winkel wil adverteerders die hun eigen SWF-bestanden willen maken, een API bieden waarmee de toepassing van de winkel vervolgens kan communiceren. De winkel wil adverteerders methoden bieden waarmee ze artiesten en cd's in de winkel kunnen opzoeken, maar wil om veiligheidsredenen ook bepaalde methoden en eigenschappen onbereikbaar maken voor de SWF-bestanden van de adverteerders.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 42 Beveiliging in AIR
Een sandboxbridge kan hiervoor zorgen. Inhoud die extern in een AIR-toepassing wordt geladen tijdens het gebruik van de runtime, heeft standaard geen toegang tot methoden of eigenschappen in de hoofdtoepassing. Met een aangepaste sandboxbridge-implementatie kan een ontwikkelaar services voor de externe inhoud bieden zonder deze methoden of eigenschappen toegankelijk te maken. De sandboxbridge is als een pad tussen vertrouwde en nietvertrouwde inhoud dat communicatie tussen de ladende en de geladen inhoud mogelijk maakt zonder objectverwijzingen toegankelijk te maken. Zie “Scripting tussen de inhoud van verschillende domeinen” op pagina 36voor meer informatie over hoe u sandboxbridges veilig gebruikt.
Bescherming tegen dynamisch gegenereerde, onveilige SWF-inhoud De methode Loader.loadBytes() biedt een toepassing de mogelijkheid om SWF-inhoud te genereren op basis van een bytearray. Injectieaanvallen op gegevens die van externe bronnen worden geladen, kunnen echter ernstige schade toebrengen bij het laden van inhoud. Dit geldt met name bij het laden van gegevens in de toepassingssandbox, waar de gegenereerde SWF-inhoud toegang heeft tot de volledige set van AIR API's. Er zijn echter ook situaties waarin het gebruik van de methode loadBytes() zonder het genereren van SWFprogrammacode vereist is. U kunt de methode loadBytes() gebruiken om grafische gegevens te genereren, bijvoorbeeld om de beeldweergavetiming te besturen. Er zijn ook situaties waarin wel programmacode mag worden gegenereerd, zoals bij het dynamisch genereren van SWF-inhoud voor het afspelen van audio. In AIR staat de methode loadBytes() u standaard niet toe om SWF-inhoud te laden; u mag alleen grafische inhoud laden. In AIR heeft de eigenschap loaderContext van de methode loadBytes() een eigenschap allowLoadBytesCodeExecution, die u op true kunt instellen om de toepassing expliciet toe te staan loadBytes() te gebruiken om SWF-programmacode te laden. In de volgende code wordt getoond hoe u deze functie gebruikt: var loader:Loader = new Loader(); var loaderContext:LoaderContext = new LoaderContext(); loaderContext.allowLoadBytesCodeExecution = true; loader.loadBytes(bytes, loaderContext);
Als u loadBytes() oproept om SWF-inhoud te laden en de eigenschap allowLoadBytesCodeExecution van het LoaderContext-object is ingesteld op false (dit is de standaardinstelling), genereert het Loader-object een SecurityError-fout. Opmerking: In een toekomstige versie van Adobe AIR wordt deze API mogelijk aangepast. In dat geval moet u mogelijk de inhoud die gebruikmaakt van de eigenschap allowLoadBytesCodeExecution van de klasse LoaderContext, opnieuw compileren.
Aanbevolen beveiligingsprocedures voor ontwikkelaars AIR-toepassingen zijn weliswaar gebaseerd op webtechnologieën maar ontwikkelaars mogen niet vergeten dat ze niet in de beveiligingssandbox van de browser werken. Dit betekent dat het mogelijk is om AIR-toepassingen te ontwikkelen die bedoeld of onbedoeld schade kunnen toebrengen aan het systeem. AIR probeert dit risico tot het minimum te beperken maar er zijn altijd wel manieren om kwetsbaarheden te genereren. In dit onderwerp worden belangrijke potentiële kwetsbaarheden besproken.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 43 Beveiliging in AIR
Risico bij het importeren van bestanden in de toepassingsbeveiligingssandbox Bestanden in de toepassingsmap zijn toegewezen aan de toepassingssandbox en beschikken over alle toegangsrechten van de runtime. Toepassingen die naar het lokale bestandssysteem schrijven, wordt aangeraden naar app-storage:/ te schrijven. Aangezien deze directory apart van de toepassingsbestanden op de computer van de gebruiker is geplaatst, zijn de bestanden niet toegewezen aan de toepassingssandbox en vormen ze een kleiner veiligheidsrisico. Ontwikkelaars wordt aangeraden het volgende in acht te nemen:
• Neem alleen indien nodig een bestand op in een AIR-bestand (in de geïnstalleerde toepassing). • Neem alleen een scriptbestand op in een AIR-bestand (in de geïnstalleerde toepassing) als het gedrag ervan volledig begrepen en vertrouwd wordt.
• Schrijf niet naar de toepassingsmap en wijzig de inhoud ervan niet. De runtime genereert een SecurityError-fout om te zorgen dat toepassingen geen bestanden en mappen via het URL-schema app:/ kunnen wijzigen of ernaar schrijven.
• Gebruik geen gegevens van een netwerkbron als parameters voor AIR API-methoden die tot de uitvoering van code kunnen leiden. Dit geldt onder andere voor het gebruik van de methode Loader.loadBytes() en de JavaScriptfunctie eval().
Risico bij het gebruiken van een externe bron voor het bepalen van paden Een AIR-toepassing kan in gevaar worden gebracht door het gebruik van externe gegevens of inhoud. Daarom moet extra worden opgelet bij het gebruik van gegevens van het netwerk of het bestandssysteem. De verantwoordelijkheid voor het geven van vertrouwen ligt uiteindelijk bij de ontwikkelaars en de netwerkverbindingen die ze maken, maar het laden van externe gegevens is altijd gevaarlijk en wordt het best niet gebruikt voor gegevensinvoer bij bewerkingen met vertrouwelijke gegevens. Ontwikkelaars wordt het volgende afgeraden:
• gegevens van een netwerkbron gebruiken om een bestandsnaam te bepalen; • gegevens van een netwerkbron gebruiken om een URL te definiëren die door de toepassing wordt gebruikt om persoonlijke informatie te verzenden.
Risico bij het gebruiken, opslaan of verzenden van onveilige gebruikersgegevens Het opslaan van gebruikersgegevens in het lokale bestandssysteem van de gebruiker brengt altijd het risico met zich mee dat deze gegevens door een kwaadwillige persoon zijn gewijzigd. Ontwikkelaars wordt aangeraden het volgende in acht te nemen:
• Als gebruikersgegevens lokaal moeten worden opgeslagen, moeten ze worden gecodeerd bij het schrijven naar het lokale bestandssysteem. Via de klasse EncryptedLocalStore biedt de runtime unieke gecodeerde opslag voor elke geïnstalleerde toepassing. Zie “Gecodeerde gegevens opslaan” op pagina 203voor meer informatie.
• Verzend gebruikersgegevens niet ongecodeerd naar een netwerkbron, tenzij de desbetreffende bron wordt vertrouwd.
• Stel nooit een standaardwachtwoord in bij het creëren van gebruikersgegevens. Laat de gebruiker zijn of haar eigen wachtwoord instellen. Gebruikers die het standaardwachtwoord niet wijzigen, stellen hun gegevens bloot aan een aanval van iemand die het standaardwachtwoord al weet.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 44 Beveiliging in AIR
Risico van een downgradeaanval Tijdens de installatie van een toepassing controleert de runtime of de toepassing momenteel niet is geïnstalleerd. Als de toepassing al is geïnstalleerd, vergelijkt de runtime het versienummer met dat van de geïnstalleerde versie. Als beide versies niet hetzelfde nummer hebben, kan de gebruiker desgewenst de bestaande installatie upgraden. De runtime garandeert echter niet dat de nieuwe versie recenter is dan de geïnstalleerde versie, alleen dat het een andere versie is. Een aanvaller kan de gebruiker een oudere versie sturen om gebruik te maken van deze kwetsbaarheid. Daarom wordt de ontwikkelaar aangeraden een versiecontrole uit te voeren bij het starten van de toepassing. Het is een goed idee om toepassingen het netwerk te laten doorzoeken op eventuele updates. Op die manier wordt onmiddellijk een verouderde versie gedetecteerd, zelfs als een aanvaller erin geslaagd is de gebruiker een oude versie te laten installeren. Ook het gebruik van een duidelijk versieschema voor uw toepassing maakt het moeilijk om gebruikers onbedoeld een oudere versie te laten installeren. Zie “Eigenschappen definiëren in het descriptorbestand van de toepassing” op pagina 46voor meer informatie over het bieden van verschillende versies van een toepassing.
Codeondertekening Alle AIR-installatiebestanden moeten zijn voorzien van codeondertekening. Codeondertekening is een cryptografisch proces waarbij wordt bevestigd dat de opgegeven oorsprong van software correct is. U kunt AIR-toepassingen ondertekenen door een certificaat van een externe certificeringsinstantie (CI) te koppelen of door uw eigen certificaat te genereren. Een commercieel certificaat van een bekende CI wordt ten zeerste aanbevolen en biedt uw gebruikers de garantie dat ze uw toepassing installeren, en geen vervalste versie. U kunt zelfondertekende certificaten genereren via adt uit de SDK of met behulp van Flash, Flex Builder of een andere toepassing die adt gebruikt voor het genereren van certificaten. Zelfondertekende certificaten bieden echter geen enkele garantie dat de toepassing die wordt geïnstalleerd, authentiek is. Zie “AIR-bestanden digitaal ondertekenen” op pagina 305en “AIR-toepassingen maken met behulp van opdrachtregelprogramma's” op pagina 328voor meer informatie over het digitaal ondertekenen van AIRtoepassingen.
45
Hoofdstuk 8: Eigenschappen van AIRtoepassingen instellen Naast alle bestanden en andere elementen die deel uitmaken van een AIR-toepassing, heeft elke AIR-toepassing een descriptorbestand nodig. Het descriptorbestand van de toepassing is een XML-bestand dat de basiseigenschappen van de toepassing definieert. Als u AIR-toepassingen ontwikkelt met behulp van Adobe® AIR™ Update for Adobe® Flash® CS3 Professional, wordt het descriptorbestand automatisch gegenereerd wanneer u een AIR-project creëert. In het menu Opdrachten > AIR Instellingen voor toepassing en installer vindt u een deelvenster om de descriptorinstellingen te wijzigen. U kunt het descriptorbestand van de toepassing ook handmatig aanpassen.
De structuur van het descriptorbestand van de toepassing Het descriptorbestand van de toepassing bevat eigenschappen die gelden voor de volledige toepassing, zoals naam, versie, copyright enzovoort. U kunt een willekeurige naam voor het descriptorbestand van de toepassing gebruiken. Wanneer u in Flash CS3 met de standaardinstellingen een AIR-bestand maakt, wordt de naam van het descriptorbestand van de toepassing gewijzigd in application.xml en wordt het bestand in een speciale map in het AIR-pakket geplaatst. Voorbeeld van een descriptorbestand van de toepassing: com.example.HelloWorld 2.0 Hello World Example Co. AIR Hello World <description> This is a example. C'est un exemple. Esto es un ejemplo. Copyright (c) 2006 Example Co. Hello World HelloWorld-debug.swf <systemChrome>none true true <minimizable>true <maximizable>false false <width>640 480 <minSize>320 240
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 46 Eigenschappen van AIR-toepassingen instellen
<maxSize>1280 960 Example Co/Hello World <programMenuFolder>Example Co icons/smallIcon.png icons/mediumIcon.png icons/bigIcon.png icons/biggestIcon.png <customUpdateUI>true false adobe.VideoFile <extension>avf <description>Adobe Video File application/vnd.adobe.video-file icons/avfIcon_16.png icons/avfIcon_32.png icons/avfIcon_48.png icons/avfIcon_128.png
Eigenschappen definiëren in het descriptorbestand van de toepassing In zijn hoofdmap bevat het descriptorbestand van de toepassing de eigenschap application met diverse kenmerken:
xmlns De AIR-naamruimte, die u als de standaard XML-naamruimte moet definiëren. De naamruimte verandert bij elke grote release van AIR (maar niet bij kleine patches). Het laatste segment van de naamruimte, bijvoorbeeld "1.0", geeft de runtimeversie aan die de toepassing nodig heeft. minimumPatchLevel Optioneel. Gebruik het kenmerk minimumPatchLevel om het minimale patchniveau van Adobe AIR op te geven dat vereist is voor de toepassing. AIR-toepassingen geven aan welke versie van AIR ze nodig hebben door de naamruimte te definiëren in het descriptorbestand van de toepassing. De naamruimte verandert bij elke grote release van AIR (bijvoorbeeld 1.0 of 1.1). De naamruimte verandert niet bij patchreleases. Patchreleases bevatten slechts een beperkt aantal probleemoplossingen en geen API-wijzigingen. Toepassingen geven doorgaans niet aan welke patchrelease ze nodig hebben. Een probleemoplossing in een patchrelease kan echter een probleem in een toepassing verhelpen. In dat geval kan een toepassing een waarde voor het kenmerk minimumPatchLevel opgeven om zeker te zijn dat de patch wordt toegepast voordat de toepassing wordt geïnstalleerd. Indien nodig vraagt het installatieprogramma van de AIR-toepassing de gebruiker de vereiste versie of patch te downloaden en te installeren. In het volgende voorbeeld ziet u een toepassingselement dat een waarde voor het kenmerk minimumPatchLevel opgeeft:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 47 Eigenschappen van AIR-toepassingen instellen
Basisinformatie van toepassingen definiëren De volgende elementen definiëren de toepassings-id, versie, naam, bestandsnaam, beschrijving en copyrightinformatie: com.example.samples.TestApp 2.0 TestApp Hello AIR Bonjour AIR Hola AIR <description>An MP3 player. Copyright (c) 2008 YourCompany, Inc.
id Een identificatiereeks die uniek is voor de toepassing; wordt ook toepassings-id genoemd. De waarde van het kenmerk is beperkt tot de volgende tekens:
• 0-9 • a-z • A-Z • . (punt) • - (koppelteken) De waarde moet uit 1 tot 212 tekens bestaan. Dit element is vereist. De tekenreeks id gebruikt een punt als scheidingsteken, net zoals bij een omgekeerd DNS-domeinadres, een Java™pakket of -klassenaam, of een Mac OS® X Universal Type Identifier. De DNS-achtige structuur is niet verplicht en AIR brengt geen koppeling tot stand tussen de naam en daadwerkelijke DNS-domeinen. version Geeft de versie-informatie voor de toepassing op. (Is niet gerelateerd aan de versie van de runtime.) De tekenreeks voor de versie is een benaming die door de toepassing wordt gedefinieerd. AIR interpreteert de tekenreeks voor de versie helemaal niet. Met andere woorden, versie '3.0' wordt niet als recenter dan versie '2.0' beschouwd. Voorbeelden: "1.0", ".4", "0.5", "4.9", "1.3.4a". Dit element is vereist. filename De tekenreeks die als bestandsnaam van de toepassing wordt gebruikt (zonder extensie) wanneer de toepassing wordt geïnstalleerd. Het toepassingsbestand start de AIR-toepassing in de runtime. Als de waarde name niet is opgegeven, wordt filename ook als de naam van de installatiemap gebruikt. Dit element is vereist. De eigenschap filename mag een willekeurig Unicode-teken (UTF-8) bevatten, behalve de volgende tekens, omdat deze tekens in verschillende bestandssystemen niet in een bestandsnaam mogen worden gebruikt: Teken
Hexadecimale code
diverse
0x00 - x1F
*
x2A
"
x22
:
x3A
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 48 Eigenschappen van AIR-toepassingen instellen
Teken
Hexadecimale code
>
x3C
<
x3E
?
x3F
\
x5C
|
x7C
De waarde filename mag niet met een punt eindigen. name (Optioneel, maar aanbevolen) De titel die wordt weergegeven door het installatieprogramma van de AIRtoepassing. Als u één enkel tekstknooppunt opgeeft (in de plaats van meerdere text-elementen), gebruikt het installatieprogramma van de AIR-toepassing deze naam, ongeacht de systeemtaal: Test Application
In het descriptorschema van de AIR 1.0-toepassing kan slechts één enkelvoudig tekstknooppunt voor de naam worden gedefinieerd (niet meerdere tekst-elementen). In AIR 1.1 kunt u meerdere talen opgeven in het element name. Voorbeeld: de volgende code geeft de naam op in drie talen (Engels, Frans en Spaans): Hello AIR Bonjour AIR Hola AIR
Het kenmerk xml:lang voor elk tekstelement geeft een taalcode op die is gedefinieerd is in RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Het installatieprogramma van de AIR-toepassing gebruikt de naam die het best overeenkomt met de gebruikersinterfacetaal van het besturingssysteem van de gebruiker. Voorbeeld: een installatie waarbij het element name van het descriptorbestand van de toepassing een waarde bevat voor de landinstelling 'en' (Engels). Het installatieprogramma van de AIR-toepassing gebruikt de naam 'en' als het besturingssysteem 'en' (Engels) identificeert als de gebruikersinterfacetaal. Het installatieprogramma gebruikt ook de naam 'en' als de gebruikersinterfacetaal van het systeem 'en-US' (Amerikaans Engels) is. Als de gebruikersinterfacetaal echter 'en-US' is en het descriptorbestand van de toepassing zowel de naam 'en-US' als de naam 'en-GB' definieert, gebruikt het installatieprogramma van de AIR-toepassing de waarde 'en-US'. Als de toepassing geen naam definieert die overeenkomt met de gebruikersinterfacetalen van het systeem, gebruikt het installatieprogramma van de AIR-toepassing de eerste namewaarde die in het descriptorbestand van de toepassing is gedefinieerd. Als geen name-element is opgegeven, geeft het installatieprogramma van de AIR-toepassing de waarde van filename weer als de toepassingsnaam. Het element name definieert alleen de toepassingstitel die in het installatieprogramma van de AIR-toepassing wordt gebruikt. Het installatieprogramma van de AIR 1.1-toepassing ondersteunt meerdere talen: Traditioneel Chinees, Vereenvoudigd Chinees, Engels, Frans, Duits, Italiaans, Japans, Koreaans, Braziliaans Portugees, Russisch en Spaans. Het installatieprogramma van de AIR-toepassing kiest de schermtaal (voor andere tekst dan de toepassingstitel en beschrijving) op basis van de gebruikersinterfacetaal van het systeem. Deze taalkeuze is onafhankelijk van de instellingen in het descriptorbestand van de toepassing.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 49 Eigenschappen van AIR-toepassingen instellen
Het element name definieert niet de landinstellingen die beschikbaar zijn voor de actieve, geïnstalleerde toepassing. Zie “AIR-toepassingen lokaliseren” op pagina 316 voor meer informatie over het ontwikkelen van meertalige toepassingen. description (Optioneel) De beschrijving van de toepassing die wordt weergegeven in het installatieprogramma van de AIR-toepassing. Als u één enkel tekstknooppunt opgeeft (in de plaats van meerdere text-elementen), gebruikt het installatieprogramma van de AIR-toepassing deze beschrijving, ongeacht de systeemtaal: <description>This is a sample AIR application.
In het descriptorschema van de AIR 1.0-toepassing kan slechts één enkelvoudig tekstknooppunt voor de naam worden gedefinieerd (niet meerdere tekst-elementen). In AIR 1.1 kunt u meerdere talen opgeven in het element description. Voorbeeld: de volgende code geeft een beschrijving op in drie talen (Engels, Frans en Spaans): <description> This is a example. C'est un exemple. Esto es un ejemplo.
Het kenmerk xml:lang voor elk tekstelement geeft een taalcode op die is gedefinieerd is in RFC4646 (http://www.ietf.org/rfc/rfc4646.txt). Het installatieprogramma van de AIR-toepassing gebruikt de beschrijving die het best overeenkomt met de gebruikersinterfacetaal van het besturingssysteem van de gebruiker. Voorbeeld: een installatie waarbij het element description van het descriptorbestand van de toepassing een waarde bevat voor de landinstelling 'en' (Engels). Het installatieprogramma van de AIR-toepassing gebruikt de naam 'en' als het systeem van de gebruiker 'en' (Engels) identificeert als de gebruikersinterfacetaal. Het installatieprogramma gebruikt ook de naam 'en' als de gebruikersinterfacetaal van het systeem 'en-US' (Amerikaans Engels) is. Als de gebruikersinterfacetaal van het systeem echter 'en-US' is en het descriptorbestand van de toepassing zowel de naam 'en-US' als de naam 'en-GB' definieert, gebruikt het installatieprogramma van de AIR-toepassing de waarde 'en-US'. Als de toepassing geen naam definieert die overeenkomt met de gebruikersinterfacetaal van het systeem, gebruikt het installatieprogramma van de AIRtoepassing de eerste description-waarde die in het descriptorbestand van de toepassing is gedefinieerd. Zie “AIR-toepassingen lokaliseren” op pagina 316 voor meer informatie over het ontwikkelen van meertalige toepassingen. copyright (Optioneel) De copyrightinformatie voor de AIR-toepassing. In Mac OS verschijnt de copyrighttekst in het venster Over voor de geïnstalleerde toepassing. In Max OS wordt de copyrightinformatie ook gebruikt in het veld NSHumanReadableCopyright in het bestand Info.plist voor de toepassing.
De installatiemap en de programmamenumap definiëren De installatiemap en de programmamenumap worden met de volgende eigenschapsinstellingen gedefinieerd: Acme <programMenuFolder>Acme/Applications
installFolder (Optioneel) Identificeert de submap van de standaard installatiemap. In Windows is de standaard installatiemap de map Program Files. In Mac OS is dit de map /Applications. Voorbeeld: als de eigenschap installFolder is ingesteld op "Acme" en een toepassing de naam "ExampleApp" heeft, wordt de toepassing in Windows in C:\Program Files\Acme\ExampleApp en in MacOS in /Applications/Acme/Example.app geïnstalleerd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 50 Eigenschappen van AIR-toepassingen instellen
Gebruik de schuine streep (/) als mapscheidingsteken als u een geneste submap wilt opgeven, zoals in het volgende voorbeeld: Acme/Power Tools
De eigenschap installFolder mag een willekeurig Unicode-teken (UTF-8) bevatten, behalve de tekens die in verschillende bestandssystemen niet in een mapnaam mogen worden gebruikt (zie de eigenschap filename hierboven voor de lijst van uitzonderingen). De eigenschap installFolder is optioneel. Als u de eigenschap installFolder niet opgeeft, wordt de toepassing geïnstalleerd in een submap van de standaard installatiemap op basis van de eigenschap name. programMenuFolder (Optioneel) Geeft de locatie aan waar snelkoppelingen naar de toepassing worden geplaatst in het menu Alle programma's van het Windows-besturingssysteem. (Deze instelling wordt momenteel genegeerd in andere besturingssystemen.) Voor de tekens in de waarde van de eigenschap gelden dezelfde beperkingen als voor de tekens in de eigenschap installFolder. Gebruik geen schuine streep (/) als laatste teken van deze waarde.
Eigenschappen van het eerste venster van de toepassing definiëren Als een AIR-toepassing wordt geladen, gebruikt de runtime de waarden in het element initialWindow om het eerste venster voor de toepassing te maken. De runtime laadt vervolgens het SWF- of HTML-bestand dat is opgegeven in het element content, in het venster. Dit is een voorbeeld van het element initialWindow: AIRTunes.swf AIR Tunes <systemChrome>none true true <minimizable>true <maximizable>true true <width>400 600 <x>150 150 <minSize>300 300 <maxSize>800 800
De onderliggende elementen van het element initialWindow bepalen de eigenschappen van het venster waarin het hoofdinhoudsbestand wordt geladen. content De waarde die wordt opgegeven voor het element content, is de URL voor het hoofdinhoudsbestand van de toepassing. Dit kan een SWF- of een HTML-bestand zijn. De URL wordt opgegeven op basis van de hoofdmap van de installatiemap van de toepassing. (Als een AIR-toepassing met ADL wordt gebruikt, is de URL gebaseerd op de map waarin zich het descriptorbestand van de toepassing bevindt. U kunt de parameter root-dir van ADL gebruiken om een andere hoofdmap op te geven.) Opmerking: Aangezien de waarde van het element content wordt beschouwd als een URL, moeten de tekens in de naam van het inhoudsbestand URL-gecodeerd zijn overeenkomstig de regels in RFC 1738. Spaties moeten bijvoorbeeld als %20 worden gecodeerd. title (Optioneel) De venstertitel.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 51 Eigenschappen van AIR-toepassingen instellen
systemChrome (Optioneel) Als u deze eigenschap op standard instelt, wordt de standaard systeeminterface van het besturingssysteem weergegeven. Als u hier none kiest, wordt de systeeminterface niet weergegeven. De instelling van de systeeminterface kan niet worden gewijzigd tijdens de runtime. transparent (Optioneel) Stel dit element in op "true" als het toepassingsvenster alfa-overvloeiing moet ondersteunen. Het kan langer duren om een transparant venster te tekenen en dit neemt ook meer geheugen in beslag. De transparantie-instelling kan niet worden gewijzigd tijdens de runtime. Belangrijk: U kunt transparent alleen op true instellen als systemChrome op none is ingesteld. visible (Optioneel) Stel dit element op true in als het hoofdvenster zichtbaar moet zijn zodra het is gecreëerd. De standaardwaarde is false. U wordt aangeraden het hoofdvenster in eerste instantie verborgen te houden zodat wijzigingen in de vensterpositie, venstergrootte en inhoudopmaak niet zichtbaar zijn. U kunt het venster vervolgens weergeven met de methode activate() van het venster of door de eigenschap visible op true in te stellen. Zie “Werken met native vensters” op pagina 58 voor meer informatie. x, y, width, height (Optioneel) De begingrenzen van het hoofdvenster van de toepassing. Als u deze waarden niet instelt, wordt de grootte van het venster bepaald door de instellingen in het SWF-hoofdbestand, of door het besturingssysteem (als HTML wordt gebruikt). minSize, maxSize (Optioneel) De minimale en maximale grootte van het venster. Als u deze waarden niet instelt, worden ze bepaald door het besturingssysteem. minimizable, maximizable, resizable (Optioneel) Bepaalt of het venster kan worden geminimaliseerd of gemaximaliseerd en of de grootte kan worden aangepast. Deze instellingen zijn standaard op true ingesteld. Opmerking: In besturingssystemen waar het maximaliseren van een venster betekent dat de grootte van het venster wordt aangepast (bijvoorbeeld Max OS X), moet zowel maximizable als resizable op false worden ingesteld om te voorkomen dat op het venster wordt ingezoomd of dat de grootte van het venster wordt aangepast.
Pictogrambestanden opgeven De eigenschap icon geeft een of meer pictogrambestanden op die voor de toepassing moeten worden gebruikt. Een pictogram is optioneel. Als u de eigenschap icon niet opgeeft, gebruikt het besturingssysteem een standaardpictogram. Het pad wordt opgegeven op basis van de hoofdmap van de toepassing. Pictogrambestanden moeten de PNG-indeling hebben. U kunt de volgende pictogramgroottes opgeven: icons/smallIcon.png icons/mediumIcon.png icons/bigIcon.png icons/biggestIcon.png
Als een element voor een bepaalde grootte aanwezig is, moet de afbeelding in het bestand exact de opgegeven grootte hebben. Als niet alle groottes aanwezig zijn, wordt de grootte die daar het dichtst bij aansluit, door het besturingssysteem aangepast voor een bepaald gebruik van het pictogram. Opmerking: De opgegeven pictogrammen worden niet automatisch toegevoegd aan het AIR-pakket. De pictogrambestanden moeten in hun correcte relatieve locaties worden opgenomen wanneer de toepassing wordt verpakt. Voor de beste resultaten geeft u voor elke beschikbare grootte een afbeelding op. Bovendien moeten de pictogrammen er goed uitzien in zowel 16- als 32-bit kleuren.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 52 Eigenschappen van AIR-toepassingen instellen
Aangepaste gebruikersinterfaces voor toepassingsupdates bieden AIR gebruikt de standaard installatievensters voor het installeren en updaten van toepassingen. U kunt echter ook uw eigen gebruikersinterface creëren voor het updaten van een toepassing. Om aan te geven dat uw toepassing het updateproces zelf afhandelt, stelt u het element customUpdateUI op true in: <customUpdateUI>true
Wanneer het element customUpdateUI in de geïnstalleerde versie van uw toepassing op true is ingesteld en de gebruiker op het AIR-bestand dubbelklikt voor een nieuwe versie of een update van de toepassing installeert met behulp van de functie voor naadloze installatie, opent de runtime de geïnstalleerde versie van de toepassing in plaats van het standaard installatieprogramma van de AIR-toepassing. De logica van uw toepassing kan vervolgens bepalen hoe de update verder wordt afgehandeld. (De toepassings- en uitgevers-id in het AIR-bestand moeten overeenkomen met die in de geïnstalleerde toepassing, anders kan de upgrade niet verdergaan.) Opmerking: Het mechanisme customUpdateUI wordt alleen gebruikt als de toepassing al is geïnstalleerd en de gebruiker op het AIR-installatiebestand dubbelklikt dat een update bevat of een update van de toepassing installeert met behulp van de functie voor naadloze installatie. U kunt een update downloaden en starten via de logica van uw eigen toepassing en desgewenst uw eigen gebruikersinterface weergeven, ongeacht of customUpdateUI op true is ingesteld. Zie “AIR-toepassingen updaten” op pagina 312 voor meer informatie.
Toepassingen laten oproepen vanuit een browser Met de volgende instelling kan de geïnstalleerde AIR-toepassing worden gestart met de browseroproepfunctie (door op een koppeling te klikken op een pagina in een webbrowser): true
De standaardwaarde is false. Als u deze waarde op true instelt, moet u een aantal gevolgen voor de beveiliging in acht nemen. Zie hiervoor “Oproepen vanuit browser” op pagina 278. Zie “AIR-toepassingen installeren en uitvoeren vanaf een webpagina” op pagina 297 voor meer informatie.
Koppelingen van bestandstypen registreren Met het element fileTypes kunt u de bestandstypen definiëren waaraan een AIR-toepassing kan worden gekoppeld. Als een AIR-toepassing is geïnstalleerd, worden alle gedefinieerde bestandstypen in het besturingssysteem geregistreerd. Als deze bestandstypen nog niet aan een andere toepassing zijn gekoppeld, worden ze aan de AIRtoepassing gekoppeld. Als u een bestaande koppeling tussen een bestandstype en een andere toepassing wilt overschrijven, gebruikt u de methode NativeApplication.setAsDefaultApplication() tijdens de runtime (bij voorkeur met toestemming van de gebruiker). Opmerking: De runtimemethoden kunnen alleen koppelingen beheren voor de bestandstypen die zijn opgegeven in het descriptorbestand van de toepassing.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 53 Eigenschappen van AIR-toepassingen instellen
adobe.VideoFile <extension>avf <description>Adobe Video File application/vnd.adobe.video-file icons/AIRApp_16.png icons/AIRApp_32.png icons/AIRApp_48.png icons/AIRApp_128.png
Het element fileTypes is optioneel. Als dit element is opgegeven, kan het een willekeurig aantal fileType-elementen bevatten. De elementen name en extension zijn vereist voor elke fileType-definitie die u opgeeft. Dezelfde naam kan voor meerdere extensies worden gebruikt. De extensie definieert het bestandstype op unieke wijze. (Let op: de extensie wordt opgegeven zonder de voorafgaande punt.) Het element description is optioneel en wordt weergegeven door de gebruikersinterface van het besturingssysteem. Ook de eigenschap contentType is optioneel. Hiermee kan het besturingssysteem in bepaalde omstandigheden de beste toepassing kiezen om een bestand te openen. De waarde moet het MIME-type van de bestandsinhoud zijn. Voor de bestandsextensie kunnen pictogrammen worden opgegeven, waarbij dezelfde indeling wordt gebruikt als het pictogramelement van de toepassing. De pictogrambestanden moeten ook in het AIR-installatiebestand worden opgenomen (ze worden niet automatisch in het pakket opgenomen). Als een bestandstype aan een AIR-toepassing is gekoppeld, wordt de toepassing opgeroepen wanneer een gebruiker een bestand van dat type opent. Als de toepassing al actief is, verzendt AIR het InvokeEvent-object naar de actieve instantie. Als de toepassing nog niet actief is, wordt deze eerst gestart. In beide gevallen kan het pad naar het bestand worden opgehaald uit het InvokeEvent-object dat door het NativeApplication-object is verstuurd. U kunt dit pad gebruiken om het bestand te openen. Zie “Bestandskoppelingen beheren” op pagina 284 en “Opdrachtregelargumenten vastleggen” op pagina 276 voor meer informatie.
54
Hoofdstuk 9: Nieuwe functionaliteit in Adobe AIR Dit onderwerp bevat een overzicht van de nieuwe functionaliteit in Adobe® AIR™ die niet beschikbaar is voor SWFinhoud die wordt uitgevoerd in Adobe® Flash® Player.
Nieuwe runtimeklassen De volgende runtimeklassen zijn nieuw in Adobe AIR. Deze zijn niet beschikbaar voor SWF-inhoud die wordt uitgevoerd in de browser: Klasse
Pakket
BrowserInvokeEvent
flash.events
Clipboard
flash.desktop
ClipboardFormats
flash.desktop
ClipboardTransferMode
flash.desktop
CompressionAlgorithm
flash.utils
DockIcon
flash.desktop
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
HTMLWindowCreateOptions
flash.html
Icon
flash.desktop
InteractiveIcon
flash.desktop
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 55 Nieuwe functionaliteit in Adobe AIR
Klasse
Pakket
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
SQLIndexSchema
flash.data
SQLResult
flash.data
SQLSchema
flash.data
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 56 Nieuwe functionaliteit in Adobe AIR
Klasse
Pakket
SQLSchemaResult
flash.data
SQLStatement
flash.data
SQLTableSchema
flash.data
SQLTransactionLockType
flash.data
SQLTriggerSchema
flash.data
SQLUpdateEvent
flash.events
SQLViewSchema
flash.data
SystemTrayIcon
flash.desktop
Updater
flash.desktop
URLRequestDefaults
flash.net
XMLSignatureValidator
flash.utils
In het pakket flash.security is ook de interface IURIDereferencer opgenomen.
Runtimeklassen met nieuwe functionaliteit De volgende klassen zijn beschikbaar voor SWF-inhoud die wordt uitgevoerd in de browser, maar AIR beschikt over aanvullende eigenschappen of methoden: Klasse
Eigenschap of methode
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
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 57 Nieuwe functionaliteit in Adobe AIR
Klasse
Eigenschap of methode
LoaderInfo
parentSandboxBridge childSandboxBridge
NetStream
resetDRMVouchers()
setDRMAuthenticationCredentials() URLRequest
followRedirects manageCookies shouldAuthenticate shouldCacheResponse userAgent userCache setLoginCredentials()
URLStream
httpResponseStatus event
Stage
nativeWindow
Security
APPLICATION
De meeste van deze nieuwe eigenschappen en methoden zijn alleen beschikbaar voor inhoud in de beveiligingssandbox van de AIR-toepassing. De nieuwe leden van de URLRequest-klassen zijn echter ook beschikbaar voor inhoud die wordt uitgevoerd in andere sandboxen. De methoden ByteArray.compress() en ByteArray.uncompress() bevatten elk een nieuwe parameter algorithm waarmee u kunt kiezen tussen Deflate- en ZLIB-compressie.
Klassen voor het framework voor servicecontrole Het pakket air.net bevat klassen voor netwerkdetectie. Dit pakket is alleen beschikbaar voor inhoud die wordt uitgevoerd in Adobe AIR. Het is opgenomen in het bestand ServiceMonitor.swc. Dit pakket bevat de volgende klassen:
• ServiceMonitor • SocketMonitor • URLMonitor
58
Hoofdstuk 10: Werken met native vensters U kunt de klassen die door de Adobe® AIR® API voor native vensters worden geboden, gebruiken om bureaubladvensters te creëren en te beheren.
Aanvullende online informatie over native vensters In de volgende informatiebronnen vindt u meer informatie over de API voor native vensters en het werken met native vensters: Snelstarthandleidingen (Adobe AIR Developer Connection) • Interactie met een venster
• Het uiterlijk van een native venster aanpassen • Eenvoudige, rechthoekige (toast-stijl) informatievensters maken • Bepalen in welke volgorde vensters worden weergegeven • In grootte verstelbare, niet-rechthoekige vensters maken Language Reference • NativeWindow
• NativeWindowInitOptions Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar 'AIR windows')
Basisinformatie over AIR-vensters AIR biedt een gebruikersvriendelijke API die op meerdere platforms kan worden gebruikt. Met deze API voor vensters kunnen met Flash®-, Flex™- en HTML-programmeertechnieken native vensters worden gemaakt (dit zijn vensters die eigen zijn aan het besturingssysteem). Met AIR hebt u een grote vrijheid bij het ontwikkelen van het uiterlijk van uw toepassing. De vensters die u maakt, kunnen er net zo uitzien als die van een standaard bureaubladtoepassing. De vensters hebben in dat geval de Applestijl als ze op de Mac worden weergegeven en voldoen aan de regels van Microsoft als ze in Windows worden weergegeven. U kunt echter ook de uitbreidbare interface met verwisselbare skins (weergaven) gebruiken die door het Flex-framework wordt geboden. Met deze interface kunt u uw eigen stijl ontwikkelen, ongeacht het besturingssysteem waarin uw toepassing wordt uitgevoerd. U kunt zelfs uw eigen vensters tekenen met vector- en bitmap-illustraties met volledige ondersteuning voor transparantie. Ook alfa-overvloeiing wordt ondersteund, waarmee u een gedeeltelijk transparant venster kunt laten overvloeien in de bureaubladachtergrond. Hebt u genoeg van die rechthoekige vensters? Teken eens een rond venster.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 59 Werken met native vensters
Vensters in AIR AIR ondersteunt drie API's voor het werken met vensters: de ActionScript-georiënteerde klasse NativeWindow, de klassen mx:WindowedApplication en mx:Window van het Flex-framework, waarin de klasse NativeWindow is verpakt, en de JavaScript-klasse Window in de HTML-omgeving. ActionScript-vensters Wanneer u vensters maakt met de klasse NativeWindow, kunt u rechtstreeks gebruikmaken van de stage en weergavelijst van Flash Player. Als u visuele objecten aan een NativeWindow wilt toevoegen, voegt u het object toe aan de weergavelijst van de vensterstage of aan een andere weergaveobject op de stage. Flex-frameworkvensters Het Flex-framework definieert zijn eigen venstercomponenten waarin de NativeWindow-API is verpakt. Deze componenten, mx:WindowedApplication en mx:Window, kunnen niet buiten het framework worden gebruikt, en kunnen dus niet worden gebruikt in AIR-toepassingen die met het Flash-programma voor het schrijven van programmacode zijn ontworpen. HTML-vensters Wanneer u HTML-vensters maakt, gebruikt u HTML, CSS en JavaScript om inhoud weer te geven. Als u een visueel object aan een HTML-venster wilt toevoegen, voegt u die inhoud toe aan het HTML DOM. HTML-vensters vormen een speciale categorie van NativeWindow. De AIR-host definieert in HTML-vensters een nativeWindow-eigenschap die toegang biedt tot de onderliggende NativeWindow-instantie. U kunt deze eigenschap gebruiken om toegang te krijgen tot de NativeWindow-eigenschappen, -methoden en -gebeurtenissen die hier worden beschreven. Opmerking: Het JavaScript-object Window heeft ook methoden voor het schrijven van scripts voor het venster waarin het object zich bevindt, zoals moveTo() en close(). Wanneer er methoden beschikbaar zijn die elkaar overlappen, kunt u de methode gebruiken die het handigst is. Het beginvenster van de toepassing Het eerste venster van uw toepassing wordt automatisch voor u gemaakt door AIR. AIR stelt de eigenschappen en inhoud van het venster in met de parameters die zijn opgegeven in het element initialWindow van het descriptorbestand van de toepassing. Als de inhoud van de hoofdmap een SWF-bestand is, maakt AIR een NativeWindow-instantie, laadt het dit SWFbestand en voegt het dit bestand toe aan de vensterstage. Als de inhoud van de hoofdmap een HTML-bestand is, maakt AIR een HTML-venster en laadt het dit HTML-bestand. Zie “De structuur van het descriptorbestand van de toepassing” op pagina 45 voor meer informatie over de venstereigenschappen die zijn opgegeven in de toepassingsdescriptor.
Klassen van native vensters De API voor native vensters bevat de volgende klassen:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 60 Werken met native vensters
Pakket
Klassen
flash.display
•
NativeWindow
•
NativeWindowInitOptions
•
NativeWindowDisplayState
•
NativeWindowResize
•
NativeWindowSystemChrome
•
NativeWindowType
Tekenreeksconstanten voor vensters worden gedefinieerd in de volgende klassen:
flash.events
•
NativeWindowDisplayState
•
NativeWindowResize
•
NativeWindowSystemChrome
•
NativeWindowType
•
NativeWindowBoundsEvent
•
NativeWindowDisplayStateEvent
Gebeurtenisstromen voor native vensters Native vensters verzenden gebeurtenissen om belanghebbende componenten te melden dat er een belangrijke wijziging zal worden doorgevoerd of al is doorgevoerd. Veel gebeurtenissen die betrekking hebben op vensters, worden in paren verzonden. De eerste gebeurtenis waarschuwt dat er binnenkort een verandering zal plaatsvinden. De tweede gebeurtenis meldt dat de wijziging heeft plaatsgevonden. U kunt een waarschuwingsgebeurtenis annuleren, maar een meldingsgebeurtenis niet. De volgende reeks gebeurtenissen laat zien hoe de gebeurtenisstroom loopt wanneer een gebruiker op de knop Maximaliseren van een venster klikt: 1 Het NativeWindow-object verzendt de gebeurtenis displayStateChanging. 2 Als de gebeurtenis niet door geregistreerde listeners wordt geannuleerd, wordt het venster gemaximaliseerd. 3 Het NativeWindow-object verzendt de gebeurtenis displayStateChange.
Daarnaast verzendt het NativeWindow-object ook gebeurtenissen voor gerelateerde wijzigingen in het formaat en de positie van het venster. Het venster verzendt geen waarschuwingsgebeurtenissen voor deze gerelateerde wijzigingen. De gerelateerde wijzigingen zijn: a De gebeurtenis move wordt verzonden als de linkerbovenhoek van het vensters is verplaatst als gevolg van het
maximaliseren. b De gebeurtenis resize wordt verzonden als het vensterformaat is gewijzigd als gevolg van het maximaliseren.
Het NativeWindow-object verzendt een vergelijkbare reeks gebeurtenissen bij het minimaliseren, sluiten en verplaatsen van vensters en bij het wijzigen of herstellen van het formaat van vensters. De waarschuwingsgebeurtenissen worden alleen verzonden wanneer een wijziging is geactiveerd via de vensterinterface of andere door het besturingssysteem gecontroleerde mechanismen. Wanneer u een venstermethode oproept om het formaat, de positie of de weergavestatus te wijzigen, verzendt het venster alleen een gebeurtenis om de wijziging te melden. U kunt desgewenst een waarschuwingsgebeurtenis verzenden met de methode dispatchEvent() van het venster en vervolgens controleren of uw waarschuwingsgebeurtenis is geannuleerd voordat u de wijziging doorvoert.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 61 Werken met native vensters
Zie ActionScript 3.0 Language and Components Reference (http://www.adobe.com/go/learn_flash_aslr_nl) voor gedetailleerde informatie over de klassen, methoden, eigenschappen en gebeurtenissen van de API voor vensters. Zie de sectie over het programmeren van de weergave in ActionScript 3.0 programmeren (http://www.adobe.com/go/programmingAS3_nl) voor algemene informatie over het gebruik van de Flashweergavelijst.
Eigenschappen die de stijl en het gedrag van een native venster bepalen De volgende eigenschappen bepalen het basisuiterlijk en -gedrag van een venster:
•
type
•
systemChrome
•
transparent
Wanneer u een venster maakt, stelt u deze eigenschappen in voor het NativeWindowInitOptions-object dat aan de vensterconstructor wordt doorgegeven. AIR leest de eigenschappen voor het beginvenster van de toepassing vanuit de toepassingsdescriptor. (Dit geldt niet voor de eigenschap type, die niet in de toepassingsdescriptor kan worden ingesteld en altijd is ingesteld op normal.) De eigenschappen kunnen niet worden gewijzigd nadat het venster is gemaakt. Sommige instellingen van deze eigenschappen sluiten elkaar uit: systemChrome kan niet worden ingesteld op standard als transparent is ingesteld op true of als type is ingesteld op lightweight.
Venstertypen In de venstertypen van AIR zijn de interface- en zichtbaarheidskenmerken van het oorspronkelijke besturingssysteem gecombineerd. Op die manier zijn er drie functionele typen vensters ontstaan. Gebruik de constanten die in de klasse NativeWindowType zijn gedefinieerd, om in de code te verwijzen naar de naam van de typen. AIR biedt de volgende venstertypen: Type
Beschrijving
Normaal
Dit is een normaal venster. Normale vensters maken gebruik van het maximale formaat van de interface en verschijnen op de taakbalk van Windows en in het venstermenu van Mac OS X.
Utiliteit
Dit is een venster met een palet met hulpmiddelen. Utiliteitsvensters maken gebruik van een afgeslankte versie van de systeeminterface en verschijnen niet op de taakbalk van Windows of in het venstermenu van Mac OS X.
Lichtgewicht
Lichtgewicht vensters hebben geen interface en verschijnen niet op de taakbalk van Windows of in het venstermenu van Mac OS X. Bovendien beschikken lichtgewicht vensters niet over een systeemmenu (Alt+Spatiebalk) in Windows. Lichtgewicht vensters zijn geschikt voor het weergeven van ballonnetjes met mededelingen en voor besturingselementen, zoals keuzelijsten met invoervak die kortstondig een weergavegebied openen. Wanneer het lichtgewicht venster type wordt gebruikt, moet systemChrome zijn ingesteld op none.
Vensterinterface De vensterinterface bestaat uit een set besturingselementen waarmee gebruikers een venster in de bureaubladomgeving kunnen manipuleren. Tot de interface-elementen behoren de titelbalk, titelbalkknoppen, vensterrand en formaatgrepen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 62 Werken met native vensters
Systeeminterface U kunt de eigenschap systemChrome instellen op standard of none. Kies standard voor de systeeminterface als u het venster wilt voorzien van de reeks standaard besturingselementen die worden gemaakt en vormgegeven door het besturingssysteem van de gebruiker. Kies none als u het venster wilt voorzien van uw eigen interface. Gebruik de constanten die in de klasse NativeWindowSystemChrome zijn gedefinieerd, om in de code te verwijzen naar de instellingen van de systeeminterface. De systeeminterface wordt beheerd door het systeem. Uw toepassing heeft niet rechtstreeks toegang tot de besturingselementen zelf, maar kan reageren op de gebeurtenissen die worden verzonden wanneer de besturingselementen worden gebruikt. Wanneer u de standaardinterface gebruikt voor een venster, moet de eigenschap transparent zijn ingesteld op false en moet de eigenschap type zijn ingesteld op normal of utility. Aangepaste interface Wanneer u een venster maakt zonder systeeminterface, moet u uw eigen interfacebesturingselementen toevoegen om de interactie tussen een gebruiker en het venster mogelijk te maken en te sturen. U hebt ook de mogelijkheid om transparante, niet-rechthoekige vensters te maken.
Venstertransparantie Als u alfa-overvloeiing wilt toestaan, waarbij het venster deels transparant wordt en overvloeit in de bureaubladachtergrond of in andere vensters, stelt u de eigenschap transparent van het venster in op true. De eigenschap transparent moet worden ingesteld voordat het venster wordt gemaakt en kan niet worden gewijzigd als het venster eenmaal is gemaakt. Een transparant venster heeft geen standaardachtergrond. Elk venstergebied dat geen object bevat dat door de toepassing is getekend, is onzichtbaar. Als voor een weergegeven object de alfa-instelling kleiner is dan één, is alles wat zich onder het object bevindt, gedeeltelijk zichtbaar door het object heen, inclusief eventuele andere weergaveobjecten, andere vensters en het bureaublad. Het opbouwen van het beeld van grote gebieden waarop alfa-overvloeiing is toegepast, kan veel tijd kosten. Gebruik dit effect daarom slechts met mate. Transparante vensters zijn handig wanneer u toepassingen wilt maken met randen die onregelmatig van vorm zijn, geleidelijk vervagen of onzichtbaar lijken. Transparantie kan niet worden gebruikt voor vensters die gebruikmaken van de systeeminterface. Bovendien wordt SWF- en PDF-inhoud in HTML niet weergegeven in transparante vensters. Zie “Belangrijke opmerkingen voor het laden van SWF- of PDF-inhoud in een HTML-pagina” op pagina 247 voor meer informatie. In bepaalde besturingssystemen wordt transparantie niet ondersteund omdat de hardware- of softwareconfiguratie dat niet toestaat of omdat de door de gebruiker gekozen weergaveopties dat verhinderen. Als transparantie niet wordt ondersteund, wordt de toepassing tegen een zwarte achtergrond geplaatst. In deze gevallen worden alle volledig transparante gebieden van de toepassingsvensters als ondoorzichtig zwarte gebieden weergegeven. De statische eigenschap NativeWindow.supportsTransparency geeft aan of venstertransparantie beschikbaar is. Als uit de test blijkt dat deze eigenschap de waarde false heeft, kunt u bijvoorbeeld een waarschuwingsvenster weergeven voor de gebruiker of de rechthoekige, niet-transparante gebruikersinterface weergeven die u voor dit soort gevallen achter de hand hebt. Bedenk dat transparantie altijd wordt ondersteund door Mac- en Windowsbesturingssystemen. Voor ondersteuning in Linux-besturingssystemen is een hulpprogramma voor samenstellend vensterbeheer vereist. Het is ook mogelijk dat vensterbeheer niet beschikbaar is vanwege de door de gebruiker gekozen weergaveopties of de hardwareconfiguratie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 63 Werken met native vensters
Transparantie in een HTML-toepassingsvenster De achtergrond van HTML-inhoud die in HTML-vensters en HTMLLoader-objecten wordt weergegeven, is standaard ondoorzichtig, zelfs als het venster waarin de inhoud wordt weergegeven, transparant is. Als u de standaardachtergrond wilt uitschakelen die voor HTML-inhoud wordt weergegeven, stelt u de eigenschap paintsDefaultBackground in op false. In het volgende voorbeeld wordt een HTMLLoader gemaakt en wordt de standaardachtergrond uitgeschakeld: var html:HTMLLoader = new HTMLLoader(); html.paintsDefaultBackground = false;
In dit voorbeeld wordt JavaScript gebruikt om de standaardachtergrond van een HTML-venster uit te schakelen: window.htmlLoader.paintsDefaultBackground = false;
Als een element in het HTML-document een achtergrondkleur instelt, is de achtergrond van dat element niet transparant. Het instellen van een waarde voor gedeeltelijke transparantie (of matheid) wordt niet ondersteund. U kunt echter een transparante afbeelding in de PNG-indeling als achtergrond voor een pagina of pagina-element gebruiken om een vergelijkbaar visueel effect te krijgen.
Een visuele venstercatalogus In de volgende tabel worden de visuele effecten van de verschillende combinaties van instellingen van venstereigenschappen getoond in Mac OS X- en Windows-besturingssystemen: Vensterinstellingen Type: normal SystemChrome: standard Transparent: false
Type: utility SystemChrome: standard Transparent: false
Mac OS X
Microsoft Windows
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 64 Werken met native vensters
Vensterinstellingen
Mac OS X
Microsoft Windows
Type: alle SystemChrome: none Transparent: false
Type: alle SystemChrome: none Transparent: true
mxWindowedApplication of mx:Window Type: alle SystemChrome: none Transparent: true
Opmerking: De volgende elementen van de systeeminterface worden niet door AIR ondersteund: de werkbalk van OS X, het proxypictogram van OS X, de titelbalkpictogrammen van Windows en een alternatieve systeeminterface.
Vensters maken AIR maakt automatisch het eerste venster voor een toepassing, maar u kunt zelf alle extra vensters maken die u nodig hebt. Als u een native venster wilt maken, gebruikt u de constructormethode NativeWindow. Als u een HTML-venster wilt maken, gebruikt u de HTMLLoader-methode createRootWindow() of roept u vanuit een HTML-document de JavaScript-methode window.open() op.
Initialisatie-eigenschappen voor vensters opgeven De initialisatie-eigenschappen van een venster kunnen niet worden gewijzigd nadat het bureaubladvenster is gemaakt. De volgende tabel bevat deze onveranderbare eigenschappen en hun standaardwaarden: Eigenschap
Standaardwaarde
systemChrome
standard
type
normal
transparent
false
maximizable
true
minimizable
true
resizable
true
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 65 Werken met native vensters
U kunt de eigenschappen voor het beginvenster dat door AIR wordt gemaakt, in het descriptorbestand van de toepassing instellen. Het hoofdvenster van een AIR-toepassing is altijd van het type normal. (Er kunnen ook extra venstereigenschappen worden opgegeven in het descriptorbestand, zoals visible, width en height, maar deze eigenschappen kunnen op elk gewenst moment worden gewijzigd.) De eigenschappen voor andere native vensters en HTML-vensters die door uw toepassing zijn gemaakt, kunt u instellen met de klasse NativeWindowInitOptions. Wanneer u een venster maakt, moet u een NativeWindowInitOptions-object waarin de venstereigenschappen zijn opgegeven, doorgeven aan de constructorfunctie NativeWindow of de HTMLLoader-methode createRootWindow(). Met de volgende code maakt u een NativeWindowInitOptions-object voor een utiliteitsvenster: var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = NativeWindowSystemChrome.STANDARD; options.type = NativeWindowType.UTILITY options.transparent = false; options.resizable = false; options.maximizable = false;
U kunt systemChrome niet instellen op standard wanneer transparent is ingesteld op true of type is ingesteld op lightweight. Opmerking: U kunt voor een venster dat is gemaakt met de JavaScript-functie window.open() geen initialisatieeigenschappen instellen. U kunt de manier waarop deze vensters zijn gemaakt, echter negeren door uw eigen HTMLHostklasse te implementeren. Zie “JavaScript-oproepen van window.open() afhandelen” op pagina 256 voor meer informatie.
Het beginvenster van de toepassing maken AIR maakt het beginvenster van de toepassing op basis van de eigenschappen die zijn opgegeven in de toepassingsdescriptor en laadt het bestand waarnaar wordt verwezen in het element content. De inhoud moet een SWF- of HTML-bestand zijn. Het beginvenster kan het hoofdvenster van uw toepassing zijn, maar het kan ook alleen maar worden gebruikt om een of meer andere vensters te starten. U hoeft dit beginvenster niet zichtbaar te maken. Het Flash-programma voor het schrijven van programmacode maakt automatisch het SWF-bestand en voegt de juiste verwijzing aan de toepassingsdescriptor toe wanneer u een project voor AIR test of publiceert. De hoofdtijdlijn fungeert als toegangspunt voor uw toepassing. Wanneer uw toepassing wordt gestart, maakt AIR een venster en wordt vervolgens het SWF-bestand van de toepassing in dat venster geladen. Als u het bureaubladvenster met ActionScript wilt besturen, gebruikt u de eigenschap nativeWindow van het Stage-object om een verwijzing naar het NativeWindow-object te verkrijgen. U kunt vervolgens de eigenschappen van het venster instellen en de venstermethoden oproepen. In het volgende voorbeeld wordt het hoofdvenster in gemaximaliseerde staat geactiveerd (vanuit het eerste frame van een Flash-FLA): import flash.display.NativeWindow; var mainWindow:NativeWindow = this.stage.nativeWindow; mainWindow.maximize(); mainWindow.activate();
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 66 Werken met native vensters
NativeWindows maken Als u een NativeWindow wilt maken, geeft u een NativeWindowInitOptions-object door aan de NativeWindowconstructor: var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = NativeWindowSystemChrome.STANDARD; options.transparent = false; var newWindow:NativeWindow = new NativeWindow(options);
Het venster wordt pas weergegeven nadat u de eigenschap visible op true hebt ingesteld of de methode activate() hebt opgeroepen. Als het venster eenmaal is gemaakt, kunt u de eigenschappen van het venster initialiseren en inhoud in het venster laden met de eigenschap stage en de Flash-technieken voor weergavelijsten. In vrijwel alle gevallen kunt u de eigenschap scaleMode van een nieuw native venster het best instellen op noScale (gebruik de constante StageScaleMode.NO_SCALE). De schaalmodi van Flash zijn ontworpen voor situaties waarin de auteur van de toepassing niet van tevoren weet wat de hoogte-breedteverhouding van het weergavegebied voor de toepassing zal zijn. Met de schaalmodi kan de auteur het minst slechte compromis kiezen: de inhoud bijsnijden, uitrekken of samenduwen, of omgeven met lege ruimte. Omdat u de weergaveruimte in AIR (het vensterframe) zelf kunt bepalen, kunt u het formaat van het venster aanpassen aan de inhoud of de inhoud aanpassen aan het venster zonder compromissen te sluiten. Opmerking: Als u wilt bepalen wat de maximum- en minimumgrootte van een venster is in het huidige besturingssysteem, gebruikt u de volgende statische NativeWindow-eigenschappen: var maxOSSize:Point = NativeWindow.systemMaxSize; var minOSSize:Point = NativeWindow.systemMinSize;
HTML-vensters maken Als u een HTML-venster wilt maken, kunt u de JavaScript-methode Window.open() of de methode createRootWindow() van de AIR-klasse HTMLLoader oproepen. Voor HTML-inhoud in een willekeurige beveiligingssandbox kan de standaard JavaScript-methode Window.open() worden gebruikt. Als de inhoud buiten de toepassingssandbox wordt uitgevoerd, kan de methode open() alleen worden opgeroepen als reactie op een handeling van de gebruiker, zoals het klikken met de muis of het indrukken van een toets. Wanneer open() wordt opgeroepen, wordt er een venster met de systeeminterface gemaakt waarin de inhoud van de opgegeven URL wordt weergegeven. Bijvoorbeeld: newWindow = window.open("xmpl.html", "logWindow", "height=600, width=400, top=10, left=10");
Opmerking: U kunt de klasse HTMLHost in ActionScript uitbreiden om het venster dat met de JavaScript-functie window.open() is gemaakt, naar wens aan te passen. Zie “Informatie over het uitbreiden van de klasse HTMLHost” op pagina 251. Inhoud in de beveiligingssandbox van de toepassing heeft toegang tot de methode HTMLLoader.createRootWindow(), die meer mogelijkheden biedt bij het maken van vensters. Met deze methode kunt u alle opties voor het maken van een nieuw venster zelf opgeven. Met de volgende JavaScript-code maakt u bijvoorbeeld een lichtgewicht venster zonder systeeminterface, dat 300 x 400 pixels groot is:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 67 Werken met native vensters
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"));
Opmerking: als de inhoud die wordt geladen door een nieuw venster, zich buiten de toepassingsbeveiligingssandbox bevindt, zijn de volgende AIR-eigenschappen niet beschikbaar voor het vensterobject: runtime, nativeWindow en htmlLoader. Vensters die zijn gemaakt met de methode createRootWindow(), blijven onafhankelijk van het openingsvenster. De eigenschappen parent en opener van het JavaScript-object Window zijn ingesteld op null. Het openingsvenster heeft toegang tot het Window-object van het nieuwe venster met behulp van de HTMLLoader-verwijzing, die is geretourneerd door de functie createRootWindow(). In de context van het vorige voorbeeld wordt met de instructie newHTMLLoader.window verwezen naar het JavaScript-object Window van het gemaakte venster. Opmerking: De functie createRootWindow() kan zowel vanuit JavaScript als vanuit ActionScript worden opgeroepen.
Inhoud toevoegen aan een venster Hoe u inhoud toevoegt aan een AIR-venster hangt af van het type venster. U kunt een filmclip maken en de tijdlijn gebruiken om de status van de toepassing te bepalen. In HTML kunt u de basisinhoud van het venster declaratief definiëren. U kunt bronnen insluiten in de toepassings-SWF of deze laden vanuit afzonderlijke toepassingsbestanden. Flash- en HTML-inhoud kan op elk gewenst moment worden gemaakt en dynamisch aan een venster worden toegevoegd. Wanneer u SWF-inhoud laadt, of HTML-inhoud die JavaScript bevat, moet u rekening houden met het beveiligingsmodel van AIR. Alle inhoud in de toepassingsbeveiligingssandbox, dat wil zeggen de inhoud die met uw toepassing is geïnstalleerd en kan worden geladen met het schema app: URL, heeft alle benodigde rechten om toegang te krijgen tot alle API's van AIR. Inhoud die van buiten deze sandbox wordt geladen, heeft geen toegang tot de API's van AIR. JavaScript-inhoud buiten de toepassingssandbox kan de eigenschappen runtime, nativeWindow en htmlLoader van het JavaScript-object Window niet gebruiken. Voor veilige cross-scripting kunt u een sandboxbridge gebruiken om een beperkte interface te bieden tussen toepassingsinhoud en niet-toepassingsinhoud. In HTML-inhoud kunt u ook pagina's van uw toepassing aan een niettoepassingssandbox toewijzen om de code op die pagina's de mogelijkheid van cross-scripting met externe inhoud te bieden. Zie “Beveiliging in AIR” op pagina 24. SWF-bestanden of afbeeldingen laden U kunt Flash-bestanden of afbeeldingen in de weergavelijst van een native venster laden met de klasse flash.display.Loader:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 68 Werken met native vensters
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); } } }
U kunt een SWF-bestand laden dat bibliotheekcode bevat voor gebruik in een HTML-toepassing. U kunt een SWFbestand heel eenvoudig in een HTML-venster laden met de tagscript, maar u kunt ook direct de Loader-API gebruiken. Opmerking: Oudere SWF-bestanden die zijn gemaakt met ActionScript 1 of 2, delen globale statussen, zoals klassedefinities, singletons en globale variabelen, als deze in hetzelfde venster worden geladen. Als een dergelijk SWFbestand alleen goed kan werken als de globale statussen ongewijzigd zijn, kan het bestand niet meer dan één keer in hetzelfde venster worden geladen. Het bestand kan in dat geval ook niet worden geladen in een venster waarin zich een ander SWF-bestand bevindt dat gebruikmaakt van overlappende klassedefinities en variabelen. Deze inhoud kan in aparte vensters worden geladen. HTML-inhoud in een NativeWindow laden Als u HTML-inhoud in een NativeWindow wilt laden, kunt u een HTMLLoader-object aan de vensterstage toevoegen en de HTML-inhoud in de HTMLLoader laden, of een venster maken dat al een HTMLLoader-object bevat met de methode HTMLLoader.createRootWindow(). In het volgende voorbeeld wordt HTML-inhoud weergegeven binnen een weergavegebied van 300 x 500 pixels op de stage van een native venster: //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) );
Opmerking: SWF- of PDF-inhoud in een HTML-bestand wordt niet weergegeven als in het venster transparantie wordt gebruikt (dat wil zeggen als de eigenschap transparent van het venster is ingesteld op true) of als het HTMLLoaderbesturingselement is geschaald.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 69 Werken met native vensters
SWF-inhoud toevoegen als laag boven op een HTML-venster Omdat HTML-vensters zich binnen een NativeWindow-instantie bevinden, kunt u zowel boven als onder de HTMLlaag in de weergavelijst Flash-weergaveobjecten toevoegen. Als u een weergaveobject boven de HTML-laag wilt toevoegen, moet u de methode addChild() van de eigenschap window.nativeWindow.stage gebruiken. Met de methode addChild() voegt u inhoud toe als een laag boven alle bestaande inhoud in het venster. Als u een weergaveobject onder de HTML-laag wilt toevoegen, moet u de methode addChildAt() van de eigenschap window.nativeWindow.stage gebruiken, waarbij u de waarde nul doorgeeft voor de parameter index. Als u een object op de nulindex plaatst, wordt bestaande inhoud, inclusief de HTML-weergave, één laag hoger geplaatst en wordt de nieuwe inhoud helemaal onderaan ingevoegd. Als u wilt dat inhoud op lagen onder de HTML-pagina zichtbaar is, moet u de eigenschap paintsDefaultBackground van het object HTMLlLoader op false instellen. Bovendien zijn elementen op de pagina waarvoor een achtergrondkleur is ingesteld, niet transparant. Als u bijvoorbeeld een achtergrondkleur instelt voor het hoofdtekstelement van de pagina, is geen enkel onderdeel van de pagina transparant. In het volgende voorbeeld ziet u hoe u Flash-weergaveobjecten als lagen boven en onder de HTML-pagina kunt toevoegen. Met dit voorbeeld maakt u twee eenvoudige vormobjecten, en plaatst u het ene object boven en het andere onder de HTML-inhoud. In dit voorbeeld wordt ook de positie van de vorm bijgewerkt op basis van de gebeurtenis enterFrame. Bouncers <script src="AIRAliases.js" type="text/javascript"> <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;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 70 Werken met native vensters
} if( this.shape.y - this.radius < 0){ this.vY = -this.vY; } 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); } de Finibus Bonorum et Malorum
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.
This paragraph has a background color.
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.
In dit voorbeeld wordt een elementaire inleiding gegeven op bepaalde geavanceerde technieken waarbij de grenzen tussen JavaScript en ActionScript in AIR worden overschreden. Bent u niet bekend met het gebruik van ActionScriptweergaveobjecten, raadpleeg dan de sectie over het programmeren van de weergave in ActionScript 3.0 programmeren voor meer informatie.
Voorbeeld: een native venster maken In het volgende voorbeeld ziet u hoe u een native venster kunt maken:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 71 Werken met native vensters
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(); }
Vensters beheren U kunt de eigenschappen en methoden van de klasse NativeWindow gebruiken om het uiterlijk, het gedrag en de levenscyclus van bureaubladvensters te beheren.
NativeWindow-instanties opvragen Als u een venster wilt bewerken, moet u eerst een instantie van het venster opvragen. U kunt een vensterinstantie opvragen uit een van de volgende locaties: De vensterconstructor Dit is de vensterconstructor voor een nieuwe NativeWindow. De vensterstage Dit is stage.nativeWindow. Een willekeurig weergaveobject op de stage Dit is myDisplayObject.stage.nativeWindow. Een venstergebeurtenis De eigenschap target van het gebeurtenisobject verwijst naar het venster dat de gebeurtenis
heeft verzonden. De globale eigenschap nativeWindow van een HTMLLoader- of HTML-venster Dit is window.nativeWindow. Het nativeApplication-object NativeApplication.nativeApplication.activeWindow verwijst naar het actieve
venster van een toepassing (maar retourneert de waarde null als het actieve venster geen venster van deze AIRtoepassing is). De array NativeApplication.nativeApplication.openedWindows bevat alle vensters in een AIRtoepassing die niet zijn gesloten.
Vensters activeren, weergeven en verbergen Als u een venster wilt activeren, roept u de NativeWindow-methode activate() op. Als het venster wordt geactiveerd, wordt het venster op de voorgrond weergegeven, krijgt het de focus voor toetsenbord- en muisbewerkingen en wordt het, indien nodig, zichtbaar gemaakt. U maakt het venster zichtbaar door het vorige formaat van het venster te herstellen of de eigenschap visible op true in te stellen. Als een venster wordt geactiveerd, wordt de volgorde van andere vensters in de toepassing niet gewijzigd. Het oproepen van de methode activate() leidt ertoe dat het venster de gebeurtenis activate verzendt.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 72 Werken met native vensters
Als u een verborgen venster wilt weergeven zonder het te activeren, stelt u de eigenschap visible in op true. Hiermee wordt het venster op de voorgrond geplaatst, maar wordt de focus niet aan het venster toegewezen. Als u een venster wilt verbergen, stelt u de eigenschap visible van dat venster in op false. Als u een venster verbergt, wordt de weergave van zowel het venster als de bijbehorende taakbalkpictogrammen en, in Mac OS X, de vermelding in het menu Vensters onderdrukt. Opmerking: In Mac OS X is het niet mogelijk om een geminimaliseerd venster met een dock-pictogram volledig te verbergen. Als de eigenschap visible van een geminimaliseerd venster is ingesteld op false, wordt het dock-pictogram voor het venster nog wel weergegeven. Als de gebruiker op het pictogram klikt, wordt de zichtbaarheid van het venster hersteld en wordt het venster opnieuw weergegeven.
De weergavevolgorde van vensters wijzigen AIR biedt verschillende methoden voor het rechtstreeks wijzigen van de weergavevolgorde van vensters. U kunt een venster vooraan of achteraan in de weergavevolgorde plaatsen en u kunt een venster boven of onder een ander venster plaatsen. Tegelijkertijd kan de gebruiker de volgorde van vensters wijzigen door deze te activeren. U kunt zorgen dat een venster steeds vóór de andere vensters wordt weergegeven door de eigenschap alwaysInFront in te stellen op true. Als deze instelling is geconfigureerd voor meer dan één venster, bepalen de vensters onderling de weergavevolgorde, maar deze vensters worden wel altijd weergegeven boven op de vensters waarvoor de eigenschap alwaysInFront is ingesteld op false. Vensters in de bovenste groep worden ook weergegeven boven op vensters in andere toepassingen, zelfs wanneer de AIR-toepassing niet actief is. Omdat dit gedrag storend kan zijn voor een gebruiker, moet u de eigenschap alwaysInFront alleen op true instellen als dat echt nodig en terecht is. Hier volgen enkele voorbeelden van gerechtvaardigd gebruik van deze instelling:
• Tijdelijke pop-upvensters voor besturingselementen (zoals knopinfo, pop-uplijsten, aangepaste menu's of keuzelijsten met invoervak) mogen deze instelling hebben. Omdat deze vensters gewoonlijk worden gesloten als ze de focus verliezen, wordt voorkomen dat ze de gebruiker het zicht op een ander venster benemen.
• Uiterst urgente foutberichten en waarschuwingen mogen deze instelling hebben. Wanneer er een onomkeerbare wijziging wordt aangebracht als de gebruiker niet tijdig reageert, kan het gerechtvaardigd zijn om een waarschuwingsvenster boven op alle andere vensters weer te geven. De meeste foutberichten en waarschuwingen kunnen echter worden verwerkt in de normale weergavevolgorde van vensters.
• Kortstondig weergegeven, eenvoudige en rechthoekige (toast-stijl) informatievensters mogen deze instelling hebben. Opmerking: AIR dwingt een gepast gebruik van de eigenschap alwaysInFront niet af. Als uw toepassing zich storend gedraagt tijdens de normale werkzaamheden van de gebruiker, zal de toepassing hoogstwaarschijnlijk al snel in de prullenbak van diezelfde gebruiker worden gedeponeerd. De klasse NativeWindow biedt de volgende eigenschappen en methoden voor het instellen van de plaats van een venster ten opzichte van andere vensters in de weergavevolgorde: Lid
Beschrijving
de eigenschap alwaysInFront
Hiermee geeft u aan of het venster in de bovenste groep vensters moet worden weergegeven. In vrijwel alle gevallen is false de beste instelling. Als u de waarde van false in true wijzigt, wordt het venster boven op alle vensters weergegeven (het venster wordt overigens niet geactiveerd). Als u de waarde van true in false wijzigt, wordt het venster achter de vensters geplaatst die zich in de bovenste groep bevinden. Het venster wordt wel vóór de andere vensters geplaatst. Als u de eigenschap voor een venster op zijn huidige waarde instelt, wordt de weergavevolgorde van vensters niet gewijzigd.
orderToFront()
Hiermee plaatst u het venster op de voorgrond.
orderInFrontOf()
Hiermee plaatst u het venster direct vóór een bepaald venster.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 73 Werken met native vensters
Lid
Beschrijving
orderToBack()
Hiermee plaatst u het venster achter alle andere vensters.
orderBehind()
Hiermee plaatst u het venster direct achter een bepaald venster.
activate()
Hiermee plaatst u het venster op de voorgrond (en bovendien wordt het venster zichtbaar en wordt de focus toegewezen aan het venster).
Opmerking: Als een venster verborgen is (visible is false) of geminimaliseerd, heeft het oproepen van methoden om de weergavevolgorde te wijzigen, geen effect.
Vensters sluiten Als u een venster wilt sluiten, gebruikt u de methode NativeWindow.close(). Als u een venster sluit, wordt de inhoud uit het venster verwijderd, maar als andere objecten verwijzingen naar deze inhoud bevatten, worden de inhoudsobjecten niet vernietigd. De methode NativeWindow.close() wordt asynchroon uitgevoerd. Dit betekent dat de toepassing die zich in het venster bevindt, actief blijft tijdens het sluiten van het venster. De methode close verzendt de gebeurtenis close wanneer het sluiten van het venster is voltooid. Het NativeWindow-object functioneert technisch gezien nog steeds, maar als u toegang probeert te krijgen tot eigenschappen en methoden van een gesloten venster, wordt er in de meeste gevallen een IllegalOperationError gegenereerd. U kunt een gesloten venster niet opnieuw openen. Controleer de eigenschap closed van een venster om na te gaan of een venster is gesloten. Als u een venster gewoon wilt verbergen, stelt u de eigenschap NativeWindow.visible in op false. Als de eigenschap Nativeapplication.autoExit op true is ingesteld (dit is de standaardinstelling), wordt de toepassing afgesloten op het moment dat het laatste venster wordt gesloten.
Het annuleren van vensterbewerkingen toestaan Wanneer voor een venster de systeeminterface wordt gebruikt, kunt u de interactie van de gebruiker met het venster annuleren door te luisteren naar de juiste gebeurtenissen en hiervan het standaardgedrag te annuleren. Wanneer een gebruiker bijvoorbeeld op het sluitvak van de systeeminterface klikt, wordt de gebeurtenis closing verzonden. Als een geregistreerde listener de methode preventDefault() van de gebeurtenis oproept, wordt het venster niet gesloten. Wanneer voor een venster niet de systeeminterface wordt gebruikt, worden er ook niet automatisch meldingsgebeurtenissen voor aanstaande wijzigingen verzonden voordat de wijziging wordt aangebracht. Als u daarom de methoden voor het sluiten van een venster oproept, waarbij de status van het venster wordt gewijzigd, of als u een van de eigenschappen van venstergrenzen instelt, kan de wijziging niet worden geannuleerd. Als u componenten in uw toepassing wilt waarschuwen voordat er een wijziging in een venster wordt aangebracht, kan de logica van uw toepassing de relevante meldingsgebeurtenis verzenden met de methode dispatchEvent() van het venster. Met de volgende logica implementeert u bijvoorbeeld een annuleerbare gebeurtenishandler voor het sluitvak van een venster: public function onCloseCommand(event:MouseEvent):void{ var closingEvent:Event = new Event(Event.CLOSING,true,true); dispatchEvent(closing); if(!closingEvent.isDefaultPrevented()){ win.close(); } }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 74 Werken met native vensters
De methode dispatchEvent() retourneert de waarde false als de methode preventDefault() van de gebeurtenis door een listener wordt opgeroepen. Aangezien de methode echter ook om andere redenen de waarde false kan retourneren, is het beter om expliciet de methode isDefaultPrevented() te gebruiken om te controleren of de wijziging moet worden geannuleerd.
Vensters maximaliseren en minimaliseren, of het vorige formaat ervan herstellen Als u het venster wilt maximaliseren, gebruikt u de methode maximize() van NativeWindow. myWindow.maximize();
Als u het venster wilt minimaliseren, gebruikt u de methode minimize() van NativeWindow. myWindow.minimize();
Als u het vorige formaat van het venster wilt herstellen (dat wil zeggen het formaat van het venster voordat het werd geminimaliseerd of gemaximaliseerd), gebruikt u de methode restore() van NativeWindow. myWindow.restore();
Opmerking: Het gedrag dat wordt vertoond wanneer u een AIR-venster maximaliseert, verschilt van het standaardgedrag in Mac OS X. Er wordt niet geschakeld tussen het door de toepassing gedefinieerde 'standaardformaat' en het laatste formaat dat door de gebruiker is ingesteld. In plaats daarvan wordt bij een AIR-venster geschakeld tussen het laatste formaat dat door de toepassing is ingesteld en het volledige bruikbare gebied van het scherm.
Voorbeeld: een venster minimaliseren, maximaliseren, herstellen en sluiten Met het volgende ActionScript-voorbeeld voor Flash worden vier tekstvelden gemaakt waarop kan worden geklikt en waarmee de methoden minimize(), maximize(), restore() en close() van NativeWindow kunnen worden geactiveerd: 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;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 75 Werken met native vensters
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); 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(); } } }
Het formaat van een venster wijzigen en het venster verplaatsen Wanneer voor een venster de systeeminterface wordt gebruikt, biedt de interface sleepbesturingselementen waarmee u het vensterformaat kunt wijzigen en het venster op het bureaublad kunt verplaatsen. Als voor een venster niet de systeeminterface wordt gebruikt, moet u uw eigen besturingselementen toevoegen om het vensterformaat te wijzigen en het venster te verplaatsen. Opmerking: Als u het formaat van een venster wilt wijzigen of een venster wilt verplaatsen, moet u eerst een verwijzing naar de NativeWindow-instantie opvragen. Zie “NativeWindow-instanties opvragen” op pagina 71 voor informatie over het opvragen van een vensterverwijzing.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 76 Werken met native vensters
Het formaat van een venster wijzigen Als u het formaat van een venster wilt wijzigen, gebruikt u de methode startResize() van NativeWindow. Als deze methode wordt opgeroepen vanuit een mouseDown-gebeurtenis, wordt het wijzigen van het vensterformaat door de muis gestuurd en is de bewerking voltooid wanneer het besturingssysteem de gebeurtenis mouseUp ontvangt. Als u startResize() oproept, geeft u een argument door dat de rand of hoek aangeeft van waaruit het vensterformaat moet worden gewijzigd. De schaalmodus van de stage bepaalt hoe de vensterstage en de inhoud daarvan zich gedragen wanneer het formaat van het venster wordt gewijzigd. Houd er rekening mee dat de schaalmodi van de stage zijn ontworpen voor situaties waarin de toepassing de grootte of hoogte-breedteverhouding van zijn weergaveruimte niet zelf kan bepalen (zoals in een webbrowser). U krijgt over het algemeen de beste resultaten door de eigenschap scaleMode van de stage in te stellen op StageScaleMode.NO_SCALE. Als u wilt dat de inhoud van het venster wordt geschaald, kunt u nog steeds de parameters scaleX en scaleY instellen als reactie op wijzigingen in de venstergrenzen. Vensters verplaatsen Als u een venster wilt verplaatsen zonder het formaat ervan te wijzigen, gebruikt u de methode NativeWindow startMove(). Net als voor de methode startResize() geldt dat wanneer de methode startMove() wordt opgeroepen vanuit de gebeurtenis mouseDown, de bewerking (het verplaatsen van het venster) door de muis wordt gestuurd en is voltooid wanneer het besturingssysteem de gebeurtenis mouseUp ontvangt. Als u meer informatie wilt over de methoden startResize en startMove, raadpleegt u ActionScript 3.0 Language and Components Reference (http://www.adobe.com/go/learn_air_aslr_nl).
Voorbeeld: het formaat van vensters wijzigen en vensters verplaatsen In het volgende voorbeeld ziet u hoe u bewerkingen zoals het wijzigen van het formaat of het verplaatsen, kunt starten voor een venster: 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
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 77 Werken met native vensters
{ var s:Sprite = new Sprite(); 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(); } } }
Luisteren naar venstergebeurtenissen Als u wilt luisteren naar gebeurtenissen die worden verzonden door een venster, registreert u een listener bij de vensterinstantie. Als u bijvoorbeeld naar de gebeurtenis closing wilt luisteren, registreert u als volgt een listener bij het venster: myWindow.addEventListener(Event.CLOSING, onClosingEvent);
Wanneer een gebeurtenis wordt verzonden, verwijst de eigenschap target naar het venster dat de gebeurtenis heeft verzonden. De meeste venstergebeurtenissen hebben twee gerelateerde berichten. Het eerste bericht geeft aan dat er een vensterwijziging ophanden is (die kan worden geannuleerd), terwijl het tweede bericht aangeeft dat de wijziging heeft plaatsgevonden. Wanneer een gebruiker bijvoorbeeld op het sluitvak van een venster klikt, wordt het bericht van de gebeurtenis closing verzonden. Als de gebeurtenis niet door listeners wordt geannuleerd, wordt het venster gesloten en wordt het bericht van de gebeurtenis close verzonden naar eventuele listeners. Gewoonlijk worden waarschuwingsgebeurtenissen, zoals closing, alleen verzonden wanneer de systeeminterface is gebruikt om een gebeurtenis te activeren. Als bijvoorbeeld de methode close() van het venster wordt opgeroepen, wordt niet automatisch de gebeurtenis closing verzonden, maar wordt alleen de gebeurtenis close verzonden. U kunt echter een closing-gebeurtenisobject maken en dit object verzenden met de methode dispatchEvent() van het venster. De volgende venstergebeurtenissen verzenden een Event-object:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 78 Werken met native vensters
Gebeurtenis
Beschrijving
activate
Deze gebeurtenis wordt verzonden wanneer het venster de focus krijgt.
deactivate
Deze gebeurtenis wordt verzonden wanneer het venster de focus verliest.
closing
Deze gebeurtenis wordt verzonden wanneer het venster zal worden gesloten. Dit gebeurt alleen automatisch als op het sluitvak van de systeeminterface wordt geklikt of wanneer in Mac OS X de opdracht Stop wordt opgeroepen.
close
Deze gebeurtenis wordt verzonden wanneer het venster is gesloten.
De volgende venstergebeurtenissen verzenden een NativeWindowBoundsEvent-object: Gebeurtenis
Beschrijving
moving
Deze gebeurtenis wordt verzonden vlak voordat de positie van de linkerbovenhoek van het venster wordt gewijzigd doordat het venster wordt verplaatst of het vensterformaat of de weergavestatus van het venster wordt gewijzigd.
move
Deze gebeurtenis wordt verzonden nadat de positie van de linkerbovenhoek is gewijzigd.
resizing
Deze gebeurtenis wordt verzonden vlak voordat de breedte of hoogte van het venster wordt gewijzigd doordat het vensterformaat of de weergavestatus van het venster wordt gewijzigd.
resize
Deze gebeurtenis wordt verzonden nadat het formaat van het venster is gewijzigd.
Voor NativeWindowBoundsEvent-gebeurtenissen kunt u de eigenschappen beforeBounds en afterBounds gebruiken om de venstergrenzen te bepalen vóór en na de aanstaande of doorgevoerde wijziging. De volgende venstergebeurtenissen verzenden een NativeWindowDisplayStateEvent-object: Gebeurtenis
Beschrijving
displayStateChanging
Deze gebeurtenis wordt verzonden vlak voordat de weergavestatus van het venster wordt gewijzigd.
displayStateChange
Deze gebeurtenis wordt verzonden nadat de weergavestatus van het venster is gewijzigd.
Voor NativeWindowDisplayStateEvent-gebeurtenissen kunt u de eigenschappen beforeDisplayState en afterDisplayState gebruiken om de weergavestatus van het venster te bepalen vóór en na de aanstaande of
doorgevoerde wijziging.
Schermvullende vensters weergeven Als u de eigenschap displayState van de stage instelt op StageDisplayState.FULL_SCREEN_INTERACTIVE, wordt het venster in de schermvullende modus weergegeven. Toetsenbordinvoer is wel toegestaan in deze modus. (In SWFinhoud die in een browser wordt uitgevoerd, is toetsenbordinvoer niet toegestaan.) Als de gebruiker de schermvullende modus wil verlaten, kan deze op Esc drukken. In het volgende ActionScript-voorbeeld voor Flash wordt een eenvoudige schermvullende tekstterminal gesimuleerd:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 79 Werken met native vensters
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); } }
80
Hoofdstuk 11: Schermen Gebruik de Adobe® AIR®-klasse Screen om informatie op te roepen over de displays die zijn aangesloten op een computer.
Aanvullende online informatie over schermen U vindt meer informatie over de klasse Screen en over het werken met schermen in de volgende bronnen: Snelstarthandleidingen (Adobe AIR Developer Connection) • Het virtuele bureaublad meten Language Reference • Screen Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar 'AIR screens')
Basisinformatie over schermen De API voor schermen bevat één enkele klasse, Screen, die statische leden gebruikt om scherminformatie op te halen bij het systeem, en instantieleden om een bepaald scherm te beschrijven. Op een computersysteem kunnen verschillende monitors of displays zijn aangesloten, die kunnen overeenkomen met verschillende bureaubladschermen in een virtuele ruimte. De AIR-klasse Screen geeft informatie over de schermen, hun relatieve opstelling en hun bruikbare ruimte. Als meer dan één monitor aan hetzelfde scherm is toegewezen, bestaat er slechts één scherm. Als een scherm groter is dan het weergavegebied van de monitor, kan niet worden bepaald welk gedeelte van het scherm momenteel zichtbaar is. Een scherm komt overeen met een onafhankelijk weergavegebied op het bureaublad. Schermen worden gedefinieerd als rechthoeken binnen het virtuele bureaublad. De linkerbovenhoek van het scherm dat als primair display is gedefinieerd, vormt de oorsprong van het coördinatensysteem van het virtuele bureaublad. Alle waarden waarmee een scherm wordt beschreven, worden opgegeven in pixels.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 81 Schermen
Schermgrenzen Virtueel scherm Grenzen bruikbaar gebied In deze schermopstelling bestaan er twee schermen op het virtuele bureaublad. De coördinaten van de linkerbovenhoek van het hoofdscherm (nr. 1) zijn altijd (0,0). Als de schermopstelling zo verandert dat scherm nr. 2 het hoofdscherm wordt, worden de coördinaten van scherm nr. 1 negatief. Menubalken, taakbalken en docks worden niet meegerekend wanneer de bruikbare grenzen voor een scherm worden opgegeven.
Zie ActionScript 3.0 Language and Components Reference (http://www.adobe.com/go/learn_air_aslr_nl) voor gedetailleerde informatie over de klasse, methoden, eigenschappen en gebeurtenissen van de API voor schermen.
Schermen opsommen U kunt de schermen op het virtuele bureaublad opsommen met de volgende methoden en eigenschappen van Screen: Methode of eigenschap
Beschrijving
Screen.screens
Geeft een array van Screen-objecten waarmee de beschikbare schermen worden beschreven. De volgorde in de array is niet significant.
Screen.mainScreen
Geeft een Screen-object voor het hoofdscherm. In Max OS X is het hoofdscherm het scherm waarop de menubalk wordt weergegeven. In Windows is het hoofdscherm het scherm dat door het systeem als primair scherm is aangewezen.
Screen.getScreensForRectangle() Geeft een array met Screen-objecten die de schermen beschrijven die door de gegeven rechthoek worden gesneden. De rechthoek die aan deze methode wordt doorgegeven, wordt uitgedrukt in pixelcoördinaten op het virtuele bureaublad. Als geen schermen de rechthoek snijden, is de array leeg. U kunt deze methode gebruiken om na te gaan op welke schermen een venster wordt weergegeven.
Sla de waarden niet op die door de methoden en eigenschappen van de klasse Screen worden geretourneerd. De gebruiker of het besturingssysteem kan de beschikbare schermen en hun opstelling op een willekeurig moment wijzigen. Het volgende voorbeeld gebruikt de API voor schermen om een venster tussen verschillende schermen te verplaatsen wanneer op de pijltoetsen wordt gedrukt. Om het venster naar het volgende scherm te verplaatsen, haalt het voorbeeld de array screens op en wordt deze verticaal of horizontaal gesorteerd (afhankelijk van de ingedrukte pijltoets). De code doorloopt vervolgens de gesorteerde array en vergelijkt elk scherm met de coördinaten van het huidige scherm. Om het huidige scherm van het venster te identificeren, roept het voorbeeld Screen.getScreensForRectangle() op door de venstergrenzen door te geven.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 82 Schermen
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 +=
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 83 Schermen
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; } } }
84
Hoofdstuk 12: Werken met native menu's Gebruik de klassen van de API voor native menu's om toepassings-, venster-, context- en pop-upmenu's te definiëren.
Aanvullende online informatie over native menu's Meer informatie over de API voor native menu's en het werken met native menu's vindt u in de volgende bronnen: Snelstarthandleidingen (Adobe AIR Developer Connection) • Native menu's toevoegen aan een AIR-toepassing Language Reference • NativeMenu
• NativeMenuItem Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar 'AIR menus')
Basisinformatie over AIR-menu's Met de native menuklassen hebt u toegang tot de native menufuncties van het besturingssysteem waarin uw toepassing wordt uitgevoerd. NativeMenu-objecten kunnen worden gebruikt voor toepassingsmenu's (beschikbaar in Mac OS X), venstermenu's (beschikbaar in Windows), contextmenu's en pop-upmenu's.
AIR-menuklassen De Adobe® AIR™-menuklassen omvatten: Pakket
Klassen
flash.display
•
NativeMenu
•
NativeMenuItem
•
ContextMenu
•
ContextMenuItem
•
Event
•
ContextMenuEvent
flash.ui
flash.events
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 85 Werken met native menu's
Menutypen AIR ondersteunt de volgende menutypen: Toepassingsmenu's Een toepassingsmenu is een globaal menu dat geldt voor de gehele toepassing.
Toepassingsmenu's worden ondersteund in Mac OS X, maar niet in Windows. In Mac OS X maakt het besturingssysteem automatisch een toepassingsmenu. U kunt de AIR API voor menu's gebruiken om items en submenu's toe te voegen aan de standaardmenu's. U kunt listeners toevoegen om de bestaande menuopdrachten af te handelen. U kunt ook bestaande items verwijderen. Venstermenu's Een venstermenu is gekoppeld aan één venster en wordt weergegeven onder de titelbalk. U kunt menu's aan een venster toevoegen door een NativeMenu-object te maken en dit toe te wijzen aan de eigenschap menu van het NativeWindow-object. Venstermenu's worden ondersteund in het besturingssysteem Windows, maar niet in Mac OS X. Native menu's kunnen alleen worden gebruikt met vensters die de systeeminterface gebruiken. Contextmenu's Contextmenu's worden geopend als reactie op klikken met de rechtermuisknop of klikken met de
Command-toets ingedrukt op een interactief object in SWF-inhoud of een documentelement in HTML-inhoud. U kunt een contextmenu maken met behulp van de AIR-klasse NativeMenu. (U kunt ook de oudere Adobe® Flash®-klasse ContextMenu gebruiken.) In HTML-inhoud kunt u de Webkit HTML- en JavaScript-API's gebruiken om contextmenu's toe te voegen aan een HTML-element. Dock- en systeemvakpictogrammenu's Deze pictogrammenu's zijn vergelijkbaar met contextmenu's en worden
toegewezen aan een toepassingspictogram in het dock van Mac OS X of het systeemvak van Windows. Dock- en systeemvakpictogrammenu's maken gebruik van de klasse NativeMenu. In Mac OS X worden de items in het menu toegevoegd boven de standaarditems van het besturingssysteem. In Windows is er geen standaardmenu. Pop-upmenu's Een pop-upmenu van AIR is vergelijkbaar met een contextmenu, maar is niet noodzakelijkerwijs gekoppeld aan een bepaald toepassingsobject of -onderdeel. U kunt pop-upmenu's op een willekeurige plaats in een venster weergeven door de methode display() van een willekeurig NativeMenu-object op te roepen. Aangepaste menu's Native menu's worden volledig door het besturingssysteem samengesteld en bestaan dus buiten
de Flash- en HTML-renderingmodellen. Het staat u volledig vrij om uw eigen niet-native menu's te maken met behulp van MXML, ActionScript of JavaScript. De AIR-menuklassen bieden geen mogelijkheid voor het beheer van het samenstellen van native menu's. Standaardmenu's De volgende standaardmenu's worden geleverd door het besturingssysteem of door een ingebouwde AIR-klasse:
• Toepassingsmenu in Mac OS X • Dock-pictogrammenu in Mac OS X • Contextmenu voor geselecteerde tekst en afbeeldingen in HTML-inhoud • Contextmenu voor geselecteerde tekst in een TextField-object (of een object dat een uitbreiding vormt voor TextField)
Menustructuur Menu's zijn hiërarchisch van aard. NativeMenu-objecten bevatten onderliggende NativeMenuItem-objecten. NativeMenuItem-objecten die submenu's vertegenwoordigen, kunnen op hun beurt weer NativeMenu-objecten bevatten. Het menuobject van het hoogste niveau (hoofdniveau) in de structuur vertegenwoordigt de menubalk voor toepassings- en venstermenu's. (Context-, pictogram- en pop-upmenu's hebben geen menubalk.)
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 86 Werken met native menu's
In het volgende diagram wordt de structuur van een typisch menu geïllustreerd. Het hoofdmenu vertegenwoordigt de menubalk en bevat twee menu-items die verwijzen naar de submenu's File en Edit. Het submenu File in deze structuur bevat twee opdrachtitems en een item dat verwijst naar het submenu Open Recent Menu, dat zelf weer drie items bevat. Het submenu Edit bevat drie opdrachten en een scheidingslijn. NativeMenu
Hoofdmenu NativeMenuItem NativeMenu
“Bestand” Menu Bestand
NativeMenuItem
“Nieuw”
NativeMenuItem
“Opslaan”
NativeMenuItem
“Recente bestanden openen”
NativeMenu
NativeMenuItem NativeMenu
Menu Recente bestanden openen
NativeMenuItem
“GreatGatsby.pdf”
NativeMenuItem
“WarAndPeace.pdf”
NativeMenuItem
“Iliad.pdf”
“Bewerken” Menu Bewerken
NativeMenuItem
“Kopiëren”
NativeMenuItem
“Plakken”
NativeMenuItem
Scheidingsbalk
NativeMenuItem
“Voorkeuren”
Voor de definitie van een submenu is zowel een NativeMenu- als een NativeMenuItem-object nodig. Het NativeMenuItem-object definieert het label dat wordt weergegeven in het bovenliggende menu en stelt de gebruiker in staat het submenu te openen. Het NativeMenu-object fungeert als container voor items in het submenu. Het NativeMenuItem-object verwijst naar het NativeMenu-object via de eigenschap submenu van het NativeMenuItem. Zie “Voorbeeld: venstermenu en toepassingsmenu” op pagina 96 voor een codevoorbeeld waarin dit menu wordt gemaakt.
Menugebeurtenissen NativeMenu- en NativeMenuItem-objecten verzenden allebei displaying- en select-gebeurtenissen: Displaying: Vlak voordat een menu wordt weergegeven, verzenden het menu en de menu-items ervan de gebeurtenis displaying naar alle geregistreerde listeners. De gebeurtenis displaying geeft u de mogelijkheid om de menu-
inhoud of de weergave van items bij te werken voordat de gebruiker het menu ziet. U kunt bijvoorbeeld in de listener voor de gebeurtenis displaying van het menu “Open Recent” de menu-items wijzigen zodat de lijst van onlangs bekeken documenten wordt weergegeven. De eigenschap target van het gebeurtenisobject is altijd het menu dat zal worden weergegeven. currentTarget is het object waarvoor de listener is geregistreerd: het menu zelf of een van de items ervan.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 87 Werken met native menu's
Opmerking: De gebeurtenis displaying wordt ook verzonden wanneer toegang wordt gezocht tot de status van het menu of een van de items ervan. Select: Wanneer de gebruiker een opdrachtitem kiest, verzendt dat item de gebeurtenis select naar eventuele geregistreerde listeners. Submenu- en scheidingslijnitems kunnen niet worden geselecteerd en verzenden dus nooit de gebeurtenis select.
De gebeurtenis select stroomt omhoog van een menu-item naar het menu dat dit item bevat, of helemaal naar het hoofdmenu. U kunt luisteren naar select-gebeurtenissen rechtstreeks op een item, of hogerop in de menustructuur. Wanneer u luistert naar de gebeurtenis select op een menu, kunt u het geselecteerde item identificeren met behulp van de eigenschap target van de gebeurtenis. Terwijl de gebeurtenis omhoogstroomt door de menuhiërarchie, identificeert de eigenschap currentTarget van het gebeurtenisobject het huidige menuobject. Opmerking: ContextMenu- en ContextMenuItem-objecten verzenden menuItemSelect- en menuSelectgebeurtenissen, evenals select- en displaying-gebeurtenissen.
Toetsequivalenten voor menuopdrachten U kunt een toetsequivalent (sneltoets) toewijzen aan een menuopdracht. Het menu-item verzendt de gebeurtenis select naar alle geregistreerde listeners wanneer de toets of toetsencombinatie wordt ingedrukt. De opdracht wordt alleen opgeroepen wanneer het menu dat het item bevat, deel uitmaakt van het menu van de toepassing of het actieve venster. Toetsequivalenten bestaan uit twee delen: een tekenreeks die de primaire toets vertegenwoordigt en een array van wijzigingstoetsen die ook moeten worden ingedrukt. Om de primaire toets toe te wijzen, stelt u de eigenschap keyEquivalent voor het menu-item in op de uit één teken bestaande tekenreeks voor die toets. Als u een hoofdletter gebruikt, wordt de Shift-toets automatisch toegevoegd aan de wijzigingsarray. In Mac OS X is de standaard wijzigingstoets de Command-toets (Keyboard.COMMAND). In Windows is dit de Controltoets (Keyboard.CONTROL). Deze standaardtoetsen worden automatisch toegevoegd aan de wijzigingsarray. Als u andere wijzigingstoetsen wilt toewijzen, wijst u een nieuwe array met de gewenste toetscodes toe aan de eigenschap keyEquivalentModifiers. De standaardarray wordt dan overschreven. Of u nu de standaard wijzigingstoetsen gebruikt dan wel een eigen wijzigingsarray toewijst, de Shift-toets wordt altijd toegevoegd wanneer de tekenreeks die u toewijst aan de eigenschap keyEquivalent een hoofdletter is. Constanten voor de toetscodes die moeten worden gebruikt voor de wijzigingstoetsen, worden gedefinieerd in de klasse Keyboard. De toegewezen tekenreeks voor het toetsequivalent wordt automatisch weergegeven naast de naam van het menuitem. De indeling is afhankelijk van het besturingssysteem van de gebruiker en de systeemvoorkeuren. Opmerking: Als u in het Windows-besturingssysteem de waarde Keyboard.COMMAND toewijst aan een toetswijzigingsarray, wordt er geen toetsequivalent weergegeven in het menu. De Control-toets moet dan worden gebruikt om de menuopdracht te activeren. In het volgende voorbeeld wordt Ctrl+Shift+G toegewezen als toetsequivalent voor een menu-item: var item:NativeMenuItem = new NativeMenuItem("Ungroup"); item.keyEquivalent = "G";
In dit voorbeeld wijst u Ctrl+Shift+G als toetsequivalent toe door de wijzigingsarray rechtstreeks in te stellen: var item:NativeMenuItem = new NativeMenuItem("Ungroup"); item.keyEquivalent = "G"; item.keyEquivalentModifiers = [Keyboard.CONTROL];
Opmerking: Toetsequivalenten worden alleen getriggerd voor toepassings- en venstermenu's. Als u een toetsequivalent toevoegt aan een context- of pop-upmenu, wordt het toetsequivalent weergegeven in het menulabel. De daaraan gekoppelde menuopdracht wordt echter nooit opgeroepen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 88 Werken met native menu's
Mnemonics Mnemonics (toetsenbordsneltoetsen in de vorm van onderstreepte letters) maken deel uit van de besturingssysteemtoetsenbordinterface voor menu's. Zowel Mac OS X als Windows stellen gebruikers in staat om menu's te openen en opdrachten te selecteren met het toetsenbord. Er zijn echter enkele subtiele verschillen. In Mac OS X typt de gebruiker de eerste letter of de eerste twee letters van het menu of de opdracht, waarna de gebruiker op Enter drukt. In Windows is maar één letter significant. Standaard is de significante letter het eerste teken van het label. Als u echter een mnemonic toewijst aan het menu-item, wordt de desbetreffende letter het significante teken. Als twee items in een menu hetzelfde significante teken hebben (ongeacht of een mnemonic is toegewezen), verandert de interactie tussen het toetsenbord en het menu enigszins. De gebruiker kan nu niet één letter indrukken om het menu of de opdracht te selecteren, maar moet de letter zo vaak als nodig indrukken om het gewenste item te markeren. Vervolgens moet de gebruiker op Enter drukken om de selectie te voltooien. Ten einde een consistent gedrag te handhaven, is het aan te raden een unieke mnemonic toe te wijzen aan ieder item van een venstermenu. Geef de gewenste mnemonic op als index bij de labeltekenreeks. De index van het eerste teken van een label is 0. Als u bijvoorbeeld “r” wilt gebruiken als mnemonic voor het menu-item met het label “Format”, stelt u de eigenschap mnemonicIndex in op 2. var item:NativeMenuItem = new NativeMenuItem("Format"); item.mnemonicIndex = 2;
Status van het menu-item Menu-items hebben de volgende twee statuseigenschappen: checked en enabled: checked Stel deze in op true als u een vinkje wilt weergeven naast het itemlabel. var item:NativeMenuItem = new NativeMenuItem("Format"); item.checked = true;
enabled Schakel deze waarde tussen true en false om aan te geven of de opdracht is ingeschakeld. Uitgeschakelde
items worden grijs weergegeven en verzenden geen gebeurtenis select. var item:NativeMenuItem = new NativeMenuItem("Format"); item.enabled = false;
Objecten koppelen aan een menu-item Met de eigenschap data van de klasse NativeMenuItem kunt u in ieder item verwijzen naar een willekeurig object. Zo kunt u in een menu met recent geopende bestanden bijvoorbeeld het File-object voor ieder document toewijzen aan ieder menu-item. var file:File = File.applicationStorageDirectory.resolvePath("GreatGatsby.pdf") var menuItem:NativeMenuItem = docMenu.addItem(new NativeMenuItem(file.name)); menuItem.data = file;
Native menu's maken In dit onderwerp wordt beschreven hoe u de verschillende soorten native menu's kunt maken die door AIR worden ondersteund.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 89 Werken met native menu's
Hoofdmenuobjecten maken Als u een NativeMenu-object wilt maken dat fungeert als basis van het menu, gebruikt u de NativeMenu-constructor: var root:NativeMenu = new NativeMenu();
Voor toepassings- en venstermenu's vertegenwoordigt het hoofdmenu de menubalk. Dit menu moet alleen items bevatten die submenu's openen. Contextmenu's en pop-upmenu's bezitten geen menubalk. Het hoofdmenu kan dus zowel opdrachten en scheidingslijnen bevatten als submenu's. Nadat u het menu hebt gemaakt, kunt u menu-items toevoegen. Items worden in het menu weergegeven in de volgorde waarin ze zijn toegevoegd, behalve als u de items bij een specifieke index toevoegt met behulp van de methode addItemAt() van een menuobject. U kunt het menu toewijzen als toepassings-, venster-, pictogram- of contextmenu. U kunt het ook weergeven als popupmenu. Dit wordt beschreven in de volgende secties: Het toepassingsmenu instellen NativeApplication.nativeApplication.menu = root;
Opmerking: Mac OS X definieert een menu met standaarditems voor iedere toepassing. Als u een nieuw NativeMenuobject toewijst aan de eigenschap menu van het NativeApplication-object, wordt het standaardmenu vervangen. U kunt er ook voor kiezen het standaardmenu te gebruiken in plaats van het te vervangen. Venstermenu's instellen nativeWindowObject.menu = root;
Contextmenu's instellen op een interactief object interactiveObject.contextMenu = root;
Dock-pictogrammenu's instellen DockIcon(NativeApplication.nativeApplication.icon).menu = root;
Opmerking: Mac OS X definieert een standaardmenu voor het dock-pictogram van de toepassing. Wanneer u een nieuw NativeMenu toewijst aan de menu-eigenschap van het DockIcon-object, worden de items in dat menu weergegeven boven de standaarditems. U kunt de standaard menu-items niet verwijderen, openen of wijzigen. Systeemvakpictogrammenu's instellen SystemTrayIcon(NativeApplication.nativeApplication.icon).menu = root;
Menu's weergeven als pop-up root.display(stage, x, y);
Submenu's maken Als u een submenu wilt maken, voegt u een NativeMenuItem-object toe aan het bovenliggende menu. Vervolgens wijst u het NativeMenu-object dat het submenu definieert, toe aan de eigenschap submenu van het item. AIR biedt u twee manieren om submenu-items en de bijbehorende menuobjecten te maken: U kunt een menu-item en het bijbehorende menuobject in één stap maken met behulp van de methode addSubmenu(): var editMenuItem:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit");
U kunt ook het menu-item maken en het menuobject in een aparte stap toewijzen aan de eigenschap submenu ervan:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 90 Werken met native menu's
var editMenuItem:NativeMenuItem = root.addItem("Edit", false); editMenuItem.submenu = new NativeMenu();
Menuopdrachten maken Als u een menuopdracht wilt maken, voegt u een NativeMenuItem-object toe aan een menu. Voeg er vervolgens een gebeurtenislistener aan toe die verwijst naar de functie die de menuopdracht implementeert: var copy:NativeMenuItem = new NativeMenuItem("Copy", false); copy.addEventListener(Event.SELECT, onCopyCommand); editMenu.addItem(copy);
U kunt luisteren naar de gebeurtenis select op het opdrachtitem zelf (zoals weergegeven in het voorbeeld), of u kunt luisteren naar de gebeurtenis select op een bovenliggend menuobject. Opmerking: Menu-items die submenu's en scheidingslijnen vertegenwoordigen, verzenden de gebeurtenis select niet en kunnen dus niet als opdracht worden gebruikt.
Menuscheidingslijnen maken Als u een scheidingslijn wilt maken, maakt u een NativeMenuItem-object. Stel de parameter isSeparator in de constructor in op true. Vervolgens voegt u het item voor de scheidingslijn op de gewenste locatie toe aan het menu. var separatorA:NativeMenuItem = new NativeMenuItem("A", true); editMenu.addItem(separatorA);
Een eventueel label dat voor de scheidingslijn wordt opgegeven, wordt niet weergegeven.
Informatie over contextmenu's In SWF-inhoud kan een object dat gegevens overneemt van InteractiveObject, een contextmenu krijgen. Hiervoor wjist u een menuobject toe aan de eigenschap contextMenu ervan. Het menuobject dat wordt toegewezen aan contextMenu, kan van het type NativeMenu of ContextMenu zijn. Met de oudere API-klassen voor contextmenu's kunt u bestaande ActionScript-code gebruiken die al contextmenu's bevat. Als u de klasse ContextMenu gebruikt, moet u daarbij de klasse ContextMenuItem gebruiken; u kunt geen NativeMenuItem-objecten toevoegen aan een ContextMenu-object en u kunt ook geen ContextMenuItem-objecten toevoegen aan een NativeMenu-object. Het voornaamste nadeel van het gebruik van de API voor contextmenu's is dat deze geen submenu's ondersteunt. Hoewel de klasse ContextMenu methoden bevat, zoals addItem(), die zijn overgenomen van de klasse NativeMenu, voegen deze methoden items toe aan de verkeerde item-array. In een contextmenu moeten alle items worden toegevoegd aan de array customItems, en niet aan de array items. Gebruik NativeMenu-objecten voor contextmenu's, of gebruik alleen de niet-overgenomen ContextMenu-methoden en -eigenschappen voor het toevoegen en beheren van items in het menu. In het volgende voorbeeld wordt een Sprite-object gemaakt en wordt er een eenvoudig contextmenu voor bewerken aan toegevoegd:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 91 Werken met native menu's
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");}
Opmerking: In tegenstelling tot SWF-inhoud die wordt weergegeven in een browseromgeving, bezitten contextmenu's in AIR geen ingebouwde opdrachten.
Informatie over contextmenu's in HTML In HTML-inhoud kan de gebeurtenis contextmenu worden gebruikt om een contextmenu weer te geven. Standaard wordt een contextmenu automatisch weergegeven wanneer de gebruiker de gebeurtenis contextmenu voor geselecteerde tekst activeert (door met de rechtermuisknop te klikken of de Command-toets ingedrukt te houden tijdens het klikken). Om te voorkomen dat het standaardmenu wordt geopend, luistert u naar de gebeurtenis contextmenu en roept u de methode preventDefault() van het gebeurtenisobject op: function showContextMenu(event){ event.preventDefault(); }
U kunt dan een aangepast contextmenu weergeven met behulp van DHTML-technieken of een native contextmenu van AIR weergeven. In het volgende voorbeeld wordt een native contextmenu weergegeven door het oproepen van de menumethode display() als reactie op de HTML-gebeurtenis contextmenu:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 92 Werken met native menu's
<script src="AIRAliases.js" language="JavaScript" type="text/javascript"> <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(); Custom context menu.
Native menu's declaratief definiëren Het kan een saaie klus zijn om de eigenschappen van een menu en de menu-items te coderen. Aangezien menu's een natuurlijke hiërarchische structuur hebben, is het echter vrij simpel om een functie die een menu maakt, te schrijven met behulp van een XML-definitie. De volgende klasse vormt een uitbreiding van NativeMenu. Hierbij wordt een XML-object opgenomen in de constructor:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 93 Werken met native menu's
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
Als u een menu wilt maken met deze klasse, geeft u als volgt een XML-menudefinitie door:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 94 Werken met native menu's
var menuDefinition:XML = <SaveCommand label='Save'/> <EditMenu label='Edit'> <PasteCommand label='Paste'/> <Jellyfish/> ; var test:DeclarativeMenu = new DeclarativeMenu(menuDefinition);
Om te luisteren naar menugebeurtenissen kunt u luisteren op het niveau van het hoofdmenu en de eigenschap event.target.name gebruiken om te controleren welke opdracht is geselecteerd. U kunt ook items in het menu opzoeken op naam en vervolgens individuele gebeurtenislisteners toevoegen.
Pop-upmenu's weergeven U kunt elk willekeurig NativeMenu-object op elk gewenst moment en een willekeurige locatie boven een venster weergeven door de menumethode display() op te roepen. Voor deze methode is een verwijzing naar de stage nodig. Alleen inhoud in de toepassingssandbox kan dus een menu weergeven als pop-up. Met de volgende methode wordt als reactie op een muisklik het menu weergegeven dat wordt gedefinieerd door een NativeMenu-object met de naam popupMenu: private function onMouseClick(event:MouseEvent):void { popupMenu.display(event.target.stage, event.stageX, event.stageY); }
Opmerking: Het menu hoeft niet te worden weergegeven als directe reactie op een gebeurtenis. Iedere methode kan de functie display() oproepen.
Menugebeurtenissen afhandelen Een menu verzendt gebeurtenissen wanneer de gebruiker het menu of een menu-item selecteert.
Overzicht van de gebeurtenissen voor menuklassen Voeg gebeurtenislisteners aan menu's of individuele items toe om menugebeurtenissen af te handelen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 95 Werken met native menu's
Object
Verzonden gebeurtenissen
NativeMenu
NativeMenuEvent.DISPLAYING NativeMenuEvent.SELECT (doorgegeven door onderliggende items en submenu's)
NativeMenuItem
NativeMenuEvent.SELECT NativeMenuEvent.DISPLAYING (doorgegeven door het bovenliggende menu)
ContextMenu
ContextMenuEvent.MENU_SELECT
ContextMenuItem
ContextMenuEvent.MENU_ITEM_SELECT NativeMenu.SELECT
Select-menugebeurtenissen Om een klik op een menu-item af te handelen, voegt u een gebeurtenislistener voor de gebeurtenis select toe aan het NativeMenuItem-object: var menuCommandX:NativeMenuItem = new NativeMenuItem("Command X"); menuCommand.addEventListener(Event.SELECT, doCommandX)
Omdat select-gebeurtenissen worden doorgegeven naar de bevattende menu's, kunt u ook luisteren naar selectgebeurtenissen in een bovenliggend menu. Wanneer u luistert op menuniveau, kunt u de eigenschap target van het gebeurtenisobject gebruiken om te controleren welke menuopdracht is geselecteerd. In het volgende voorbeeld wordt het label van de geselecteerde opdracht getraceerd: 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"); }
Als u de klasse ContextMenuItem gebruikt, kunt u luisteren naar de gebeurtenis select of menuItemSelect. De gebeurtenis menuItemSelect geeft u aanvullende informatie over het object waarvan het contextmenu eigendom is, maar wordt niet doorgegeven naar de bevattende menu's.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 96 Werken met native menu's
Displaying-menugebeurtenissen Om het openen van een menu af te handelen, kunt u een listener toevoegen voor de gebeurtenis displaying die wordt verzonden voordat een menu wordt weergegeven. U kunt de gebeurtenis displaying gebruiken om het menu te updaten, bijvoorbeeld door items toe te voegen of te verwijderen, of door de ingeschakelde of aangevinkte status van afzonderlijke items te updaten.
Voorbeeld: venstermenu en toepassingsmenu In het volgende voorbeeld ziet u hoe u het menu maakt dat wordt weergegeven in “Menustructuur” op pagina 85. Dit menu is zo ontworpen dat het zowel werkt in Windows (waarvoor alleen venstermenu's worden ondersteund) als in Mac OS X (waarvoor alleen toepassingsmenu's worden ondersteund). Om dit onderscheid kunnen maken, controleert de constructor van de klasse MenuExample de statische supportsMenu-eigenschappen van de klassen NativeWindow en NativeApplication. Als NativeWindow.supportsMenu de waarde true heeft, maakt de constructor een NativeMenu-object voor het venster, waarna de submenu's File en Edit worden gemaakt en toegevoegd. Als NativeApplication.supportsMenu de waarde true heeft, maakt de constructor de menu's File en Edit, waarna deze worden toegevoegd aan het bestaande menu dat wordt geleverd door het besturingssysteem Mac OS X. Dit voorbeeld illustreert ook de afhandeling van menugebeurtenissen. De gebeurtenis select wordt zowel op itemals op menuniveau afgehandeld. Ieder menu in de keten, van het menu dat het geselecteerde item bevat tot het hoofdmenu, reageert op de gebeurtenis select. De gebeurtenis displaying wordt gebruikt met het menu met recent geopende bestanden. Vlak voordat het menu wordt geopend, worden de items in het menu vernieuwd aan de hand van de array met recent geopende documenten (die in dit voorbeeld niet verandert). Hoewel het in dit voorbeeld niet wordt geïllustreerd, kunt u ook luisteren naar displaying-gebeurtenissen voor afzonderlijke items. 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();
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 97 Werken met native menu's
} 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);
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 98 Werken met native menu's
} 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; } } }
99
Hoofdstuk 13: Taakbalkpictogrammen Veel besturingssystemen hebben een taakbalk, zoals het dock van Mac OS X, dat pictogrammen (in Mac OS 'symbolen') kan bevatten die toepassingen vertegenwoordigen. Adobe® AIR® biedt een interface voor interactie met het taakbalkpictogram van een toepassing via de eigenschap NativeApplication.nativeApplication.icon.
Aanvullende online informatie over taakbalkpictogrammen In de volgende bronnen vindt u meer informatie over het werken met taakbalken: Snelstarthandleidingen (Adobe AIR Developer Connection) • Werken met systeemvak- en dock-pictogrammen Language Reference • DockIcon
• SystemTrayIcon Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar 'AIR taskbar icons')
Informatie over taakbalkpictogrammen AIR maakt automatisch het object NativeApplication.nativeApplication.icon. Het objecttype is DockIcon of SystemTrayIcon, afhankelijk van het besturingssysteem. U kunt bepalen welke van deze InteractiveIcon-subklassen AIR in het huidige besturingssysteem ondersteunt met behulp van de eigenschappen NativeApplication.supportsDockIcon en NativeApplication.supportsSystemTrayIcon. De basisklasse InteractiveIcon biedt de eigenschappen width, height en bitmaps, die u kunt gebruiken om de afbeelding voor het pictogram te wijzigen. Als u echter eigenschappen die specifiek zijn voor DockIcon of SystemTrayIcon in het verkeerde besturingssysteem opvraagt, wordt er een runtimefout gegenereerd. Als u de afbeelding die voor een pictogram wordt gebruikt, wilt instellen of wijzigen, maakt u een array met een of meer afbeeldingen en wijst u deze toe aan de eigenschap NativeApplication.nativeApplication.icon.bitmaps. De grootte van taakbalkpictogrammen kan per besturingssysteem verschillen. Als u wilt voorkomen dat de kwaliteit van de pictogramafbeelding vermindert door het wijzigen van het formaat, voegt u afbeeldingen in verschillende formaten toe aan de array bitmaps. Als u meer dan één afbeelding aanbiedt, selecteert AIR automatisch het formaat dat het dichtst bij de huidige weergavegrootte van het taakbalkpictogram komt, en wordt het formaat van de afbeelding alleen aangepast als dat noodzakelijk is. In het volgende voorbeeld ziet u hoe u de afbeelding voor een taakbalkpictogram instelt met twee afbeeldingen: NativeApplication.nativeApplication.icon.bitmaps = [bmp16x16.bitmapData, bmp128x128.bitmapData];
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 100 Taakbalkpictogrammen
Als u de pictogramafbeelding wilt wijzigen, wijst u een array met de nieuwe afbeelding(en) toe aan de eigenschap bitmaps. U kunt animatie aan het pictogram toevoegen door de afbeelding te wijzigen als reactie op de gebeurtenis enterFrame of timer. Als u het pictogram uit het systeemvak van Windows wilt verwijderen of als u de standaardweergave van pictogrammen in Mac OS X wilt herstellen, stelt u bitmaps in op een lege array: NativeApplication.nativeApplication.icon.bitmaps = [];
Dock-pictogrammen AIR ondersteunt pictogrammen in het dock wanneer NativeApplication.supportsDockIcon is ingesteld op true. De eigenschap NativeApplication.nativeApplication.icon vertegenwoordigt het toepassingspictogram in het dock (geen vensterpictogram in het dock). Opmerking: AIR biedt geen ondersteuning voor veranderende vensterpictogrammen in het dock in Mac OS X. Ook zijn wijzigingen in het dock-pictogram voor een toepassing alleen van kracht op het moment dat de toepassing wordt uitgevoerd en krijgt het pictogram weer zijn normale uiterlijk wanneer de toepassing wordt afgesloten.
Menu's van pictogrammen in het dock U kunt opdrachten toevoegen aan het standaardmenu van een dock door een NativeMenu-object met deze opdrachten te maken en dit object vervolgens toe te wijzen aan de eigenschap NativeApplication.nativeApplication.icon.menu. De items in het menu worden boven de standaarditems in het dock-menu weergegeven.
Het pictogram in het dock laten bewegen U kunt een pictogram in het dock laten bewegen door de methode NativeApplication.nativeApplication.icon.bounce() op te roepen. Als u de parameter bounce() priority instelt op informational (informatief), beweegt het pictogram één keer. Als u deze parameter instelt op critical (kritiek), beweegt het pictogram totdat de gebruiker de toepassing activeert. Constanten voor de parameter priority worden gedefineerd in de klasse NotificationType. Opmerking: Het pictogram beweegt niet als de toepassing al actief is.
Gebeurtenissen van pictogrammen in het dock Wanneer op een dock-pictogram wordt geklikt, verzendt het NativeApplication-object de gebeurtenis invoke. Als de toepassing nog niet wordt uitgevoerd, wordt deze door het systeem gestart. Als de toepassing wel wordt uitgevoerd, wordt de gebeurtenis invoke verzonden naar de actieve toepassingsinstantie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 101 Taakbalkpictogrammen
Systeemvakpictogrammen AIR ondersteunt systeemvakpictogrammen wanneer NativeApplication.supportsSystemTrayIcon is ingesteld op true, hetgeen momenteel alleen in Windows het geval is. In Windows worden systeemvakpictogrammen in het gedeelte helemaal links op de (horizontale) taakbalk weergegeven. Er wordt standaard geen enkel pictogram weergegeven. Als u een pictogram wilt weergeven, wijst u een array met BitmapData-objecten toe aan de eigenschap bitmaps van het pictogram. Als u de pictogramafbeelding wilt wijzigen, wijst u een array met de nieuwe afbeeldingen toe aan de eigenschap bitmaps. Als u het pictogram wilt verwijderen, stelt u bitmaps in op null.
Menu's van systeemvakpictogrammen U kunt een menu aan een systeemvakpictogram toevoegen door een NativeMenu-object te maken en dit object vervolgens aan de eigenschap NativeApplication.nativeApplication.icon.menu toe te wijzen (er is geen standaardmenu beschikbaar in het besturingssysteem). U kunt het menu van het systeemvakpictogram openen door met de rechtermuisknop op het pictogram te klikken.
Knopinfo van systeemvakpictogrammen Voeg knopinfo toe aan een pictogram door de eigenschap voor knopinfo in te stellen: NativeApplication.nativeApplication.icon.tooltip = "Application name";
Gebeurtenissen van systeemvakpictogrammen Het object SystemTrayIcon waarnaar wordt verwezen met de eigenschap NativeApplication.nativeApplication.icon, verzendt een ScreenMouseEvent voor de gebeurtenissen click, mouseDown, mouseUp, rightClick, rightMouseDown en rightMouseUp. U kunt deze gebeurtenissen samen met een pictogrammenu gebruiken om gebruikers in staat te stellen met uw toepassing te interageren wanneer deze geen zichtbare vensters heeft.
Voorbeeld: een toepassing maken zonder vensters In het volgende voorbeeld wordt een AIR-toepassing gemaakt met een systeemvakpictogram maar zonder zichtbare vensters. Het systeemvakpictogram heeft een menu met één opdracht voor het afsluiten van de toepassing.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 102 Taakbalkpictogrammen
package { import import import import import import import import import import
flash.display.Loader; flash.display.NativeMenu; flash.display.NativeMenuItem; flash.display.NativeWindow; flash.display.Sprite; flash.desktop.DockIcon; flash.desktop.SystemTrayIcon; flash.events.Event; flash.net.URLRequest; flash.desktop.NativeApplication;
public class SysTrayApp extends Sprite { public function SysTrayApp():void{ NativeApplication.nativeApplication.autoExit = false; var icon:Loader = new Loader(); var iconMenu:NativeMenu = new NativeMenu(); var exitCommand:NativeMenuItem = iconMenu.addItem(new NativeMenuItem("Exit")); exitCommand.addEventListener(Event.SELECT, function(event:Event):void { NativeApplication.nativeApplication.icon.bitmaps = []; NativeApplication.nativeApplication.exit(); }); if (NativeApplication.supportsSystemTrayIcon) { NativeApplication.nativeApplication.autoExit = false; icon.contentLoaderInfo.addEventListener(Event.COMPLETE, iconLoadComplete); icon.load(new URLRequest("icons/AIRApp_16.png")); var systray:SystemTrayIcon = NativeApplication.nativeApplication.icon as SystemTrayIcon; 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]; } } }
Opmerking: In het voorbeeld wordt aangenomen dat er afbeeldingsbestanden aanwezig zijn met de naam AIRApp_16.png en AIRApp_128.png in de submap icons van de toepassing. (In de SDK van AIR vindt u voorbeeldpictogrambestanden, die u naar uw eigen projectmap kunt kopiëren.)
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 103 Taakbalkpictogrammen
Taakbalkpictogrammen en -knoppen voor vensters In een speciaal gebied van de taakbalk of het dock worden gewoonlijk pictogrammen of knoppen weergegeven die vensters vertegenwoordigen en waarmee gebruikers gemakkelijk toegang kunnen krijgen tot vensters die zich op de achtergrond bevinden of zijn geminimaliseerd. In het dock van Mac OS X wordt een pictogram weergegeven voor een toepassing, maar ook een pictogram voor elk geminimaliseerd venster. Op de taakbalk van Microsoft Windows wordt een knop weergegeven met het programmapictogram en de titel voor elk normaal venster van de toepassing.
De taakbalkknop voor een venster markeren Wanneer een venster zich op de achtergrond bevindt, kunt u de gebruiker waarschuwen wanneer betreffende dat venster een gebeurtenis plaatsvindt die van belang is voor de gebruiker. In Mac OS X kunt u de gebruiker waarschuwen door het toepassingspictogram in het dock te laten bewegen (zoals is beschreven in “Het pictogram in het dock laten bewegen” op pagina 100). In Windows kunt u de taakbalkknop van een venster markeren door de methode notifyUser() van de NativeWindow-instantie op te roepen. De parameter type die aan de methode wordt doorgegeven, bepaalt de urgentie van de waarschuwing:
•
NotificationType.CRITICAL: het pictogram van het venster knippert totdat de gebruiker het venster op de
voorgrond plaatst.
•
NotificationType.INFORMATIONAL: het pictogram van het venster wordt gemarkeerd door een kleurwijziging.
Met de volgende instructie zorgt u dat de taakbalkknop van een venster wordt gemarkeerd: stage.nativeWindow.notifyUser(NotificationType.CRITICAL);
De methode NativeWindow.notifyUser() heeft alleen effect als u deze methode oproept in een besturingssysteem dat waarschuwingen op vensterniveau ondersteunt. Gebruik de eigenschap NativeWindow.supportsNotification om te controleren of vensterwaarschuwingen worden ondersteund.
Vensters zonder taakbalkknoppen of -pictogrammen maken In Windows worden vensters van het type utility of lightweight niet op de taakbalk weergegeven. Ook onzichtbare vensters verschijnen niet op de taakbalk. Omdat het beginvenster noodzakelijkerwijs van het type normal is, moet u dit beginvenster sluiten of zorgen dat het onzichtbaar blijft als u een toepassing wilt maken waarvan de vensters niet als knop op de taakbalk worden weergegeven. Als u alle vensters van uw toepassing wilt sluiten zonder de toepassing af te sluiten, stelt u de eigenschap autoExit van het object NativeApplication in op false voordat u het laatste venster sluit. Als u eenvoudig wilt voorkomen dat het beginvenster ooit zichtbaar wordt, voegt u false toe aan het element van het descriptorbestand van de toepassing. (Stel de eigenschap visible niet in op true en roep ook niet de methode activate() van het venster op.) Stel voor nieuwe vensters die door de toepassing worden geopend, de eigenschap type van het object NativeWindowInitOption dat wordt doorgegeven aan de vensterconstructor, in op NativeWindowType.UTILITY of NativeWindowType.LIGHTWEIGHT. In Mac OS X worden geminimaliseerde vensters weergegeven op de dock-taakbalk. U kunt voorkomen dat het pictogram van een geminimaliseerd venster wordt weergegeven door het venster te verbergen in plaats van te minimaliseren. In het volgende voorbeeld wordt geluisterd naar een gebeurtenis die nativeWindowDisplayState verandert en wordt deze gebeurtenis geannuleerd als het venster wordt geminimaliseerd. In plaats daarvan stelt de handler de eigenschap visible van het venster in op false:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 104 Taakbalkpictogrammen
private function preventMinimize(event:NativeWindowDisplayStateEvent):void{ if(event.afterDisplayState == NativeWindowDisplayState.MINIMIZED){ event.preventDefault(); event.target.visible = false; } }
Als een venster wordt geminimaliseerd in het dock van Mac OS X wanneer u de eigenschap visible op false instelt, wordt het pictogram niet uit het dock verwijderd. Een gebruiker kan in dat geval nog steeds op het pictogram klikken om het venster opnieuw weer te geven.
105
Hoofdstuk 14: Werken met het bestandssysteem U gebruikt de klassen van de Adobe® AIR™-API voor het bestandssysteem voor toegang tot het bestandssysteem van de hostcomputer. Met deze klassen kunt u toegang krijgen tot mappen en bestanden en deze beheren, mappen en bestanden maken, gegevens naar bestanden schrijven enzovoort.
Aanvullende online informatie over de AIR API voor het bestandssysteem Meer informatie over het gebruik van de klassen in de API voor het bestandssysteem vindt u in de volgende bronnen: Snelstarthandleidingen (Adobe AIR Developer Connection) • Een editor voor tekstbestanden maken Language Reference • File
• FileStream • FileMode Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar 'AIR filesystem')
Basisinformatie over AIR-bestanden Adobe AIR biedt klassen die u kunt gebruiken om toegang te krijgen tot bestanden en mappen, en deze te maken en te beheren. Deze klassen, die zich bevinden in het pakket flash.filesystem, worden als volgt gebruikt: File-klasse
Beschrijving
File
Het File-object vertegenwoordigt een pad naar een bestand of map. U gebruikt een File-object om een aanwijzer naar een bestand of map te maken, waarbij interactie met het bestand of de map wordt gestart.
FileMode
De klasse FileMode definieert tekenreeksconstanten die worden gebruikt in de parameter fileMode van de methoden open() en openAsync() van de klasse FileStream. De parameter fileMode van deze methoden bepaalt de mogelijkheden die beschikbaar zijn voor het FileStream-object als het bestand eenmaal is geopend. Het gaat hierbij om schrijven, lezen, toevoegen en bijwerken.
FileStream
Het FileStream-object wordt gebruikt om bestanden te openen voor lezen en schrijven. Als u een File-object hebt gemaakt dat een nieuw of bestaand bestand aanwijst, geeft u die aanwijzer door aan het FileStream-object zodat u gegevens in het bestand kunt openen en manipuleren.
Bepaalde methoden in de klasse File hebben zowel een synchrone als een asynchrone versie:
•
File.copyTo() en File.copyToAsync()
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 106 Werken met het bestandssysteem
•
File.deleteDirectory() en File.deleteDirectoryAsync()
•
File.deleteFile() en File.deleteFileAsync()
•
File.getDirectoryListing() en File.getDirectoryListingAsync()
•
File.moveTo() en File.moveToAsync()
•
File.moveToTrash() en File.moveToTrashAsync()
Ook werken FileStream-bewerkingen synchroon of asynchroon afhankelijk van de manier waarop het FileStreamobject het bestand opent: door het oproepen van de methode open() of door het oproepen van de methode openAsync(). Met de asynchrone versies kunt u processen opstarten die op de achtergrond worden uitgevoerd en gebeurtenissen verzenden wanneer ze zijn voltooid (of wanneer er een fout optreedt). Andere code kan worden uitgevoerd terwijl deze asynchrone achtergrondprocessen plaatsvinden. Met asynchrone versies van de bewerkingen moet u gebeurtenislistenerfuncties instellen met behulp van de methode addEventListener() van het File- of FileStreamobject dat de functie oproept. Met asynchrone versies kunt u eenvoudiger code schrijven die niet afhankelijk is van het instellen van gebeurtenislisteners. Aangezien geen andere code kan worden uitgevoerd terwijl een synchrone methode wordt uitgevoerd, is het mogelijk dat belangrijke processen worden onderbroken, zoals de rendering van weergaveobjecten en animatie.
Werken met File-objecten Een File-object is een aanwijzer naar een bestand of map in het bestandssysteem. De klasse File is een uitbreiding van de klasse FileReference. De klasse FileReference, die beschikbaar is in Adobe® Flash® Player en AIR, vertegenwoordigt een aanwijzer voor een bestand, maar de klasse File voegt eigenschappen en methoden toe die uit veiligheidsoverwegingen niet worden blootgesteld in Flash Player (in een SWF-bestand dat wordt uitgevoerd in een browser).
Informatie over de klasse File U kunt de klasse File voor het volgende gebruiken:
• het ophalen van het pad naar speciale mappen, inclusief de gebruikersmap, de documentenmap van de gebruiker, de map van waaruit de toepassing is gestart en de toepassingsmap;
• het kopiëren van bestanden en mappen; • het verplaatsen van bestanden en mappen; • het verwijderen van bestanden en mappen (of het verplaatsen ervan naar de prullenbak); • het weergeven van lijsten van bestanden en mappen die zich bevinden in een map; • het maken van tijdelijke bestanden en mappen. Als een File-object eenmaal een bestandsmap aanwijst, kunt u dat object gebruiken om bestandsgegevens te lezen en te schrijven met behulp van de klasse FileStream. Een File-object kan het pad aanwijzen van een bestand dat of een map die nog niet bestaat. U kunt zo'n File-object gebruiken bij het maken van een bestand of map.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 107 Werken met het bestandssysteem
Paden van File-objecten Ieder File-object heeft twee eigenschappen die het pad ervan definiëren: Eigenschap
Beschrijving
nativePath
Geeft het platformspecifieke pad naar een bestand op. In Windows kan een pad bijvoorbeeld "C:\Voorbeeldmap\test.txt" zijn, terwijl in Mac OS het pad "/Voorbeeldmap/test.txt" is. De eigenschap nativePath gebruikt de backslash (\) als scheidingsteken voor mappen in Windows, en de schuine streep (/) in Mac OS.
url
Het URL-schema file kan dit gebruiken om een bestand aan te wijzen. In Windows kan een pad bijvoorbeeld "file:///C:/Voorbeeldmap/test.txt" zijn, terwijl in Mac OS het pad "file:///Voorbeeldmap/test.txt" is. De runtime bevat nog andere speciale URL-schema’s behalve file; deze worden beschreven in “Ondersteunde URLschema's” op pagina 111
De klasse File biedt eigenschappen voor het aanwijzen van standaardmappen in zowel Mac als Windows.
File-objecten een map laten aanwijzen Er zijn verschillende manieren om een File-object zo in te stellen dat het een map aanwijst.
De homemap van de gebruiker aanwijzen U kunt een File-object de homemap van de gebruiker laten aanwijzen. In Windows is de homemap de bovenliggende map van "Mijn documenten" (bijvoorbeeld "C:\Documents and Settings\gebruikersnaam\Mijn documenten"). In Mac OS is dit de map Users/gebruikersnaam. Met de volgende code stelt u een File-object zo in dat het de submap AIR Test van de homemap aanwijst: var file:File = File.userDirectory.resolvePath("AIR Test");
De documentenmap van de gebruiker aanwijzen U kunt een File-object de documentenmap van de gebruiker laten aanwijzen. In Windows is dit gewoonlijk de map "Mijn documenten" (bijvoorbeeld "C:\Documents and Settings\gebruikersnaam\Mijn documenten"). In Mac OS is dit de map Users/gebruikersnaam/Documents. Met de volgende code stelt u een File-object zo in dat het de submap AIR Test van de documentenmap aanwijst: var file:File = File.documentsDirectory.resolvePath("AIR Test");
De bureaubladmap aanwijzen U kunt een File-object het bureaublad laten aanwijzen. Met de volgende code stelt u een File-object zo in dat het de submap AIR Test van het bureaublad aanwijst: var file:File = File.desktopDirectory.resolvePath("AIR Test");
De opslagmap van een toepassing aanwijzen U kunt een File-object de opslagmap van een toepassing laten aanwijzen. Bij iedere AIR-toepassing is er een uniek gekoppeld pad dat de opslagmap van de toepassing definieert. Deze map is uniek voor iedere toepassing en iedere gebruiker. U kunt deze map desgewenst gebruiken om gebruikers- en toepassingsspecifieke gegevens (bijvoorbeeld gebruikersgegevens of voorkeurenbestanden) op te slaan. Met de volgende code wijst een File-object bijvoorbeeld een voorkeurenbestand met de naam prefs.xml aan dat zich bevindt in de opslagmap van de toepassing: var file:File = File.applicationStorageDirectory; file = file.resolvePath("prefs.xml";
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 108 Werken met het bestandssysteem
De locatie van de opslagmap van de toepassing is gebaseerd op de gebruikersnaam, de toepassings-id en de uitgevers-id:
• In Mac OS, in: /Users/gebruikersnaam/Library/Preferences/toepassings-id.uitgevers-id/Local Store/
Bijvoorbeeld: /Users/babbage/Library/Preferences/com.example.TestApp.02D88EEED35F84C264A183921344EEA353 A629FD.1/Local Store
• In Windows, in de map Documents and Settings in: gebruikersnaam/Application Data/toepassings-id.uitgevers-id/Local Store/ Bijvoorbeeld: C:\Documents and Settings\babbage\Application Data\com.example.TestApp.02D88EEED35F84C264A183921344EEA353A629FD.1\Local Store
De URL (en de eigenschap url) van een File-object dat is gemaakt met File.applicationStorageDirectory, gebruikt het URL-schema app-storage (zie “Ondersteunde URL-schema's” op pagina 111). Zie het volgende voorbeeld: var dir:File = File.applicationStorageDirectory; dir = dir.resolvePath("preferences"); trace(dir.url); // app-storage:/preferences
De toepassingsmap aanwijzen U kunt een File-object de map laten aanwijzen waarin de toepassing is geïnstalleerd. Deze wordt de toepassingsmap genoemd. U kunt verwijzen naar deze map met behulp van de eigenschap File.applicationDirectory. U kunt deze map gebruiken om het descriptorbestand van de toepassing te onderzoeken, of andere resources die met de toepassing zijn geïnstalleerd. Met de volgende code wijst een File-object bijvoorbeeld de map images in de toepassingsmap aan: var dir:File = File.applicationDirectory; dir = dir.resolvePath("images");
De URL (en de eigenschap url) van een File-object dat is gemaakt met File.applicationDirectory, gebruikt het URL-schema app (zie “Ondersteunde URL-schema's” op pagina 111). Zie het volgende voorbeeld: var dir:File = File.applicationDirectory; dir = dir.resolvePath("images"); trace(dir.url); // app:/images
De hoofdmap van het bestandssysteem aanwijzen De methode File.getRootDirectories() geeft een lijst weer van alle hoofdvolumes (zoals C:) en alle gekoppelde volumes op een Windows-computer. Op een Mac geeft deze methode altijd als resultaat de unieke hoofdmap van de computer (de map "/").
Een expliciete map aanwijzen U kunt het File-object een expliciete map laten aanwijzen door de eigenschap nativePath van het File-object in te stellen, zoals in het volgende voorbeeld (in Windows): var file:File = new File(); file.nativePath = "C:\\AIR Test\";
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 109 Werken met het bestandssysteem
Navigeren naar relatieve paden U kunt de methode resolvePath() gebruiken om een pad te verkrijgen dat is gebaseerd op een ander gegeven pad. Met de volgende code stelt u bijvoorbeeld een File-object zo in dat het de submap AIR Test van de homemap van de gebruiker aanwijst: var file:File = File.userDirectory; file = file.resolvePath("AIR Test");
U kunt ook de eigenschap url van een File-object gebruiken om dit een map te laten aanwijzen op basis van een URLtekenreeks, zoals bij het volgende: var urlStr:String = "file:///C:/AIR Test/"; var file:File = new File() file.url = urlStr;
Zie “Bestandspaden wijzigen” op pagina 111 voor meer informatie.
De gebruiker naar de gewenste map laten bladeren en deze selecteren De klasse File bevat de methode browseForDirectory(), die een systeemdialoogvenster presenteert waarin de gebruiker de map kan selecteren die aan het object moet worden toegewezen. De methode browseForDirectory() is asynchroon. Deze verzendt de gebeurtenis select als de gebruiker een map selecteert en op de knop Openen klikt. De gebeurtenis cancel wordt verzonden als de gebruiker op de knop Annuleren klikt. Met de volgende code kan de gebruiker bijvoorbeeld een map selecteren en wordt na selectie het pad van de map als uitvoergegeven ingesteld: var file:File = new File(); file.addEventListener(Event.SELECT, dirSelected); file.browseForDirectory("Select a directory"); function dirSelected(e:Event):void { trace(file.nativePath); }
De map aanwijzen van waaruit de toepassing is opgeroepen U kunt de locatie opvragen van de map van waaruit een toepassing is opgeroepen door de eigenschap currentDirectory van het InvokeEvent-object te controleren dat wordt verzonden wanneer de toepassing wordt opgeroepen. Zie “Opdrachtregelargumenten vastleggen” op pagina 276 voor meer informatie.
File-objecten een bestand laten aanwijzen Er zijn verschillende manieren om het bestand in te stellen dat door een File-object wordt aangewezen.
Expliciete bestandspaden aanwijzen U kunt de methode resolvePath() gebruiken om een pad te verkrijgen dat is gebaseerd op een ander gegeven pad. Met de volgende code wijst een File-object bijvoorbeeld het bestand log.txt aan dat zich bevindt in de opslagmap van de toepassing: var file:File = File.applicationStorageDirectory; file = file.resolvePath("log.txt");
U kunt de eigenschap url van een File-object gebruiken om dit een bestand of map te laten aanwijzen op basis van een URL-tekenreeks, zoals in het volgende voorbeeld:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 110 Werken met het bestandssysteem
var urlStr:String = "file:///C:/AIR Test/test.txt"; var file:File = new File() file.url = urlStr;
U kunt de URL ook doorgeven naar de constructorfunctie File(), zoals in het volgende voorbeeld: var urlStr:String = "file:///C:/AIR Test/test.txt"; var file:File = new File(urlStr);
De eigenschap url retourneert altijd de URI-gecodeerde versie van de URL (spaties worden bijvoorbeeld vervangen door "%20"): file.url = "file:///c:/AIR Test"; trace(file.url); // file:///c:/AIR%20Test
U kunt ook de eigenschap nativePath van een File-object gebruiken om een expliciet pad in te stellen. Als de volgende code bijvoorbeeld wordt uitgevoerd op een Windows-computer, wordt een File-object ingesteld op het bestand test.txt in de submap AIR Test van het C:-station: var file:File = new File(); file.nativePath = "C:/AIR Test/test.txt";
U kunt dit pad ook doorgeven naar de constructorfunctie File(), zoals in het volgende voorbeeld: var file:File = new File("C:/AIR Test/test.txt");
In Windows kunt u de schuine streep (/) of de backslash (\) gebruiken als padscheidingsteken voor de eigenschap nativePath. In Mac OS gebruikt u de schuine streep (/) als padscheidingsteken voor nativePath: var file:File = new File(/Users/dijkstra/AIR Test/test.txt");
Zie “Bestandspaden wijzigen” op pagina 111 voor meer informatie.
Opsommingen maken van bestanden in een map U kunt de methode getDirectoryListing() van een File-object gebruiken om een array op te halen van Fileobjecten die bestanden en submappen aanwijzen op het hoofdniveau van een map. Zie “Opsommingen maken van mappen” op pagina 116 voor meer informatie.
De gebruiker naar het gewenste bestand laten bladeren en dit selecteren De klasse File bevat de volgende methoden die een systeemdialoogvenster presenteren waarin de gebruiker een bestand kan selecteren dat aan het object moet worden toegewezen:
•
browseForOpen()
•
browseForSave()
•
browseForOpenMultiple()
Deze methoden zijn allemaal asynchroon. De methoden browseForOpen() en browseForSave() verzenden de gebeurtenis select wanneer de gebruiker een bestand selecteert (of een doelpad, bij het gebruik van browseForSave()). Met de methoden browseForOpen() en browseForSave() wijst het File-doelobject na selectie de geselecteerde bestanden aan. De methode browseForOpenMultiple() verzendt de gebeurtenis selectMultiple wanneer de gebruiker bestanden selecteert. De gebeurtenis selectMultiple is van het type FileListEvent. Dit type heeft de eigenschap files, die bestaat uit een array van File-objecten (die de geselecteerde bestanden aanwijzen).
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 111 Werken met het bestandssysteem
De volgende code presenteert de gebruiker bijvoorbeeld met het dialoogvenster “Openen” waarin deze een bestand kan selecteren: 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); }
Als er in de toepassing een ander dialoogvenster voor het bladeren naar mappen of bestanden open is wanneer u een bladermethode oproept, produceert de runtime een uitzonderingsfout.
Bestandspaden wijzigen U kunt ook het pad van een bestaand File-object wijzigen door de methode resolvePath() op te roepen, of door de eigenschap nativePath of url van het object op te roepen, zoals in de volgende voorbeelden (voor 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
Wanneer u de eigenschap nativePath gebruikt, kunt u de schuine streep (/) of de backslash (\) gebruiken als scheidingsteken voor mappen in Windows. In Mac OS gebruikt u de schuine streep (/). Vergeet in Windows niet de backslash tweemaal te typen in tekenreeksliterals.
Ondersteunde URL-schema's U kunt elk van de volgende URL-schema's gebruiken voor het definiëren van de eigenschap url van een File-object:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 112 Werken met het bestandssysteem
URL-schema
Beschrijving
file
Wordt gebruikt om een pad op te geven dat is gebaseerd op de hoofdmap van het bestandssysteem. Bijvoorbeeld: file:///c:/AIR Test/test.txt
De URL-standaard bepaalt dat een bestands-URL de volgende vorm heeft: file:///<pad>. Als speciaal geval kan een lege tekenreeks zijn. Dit wordt geïnterpreteerd als "de computer van waaruit de URL wordt geïnterpreteerd". Om deze reden hebben bestands-URL's vaak drie schuine strepen (///). app
Wordt gebruikt om een pad op te geven dat is gebaseerd op de hoofdmap (de map met het bestand application.xml van de geïnstalleerde toepassing) van de geïnstalleerde toepassing. Het volgende pad wijst bijvoorbeeld de submap images van de map van de geïnstalleerde toepassing aan: app:/images
app-storage
Wordt gebruikt om een pad op te geven dat is gebaseerd op de opslagmap van de toepassing. Voor elke geïnstalleerde toepassing definieert AIR een unieke opslagmap. Dit is de plaats waar gegevens worden opgeslagen die eigen zijn aan die toepassing. Het volgende pad verwijst bijvoorbeeld naar het bestand prefs.xml in de submap settings van de opslagmap van een toepassing: app-storage:/settings/prefs.xml
Het relatieve pad tussen twee bestanden opzoeken U kunt de methode getRelativePath() gebruiken om het relatieve pad tussen twee bestanden op te zoeken: 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
De tweede parameter van de methode getRelativePath(), de parameter useDotDot maakt het mogelijk dat de syntaxis .. wordt geretourneerd in resultaten om bovenliggende mappen aan te geven: 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
Canonieke versies van bestandsnamen verkrijgen Bestands- en padnamen zijn gewoonlijk niet hoofdlettergevoelig. In het volgende voorbeeld wijzen twee File-objecten hetzelfde bestand aan: File.documentsDirectory.resolvePath("test.txt"); File.documentsDirectory.resolvePath("TeSt.TxT");
Documenten en mapnamen maken echter wel gebruik van hoofdletters en kleine letters. Bij het volgende wordt ervan uitgegaan dat de documentenmap een map met de naam AIR Test bevat, zoals in de volgende voorbeelden:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 113 Werken met het bestandssysteem
var file:File = File.documentsDirectory.resolvePath("AIR test"); trace(file.nativePath); // ... AIR test file.canonicalize(); trace(file.nativePath); // ... AIR Test
De methode canonicalize converteert het nativePath-object zodat de juiste hoofdletters en kleine letters worden gebruikt voor de bestands- of mapnaam. U kunt de methode canonicalize() ook gebruiken om korte bestandsnamen ("8.3"-namen) te converteren naar lange bestandsnamen in Windows, zoals in de volgende voorbeelden: var path:File = new File(); path.nativePath = "C:\\AIR~1"; path.canonicalize(); trace(path.nativePath); // C:\AIR Test
Werken met pakketten en symbolische koppelingen Verschillende besturingssystemen ondersteunen pakketbestanden en symbolische koppelingsbestanden: Pakketten In Mac OS kunnen mappen worden aangewezen als pakketten. Ze worden dan in de Finder van Mac OS als één bestand en niet als een map weergegeven. Symbolische koppelingen Met symbolische koppelingen kan een bestand een ander bestand of een map op de schijf aanwijzen. Symbolische koppelingen zijn vergelijkbaar met aliassen, maar ze zijn niet hetzelfde. Een alias wordt altijd als een bestand (en niet als een map) gerapporteerd, en het lezen van of schrijven naar een alias of snelkoppeling is nooit van invloed op het oorspronkelijke bestand of de map die deze aanwijst. Een symbolische koppeling daarentegen gedraagt zich precies hetzelfde als het bestand of de map die deze koppeling aanwijst. Een symbolische koppeling kan als een bestand of een map worden gerapporteerd. Het lezen van of schrijven naar een symbolische koppeling is van invloed op het bestand of de map die deze koppeling aanwijst, en niet op de symbolische koppeling zelf. De klasse File bevat de eigenschappen isPackage en isSymbolicLink, waarmee kan worden gecontroleerd of een File-object naar een pakket dan wel naar een symbolische koppeling verwijst. De volgende code doorzoekt de bureaubladmap van de gebruiker en geeft een lijst weer van de submappen die geen pakketten zijn: 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); } }
De volgende code doorzoekt de bureaubladmap van de gebruiker en geeft een lijst weer van de bestanden en mappen die geen symbolische koppelingen zijn:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 114 Werken met het bestandssysteem
var desktopNodes:File = File.desktopDirectory.getDirectoryListing(); for (var i:uint = 0; i < desktopNodes.length; i++) { if (!desktopNodes[i].isSymbolicLink) { trace(desktopNodes[i].name); } }
De methode canonicalize() wijzigt het pad van een symbolische koppeling zodat deze het bestand of de map aanwijst waarnaar de koppeling verwijst. De volgende code doorzoekt de bureaubladmap van de gebruiker en rapporteert de paden waarnaar wordt verwezen door bestanden die symbolische koppelingen zijn: 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); } }
De beschikbare ruimte op een volume bepalen De eigenschap spaceAvailable van een File-object is de beschikbare ruimte op de File-locatie, in bytes. De volgende code controleert bijvoorbeeld de ruimte die beschikbaar is in de opslagmap van de toepassing: trace(File.applicationStorageDirectory.spaceAvailable);
Als het File-object verwijst naar een map, geeft de eigenschap spaceAvailable de ruimte aan die in die map beschikbaar is voor bestanden. Als het File-object verwijst naar een bestand, geeft de eigenschap spaceAvailable de ruimte aan die beschikbaar is als het bestand in grootte toeneemt. Als de bestandslocatie niet bestaat, wordt de eigenschap spaceAvailable ingesteld op 0. Als het File-object verwijst naar een symbolische koppeling, wordt de eigenschap spaceAvailable ingesteld op de ruimte die beschikbaar is op de locatie die de symbolische koppeling aanwijst. De ruimte die beschikbaar is voor een bestand of map, is in het algemeen hetzelfde als de ruimte die beschikbaar is op het volume dat het bestand of de map bevat. Bij de beschikbare ruimte kan echter rekening worden gehouden met accountquota's en groottebeperkingen per map. Het toevoegen van een bestand of map aan een volume vereist in het algemeen meer ruimte dan de werkelijke grootte van het bestand of de grootte van de inhoud van de map. Het besturingssysteem kan bijvoorbeeld meer ruimte nodig hebben om indexgegevens op te slaan. Het is ook mogelijk dat de vereiste schijfsectoren meer ruimte gebruiken. Bovendien verandert de beschikbare ruimte dynamisch. U kunt dus niet verwachten dat de volledige gerapporteerde schijfruimte kan worden toegewezen voor bestandsopslag. Zie “Lezen van en schrijven naar bestanden” op pagina 120 voor meer informatie.
Informatie over het bestandssysteem ophalen De klasse File bevat de volgende statische eigenschappen die nuttige informatie over het bestandssysteem kunnen geven:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 115 Werken met het bestandssysteem
Eigenschap
Beschrijving
File.lineEnding
Het regeleindeteken dat wordt gebruikt door het hostbesturingssysteem. In Mac OS is dit het line feed-teken. In Windows is dit het carriage return-teken, gevolgd door het line feed-teken.
File.separator
Het teken dat in het hostbesturingssysteem wordt gebruikt om de onderdelen van paden te scheiden. In Mac OS is dit de schuine streep (/). In Windows is dit de backslash (\).
File.systemCharset
De standaardcodering die door het hostbesturingssysteem wordt gebruikt voor bestanden. Dit heeft betrekking op de tekenset die door het besturingssysteem wordt gebruikt en die correspondeert met de taal.
De klasse Capabilities bevat ook systeeminformatie die nuttig kan zijn bij het werken met bestanden: Eigenschap
Beschrijving
Capabilities.hasIME
Geeft aan of de speler op een systeem wordt uitgevoerd waarop een invoermethode-editor (IME) is geïnstalleerd (true) of niet (false).
Capabilities.language
Geeft de taalcode op van het systeem waarop de speler wordt uitgevoerd.
Capabilities.os
Geeft het huidige besturingssysteem op.
Werken met mappen De runtime biedt u mogelijkheden om te werken met mappen in het lokale bestandssysteem. Zie “File-objecten een map laten aanwijzen” op pagina 107 voor meer informatie over het maken van File-objecten die mappen aanwijzen.
Mappen maken Met de methode File.createDirectory() kunt u een map maken. Met de volgende code maakt u bijvoorbeeld een map met de naam AIR Test die een submap is van de homemap van de gebruiker: var dir:File = File.userDirectory.resolvePath("AIR Test"); dir.createDirectory();
Als die map al bestaat, doet de methode createDirectory() verder niets. In bepaalde modi maakt een FileStream-object mappen wanneer bestanden worden geopend. Ontbrekende mappen worden gemaakt wanneer u een FileStream-instantie instantieert met de parameter fileMode van de FileStream()constructor ingesteld op FileMode.APPEND of FileMode.WRITE. Zie “Workflow voor het lezen van en schrijven naar bestanden” op pagina 120 voor meer informatie.
Tijdelijke mappen maken De klasse File bevat de methode createTempDirectory(), die een map maakt in de Temp-map van het systeem, zoals in het volgende voorbeeld: var temp:File = File.createTempDirectory();
De methode createTempDirectory() maakt automatisch een unieke tijdelijke map (zodat u niet zelf een nieuwe unieke locatie hoeft te bepalen).
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 116 Werken met het bestandssysteem
U kunt een tijdelijke map gebruiken om tijdelijke bestanden die worden gebruikt gedurende een sessie van de toepassing, tijdelijk op te slaan. Er is ook de methode createTempFile() voor het maken van nieuwe unieke tijdelijke bestanden in de Temp-map van het systeem. U kunt desgewenst de tijdelijke map verwijderen voordat de toepassing wordt gesloten, aangezien deze map niet automatisch wordt verwijderd.
Opsommingen maken van mappen U kunt de methode getDirectoryListing() of getDirectoryListingAsync() van een File-object gebruiken om een array op te halen van File-objecten die bestanden en submappen aanwijzen in een map. De volgende code geeft bijvoorbeeld een lijst weer van de inhoud van de documentenmap van de gebruiker (zonder submappen te doorzoeken): 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); }
Als u de asynchrone versie van de methode gebruikt, heeft het gebeurtenisobject directoryListing de eigenschap files, die bestaat uit de array van File-objecten die betrekking hebben op de mappen: 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); } }
Mappen kopiëren en verplaatsen U kunt een map kopiëren of verplaatsen met behulp van dezelfde methoden die u gebruikt om een bestand te kopiëren of te verplaatsen. Met de volgende code kopieert u bijvoorbeeld een map synchroon: var sourceDir:File = File.documentsDirectory.resolvePath("AIR Test"); var resultDir:File = File.documentsDirectory.resolvePath("AIR Test Copy"); sourceDir.copyTo(resultDir);
Wanneer u "true" opgeeft voor de parameter overwrite van de methode copyTo(), worden alle bestanden en mappen in een bestaande doelmap verwijderd en vervangen door de bestanden en mappen uit de bronmap (zelfs als het doelbestand niet bestaat in de bronmap). De map die u opgeeft bij de parameter newLocation van de methode copyTo(), definieert het pad naar de resulterende map. Deze parameter definieert niet de bovenliggende map die de resulterende map zal bevatten. Zie “Bestanden kopiëren en verplaatsen” op pagina 118 voor meer informatie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 117 Werken met het bestandssysteem
De inhoud van mappen verwijderen De klasse File bevat de methoden deleteDirectory() en deleteDirectoryAsync(). Deze methoden verwijderen mappen, de eerste op synchrone wijze, de tweede op asynchrone wijze (zie “Basisinformatie over AIR-bestanden” op pagina 105). Beide methoden bevatten de parameter deleteDirectoryContents (die een Booleaanse waarde heeft). Wanneer deze parameter wordt ingesteld op true (de standaardwaarde is false), verwijdert de oproep van deze methode mappen die niet leeg zijn. Bij gebruik van de standaardwaarde worden alleen lege mappen verwijderd. De volgende code verwijdert bijvoorbeeld synchroon de submap AIR Test van de documentenmap van de gebruiker: var directory:File = File.documentsDirectory.resolvePath("AIR Test"); directory.deleteDirectory(true);
De volgende code verwijdert asynchroon de submap AIR Test van de documentenmap van de gebruiker: var directory:File = File.documentsDirectory.resolvePath("AIR Test"); directory.addEventListener(Event.COMPLETE, completeHandler) directory.deleteDirectoryAsync(true); function completeHandler(event:Event):void { trace("Deleted.") }
Ook beschikbaar zijn de methoden moveToTrash() en moveToTrashAsync(), die u kunt gebruiken om een map te verplaatsen naar de systeemprullenbak. Zie “Bestanden verplaatsen naar de prullenbak” op pagina 119 voor meer informatie.
Werken met bestanden Met behulp van de AIR API voor het bestandssysteem kunt u basismogelijkheden voor de interactie tussen bestanden toevoegen aan uw toepassingen. U kunt bijvoorbeeld lezen van en schrijven naar bestanden, bestanden kopiëren en verwijderen enzovoort. Aangezien uw toepassingen toegang kunnen krijgen tot het lokale bestandssysteem, is het aan te raden “Beveiliging in AIR” op pagina 24 te raadplegen als u dat nog niet hebt gedaan. Opmerking: U kunt een bestandstype koppelen aan een AIR-toepassing (zodat de toepassing wordt geopend wanneer u dubbelklikt op het bestand). Zie “Bestandskoppelingen beheren” op pagina 284 voor meer informatie.
Bestandsinformatie ophalen De klasse File bevat de volgende eigenschappen die informatie verstrekken over een bestand dat of een map die wordt aangewezen door een File-object: File-eigenschap
Beschrijving
creationDate
De aanmaakdatum van het bestand op de lokale schijf.
creator
Verouderd - gebruik de eigenschap extension. (Deze eigenschap rapporteert het Macintosh-creatortype van het bestand; dit wordt alleen gebruikt in Mac OS-versies voorafgaand aan Mac OS X.)
exists
Geeft aan of het bestand of de map waarnaar wordt verwezen, bestaat.
extension
De bestandsextensie, die bestaat uit het deel van de naam na (en niet inclusief) de laatste punt ("."). Als de bestandsnaam geen punt bevat, is de extensie null.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 118 Werken met het bestandssysteem
File-eigenschap
Beschrijving
icon
Een Icon-object dat de pictogrammen bevat die zijn gedefinieerd voor het bestand.
isDirectory
Geeft aan of de File-objectverwijzing betrekking heeft op een map.
modificationDate
De datum waarop het bestand of de map op de lokale schijf voor het laatst is gewijzigd.
name
De naam van het bestand of de map (inclusief de eventuele bestandsextensie) op de lokale schijf.
nativePath
Het volledige pad in de representatie van het hostbesturingssysteem. Zie “Paden van File-objecten” op pagina 107.
parent
De map die de map of het bestand bevat dat wordt vertegenwoordigd door het File-object. Deze eigenschap is null als het File-object verwijst naar een bestand of map in de hoofdmap van het bestandssysteem.
size
De grootte van het bestand op de lokale schijf (in bytes).
type
Verouderd - gebruik de eigenschap extension. (Op de Macintosh is deze eigenschap het bestandstype van vier tekens; dit wordt alleen gebruikt in Mac OS-versies voorafgaand aan Mac OS X.)
url
De URL voor het bestand of de map. Zie “Paden van File-objecten” op pagina 107.
Zie het item File class in ActionScript 3.0 Language and Components Reference (http://www.adobe.com/go/learn_air_aslr_nl) voor meer informatie over deze eigenschappen.
Bestanden kopiëren en verplaatsen De klasse File bevat twee methoden voor het kopiëren van bestanden of mappen: copyTo() en copyToAsync(). De klasse File bevat twee methoden voor het verplaatsen van bestanden of mappen: moveTo() en moveToAsync(). De methoden copyTo() en moveTo() werken synchroon, de methoden copyToAsync() en moveToAsync() asynchroon (zie “Basisinformatie over AIR-bestanden” op pagina 105). Als u een bestand wilt kopiëren of verplaatsen, stelt u twee File-objecten in. Een van deze objecten wijst het bestand aan dat u wilt kopiëren of verplaatsen. Dit is het object dat de kopieer- of verplaatsingsmethode oproept. Het andere object wijst het doelpad (resultaat) aan. Met de volgende code kopieert u het bestand test.txt van de submap AIR Test van de documentenmap van de gebruiker naar het bestand copy.txt in dezelfde map: var original:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var newFile:File = File.resolvePath("AIR Test/copy.txt"); original.copyTo(newFile, true);
In dit voorbeeld is de waarde van de parameter overwrite van de methode copyTo() (de tweede parameter) ingesteld op true. Door deze parameter in te stellen op true wordt een bestaand doelbestand overschreven. Deze parameter is optioneel. Als u de parameter instelt op false (de standaardwaarde), verzendt de bewerking de gebeurtenis IOErrorEvent als het doelbestand al bestaat. Het bestand wordt dan niet gekopieerd. De “Async”-versies van de kopieer- en verplaatsingsmethoden werken asynchroon. Gebruik de methode addEventListener() om te controleren of de taak al is voltooid, en of er eventuele fouten zijn opgetreden, bijvoorbeeld met de volgende code:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 119 Werken met het bestandssysteem
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."); }
De klasse File bevat ook de methoden File.moveToTrash() en File.moveToTrashAsync(), die een bestand of map naar de systeemprullenbak verplaatsen.
Bestanden verwijderen De klasse File bevat de methoden deleteFile() en deleteFileAsync(). Deze methoden verwijderen bestanden, de eerste op synchrone wijze, de tweede op asynchrone wijze (zie “Basisinformatie over AIR-bestanden” op pagina 105). De volgende code verwijdert bijvoorbeeld synchroon het bestand test.txt uit de documentenmap van de gebruiker: var file:File = File.documentsDirectory.resolvePath("test.txt"); file.deleteFile();
De volgende code verwijdert asynchroon het bestand test.txt uit de documentenmap van de gebruiker: var file:File = File.documentsDirectory.resolvePath("test.txt"); file.addEventListener(Event.COMPLETE, completeHandler) file.deleteFileAsync(); function completeHandler(event:Event):void { trace("Deleted.") }
Ook beschikbaar zijn de methoden moveToTrash() en moveToTrashAsync(), die u kunt gebruiken om een bestand of map te verplaatsen naar de systeemprullenbak. Zie “Bestanden verplaatsen naar de prullenbak” op pagina 119 voor meer informatie.
Bestanden verplaatsen naar de prullenbak De klasse File bevat de methoden moveToTrash() en moveToTrashAsync(). Deze methoden sturen een bestand of map naar de systeemprullenbak, de eerste synchroon, de tweede asynchroon (zie “Basisinformatie over AIRbestanden” op pagina 105). De volgende code verplaatst bijvoorbeeld synchroon het bestand test.txt uit de documentenmap van de gebruiker naar de systeemprullenbak: var file:File = File.documentsDirectory.resolvePath("test.txt"); file.moveToTrash();
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 120 Werken met het bestandssysteem
Tijdelijke bestanden maken De klasse File bevat de methode createTempFile(), die een bestand maakt in de Temp-map van het systeem, zoals in het volgende voorbeeld: var temp:File = File.createTempFile();
De methode createTempFile() maakt automatisch een uniek tijdelijk bestand (zodat u niet zelf een nieuwe unieke locatie hoeft te bepalen). U kunt een tijdelijk bestand gebruiken om informatie die wordt gebruikt gedurende een sessie van de toepassing, tijdelijk op te slaan. Er is ook de methode createTempDirectory() voor het maken van een unieke tijdelijke map in de Temp-map van het systeem. U kunt desgewenst het tijdelijke bestand verwijderen voordat de toepassing wordt gesloten, aangezien dit bestand niet automatisch wordt verwijderd.
Lezen van en schrijven naar bestanden Met de klasse FileStream kunnen AIR-toepassingen lezen van en schrijven naar het bestandssysteem.
Workflow voor het lezen van en schrijven naar bestanden De workflow voor het lezen van en schrijven naar bestanden is als volgt. Initialiseer een File-object dat het pad aanwijst. Dit is het pad van het bestand waarmee u wilt werken (of een bestand dat u later zult maken). var file:File = File.documentsDirectory; file = file.resolvePath("AIR Test/testFile.txt");
In dit voorbeeld worden de eigenschap File.documentsDirectory en de methode resolvePath()van een Fileobject gebruikt om het File-object te initialiseren. Er zijn echter allerlei andere manieren om een File-object een bestand te laten aanwijzen. Zie “File-objecten een bestand laten aanwijzen” op pagina 109 voor meer informatie. Initialiseer een FileStream-object. Roep de methode open() of openAsync() van het FileStream-object op. Welke methode u oproept, hangt ervan af of u het bestand wilt openen voor synchrone dan wel asynchrone bewerkingen. Gebruik het File-object als parameter file van de methode open. Bij de parameter fileMode geeft u een constante uit de klasse FileMode op die bepaalt op welke manier u het bestand wilt gebruiken. De volgende code initialiseert bijvoorbeeld een FileStream-object dat wordt gebruikt om een bestand te maken en eventuele bestaande gegevens te overschrijven: var fileStream:FileStream = new FileStream(); fileStream.open(file, FileMode.WRITE);
Zie “FileStream-objecten initialiseren, en bestanden openen en sluiten” op pagina 122 en “FileStream-modi voor openen” op pagina 121 voor meer informatie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 121 Werken met het bestandssysteem
Als u het bestand asynchroon hebt geopend (met de methode openAsync()), moet u gebeurtenislisteners toevoegen en instellen voor het FileStream-object. Deze gebeurtenislistenermethoden reageren op gebeurtenissen die onder allerlei verschillende omstandigheden worden verzonden door het FileStream-object, bijvoorbeeld wanneer gegevens worden ingelezen van het bestand, wanneer I/O-fouten worden aangetroffen of wanneer alle gegevens die moeten worden geschreven, geschreven zijn. Zie “Asynchroon programmeren en de gebeurtenissen die worden gegenereerd door een FileStream-object dat asynchroon is geopend” op pagina 126 voor meer informatie. Neem zonodig code op voor het lezen en schrijven van gegevens. Er zijn heel veel methoden uit de klasse FileStream die betrekking hebben op lezen en schrijven. (Ze beginnen allemaal met "read" of "write".) De methode die u kiest om gegevens te lezen of te schrijven, is afhankelijk van de indeling van de gegevens in het doelbestand. Als het doelbestand bijvoorbeeld UTF-gecodeerde tekst bevat, kunt u de methoden readUTFBytes() en writeUTFBytes() gebruiken. Als u de gegevens wilt verwerken als bytearrays, kunt u de methoden readByte(), readBytes(), writeByte() en writeBytes() gebruiken. Zie “Gegevensindelingen, en de methode voor lezen en schrijven kiezen” op pagina 127 voor meer informatie. Als u het bestand asynchroon hebt geopend, moet u er zeker van zijn dat er voldoende gegevens beschikbaar zijn voordat u een leesmethode oproept. Zie “De leesbuffer en de eigenschap bytesAvailable van een FileStream-object” op pagina 124 voor meer informatie. Voordat u gegevens naar een bestand schrijft, kunt u eventueel de hoeveelheid beschikbare schijfruimte nagaan door de eigenschap spaceAvailable van het File-object te controleren. Zie “De beschikbare ruimte op een volume bepalen” op pagina 114 voor meer informatie. Roep de methode close() van het FileStream-object op wanneer u klaar bent met het bestand. Het bestand wordt dan beschikbaar voor andere toepassingen. Zie “FileStream-objecten initialiseren, en bestanden openen en sluiten” op pagina 122 voor meer informatie. Als u een voorbeeldtoepassing wilt zien die van de klasse FileStream gebruikmaakt om bestanden te lezen en te schrijven, raadpleegt u de volgende artikelen in het Adobe AIR Developer Center:
• Een editor voor tekstbestanden maken
Werken met FileStream-objecten De klasse FileStream definieert methoden voor het openen, lezen en schrijven van bestanden.
FileStream-modi voor openen De methoden open() en openAsync() van een FileStream-object bevatten elk de parameter fileMode, die bepaalde eigenschappen van een bestandsstroom definieert, inclusief de volgende:
• de mogelijkheid om van het bestand te lezen; • de mogelijkheid om naar het bestand te schrijven; • of gegevens bij het schrijven altijd worden toegevoegd voorbij het einde van het bestand (append); • wat er moet gebeuren als het bestand niet bestaat (en als de bovenliggende mappen niet bestaan). Hieronder worden de verschillende bestandsmodi beschreven (die u kunt opgeven als de parameter fileMode van de methoden open() en openAsync()):
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 122 Werken met het bestandssysteem
FileMode-type
Beschrijving
FileMode.READ
Geeft aan dat het bestand alleen open is voor lezen.
FileMode.WRITE
Geeft aan dat het bestand open is voor schrijven. Als het bestand niet bestaat, wordt het gemaakt wanneer het FileStream-object wordt geopend. Als het bestand wel bestaat, worden eventuele bestaande gegevens verwijderd.
FileMode.APPEND
Geeft aan dat het bestand open is voor het toevoegen van gegevens. Als het bestand niet bestaat, wordt het gemaakt. Als het bestand wel bestaat, worden bestaande gegevens niet overschreven. Het schrijven begint aan het einde van het bestand.
FileMode.UPDATE
Geeft aan dat het bestand open is voor lezen en schrijven. Als het bestand niet bestaat, wordt het gemaakt. Selecteer deze modus voor willekeurige lees-/schrijftoegang tot het bestand. U kunt gegevens lezen vanuit een willekeurige positie in het bestand. Wanneer u schrijft naar het bestand, overschrijven alleen de geschreven bytes bestaande bytes (alle overige bytes blijven ongewijzigd).
FileStream-objecten initialiseren, en bestanden openen en sluiten Wanneer u een FileStream-object opent, stelt u het beschikbaar om gegevens in een bestand te lezen en ernaar te schrijven. U opent een FileStream-object door een File-object door te geven aan de methode open() of openAsync() van het FileStream-object: var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt"); var myFileStream:FileStream = new FileStream(); myFileStream.open(myFile, FileMode.READ);
De parameter fileMode (de tweede parameter van de methoden open() en openAsync()) geeft de modus op waarin het bestand moet worden geopend: voor lezen, schrijven, toevoegen (append) of bijwerken (update). Zie de vorige sectie, “FileStream-modi voor openen” op pagina 121, voor meer informatie. Als u de methode openAsync() gebruikt om het bestand te openen voor asynchrone bestandsbewerkingen, moet u gebeurtenislisteners instellen voor de afhandeling van de asynchrone gebeurtenissen: 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 { // ... }
Het bestand wordt geopend voor synchrone of asynchrone bewerkingen, afhankelijk van de methode die u gebruikt: open() of openAsync(). Zie “Basisinformatie over AIR-bestanden” op pagina 105 voor meer informatie. Als u de parameter fileMode instelt op FileMode.READ of FileMode.UPDATE in de openmethode van het FileStreamobject, worden gegevens in de leesbuffer ingelezen zodra u het FileStream-object opent. Zie “De leesbuffer en de eigenschap bytesAvailable van een FileStream-object” op pagina 124 voor meer informatie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 123 Werken met het bestandssysteem
U kunt de methode close() van een FileStream-object oproepen om het bijbehorende bestand te sluiten, zodat dit beschikbaar wordt voor gebruik door andere toepassingen.
De eigenschap position van een FileStream-object De eigenschap position van een FileStream-object bepaalt waar gegevens worden gelezen of geschreven bij de volgende lees- of schrijfmethode. Voordat u een lees- of schrijfbewerking uitvoert, stelt u de eigenschap position in op een geldige positie in het bestand. De volgende code schrijft bijvoorbeeld de tekenreeks "hello" (in UTF-codering) naar positie 8 in het bestand: 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");
Wanneer u een FileStream-object voor het eerst opent, is de eigenschap position ingesteld op 0. Voordat een leesbewerking wordt uitgevoerd, moet de waarde van position minimaal 0 zijn en minder dan het aantal bytes in het bestand (de bestaande posities in het bestand). De waarde van de eigenschap position wordt alleen gewijzigd onder de volgende omstandigheden:
• wanneer u de eigenschap position expliciet instelt; • wanneer u een leesmethode oproept; • wanneer u een schrijfmethode oproept. Wanneer u een lees- of schrijfmethode van een FileStream-object oproept, wordt de waarde van de eigenschap position onmiddellijk verhoogd met het aantal bytes dat u leest of schrijft. Afhankelijk van de leesmethode die u gebruikt, wordt de waarde van de eigenschap position verhoogd met het aantal bytes dat u opgeeft om te lezen, of met het beschikbare aantal bytes. Wanneer u vervolgens een lees- of schrijfmethode oproept, begint deze te lezen of te schrijven bij de nieuwe positie. 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
Hiervoor geldt echter een uitzondering: bij een FileStream die wordt geopend in de toevoegmodus (append), wordt de waarde van de eigenschap position niet gewijzigd na het oproepen van een schrijfmethode. (In de toevoegmodus worden gegevens altijd aan het einde van het bestand geschreven, onafhankelijk van de waarde van de eigenschap position.) Bij een bestand dat is geopend voor asynchrone bewerkingen, wordt de schrijfbewerking pas voltooid wanneer de volgende regel code is uitgevoerd. U kunt echter meerdere asynchrone methoden na elkaar oproepen; de runtime voert ze dan in de juiste volgorde uit:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 124 Werken met het bestandssysteem
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."); }
De trace-uitvoer voor de code in dit voorbeeld is: started. finished.
U kunt de waarde van position opgeven onmiddellijk nadat u een lees- of schrijfmethode hebt opgeroepen (of op een willekeurig ander moment); de volgende lees- of schrijfbewerking vindt plaats vanaf die positie. Bij de volgende code wordt de eigenschap position bijvoorbeeld ingesteld onmiddellijk na het oproepen van de bewerking writeBytes(); position wordt ingesteld op die waarde (300), zelfs nadat de schrijfbewerking is voltooid: 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
De leesbuffer en de eigenschap bytesAvailable van een FileStream-object Wanneer een FileStream-object met leesmogelijkheden (een object waarbij de parameter fileMode van de methode open() of openAsync() is ingesteld op READ of UPDATE) wordt geopend, slaat de runtime de gegevens op in een interne buffer. Het FileStream-object begint gegevens in de buffer in te lezen zodra u het bestand opent (door de methode open() of openAsync() van het FileStream-object op te roepen). Voor een bestand dat is geopend voor synchrone bewerkingen (met behulp van de methode open()), kunt u de aanwijzer position altijd instellen op een willekeurige geldige positie (binnen de grenzen van het bestand) en beginnen met het inlezen van een willekeurige hoeveelheid gegevens (binnen de grenzen van het bestand), zoals aangegeven in de volgende code (waarbij ervan wordt uitgegaan dat het bestand minimaal 100 bytes omvat): 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);
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 125 Werken met het bestandssysteem
Of een bestand nu wordt geopend voor synchrone dan wel asynchrone bewerkingen, de leesmethode leest altijd uit de "beschikbare" bytes (vertegenwoordigd door de eigenschap bytesAvalable). Als synchroon wordt gelezen, zijn alle bytes van het bestand op elk willekeurig moment beschikbaar. Als asynchroon wordt gelezen, worden de bytes beschikbaar gesteld vanaf de positie die wordt aangegeven door de eigenschap position terwijl de buffer op asynchrone wijze steeds verder wordt gevuld (gesignaleerd door progress-gebeurtenissen). Voor bestanden die zijn geopend voor synchrone bewerkingen wordt de eigenschap bytesAvailable altijd zo ingesteld dat deze het aantal bytes vanaf de eigenschap position tot het einde van het bestand vertegenwoordigt (alle bytes in het bestand zijn altijd beschikbaar voor lezen). Voor bestanden die zijn geopend voor asynchrone bewerkingen moet u ervoor zorgen dat de leesbuffer voldoende gegevens heeft verbruikt voordat een leesmethode wordt opgeroepen. Voor een bestand dat asynchroon is geopend, geldt dat naarmate de leesbewerking vordert, de gegevens uit het bestand aan de buffer worden toegevoegd, beginnende bij de waarde van position die werd opgegeven toen de leesbewerking werd gestart. De waarde van de eigenschap bytesAvailable wordt verhoogd met iedere byte die wordt gelezen. De eigenschap bytesAvailable geeft het aantal bytes aan dat beschikbaar is, vanaf de byte die zich bevindt op de positie die wordt aangegeven door de eigenschap position tot het einde van de buffer. Het FileStream-object verzendt regelmatig de gebeurtenis progress. Voor een bestand dat asynchroon is geopend, verzendt het FileStream-object periodiek de gebeurtenis progress naarmate gegevens beschikbaar worden in de leesbuffer. De volgende code leest bijvoorbeeld gegevens in een ByteArray-object (bytes) terwijl dit in de buffer wordt ingelezen: 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); }
Voor een bestand dat asynchroon is geopend, kunnen alleen de gegevens in de leesbuffer worden gelezen. Terwijl u de gegevens leest, worden ze verwijderd uit de leesbuffer. Voor leesbewerkingen moet u ervoor zorgen dat de gegevens aanwezig zijn in de leesbuffer voordat u de leesbewerking oproept. De volgende code leest bijvoorbeeld 8000 bytes aan gegevens vanaf positie 4000 in het bestand: 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"); } }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 126 Werken met het bestandssysteem
Tijdens een schrijfbewerking leest het FileStream-object geen gegevens in de leesbuffer. Wanneer een schrijfbewerking wordt voltooid (alle gegevens in de schrijfbuffer zijn naar het bestand geschreven), start het FileStream-object een nieuwe leesbuffer (ervan uitgaande dat het gekoppelde FileStream-object is geopend met leescapaciteiten) en begint het gegevens in de leesbuffer in te lezen, beginnende bij de positie die wordt aangegeven door de eigenschap position. De eigenschap position kan de positie aangeven van de byte die het laatst is geschreven, of een andere positie als de gebruiker een andere waarde voor het position-object na de schrijfbewerking heeft opgegeven.
Asynchroon programmeren en de gebeurtenissen die worden gegenereerd door een FileStream-object dat asynchroon is geopend Als een bestand asynchroon is geopend (via de methode openAsync()), wordt het lezen en schrijven van bestanden asynchroon uitgevoerd. Terwijl gegevens in de leesbuffer worden ingelezen en outputgegevens worden geschreven, kan andere ActionScript-code worden uitgevoerd. Dat wil zeggen dat u moet registreren voor gebeurtenissen die worden gegenereerd door het FileStream-object dat asynchroon is geopend. Door te registreren voor de gebeurtenis progress kunt u op de hoogte worden gebracht wanneer nieuwe gegevens beschikbaar worden voor lezen, zoals in de volgende code: 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"); }
U kunt alle gegevens lezen door te registreren voor de gebeurtenis complete, zoals in de volgende code: 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"); }
Net zoals inputgegevens worden gebufferd om asynchroon lezen mogelijk te maken, worden gegevens die u naar een asynchrone stroom schrijft, asynchroon gebufferd en naar het bestand geschreven. Terwijl gegevens naar een bestand worden geschreven, verzendt het FileStream-object periodiek een OutputProgressEvent-object. Een OutputProgressEvent-object bevat de eigenschap bytesPending, die is ingesteld op het aantal bytes dat nog moet worden geschreven. U kunt registreren dat u op de hoogte moet worden gebracht van de gebeurtenis outputProgress terwijl deze buffer naar het bestand wordt geschreven, bijvoorbeeld om een voortgangsdialoogvenster weer te geven. In het algemeen is dit echter niet noodzakelijk. U kunt met name de methode close() oproepen zonder dat u zich zorgen hoeft te maken over de ongeschreven bytes. Het FileStream-object blijft gegevens schrijven en de gebeurtenis close wordt gegenereerd nadat de laatste byte naar het bestand is geschreven en het onderliggende bestand is gesloten.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 127 Werken met het bestandssysteem
Gegevensindelingen, en de methode voor lezen en schrijven kiezen Elk bestand bestaat uit een set bytes op een schijf. In ActionScript kunnen de gegevens van een bestand altijd worden weergegeven als een bytearray. De volgende code leest bijvoorbeeld de gegevens van het bestand in een ByteArrayobject met de naam 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 volgende code schrijft gegevens van een ByteArray-object met de naam bytes naar een bestand: 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);
Het zal echter vaak gebeuren dat u de gegevens niet wilt opslaan in een ActionScript ByteArray-object. Het gegevensbestand heeft ook vaak een specifieke bestandsindeling. De gegevens in het bestand kunnen bijvoorbeeld een tekstindeling hebben; u kunt zulke gegevens weergeven in een String-object. Om deze reden omvat de klasse FileStream lees- en schrijfmethoden voor het lezen en schrijven van gegevens van en naar andere typen dan ByteArray-objecten. Met de methode readMultiByte() kunt u bijvoorbeeld gegevens lezen uit een bestand en opslaan in een tekenreeks, zoals in de volgende code: 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 tweede parameter van de methode readMultiByte() geeft de tekstindeling aan die ActionScript gebruikt om de gegevens te interpreteren (in het voorbeeld "iso-8859-1"). ActionScript ondersteunt veelgebruikte tekensetcoderingen. Deze worden aangegeven in de ActionScript 3.0 Language Reference (zie Supported character setssupported character sets op http://livedocs.macromedia.com/flex/2/langref/charset-codes.html). De klasse FileStream bevat ook de methode readUTFBytes(), die gegevens uit de leesbuffer in een tekenreeks inleest met gebruikmaking van de tekenset UTF-8. Aangezien tekens in de tekenset UTF-8 een variabele lengte hebben, kunt u readUTFBytes() niet gebruiken in een methode die reageert op de gebeurtenis progress, aangezien de gegevens aan het einde van de leesbuffer een onvolledig teken kunnen vertegenwoordigen. (Dit geldt ook wanneer u de methode readMultiByte() gebruikt met een tekencodering met variabele lengte.) Om deze reden moet de gehele set gegevens worden gelezen wanneer het FileStream-object de gebeurtenis complete verzendt.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 128 Werken met het bestandssysteem
Er zijn ook vergelijkbare schrijfmethoden, writeMultiByte() en writeUTFBytes(), voor het werken met Stringobjecten en tekstbestanden. Ook de methoden readUTF() en writeUTF() (niet te verwarren met readUTFBytes() en writeUTFBytes()) lezen en schrijven de tekstgegevens naar een bestand, maar bij deze methoden wordt ervan uitgegaan dat de tekstgegevens worden voorafgegaan door gegevens waarmee de lengte van de tekstgegevens wordt aangegeven. Dit is niet gebruikelijk bij standaard tekstbestanden. Bepaalde UTF-gecodeerde tekstbestanden beginnen met het teken "UTF-BOM" (byte order mark) dat de Endianness en het coderingsformaat (zoals UTF-16 of UTF-32) aangeeft. Zie “Voorbeeld: Een XML-bestand lezen in een XML-object” op pagina 128 voor een voorbeeld van het lezen en schrijven naar een tekstbestand. readObject() en writeObject() zijn handige manieren om gegevens op te slaan en op te halen voor complexe
ActionScript-objecten. De gegevens worden gecodeerd in AMF (ActionScript Message Format). Dit is een eigen indeling van ActionScript. Andere toepassingen dan AIR, Flash Player, Flash Media Server en Flex Data Services hebben geen ingebouwde API's voor het werken met gegevens in deze indeling. Er zijn een paar andere lees- en schrijfmethoden (zoals readDouble() en writeDouble()). Als u deze gebruikt, moet u er zeker van zijn dat de bestandsindeling overeenkomt met de indeling van de gegevens die worden gedefinieerd door deze methoden. Bestandsindelingen zijn vaak complexer dan eenvoudige tekstindelingen. Een MP3-bestand bevat bijvoorbeeld gecomprimeerde gegevens die alleen kunnen worden geïnterpreteerd met behulp van de decompressie- en decoderingsalgoritmen die specifiek zijn voor MP3-bestanden. MP3-bestanden kunnen ook ID3-tags bevatten die metatag-informatie over het bestand bevatten (bijvoorbeeld de titel en de artiest van een nummer). Er zijn meerdere versies van de ID3-indeling. De eenvoudigste (ID3 versie 1) wordt besproken in de sectie “Voorbeeld: Gegevens lezen en schrijven met willekeurige toegang” op pagina 129. Andere bestandsindelingen (voor afbeeldingen, databases, toepassingsdocumenten enzovoort) hebben andere structuren. Als u met deze gegevens wilt werken in ActionScript, moet u begrijpen hoe de gegevens zijn gestructureerd.
Voorbeeld: Een XML-bestand lezen in een XML-object In de volgende voorbeelden ziet u hoe u kunt lezen van en schrijven naar een tekstbestand dat XML-gegevens bevat. Om te lezen van het bestand, initialiseert u de File- en FileStream-objecten, roept u de methode readUTFBytes() van het FileStream-object op en converteert u de tekenreeks naar een XML-object: 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();
Om de gegevens naar het bestand te schrijven, hoeft u alleen maar de correcte File- en FileStream-objecten in te stellen en vervolgens een schrijfmethode van het FileStream-object op te roepen. Geef de tekenreeksversie van de XMLgegevens door aan de schrijfmethode zoals in de volgende code:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 129 Werken met het bestandssysteem
var prefsXML:XML = <prefs>true; var file:File = File.documentsDirectory.resolvePath("AIR Test/preferences.xml"); fileStream = new FileStream(); fileStream.open(file, FileMode.WRITE); var outputString:String = '\n'; outputString += prefsXML.toXMLString(); fileStream.writeUTFBytes(outputString); fileStream.close();
Bij deze voorbeelden wordt gebruikgemaakt van de methoden readUTFBytes() en writeUTFBytes(), omdat er bij deze methoden van wordt uitgegaan dat de bestanden de UTF-8-indeling hebben. Als dat niet het geval is, moet u mogelijk een andere methode gebruiken (zie “Gegevensindelingen, en de methode voor lezen en schrijven kiezen” op pagina 127). Bij de voorgaande voorbeelden worden FileStream-objecten gebruikt die zijn geopend voor synchrone bewerkingen. U kunt ook bestanden openen voor asynchrone bewerkingen (die gebruikmaken van gebeurtenislistenerfuncties om te reageren op gebeurtenissen). In de volgende voorbeeldcode ziet u hoe u een XML-bestand asynchroon kunt lezen: 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(); }
De methode processXMLData() wordt opgeroepen wanneer het gehele bestand in de leesbuffer is ingelezen (wanneer het FileStream-object de gebeurtenis complete verzendt). Deze roept de methode readUTFBytes() op om een tekenreeksversie van de leesgegevens te verkrijgen en maakt op basis van die tekenreeks het XML-object prefsXML.
Voorbeeld: Gegevens lezen en schrijven met willekeurige toegang MP3-bestanden kunnen ID3-tags bevatten. Dit zijn secties aan het begin of einde van een bestand die metagegevens bevatten die de opname identificeren. Van de indeling van de ID3-tag bestaan verschillende versies. In dit voorbeeld ziet u hoe u kunt lezen van en schrijven naar een MP3-bestand dat de eenvoudigste ID3-indeling bevat (ID3 versie 1.0) met gebruikmaking van willekeurige toegang tot de gegevens. Dit wil zeggen dat wordt gelezen van en geschreven naar willekeurige locaties in het bestand. Bij een MP3-bestand dat een ID3-tag van versie 1 bevat, bevinden de ID3-gegevens zich aan het einde van het bestand, in de laatste 128 bytes. Wanneer een bestand wordt geopend voor willekeurige lees-/schrijftoegang, is het belangrijk om FileMode.UPDATE op te geven als de parameter fileMode voor de methode open() of openAsync(): var file:File = File.documentsDirectory.resolvePath("My Music/Sample ID3 v1.mp3"); var fileStr:FileStream = new FileStream(); fileStr.open(file, FileMode.UPDATE);
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 130 Werken met het bestandssysteem
Hiermee kunt u zowel lezen van als schrijven naar het bestand. Bij het openen van het bestand kunt u de aanwijzer position neerzetten op de positie 128 bytes vóór het einde van het bestand: fileStr.position = file.size - 128;
Deze code stelt de eigenschap position in op deze locatie in het bestand, aangezien de ID3-indeling v1.0 bepaalt dat de ID3-taggegevens worden opgeslagen in de laatste 128 bytes van het bestand. Deze specificatie bevat verder het volgende:
• De eerste 3 bytes van de tag bevatten de tekenreeks "TAG". • De volgende 30 tekens bevatten de titel van de MP3-track in de vorm van een tekenreeks. • De volgende 30 tekens bevatten de naam van de artiest in de vorm van een tekenreeks. • De volgende 30 tekens bevatten de naam van het album in de vorm van een tekenreeks. • De volgende 4 tekens bevatten het jaar in de vorm van een tekenreeks. • De volgende 30 tekens bevatten het commentaar in de vorm van een tekenreeks. • De volgende byte bevat een code die het genre van de track aangeeft. • Alle tekstgegevens hebben de indeling ISO 8859-1. De methode id3TagRead() controleert de gegevens nadat deze zijn ingelezen (na het plaatsvinden van de gebeurtenis 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); } }
U kunt ook met willekeurige toegang naar het bestand schrijven. U kunt bijvoorbeeld de variabele id3Title parseren om er zeker van te zijn dat het correcte hoofdlettergebruik wordt toegepast (met behulp van methoden van de klasse String) en dan een gewijzigde tekenreeks met de naam newTitle naar het bestand schrijven, zoals in de volgende code: fileStr.position = file.length - 125; // 128 - 3 fileStr.writeMultiByte(newTitle, "iso-8859-1");
Ten einde te voldoen aan de standaard voor ID3 versie 1, moet de lengte van de tekenreeks newTitle 30 tekens zijn, aan het einde opgevuld met de tekencode 0 (String.fromCharCode(0)).
131
Hoofdstuk 15: Slepen en neerzetten Gebruik de klassen in de API voor slepen en neerzetten voor ondersteuning van bewegingen voor slepen en neerzetten in de gebruikersinterface. Een beweging is in deze context een actie van de gebruiker die wordt overgebracht door het besturingssysteem en uw toepassing, met de bedoeling om gegevens de kopiëren, te verplaatsen of te koppelen. Een uitsleepbeweging treedt op wanneer de gebruiker een object uit een component of een toepassing sleept. Een insleepbeweging treedt op wanneer de gebruiker een object naar een component of een toepassing sleept. Via de API voor slepen en neerzetten kan een gebruiker gegevens slepen tussen toepassingen en tussen componenten in een toepassing. Onder andere de volgende overdrachtsindelingen worden ondersteund:
• Bitmaps • Bestanden • Tekst met HTML-opmaak • Tekst • RTF-gegevens • URL's • Geserialiseerde objecten • Objectverwijzingen (alleen geldig binnen de brontoepassing)
Aanvullende online informatie over slepen en neerzetten In de volgende bronnen vindt u meer informatie over het werken met de API voor slepen en neerzetten: Snelstarthandleidingen (Adobe AIR Developer Connection) • Ondersteuning voor slepen en neerzetten en voor kopiëren en plakken Language Reference • NativeDragManager
• NativeDragOptions • Clipboard • NativeDragEvent Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar 'AIR drag and drop')
Basisinformatie over slepen en neerzetten De API voor slepen en neerzetten bevat de volgende klassen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 132 Slepen en neerzetten
Pakket
Klassen
flash.desktop
•
NativeDragManager
•
NativeDragOptions
•
clipboard
•
NativeDragActions
•
ClipboardFormat
•
ClipboardTransferModes
Constanten die worden gebruikt met de API voor slepen en neerzetten, zijn gedefinieerd in de volgende klassen:
flash.events
•
NativeDragActions
•
ClipboardFormat
•
ClipboardTransferModes
NativeDragEvent
Stadia van bewegingen voor slepen en neerzetten De beweging voor slepen en neerzetten bestaat uit drie stadia: Initiëren Een gebruiker start het slepen en neerzetten door te slepen vanuit een component of een item in een component
terwijl de muisknop is ingedrukt. De component waaruit het gesleepte item afkomstig is, wordt gewoonlijk de sleepinitiator genoemd en deze verzendt de gebeurtenissen nativeDragStart en nativeDragComplete. Een Adobe® AIR™-toepassing start een sleepbewerking door het oproepen van de methode NativeDragManager.doDrag() als reactie op de gebeurtenis mouseDown of mouseMove. Slepen Terwijl de muisknop is ingedrukt, verplaatst de gebruiker de muiscursor naar een andere component of toepassing, of naar het bureaublad. Tijdens het slepen wordt optioneel een tijdelijke afbeelding weergegeven. Zolang het slepen duurt, verzendt het initiatorobject nativeDragUpdate-gebeurtenissen. Wanneer de gebruiker de muis over een mogelijk neerzetdoel beweegt, verzendt het neerzetdoel de gebeurtenis nativeDragEnter. De gebeurtenishandler kan het gebeurtenisobject inspecteren om te bepalen of de gesleepte gegevens beschikbaar zijn in een indeling die het doel accepteert, en als dat het geval is, de gebruiker de gegevens daarop laten neerzetten door de methode NativeDragManager.acceptDragDrop() op te roepen.
Zolang de sleepbeweging over een interactief object plaatsvindt, verzendt dat object nativeDragOver-gebeurtenissen. Wanneer de sleepbeweging het interactieve object verlaat, verzendt het object de gebeurtenis nativeDragExit. Neerzetten De gebruiker laat de muisknop los op een geschikt neerzetdoel. Als het doel een AIR-toepassing of -
component is, verzendt de component de gebeurtenis nativeDragDrop. De gebeurtenishandler kan toegang krijgen tot de gegevens die door het gebeurtenisobject worden overgedragen. Als het doel zich buiten AIR bevindt, wordt het neerzetten afgehandeld door het besturingssysteem of een andere toepassing. In beide gevallen verzendt het object dat de beweging initieert de gebeurtenis nativeDragComplete (als het slepen in AIR is gestart). Met de klasse NativeDragManager worden zowel insleep- als uitsleepbewegingen beheerd. Alle leden van de klasse NativeDragManager zijn statisch; maak geen instantie van deze klasse.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 133 Slepen en neerzetten
Clipboard-objecten Gegevens die in of uit een toepassing of component worden gesleept, bevinden zich in een Clipboard-object. Eén Clipboard-object kan verschillende weergaven van dezelfde gegevens beschikbaar maken om de kans te vergroten dat een andere toepassing de gegevens kan begrijpen en gebruiken. Een afbeelding kan bijvoorbeeld worden opgenomen als afbeeldingsgegevens, een geserialiseerd bitmapobject en een bestand. Het omzetten van de gegevens naar een bepaalde indeling kan worden uitgevoerd door een renderfunctie die pas wordt opgeroepen als de gegevens zijn gelezen. Wanneer een sleepbeweging is gestart, is het Clipboard-object alleen toegankelijk vanuit een gebeurtenishandler voor de gebeurtenissen nativeDragEnter, nativeDragOver en nativeDragDrop. Nadat de sleepbeweging is beëindigd, kan het Clipboard-object niet worden gelezen of opnieuw worden gebruikt. Een toepassingsobject kan worden overgedragen als een verwijzing en als een geserialiseerd object. Verwijzingen zijn alleen geldig binnen de brontoepassing. Geserialiseerde objecten kunnen worden overgedragen tussen AIRtoepassingen, maar kunnen alleen worden gebruikt met objecten die geldig blijven wanneer ze zijn geserialiseerd en gedeserialiseerd. Objecten die zijn geserialiseerd, worden geconverteerd naar de AMF3-indeling (Action Message Format voor ActionScript 3), een indeling voor gegevensoverdracht op basis van tekenreeksen. Werken met het Flex-framework In de meeste gevallen is het beter om de API voor slepen en neerzetten van Adobe® Flex™ te gebruiken bij het bouwen van Flex-toepassingen. Het Flex-framework beschikt over een equivalente functieset wanneer een Flex-toepassing wordt uitgevoerd in AIR (het maakt intern gebruik van de NativeDragManager van AIR). Flex beschikt ook over een beperkte functieset wanneer een toepassing of component wordt uitgevoerd in de browseromgeving, die meer beperkingen heeft. AIR-klassen kunnen niet worden gebruikt in componenten of toepassingen die buiten de runtimeomgeving van AIR worden uitgevoerd.
Ondersteuning voor de uitsleepbeweging Voor ondersteuning van de uitsleepbeweging moet u een Clipboard-object maken als reactie op de gebeurtenis mouseDown en deze naar de methode NativeDragManager.doDrag() verzenden. Uw toepassing kan vervolgens naar de gebeurtenis nativeDragComplete van het initiatorobject luisteren om te bepalen welke actie moet worden uitgevoerd wanneer de gebruiker de beweging voltooit of annuleert.
Gegevens voorbereiden voor overdracht Om gegevens of een object voor te bereiden op slepen, maakt u een Clipboard-object en voegt u de gegevens die moeten worden overgebracht toe in een of meer indelingen. U kunt de standaard gegevensindelingen gebruiken voor het doorgeven van gegevens die automatisch kunnen worden omgezet in native klembordindelingen en toepassingsspecifieke indelingen gebruiken voor het doorgeven van objecten. Als het een grote belasting voor de processor is om de gegevens die moeten worden overgebracht, te converteren naar een bepaalde indeling, kunt u de naam opgeven van een handlerfunctie die de conversie uitvoert. Deze functie wordt alleen opgeroepen als de ontvangende component of toepassing de bijbehorende indeling leest. Zie “Klembordgegevensindelingen” op pagina 153 voor meer informatie. In het volgende voorbeeld wordt een Clipboard-object gemaakt dat een bitmap in diverse indelingen bevat: een bitmapobject, een native bitmapindeling en een bestandenlijstindeling die het bestand bevat waaruit de bitmap oorspronkelijk is geladen:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 134 Slepen en neerzetten
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; }
Uitsleepbewerkingen starten Om een sleepbewerking te starten, roept u de methode NativeDragManager.doDrag() op als reactie op het indrukken van de muis. De methode doDrag() is een statische methode met de volgende parameters: Parameter
Beschrijving
initiator
Het object van waaruit wordt gesleept en dat de gebeurtenissen dragStart en dragComplete verzendt. De initiator moet een interactief object zijn.
klembord
Het Clipboard-object dat de gegevens bevat die moeten worden overgedragen. Naar het Clipboard-object wordt verwezen in de NativeDragEvent-objecten die worden verzonden tijdens het slepen en neerzetten.
dragImage
(Optioneel) Een BitmapData-object dat tijdens het slepen wordt weergegeven. De afbeelding kan een alfawaarde opgeven. (Opmerking: Microsoft Windows past altijd een vaste alfa-vervaging toe bij het verslepen van afbeeldingen.)
offset
(Optioneel) Een Point-object waarmee de afstand van de sleepafbeelding vanaf de hotspot van de muis wordt opgegeven. Gebruik negatieve coördinaten om de sleepafbeelding naar boven en naar links ten opzichte van de muiscursor te verplaatsen. Als er geen afstand is opgegeven, wordt de linkerbovenhoek van de sleepafbeelding op de hotspot van de muis geplaatst.
actionsAllowed
(Optioneel) Een NativeDragOptions-object waarmee de acties (kopiëren, verplaatsen of koppelen) worden opgegeven die geldig zijn voor de sleepbewerking. Als er geen argument is opgegeven, zijn alle acties toegestaan. In NativeDragEvent-objecten wordt naar het DragOptions-object verwezen om het mogelijk te maken dat een sleepdoel controleert of de toegestane acties compatibel zijn met de functie van de doelcomponent. Een “prullenbak”-component accepteert bijvoorbeeld alleen sleepbewegingen voor een verplaatsingsactie.
In het volgende voorbeeld ziet u hoe u een sleepbewerking start voor een bitmapobject dat uit een bestand is geladen. In het voorbeeld wordt een afbeelding geladen en wordt de sleepbewerking gestart bij de gebeurtenis mouseDown.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 135 Slepen en neerzetten
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,
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 136 Slepen en neerzetten
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); } } }
Uitsleepoverdrachten voltooien Wanneer een gebruiker het gesleepte item neerzet door de muisknop los te laten, verzendt het initiatorobject de gebeurtenis nativeDragComplete. U kunt de eigenschap dropAction van het gebeurtenisobject controleren en vervolgens de juiste actie uitvoeren. Als de actie bijvoorbeeld NativeDragAction.MOVE, is, kunt u het bronitem op de bronlocatie verwijderen. De gebruiker kan een sleepbeweging annuleren door de muisknop los te laten terwijl de cursor zich buiten een geschikt neerzetdoel bevindt. De sleepbeheerder stelt de eigenschap dropAction voor een geannuleerde beweging in op NativeDragAction.NONE.
Ondersteuning voor de insleepbeweging Voor ondersteuning van de insleepbeweging moet uw toepassing (gewoonlijk een visuele component van uw toepassing) reageren op de gebeurtenis nativeDragEnter of nativeDragOver.
Stappen waaruit een neerzetbewerking gewoonlijk bestaat Een neerzetbewerking bestaat gewoonlijk uit de volgende reeks gebeurtenissen: 1 De gebruiker sleept een Clipboard-object over een component. 2 De component verzendt de gebeurtenis nativeDragEnter. 3 De gebeurtenishandler nativeDragEnter controleert de beschikbare gegevensindelingen en toegestane acties van
het gebeurtenisobject. Als de component het neerzetten kan verwerken, wordt NativeDragManager.acceptDragDrop() opgeroepen.
4 NativeDragManager wijzigt de muiscursor om aan te geven dat het object kan worden neergezet. 5 De gebruiker zet het object neer op de component. 6 De ontvangende component verzendt de gebeurtenis nativeDragDrop. 7 De ontvangende component leest de gegevens in de gewenste indeling uit het Clipboard-object in het
gebeurtenisobject.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 137 Slepen en neerzetten
8 Als de sleepbeweging is gestart in een AIR-toepassing, verzendt het initiërende interactieve object de gebeurtenis nativeDragComplete. Als de beweging buiten AIR is gestart, wordt geen feedback verzonden.
Insleepbewegingen bevestigen Wanneer een gebruiker een klemborditem binnen de grenzen van een visuele component sleept, verzendt de component de gebeurtenissen nativeDragEnter en nativeDragOver. Om te bepalen of de component het klemborditem kan accepteren, kunnen de handlers voor deze gebeurtenissen de eigenschappen clipboard en allowedActions van het gebeurtenisobject controleren. De gebeurtenishandler moet de methode NativeDragManager.acceptDragDrop() met een verwijzing naar de ontvangende component oproepen om aan te geven dat de component het neerzetten kan accepteren. Als meerdere geregistreerde gebeurtenislisteners de methode acceptDragDrop() oproepen, heeft de laatste handler in de lijst de hoogste prioriteit. De oproep acceptDragDrop() blijft geldig tot de muis buiten de grenzen van het accepterende object komt, waardoor de gebeurtenis nativeDragExit wordt geactiveerd. Als er meerdere acties zijn toegestaan in de parameter allowedActions die aan doDrag() is doorgegeven, kan de gebruiker een aanpassingstoets ingedrukt houden om aan te geven welke actie moet worden uitgevoerd. De sleepbeheerder wijzigt de cursorafbeelding om de gebruiker te laten weten welke actie wordt uitgevoerd als het neerzetten wordt voltooid. De bedoelde actie wordt gerapporteerd aan de eigenschap dropAction van het NativeDragEvent-object. De ingestelde actie voor een sleepbeweging is slechts een voorstel. De componenten die bij de overdracht zijn betrokken, moeten het juiste gedrag implementeren. Het gesleepte item moet bijvoorbeeld door de sleepinitiator worden verwijderd en door het neerzetdoel worden toegevoegd om een verplaatsingsactie te voltooien. De neerzetactie kan door het sleepdoel tot een van de drie mogelijke acties worden beperkt door de eigenschap dropAction van de klasse NativeDragManager in te stellen. Als een gebruiker een andere actie wil kiezen met het toetsenbord, wordt de cursor voor een niet-beschikbare actie weergegeven. Stel de eigenschap dropAction in de handlers voor de gebeurtenissen nativeDragEnter en nativeDragOver in. In het volgende voorbeeld ziet u een gebeurtenishandler voor de gebeurtenis nativeDragEnter of nativeDragOver. Deze handler accepteert alleen een insleepbeweging als het klembord dat wordt gesleept tekst bevat. 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 } }
Het neerzetten voltooien Wanneer de gebruiker een gesleept item neerzet op een interactief object dat de beweging heeft geaccepteerd, verzendt het interactieve object de gebeurtenis nativeDragDrop. De handler voor deze gebeurtenis kan de gegevens ophalen uit de eigenschap clipboard van het gebeurtenisobject. Wanneer het klembord een toepassingsspecifieke indeling bevat, bepaalt de parameter transferMode die aan de methode getData() van het Clipboard-object is doorgegeven, of de sleepbeheerder een verwijzing of een geserialiseerde versie van het object retourneert. In het volgende voorbeeld ziet u een gebeurtenishandler voor de gebeurtenis nativeDragDrop:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 138 Slepen en neerzetten
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)); }
Wanneer de gebeurtenishandler is afgesloten, is het Clipboard-object niet meer geldig. Bij elke poging om toegang tot het object of de gegevens te krijgen, wordt een fout gegenereerd.
De visuele weergave van een component bijwerken De visuele weergave van een component kan worden bijgewerkt op basis van de NativeDragEvent-gebeurtenissen. In de volgende tabel wordt beschreven welke typen wijzigingen een component gewoonlijk aanbrengt als reactie op de verschillende gebeurtenissen: Gebeurtenis
Beschrijving
nativeDragStart
Het initiërende interactieve object kan met de gebeurtenis nativeDragStart visueel aangeven dat de sleepbeweging afkomstig is van dat interactieve object.
nativeDragUpdate
Het initiërende interactieve object kan de gebeurtenis nativeDragUpdate gebruiken om de status bij te werken tijden de beweging.
nativeDragEnter
Een mogelijk ontvangend interactief object kan deze gebeurtenis gebruiken om de focus te nemen of visueel aangeven dat het neerzetten wel of niet wordt geaccepteerd.
nativeDragOver
Een mogelijk ontvangend interactief object kan deze gebeurtenis gebruiken om te reageren op de beweging van de muis binnen het interactieve object, bijvoorbeeld wanneer de muis een dynamische regio van een complexe component, zoals een stratenplan, bereikt.
nativeDragExit
Een mogelijk ontvangend interactief object kan deze gebeurtenis gebruiken om de status te herstellen wanneer een sleepbeweging buiten de grenzen komt.
nativeDragComplete
Het initiërende interactieve object kan deze gebeurtenis gebruiken om het bijbehorende gegevensmodel bij te werken, zoals het verwijderen van een item uit een lijst, en om de visuele status te herstellen.
Muisposities bijhouden tijdens een sleepbeweging Terwijl de muis over een component wordt gesleept, verzendt die component nativeDragOver-gebeurtenissen. Deze gebeurtenissen worden elke paar milliseconden verzonden en ook wanneer de muis beweegt. Het gebeurtenisobject nativeDragOver kan worden gebruikt om de positie van de muis in de component te bepalen. Toegang tot de muispositie kan nuttig zijn in situaties waarin de ontvangende component complex is maar niet uit subcomponenten bestaat. Als uw toepassing bijvoorbeeld een bitmap met een stratenplan weergeeft en u zones op de kaart wilt markeren wanneer de gebruiker daar gegevens heen sleept, kunt u met de muiscoördinaten in de gebeurtenis nativeDragOver de muispositie op de kaart bijhouden.
HTML slepen en neerzetten Als u gegevens in en uit een HTML-toepassing wilt slepen (of in en uit de HTML die wordt weergegeven in een HTMLLoader), kunt u gebeurtenissen voor het slepen en neerzetten van HTML gebruiken. Met de API voor het slepen en neerzetten van HTML kunt u gegevens slepen naar en vanuit DOM-elementen in de HTML-inhoud.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 139 Slepen en neerzetten
Opmerking: U kunt ook de API's NativeDragEvent en NativeDragManager van AIR gebruiken door te luisteren naar gebeurtenissen van het HTMLLoader-object dat de HTML-inhoud bevat. De API voor HTML is echter beter geïntegreerd met het HTML DOM en geeft u meer controle over het standaardgedrag.
Standaardgedrag bij slepen en neerzetten De HTML-omgeving beschikt over standaardgedrag voor bewegingen die betrekking hebben op het slepen en neerzetten van tekst, afbeeldingen en URL's. Met het standaardgedrag kunt u deze typen gegevens altijd uit een element slepen. U kunt echter alleen tekst naar een element slepen en alleen naar elementen in een bewerkbaar gebied op een pagina. Wanneer u tekst sleept tussen of in bewerkbare gebieden op een pagina, wordt de tekst standaard verplaatst. Wanneer u tekst vanuit een niet-bewerkbaar gebied of van buiten de toepassing naar een bewerkbaar gebied sleept, wordt de tekst standaard gekopieerd. U kunt het standaardgedrag overschrijven door de gebeurtenissen voor slepen en neerzetten zelf af te handelen. Als u het standaardgedrag wilt annuleren, moet u de methode preventDefault() oproepen van de objecten die worden verzonden voor gebeurtenissen voor slepen en neerzetten. Vervolgens kunt u gegevens in het neerzetdoel invoegen en gegevens uit het sleepdoel verwijderen om de gekozen actie uit te voeren. Standaard kan de gebruiker elke tekst selecteren en slepen, en afbeeldingen en koppelingen slepen. Met de CSSeigenschap -webkit-user-select van de WebKit kunt u bepalen hoe elk HTML-element kan worden geselecteerd. Als u bijvoorbeeld -webkit-user-select op none instelt, kan de inhoud van het element niet worden geselecteerd en dus ook niet worden gesleept. U kunt ook de CSS-eigenschap -webkit-user-drag gebruiken om te bepalen of een element in zijn geheel kan worden gesleept. De inhoud van het element wordt echter afzonderlijk behandeld. De gebruiker kan ook een geselecteerd gedeelte van de tekst slepen. Zie “Extensies voor CSS” op pagina 219 voor meer informatie.
Gebeurtenissen voor slepen en neerzetten in HTML Het initiatorelement van waaruit een sleepbeweging afkomstig is, verzendt de volgende gebeurtenissen: Gebeurtenis
Beschrijving
dragstart
Wordt verzonden wanneer de gebruiker de sleepbeweging start. De handler voor deze gebeurtenis kan indien nodig het slepen voorkomen door de methode preventDefault() van het gebeurtenisobject op te roepen. Stel de eigenschap effectAllowed in om te bepalen of de gesleepte gegevens kunnen worden gekopieerd, gekoppeld of verplaatst. Geselecteerde tekst, afbeeldingen en koppelingen worden standaard op het klembord geplaatst, maar u kunt verschillende gegevens voor de sleepbeweging instellen met de eigenschap dataTransfer van het gebeurtenisobject.
drag
Wordt continu verzonden tijdens de sleepbeweging.
dragend
Wordt verzonden wanneer de gebruiker de muisknop loslaat om de sleepbeweging te beëindigen.
Een sleepdoel verzendt de volgende gebeurtenissen:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 140 Slepen en neerzetten
Gebeurtenis
Beschrijving
dragover
Wordt continu verzonden zolang de sleepbeweging plaatsvindt binnen de grenzen van het element. De handler voor deze gebeurtenis moet de eigenschap dataTransfer.dropEffect instellen om aan te geven of de neergezette gegevens worden gekopieerd, verplaatst of gekoppeld wanneer de gebruiker de muisknop loslaat.
dragenter
Wordt verzonden wanneer de sleepbeweging binnen de grenzen van het element komt. Als u eigenschappen van een dataTransfer-object wijzigt in een handler voor de dragenter-gebeurtenis, worden die wijzigingen overschreven door de volgende dragover-gebeurtenis. Er is echter een korte vertraging tussen een dragenter-gebeurtenis en de eerste dragover-gebeurtenis, waardoor de cursor kan gaan knipperen als andere eigenschappen zijn ingesteld. In veel gevallen kunt u dezelfde gebeurtenishandler gebruiken voor beide gebeurtenissen.
dragleave
Wordt verzonden wanneer de sleepbeweging buiten de grenzen van het element komt.
drop
Wordt verzonden wanneer de gebruiker de gegevens op het element neerzet. De gesleepte gegevens zijn alleen toegankelijk in de handler voor deze gebeurtenis.
Het gebeurtenisobject dat wordt verzonden als reactie op deze gebeurtenissen, is vergelijkbaar met een muisgebeurtenis. Met eigenschappen van een muisgebeurtenis, zoals (clientX, clientY) en (screenX, screenY), kunt u de positie van de muis bepalen. De belangrijkste eigenschap van een sleepgebeurtenisobject is dataTransfer, dat de gegevens bevat die worden gesleept. Het dataTransfer-object heeft de volgende eigenschappen en methoden: Eigenschap of methode
Beschrijving
effectAllowed
Het effect dat is toegestaan door de bron van waaruit wordt gesleept. Gewoonlijk wordt deze waarde ingesteld door de handler voor de gebeurtenis dragstart. Zie “Sleepeffecten in HTML” op pagina 141.
dropEffect
Het effect dat is gekozen door het doel of door de gebruiker. Als u dropEffect instelt in een gebeurtenishandler voor dragover of dragenter, wordt de muiscursor door AIR bijgewerkt en geeft deze het effect aan dat optreedt als de gebruiker de muis loslaat. Als de ingestelde waarde voor dropEffect niet overeenkomt met een van de toegestane effecten, is neerzetten niet toegestaan en wordt de cursor voor een niet-beschikbare actie weergegeven. Als u geen waarde voor dropEffect hebt ingesteld als reactie op de laatste dragover- of dragenter-gebeurtenis, kan de gebruiker uit de toegestane effecten kiezen met de standaard aanpassingstoetsen van het besturingssysteem. Het uiteindelijke effect wordt gerapporteerd door de eigenschap dropEffect van het object dat wordt verzonden voor dragend. Als de gebruiker het neerzetten annuleert door de muisknop los te laten buiten een geschikt doel, wordt dropEffect ingesteld op none.
types
Een array met de MIME-tekenreeksen voor elke gegevensindeling die aanwezig is in het object dataTransfer.
getData(mimeType)
Hiermee worden de gegevens opgehaald in de indeling die is opgegeven met de parameter mimeType. De methode getData() kan alleen worden opgeroepen als reactie op de gebeurtenis drop.
setData(mimeType)
Hiermee worden gegevens aan dataTransfer toegevoegd in de indeling die is opgegeven met de parameter mimeType. U kunt gegevens in meerdere indelingen toevoegen door setData() op te roepen voor elk MIME-type. Alle gegevens die door het standaardgedrag voor neerzetten in het object dataTransfer worden geplaatst, worden gewist. De methode setData() kan alleen worden opgeroepen als reactie op de gebeurtenis dragstart.
clearData(mimeType)
Hiermee worden alle gegevens gewist in de indeling die is opgegeven met de parameter mimeType.
setDragImage(image, offsetX, offsetY)
Hiermee stelt u een aangepaste sleepafbeelding in. De methode setDragImage() kan alleen worden opgeroepen als reactie op de gebeurtenis dragstart.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 141 Slepen en neerzetten
MIME-typen voor het slepen en neerzetten van HTML U kunt onder andere de volgende MIME-typen gebruiken met het object dataTransfer van een gebeurtenis voor het slepen en neerzetten van HTML: Gegevensindeling
MIME-type
Tekst
"text/plain"
HTML
"text/html"
URL
"text/uri-list"
Bitmap
"image/x-vnd.adobe.air.bitmap"
Bestandenlijst
"application/x-vnd.adobe.air.file-list"
U kunt ook andere MIME-tekenreeksen gebruiken, zoals tekenreeksen die door de toepassing zijn gedefinieerd. Het is echter mogelijk dat andere toepassingen de overgedragen gegevens niet herkennen of kunnen gebruiken. Het is uw verantwoordelijkheid om gegevens aan het object dataTransfer toe te voegen in de verwachte indeling. Belangrijk: Alleen code die in de toepassingssandbox wordt uitgevoerd, heeft toegang tot neergezette bestanden. Als een eigenschap van een File-object wordt gelezen of ingesteld in een externe sandbox, wordt een beveiligingsfout gegenereerd. Zie “Bestanden neerzetten in niet-toepassingssandboxen in HMTL” op pagina 145 voor meer informatie.
Sleepeffecten in HTML De initiator van de sleepbeweging kan de toegestane sleepeffecten beperken door de eigenschap dataTransfer.effectAllowed in te stellen in de handler voor de gebeurtenis dragstart. De volgende tekenreeken kunnen worden gebruikt: Tekenreekswaarde
Beschrijving
"none"
Er zijn geen sleepbewerkingen toegestaan.
"copy"
De gegevens worden naar het doel gekopieerd terwijl de oorspronkelijke gegevens op hun plaats blijven staan.
"link"
De gegevens worden met het neerzetdoel gedeeld via een koppeling met de oorspronkelijke gegevens.
"move"
De gegevens worden naar het doel gekopieerd en van de oorspronkelijke locatie verwijderd.
"copyLink"
De gegevens kunnen worden gekopieerd of gekoppeld.
"copyMove"
De gegevens kunnen worden gekopieerd of verplaatst.
"linkMove"
De gegevens kunnen worden gekoppeld of verplaatst.
"all"
De gegevens kunnen worden gekopieerd, verplaatst of gekoppeld. All is het standaardeffect wanneer u het standaardgedrag uitschakelt.
Het doel van de sleepbeweging kan de eigenschap dataTransfer.dropEffect instellen om aan te geven welke actie wordt uitgevoerd als de gebruiker de gegevens heeft neergezet. Als het neerzeteffect een van de toegestane acties is, wordt de juiste cursor voor kopiëren, verplaatsen of koppelen weergegeven. Als dat niet zo is, wordt de cursor voor een niet-beschikbare actie weergegeven. Als door het doel geen neerzeteffect is ingesteld, kan de gebruiker een toegestane actie kiezen met de aanpassingstoetsen. Stel de waarde van dropEffect in de handlers voor de gebeurtenissen dragover en dragenter in:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 142 Slepen en neerzetten
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"; }
Opmerking: Hoewel u de eigenschap dropEffect altijd moet instellen in de handler voor dragenter, moet u niet vergeten dat de volgende dragover-gebeurtenis de standaardwaarde van de eigenschap herstelt. Stel dropEffect in als reactie op beide gebeurtenissen.
Gegevens uit een HTML-element slepen Bij het standaardgedrag kan de meeste inhoud van een HTML-pagina via slepen worden gekopieerd. Met de CSSeigenschappen -webkit-user-select en -webkit-user-drag kunt u bepalen welke inhoud mag worden gesleept. Overschrijf het standaardgedrag voor uitslepen in de handler voor de gebeurtenis dragstart. Roep de methode setData() van de eigenschap dataTransfer van het gebeurtenisobject op om uw eigen gegevens in de sleepbeweging te plaatsen. Stel de eigenschap dataTransfer.effectAllowed van het gebeurtenisobject dat voor de gebeurtenis dragstart wordt verzonden in om aan te geven welke sleepeffecten een bronobject ondersteunt wanneer u geen gebruik maakt van het standaardgedrag. U kunt elke combinatie van effecten kiezen. Als een bronelement bijvoorbeeld de effecten kopiëren en koppelen ondersteunt, stelt u de eigenschap in op "copyLink".
Gesleepte gegevens instellen Voeg de gegevens voor de sleepbeweging met de eigenschap dataTransfer toe in de handler voor de gebeurtenis dragstart. Gebruik de methode dataTransfer.setData() om gegevens op het klembord te plaatsen en geef daarbij het MIME-type en de gegevens die u wilt overdragen door. Als uw toepassing bijvoorbeeld een afbeeldingselement met de id imageOfGeorge bevat, kunt u de volgende gebeurtenishandler voor dragstart gebruiken. In dit voorbeeld ziet u hoe weergaven van een afbeelding van George in verschillende gegevensindelingen worden toegevoegd, waardoor de kans groter wordt dat andere toepassingen de gesleepte gegevens kunnen gebruiken. 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)); }
Opmerking: Wanneer u de methode setData() van het object dataTransfer oproept, worden geen gegevens toegevoegd als het standaardgedrag voor slepen en neerzetten wordt gebruikt.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 143 Slepen en neerzetten
Gegevens naar een HTML-element slepen Bij het standaardgedrag mag alleen tekst worden gesleept naar bewerkbare gebieden van de pagina. U kunt opgeven dat een element en de onderliggende elementen bewerkbaar mogen worden gemaakt, door het kenmerk contenteditable op te nemen in de openingscode van het element. U kunt ook een heel document bewerkbaar maken door de eigenschap designMode van het documentobject in te stellen op "on". U kunt alternatief insleepgedrag op een pagina mogelijk maken door het verwerken van de gebeurtenissen dragenter, dragover en drop voor alle elementen die gesleepte gegevens kunnen accepteren.
Inslepen mogelijk maken Als u de insleepbeweging wilt afhandelen, moet u eerst het standaardgedrag annuleren. Luister naar de gebeurtenissen dragenter en dragover van alle HTML-elementen die u wilt gebruiken als neerzetdoelen. Roep in de handlers voor deze gebeurtenissen de methode preventDefault() van het verzonden gebeurtenisobject aan. Als u het standaardgedrag annuleert, mogen niet-bewerkbare gebieden neergezette gegevens ontvangen.
Neergezette gegevens ophalen U kunt de neergezette gegevens ophalen in de handler voor de gebeurtenis ondrop: function doDrop(event){ droppedText = event.dataTransfer.getData("text/plain"); }
Gebruik de methode dataTransfer.getData() om de gegevens op het klembord te lezen en geef daarbij het MIMEtype door van de gegevensindeling die u wilt lezen. Met de eigenschap types van het object dataTransfer kunt u te weten komen welke gegevensindelingen beschikbaar zijn. De array types bevat de MIME-typetekenreeks van elke beschikbare indeling. Wanneer u het standaardgedrag in de gebeurtenis dragenter of dragover annuleert, bent u er verantwoordelijk voor dat neergezette gegevens op de juiste plaats in het document worden ingevoegd. Er bestaat geen API om een muispositie te converteren naar een invoegpositie in een element. Hierdoor kan het moeilijk zijn om sleepbewegingen voor invoegbewerkingen te implementeren.
Voorbeeld: het standaardgedrag voor het inslepen van HTML overschrijven In dit voorbeeld wordt een neerzetdoel geïmplementeerd waarmee een tabel wordt weergegeven met elke gegevensindeling die beschikbaar is in het neergezette item. Het standaardgedrag wordt gebruikt, waardoor tekst, koppelingen en afbeeldingen in de toepassing mogen worden gesleept. In dit voorbeeld wordt het standaardgedrag voor inslepen overschreven voor het div-element dat optreedt als neerzetdoel. Als u wilt dat niet-bewerkbare inhoud een insleepbeweging accepteert, is het belangrijk dat u de methode preventDefault() oproept van het gebeurtenisobject dat wordt verzonden voor de gebeurtenissen dragenter en dragover. Als reactie op de gebeurtenis drop converteert de handler de overgedragen gegevens naar een HTMLrijelement en wordt deze rij ingevoegd in een tabel die wordt weergegeven.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 144 Slepen en neerzetten
Drag-and-drop <script language="javascript" type="text/javascript" src="AIRAliases.js"> <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 = "" + event.dataTransfer.getData("text/plain") + " | " + "" + event.dataTransfer.getData("text/html") + " | " + "" + event.dataTransfer.getData("text/uri-list") + " | " + "" + event.dataTransfer.getData("application/x-vnd.adobe.air.file-list") + " | "; 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); } Source
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 145 Slepen en neerzetten
Items to drag:
- Plain text.
- HTML formatted text.
- A URL.
- Uses "-webkit-user-drag:none" style.
- Uses "-webkit-user-select:none" style.
Target
Drag items from the source list (or elsewhere).
Plain text | Html text | URL | File list | Bitmap Data |
| | | | td> |
Bestanden neerzetten in niet-toepassingssandboxen in HMTL Inhoud die niet van de toepassing afkomstig is, heeft geen toegang tot File-objecten die worden gemaakt wanneer bestanden naar een AIR-toepassing worden gesleept. Het is ook niet mogelijk een van deze File-objecten aan inhoud van de toepassing door te geven via een sandboxbridge. (De objecteigenschappen moeten worden benaderd tijdens het serialiseren.) U kunt echter wel bestanden in uw toepassing neerzetten door te luisteren naar de nativeDragDropgebeurtenissen van AIR voor het HTMLLoader-object. Als een gebruiker een bestand neerzet in een frame dat inhoud bevat die niet van de toepassing afkomstig is, wordt de neerzetgebeurtenis gewoonlijk niet van het onderliggende naar het bovenliggende item doorgevoerd. Omdat de gebeurtenissen die door de HTMLLoader (die de container is voor alle HTML-inhoud in een AIR-toepassing) worden verzonden geen deel uitmaken van de HTML-gebeurtenissenstroom, kunt u de neerzetgebeurtenis echter nog steeds ontvangen in inhoud van de toepassing. Om de gebeurtenis voor het neerzetten van een bestand te ontvangen, voegt het bovenliggende document een gebeurtenislistener aan het HTMLLoader-object toe met de verwijzing die is geleverd door window.htmlLoader: window.htmlLoader.addEventListener("nativeDragDrop",function(event){ var filelist = event.clipboard.getData(air.ClipboardFormats.FILE_LIST_FORMAT); air.trace(filelist[0].url); });
In het volgende voorbeeld laadt een bovenliggend document een onderliggende pagina in een externe sandbox (http://localhost/). Het bovenliggende document luistert naar de gebeurtenis nativeDragDrop van het HTMLLoaderobject en haalt hier de bestands-URL uit op.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 146 Slepen en neerzetten
Drag-and-drop in a remote sandbox <script language="javascript" type="text/javascript" src="AIRAliases.js"> <script language="javascript"> window.htmlLoader.addEventListener("nativeDragDrop",function(event){ var filelist = event.clipboard.getData(air.ClipboardFormats.FILE_LIST_FORMAT); air.trace(filelist[0].url); }); <iframe src="child.html" sandboxRoot="http://localhost/" documentRoot="app:/" frameBorder="0" width="100%" height="100%">
Het onderliggende document moet een geldig neerzetdoel zijn. Hiervoor moet de methode preventDefault() van het Event-object in handlers van de HTML-gebeurtenissen dragenter en dragover worden voorkomen, anders kan de neerzetgebeurtenis niet plaatsvinden.
Drag and drop target <script language="javascript" type="text/javascript"> function preventDefault(event){ event.preventDefault(); }
Drop Files Here
Zie “Programmeren in HTML en JavaScript” op pagina 221 voor meer informatie.
147
Hoofdstuk 16: kopiëren en plakken Gebruik de klassen in de klembord-API om informatie van en naar het systeemklembord te kopiëren. De volgende gegevensindelingen kunnen worden gebruikt om informatie van en naar een Adobe® AIR™-toepassing te kopiëren:
• Bitmaps • Bestanden • Tekst • Tekst met HTML-opmaak • RTF-gegevens • URL-tekenreeksen • Geserialiseerde objecten • Objectverwijzingen (alleen geldig binnen de brontoepassing)
Aanvullende online informatie over kopiëren en plakken Meer informatie over kopiëren en plakken vindt u in deze bronnen: Snelstarthandleidingen (Adobe AIR Developer Connection) • Ondersteuning voor slepen en neerzetten en voor kopiëren en plakken Language Reference • Clipboard
• ClipboardFormats • ClipboardTransferMode Meer informatie • Adobe AIR Developer Connection for Flash (zoek naar 'AIR copy and paste')
Basisbeginselen van kopiëren en plakken De kopiëren-en-plakken-API bevat de volgende klassen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 148 kopiëren en plakken
Pakket
Klassen
flash.desktop
•
clipboard
•
ClipboardFormats
•
ClipboardTransferMode
Constanten voor gebruik met de kopiëren-en-plakken-API worden in de volgende klassen gedefinieerd:
•
ClipboardFormats
•
ClipboardTransferMode
De statische eigenschap Clipboard.generalClipboard vertegenwoordigt het klembord van het besturingssysteem. De klasse Clipboard biedt methoden voor het lezen en schrijven van gegevens van en naar klembordobjecten. U kunt ook nieuwe klembordobjecten creëren om gegevens over te brengen via de kopiëren-en-plakken-API. De HTML-omgeving biedt een alternatieve API voor kopiëren en plakken. Code die binnen de toepassingssandbox wordt uitgevoerd, kan een willekeurige van deze twee API's gebruiken maar alleen de HTML-API kan in niettoepassingsinhoud worden gebruikt. (Zie “HTML kopiëren en plakken” op pagina 149.) De klassen HTMLLoader en TextField passen standaardgedrag toe op de normale sneltoetsen voor kopiëren en plakken. Als u kopiëren en plakken in aangepaste componenten wilt gebruiken, kunt u rechtstreeks op deze toetsaanslagen wachten. U kunt ook native menuopdrachten met andere sneltoetsen creëren om onrechtstreeks op de toetsaanslagen te reageren. U kunt in één klembordobject meerdere voorstellingen van dezelfde informatie beschikbaar maken om het andere toepassingen makkelijker te maken de gegevens te begrijpen en te gebruiken. Een afbeelding kan bijvoorbeeld als grafische gegevens, een geserialiseerd bitmapobject en een bestand worden opgenomen. Het omzetten van gegevens naar een indeling kan worden uitgesteld zodat de indeling pas wordt gecreëerd nadat de gegevens in de desbetreffende indeling zijn gelezen. Opmerking: Er is geen garantie dat de gegevens die naar het klembord zijn geschreven, beschikbaar blijven nadat een AIR-toepassing is afgesloten.
Lezen van en schrijven naar het systeemklembord Als u de inhoud van het klembord van het besturingssysteem wilt lezen, roept u de methode getData() van het object Clipboard.generalClipboard op, waarbij u de naam opgeeft van de indeling die u wilt lezen: import flash.desktop.Clipboard; import flash.desktop.ClipboardFormats; if(Clipboard.generalClipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)){ var text:String = Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT); }
Als u naar het klembord wilt schrijven, voegt u de gegevens in een of meer indelingen toe aan het object Clipboard.generalClipboard. Bestaande gegevens in dezelfde indeling worden automatisch overschreven. Het is echter aan te raden het systeemklembord te wissen voordat u nieuwe gegevens naar het klembord schrijft om te zorgen dat ook niet-verwante gegevens in andere indelingen worden gewist.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 149 kopiëren en plakken
import flash.desktop.Clipboard; import flash.desktop.ClipboardFormats; var textToCopy:String = "Copy to clipboard."; Clipboard.generalClipboard.clear(); Clipboard.generalClipboard.setData(ClipboardFormats.TEXT_FORMAT, textToCopy, false);
Opmerking: Alleen code die in de toepassingssandbox wordt uitgevoerd, heeft rechtstreeks toegang tot het systeemklembord. Bij niet-toepassings HTML-inhoud hebt u alleen toegang tot het klembord via de eigenschap clipboardData van een gebeurtenisobject dat is verzonden door een van de HTML kopiëren-en-plakkengebeurtenissen.
HTML kopiëren en plakken De HTML-omgeving heeft een eigen set van gebeurtenissen en standaardgedrag voor kopiëren en plakken. Alleen code die in de toepassingssandbox wordt uitgevoerd, heeft rechtstreeks toegang tot het systeemklembord via het AIRobject Clipboard.generalClipboard. JavaScript-code in een niet-toepassingssandbox heeft toegang tot het klembord via het gebeurtenisobject dat is verzonden als reactie op een van de kopiëren-en-plakken-gebeurtenissen die zijn verzonden door een element in een HTML-document. Kopiëren-en-plakken-gebeurtenissen zijn onder andere: copy, cut en paste. Het object dat voor deze gebeurtenissen is verzonden, biedt toegang tot het klembord via de eigenschap clipboardData.
Standaardgedrag Als reactie op de kopieeropdracht worden de geselecteerde items standaard door AIR gekopieerd. Deze opdracht kan via een sneltoets of een snelmenu worden gegenereerd. In bewerkbare zones wordt tekst als reactie op de knipopdracht door AIR geknipt, of als reactie op de plakopdracht door AIR geplakt op de cursorpositie of de geselecteerde tekst. Als u een ander gedrag wenst, kan uw gebeurtenishandler de methode preventDefault() van het verzonden gebeurtenisobject oproepen.
Eigenschap clipboardData van gebeurtenisobject gebruiken Met de eigenschap clipboardData van het gebeurtenisobject dat als reactie op een van de kopieer- of plakgebeurtenissen is verzonden, kunt u klembordgegevens lezen en schrijven. Als u naar het klembord wilt schrijven bij het werken met een kopieer- of knipgebeurtenis, gebruikt u de methode setData() van het object clipboardData, waarbij u de te kopiëren gegevens en het MIME-type opgeeft: function customCopy(event){ event.clipboardData.setData("text/plain", "A copied string."); }
Als u toegang wilt tot de gegevens die worden geplakt, gebruikt u de methode getData() van het object clipboardData, waarbij u het MIME-type van de gegevensindeling opgeeft. De beschikbare indelingen worden weergegeven door de eigenschap types. function customPaste(event){ var pastedData = event.clipboardData("text/plain"); }
De methode getData() en de eigenschap types zijn alleen toegankelijk in het gebeurtenisobject dat is verzonden door de gebeurtenis paste.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 150 kopiëren en plakken
Het volgende voorbeeld geeft aan hoe u het standaardgedrag bij kopiëren en plakken in een HTML-pagina kunt wijzigen. De gebeurtenishandler copy maakt de gekopieerde tekst cursief en kopieert deze als HTML-tekst naar het klembord. De gebeurtenishandler cut kopieert de geselecteerde gegevens naar het klembord en verwijdert deze uit het document. De gebeurtenishandler paste voegt de inhoud van het klembord als HTML in en maakt de ingevoegde tekst vet.
Copy and Paste <script language="javascript" type="text/javascript"> function onCopy(event){ var selection = window.getSelection(); event.clipboardData.setData("text/html","
" + selection + ""); event.preventDefault(); } function onCut(event){ var selection = window.getSelection(); event.clipboardData.setData("text/html","
" + selection + ""); 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(); }
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.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 151 kopiëren en plakken
Menuopdrachten en toetsaanslagen voor kopiëren en plakken De kopiëren-en-plakken-functionaliteit wordt doorgaans geactiveerd door menuopdrachten en sneltoetsen. In OS X maakt het besturingssysteem automatisch een bewerkingsmenu met de opdrachten Kopiëren en Plakken. U moet echter listeners aan deze menuopdrachten toevoegen om uw eigen functies eraan te koppelen. In Windows kunt u een native bewerkingsmenu toevoegen aan elk venster dat de systeeminterface gebruikt. (U kunt ook niet-native menu's maken met Flex en ActionScript of - bij HTML-inhoud - DHTML gebruiken, maar dat valt niet binnen het kader van deze handleiding.) De kopiëren-en-plakken-functionaliteit wordt doorgaans geactiveerd door menuopdrachten en sneltoetsen. In OS X maakt het besturingssysteem automatisch een bewerkingsmenu met de opdrachten Kopiëren en Plakken. U moet echter listeners aan deze menuopdrachten toevoegen om uw eigen functies eraan te koppelen. In Windows kunt u een native bewerkingsmenu toevoegen aan elk venster dat de systeeminterface gebruikt. (U kunt ook niet-native menu's maken met ActionScript of - bij HTML-inhoud - DHTML gebruiken, maar dat valt niet binnen het kader van deze handleiding.) Als u de opdrachten Kopiëren en Plakken wilt laten activeren door sneltoetsen, kunt u toetsencombinaties aan de overeenkomstige opdrachten toewijzen in een native toepassing of venstermenu, of rechtstreeks op de toetsaanslagen wachten.
Kopieer- of plakbewerking starten met een menuopdracht Als u een kopieer- of plakbewerking wilt laten activeren door een menuopdracht, moet u listeners voor de gebeurtenis select toevoegen aan de menu-items die uw handlerfuncties oproepen. Wanneer uw handlerfunctie wordt opgeroepen, kunt u het object waarvan moet worden gekopieerd of waarnaar moet worden geplakt, vinden met behulp van de eigenschap focus van de fase. Vervolgens kunt u de overeenkomstige methode voor het object met focus (of een algemene alternatieve methode als geen enkel object focus heeft) oproepen om de logica voor kopiëren, knippen of plakken uit te voeren. De volgende gebeurtenishandler copy controleert bijvoorbeeld of het object met focus het juiste type is (in dit geval de klasse Scrap) en roept vervolgens de methode doCopy() voor het object op. function copyCommand(event:Event):void{ if(NativeApplication.nativeApplication.activeWindow.stage.focus is Scrap){ Scrap(NativeApplication.nativeApplication.activeWindow.stage.focus).doCopy(); } else { NativeApplication.nativeApplication.copy(); } }
Als copyCommand() in het voorbeeld de klasse van het object met focus niet herkent, wordt de NativeApplicationmethode copy() opgeroepen. De NativeApplication-methode copy() verzendt een interne opdracht Kopiëren naar het object met focus. De interne opdracht wordt alleen door de objecten TextArea en HTMLLoader herkend. Er zijn soortgelijke opdrachten beschikbaar voor Knippen, Plakken, Alles selecteren en (alleen voor TextArea) Wissen, Ongedaan maken en Opnieuw. Opmerking: Er is geen API beschikbaar om op deze interne opdrachten te reageren in een aangepaste component. U moet de klasse TextArea of HTMLLoader uitbreiden of een van deze objecten opnemen in uw aangepaste component. Als u een TextArea- of HTMLLoader-object opneemt, moet uw component de focus zo beheren dat het TextArea- of HTMLLoader-object altijd focus behoudt wanneer de component zelf focus heeft.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 152 kopiëren en plakken
Bij HTML-inhoud kunt u het standaardgedrag voor kopiëren en plakken activeren met behulp van de NativeApplication-bewerkingsopdrachten. In het volgende voorbeeld wordt een bewerkingsmenu voor een bewerkbaar HTML-document gemaakt: In het vorige voorbeeld wordt het toepassingsmenu voor Mac OS X vervangen. U kunt echter ook het standaard bewerkingsmenu gebruiken door de bestaande menuopdrachten te zoeken en er gebeurtenislisteners aan toe te voegen. Als u een snelmenu gebruikt om een kopieer- of plakopdracht op te roepen, kunt u de eigenschap contextMenuOwner gebruiken van het ContextMenuEvent-object dat wordt verzonden bij het openen van het menu of het selecteren van een menuopdracht, om te bepalen welk object de juiste bestemming van de kopieer- of plakopdracht is.
Standaard menuopdrachten zoeken in Mac OS X U kunt het standaard bewerkingsmenu en de specifieke kopieer-, knip- en plakopdrachten in het toepassingsmenu voor Mac OS X zoeken door de menuhiërarchie te doorzoeken met behulp van de eigenschap label van de NativeMenuItem-objecten. Met de volgende functie neemt u bijvoorbeeld een naam en zoekt u de opdracht met het overeenkomstige label in het menu: 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, recurse); } if(searchItem != null){ break; } } return searchItem; }
U kunt de parameter recurse instellen op true als u submenu's in de zoekactie wilt opnemen, of op false als u alleen de opdrachten van hetzelfde niveau wilt zoeken.
Kopieer- of plakopdracht starten met een toetsaanslag Als uw toepassing native venster- of toepassingsmenu's voor kopiëren en plakken gebruikt, kunt u toetsencombinaties aan de menuopdrachten toewijzen die als sneltoetsen reageren. U kunt echter ook zelf naar de overeenkomstige toetsaanslagen luisteren, zoals in het volgende voorbeeld wordt geïllustreerd:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 153 kopiëren en plakken
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; } } }
Bij HTML-inhoud worden standaard de sneltoetsen voor kopieer- en plakopdrachten toegepast. Het is niet mogelijk om met een toetsgebeurtenislistener alle toetsaanslagen te detecteren die doorgaans voor kopiëren en plakken worden gebruikt. Als u het standaardgedrag wilt wijzigen, wordt u aangeraden naar de gebeurtenissen copy en paste zelf te luisteren.
Klembordgegevensindelingen Klembordindelingen beschreven de gegevens die in een klembordobject zijn geplaatst. AIR zet de standaard gegevensindelingen automatisch om van ActionScript-gegevenstypen in systeemklembordindelingen, en omgekeerd. Bovendien kunnen toepassingsobjecten worden overgebracht binnen en tussen AIR-toepassingen met behulp van toepassingsspecifieke indelingen. Een klembordobject kan dezelfde informatie in meerdere indelingen bevatten. Een klembordobject dat een sprite representeert, kan bijvoorbeeld een referentie-indeling bevatten voor gebruik in dezelfde toepassing, een geserialiseerde indeling voor gebruik door een andere AIR-toepassing, een bitmapindeling voor gebruik door een grafische editor en een bestandenlijstindeling, mogelijk met uitgestelde rendering om een PNG-bestand te coderen, voor het kopiëren of slepen van een representatie van de sprite naar het bestandssysteem.
Standaard gegevensindelingen De constanten die de standaard indelingsnamen definiëren, staan in de klasse ClipboardFormats:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 154 kopiëren en plakken
Constante
Beschrijving
TEXT_FORMAT
Gegevens met tekstindeling worden omgezet in de ActionScript-klasse String, en omgekeerd.
HTML_FORMAT
Tekst met HTML-markeringen.
RICH_TEXT_FORMAT
RTF-gegevens worden omgezet in de ActionScript-klasse ByteArray, en omgekeerd. De RTF-markeringen worden op geen enkele manier geïnterpreteerd of omgezet.
BITMAP_FORMAT
Gegevens met bitmapindeling worden omgezet in de ActionScript-klasse BitmapData, en omgekeerd.
FILE_LIST_FORMAT
Gegevens met bestandenlijstindeling worden omgezet in een array van ActionScript File-objecten, en omgekeerd.
URL_FORMAT
Gegevens met URL-indeling worden omgezet in de ActionScript-klasse String, en omgekeerd.
Opmerking: Flash-tekstbesturingselementen en -componenten bieden momenteel nog geen ondersteuning voor RTFgegevens. Als u RTF-gegevens in een besturingselement wilt plakken, zet u eerst de RTF-markering om in een HTMLmarkering (of tekst zonder opmaak). Op dezelfde manier moet u om RTF-gegevens naar het klembord te kopiëren, een tekst- of HTML-tekenreeks omzetten in een ByteArray-object met de juiste RTF-markeringen. Flash biedt geen hulpprogrammaklasse voor de conversie van RTF-gegevens naar een andere indeling. Bij het kopiëren en plakken van gegevens als reactie op een copy-, cut- of paste- gebeurtenis in HTML-inhoud, moet u MIME-typen gebruiken in plaats van ClipboardFormat-tekenreeksen. De volgende MIME-typen zijn geldig voor gegevens: MIME-type
Beschrijving
Tekst
"text/plain"
URL
"text/uri-list"
Bitmap
"image/x-vnd.adobe.air.bitmap"
Bestandenlijst
"application/x-vnd.adobe.air.file-list"
Opmerking: RTF-gegevens zijn niet beschikbaar via de eigenschap clipboardData van het gebeurtenisobject dat is verzonden als reactie op een paste-gebeurtenis in HTML-inhoud.
Aangepaste gegevensindelingen U kunt toepassingsspecifieke, aangepaste indelingen gebruiken om objecten als verwijzingen of geserialiseerde kopieën over te brengen. Verwijzingen zijn alleen geldig binnen dezelfde AIR-toepassing. Geserialiseerde objecten kunnen tussen Adobe AIR-toepassingen worden overgebracht maar kunnen alleen worden gebruikt met objecten die geldig blijven nadat ze zijn geserialiseerd en gedeserialiseerd. Objecten kunnen doorgaans worden geserialiseerd als hun eigenschappen van een eenvoudig type zijn of als de objecten serialiseerbaar zijn. Als u een geserialiseerd object aan een klembordobject wilt toevoegen, stelt u de serialiseerbare parameter in op true wanneer u de methode Clipboard.setData() oproept. De naam van de indeling kan die van een standaardindeling zijn, of een willekeurige tekenreeks die door uw toepassing wordt gedefinieerd.
Overdrachtsmodi Wanneer u een object in een aangepaste gegevensindeling naar het klembord schrijft, kunnen de objectgegevens als verwijzing of als geserialiseerde kopie van het oorspronkelijke object worden gelezen van het klembord. AIR definieert vier overdrachtsmodi die bepalen of objecten als verwijzingen of als geserialiseerde kopieën worden overgebracht:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 155 kopiëren en plakken
Overdrachtsmodus
Beschrijving
ClipboardTransferModes.ORIGINAL_ONLY
Er wordt alleen een verwijzing geretourneerd. Als er geen verwijzing beschikbaar is, wordt een nulwaarde geretourneerd.
ClipboardTransferModes.ORIGINAL_PREFERRED
Als er een verwijzing beschikbaar is, wordt deze geretourneerd. Als dat niet het geval is, wordt een geserialiseerde kopie geretourneerd.
ClipboardTransferModes.CLONE_ONLY
Er wordt alleen een geserialiseerde kopie geretourneerd. Als er geen geserialiseerde kopie beschikbaar is, wordt een nulwaarde geretourneerd.
ClipboardTransferModes.CLONE_PREFERRED
Als er een geserialiseerde kopie beschikbaar is, wordt deze geretourneerd. Als dat niet het geval is, wordt een verwijzing geretourneerd.
Aangepaste gegevensindelingen lezen en schrijven Wanneer u een object naar het klembord schrijft, kunt u een willekeurige tekenreeks gebruiken die niet begint met het gereserveerde voorvoegsel air: voor de indelingsparameter. Gebruik dezelfde tekenreeks als indeling voor het lezen van het object. De volgende voorbeelden illustreren hoe u objecten leest van en schrijft naar het klembord: public function createClipboardObject(object:Object):Clipboard{ var transfer:Clipboard = new Clipboard(); transfer.setData("object", object, true); }
Als u een geserialiseerd object uit het klembordobject wilt halen (na een neerzet- of plakbewerking), gebruikt u dezelfde indelingsnaam en de overdrachtsmodus cloneOnly of clonePreferred. var transfer:Object = clipboard.getData("object", ClipboardTransferMode.CLONE_ONLY);
Er wordt altijd een verwijzing toegevoegd aan het klembordobject. Als u de verwijzing - en niet de geserialiseerde kopie - uit het klembordobject wilt halen (na een neerzet- of plakbewerking), gebruikt u de overdrachtsmodus originalOnly of originalPreferred: var transferredObject:Object = clipboard.getData("object", ClipboardTransferMode.ORIGINAL_ONLY);
Verwijzingen zijn alleen geldig als het klembordobject afkomstig is uit de actuele AIR-toepassing. Gebruik de overdrachtsmodus originalPreferred om toegang te verkrijgen tot de verwijzing als deze beschikbaar is, of tot de geserialiseerde kopie als de verwijzing niet beschikbaar is.
Uitgestelde rendering Als het maken van een gegevensindeling de processor zwaar belast, kunt u uitgestelde rendering toepassen door een functie in te stellen die de gegevens op aanvraag levert. Deze functie wordt alleen opgeroepen als een ontvanger van de neerzet- of plakbewerking om gegevens in de uitgestelde indeling vraagt. De renderfunctie wordt met de methode setDataHandler() aan een klembordobject toegevoegd. De functie moet de gegevens in de juiste indeling retourneren. Als u bijvoorbeeld setDataHandler(ClipboardFormat.TEXT_FORMAT, writeText) hebt opgeroepen, moet de functie writeText() een tekenreeks retourneren. Als een gegevensindeling van hetzelfde type met de methode setData() aan een klembordobject wordt toegevoegd, hebben die gegevens voorrang op de uitgestelde versie (de renderfunctie wordt nooit opgeroepen). Als dezelfde klembordgegevens een tweede keer worden benaderd, wordt de renderfunctie mogelijk (opnieuw) opgeroepen. Opmerking: In Mac OS X treedt geen uitgestelde rendering op bij het gebruik van de standaard AIR-klembordindelingen. De renderfunctie wordt onmiddellijk opgeroepen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 156 kopiëren en plakken
Tekst plakken met behulp van uitgestelde rendering Het volgende voorbeeld illustreert hoe u uitgestelde rendering toepast. Wanneer in dit voorbeeld op de knop Copy wordt geklikt, wist de toepassing het systeemklembord om te zorgen dat er geen gegevens van vorige klembordbewerkingen meer aanwezig zijn. Vervolgens wordt de functie renderData() op het klembord geplaatst met de klembordmethode setDataHandler(). Wanneer op de knop Paste wordt geklikt, haalt de toepassing de tekst op uit het klembord en wordt de doeltekst ingevoegd. Aangezien de tekstgegevensindeling op het klembord is ingesteld met een functie en niet met een tekenreeks, roept het klembord de functie renderData() op. De functie renderData() retourneert de tekst in de brontekst, waarna deze aan de doeltekst wordt toegewezen. Let op: als u brontekst bewerkt voordat u op de knop Paste klikt, worden de bewerkingen opgenomen in de geplakte tekst, zelfs als de bewerking plaatsvindt nadat u op de knop Copy hebt geklikt. De renderfunctie kopieert de brontekst namelijk pas nadat op de knop Paste is geklikt. (Wanneer u uitgestelde rendering in een echte toepassing gebruikt, kunt u het best de brongegevens opslaan of vergrendelen om dit probleem te voorkomen.) package { import import import import import
flash.desktop.Clipboard; flash.desktop.ClipboardFormats; flash.display.Sprite; flash.text.TextField; flash.events.MouseEvent;
public class DeferredRenderingExample extends Sprite { var sourceTxt:TextField; var destinationTxt:TextField; public function DeferredRenderingExample():void { sourceTxt = createTextField(10, 10, 210, 380, false); addChild(sourceTxt); sourceTxt.text = "Neque porro quisquam est qui dolorem " + "ipsum quia dolor sit amet, consectetur, adipisci velit." destinationTxt = createTextField(330, 10, 210, 380, false); addChild(destinationTxt); var copyBtn:TextField = createTextField(230, 50, 90, 20, true); copyBtn.text = "Copy"; addChild(copyBtn); copyBtn.addEventListener(MouseEvent.CLICK, onCopy); var pasteBtn:TextField = createTextField(230, 80, 90, 20, true); pasteBtn.text = "Paste"; addChild(pasteBtn); pasteBtn.addEventListener(MouseEvent.CLICK, onPaste); } private function createTextField(x:Number, y:Number, width:Number, height:Number, isBtn:Boolean = false):TextField { var newTxt:TextField = new TextField(); newTxt.x = x; newTxt.y = y;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 157 kopiëren en plakken
newTxt.height = height; newTxt.width = width; newTxt.border = true; newTxt.background = true; if (isBtn) { newTxt.backgroundColor = 0xDDDDDDEE; newTxt.selectable = false; } else { newTxt.multiline = true; newTxt.wordWrap = true; newTxt.backgroundColor = 0xEEEEEEEE; } return newTxt; } public function onCopy(event:MouseEvent):void { Clipboard.generalClipboard.clear(); Clipboard.generalClipboard.setDataHandler(ClipboardFormats.TEXT_FORMAT, renderData); } public function onPaste(event:MouseEvent):void { destinationTxt.text = Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT) as String; } public function renderData():String { trace("Rendering data"); var sourceStr:String = sourceTxt.text; if (sourceTxt.selectionEndIndex > sourceTxt.selectionBeginIndex) { // something is selected return sourceStr.substring(sourceTxt.selectionBeginIndex, sourceTxt.selectionEndIndex); } else { return sourceStr; } } } }
158
Hoofdstuk 17: Werken met bytearrays Met de klasse ByteArray kunt u een binaire gegevensstroom, die in feite een array met bytes is, lezen en schrijven. Met deze klasse krijgt u toegang tot gegevens op het meest elementaire niveau. Omdat computergegevens bestaan uit bytes, of groepen van 8 bits, kunt u door het lezen van gegevens in bytes toegang krijgen tot gegevens waarvoor geen klassen en toegangsmethoden bestaan. Met de klasse ByteArray kunt u elke gegevensstroom, van een bitmap tot een gegevensstroom die via het netwerk wordt verzonden, parseren op byteniveau. Met de methode writeObject() kunt u een object in geserialiseerde AMF-indeling (Action Message Format) schrijven naar een bytearray, terwijl u met de methode readObject() een geserialiseerd object uit een bytearray kunt inlezen in een variabele van het oorspronkelijke gegevenstype. U kunt alle objecten serialiseren, behalve weergaveobjecten (objecten die op de weergavelijst kunnen worden geplaatst). U kunt geserialiseerde objecten ook opnieuw aan aangepaste klasse-instanties toewijzen als de aangepaste klasse beschikbaar is voor de runtime. Nadat een object naar AMF is geconverteerd, kunt u het verzenden via een netwerkverbinding of opslaan in een bestand. In de Adobe® AIR™-voorbeeldtoepassing die hier wordt beschreven, wordt een ZIP-bestand gelezen als voorbeeld van het verwerken van een bytestroom; de lijst met bestanden in het ZIP-bestand wordt uitgepakt en naar de desktop geschreven.
Bytearrays lezen en schrijven De klasse ByteArray is een onderdeel van het pakket flash.utils. Als u een ByteArray-object wilt maken in ActionScript 3.0, importeert u de klasse ByteArray en roept u de constructor op, zoals weergegeven in het volgende voorbeeld: import flash.utils.ByteArray; var stream:ByteArray = new ByteArray();
ByteArray, methoden Elke zinvolle gegevensstroom wordt geordend in een indeling waarin u de gewenste informatie kunt zoeken. Een record in een eenvoudig werknemersbestand kan bijvoorbeeld een id-nummer, een naam, een adres, een telefoonnummer enzovoort bevatten. Een MP3-geluidsbestand bevat een ID3-code met de titel, de auteur, het album, de publicatiedatum en het genre van het bestand dat wordt gedownload. Door deze indeling weet u in welke volgorde de gegevens in de gegevensstroom zijn opgenomen. U kunt de bytestroom daardoor op een intelligente manier lezen. De klasse ByteArray bevat diverse methoden waarmee u een gegevensstroom eenvoudiger kunt lezen of schrijven. Enkele van deze methoden zijn: readBytes() en writeBytes(), readInt() en writeInt(), readFloat() en writeFloat(), readObject() en writeObject(), en readUTFBytes() en writeUTFBytes(). Met deze methoden kunt u gegevens uit een gegevensstroom inlezen in variabelen van bepaalde gegevenstypen en vanuit bepaalde gegevenstypen rechtstreeks naar de binaire gegevensstroom schrijven. Met de volgende code wordt bijvoorbeeld een eenvoudige array met tekenreeksen en getallen met een drijvende komma gelezen en wordt elk element naar een bytearray geschreven. Door de indeling van de array kan de code de juiste ByteArray-methoden (writeUTFBytes() en writeFloat()) oproepen voor het schrijven van de gegevens. Door het herhaalde gegevenspatroon wordt het mogelijk de array in een lus te lezen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 159 Werken met bytearrays
// 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
De eigenschap position In de eigenschap position wordt de huidige positie opgeslagen van de pointer die de index van de bytearray bepaalt tijdens het lezen of schrijven. De initiële waarde van de eigenschap position is 0 (nul), zoals wordt weergegeven in de volgende code: var bytes:ByteArray = new ByteArray(); trace("bytes.position is initially: " + bytes.position); // 0
Wanneer u een bytearray leest of er naar schrijft, wordt de eigenschap position bijgewerkt met de methode die u gebruikt, zodat wordt verwezen naar de locatie die volgt op de laatste byte die is gelezen of geschreven. Met de volgende code wordt bijvoorbeeld een tekenreeks naar een bytearray geschreven en verwijst de eigenschap position daarna naar de byte die volgt op de tekenreeks in de 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
Bij een leesbewerking wordt de eigenschap position verhoogd met het aantal gelezen bytes. 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!
U kunt de eigenschap position instellen op een specifieke locatie in de bytearray om vanaf dat punt te lezen of te schrijven.
De eigenschappen bytesAvailable en length De eigenschappen length en bytesAvailable geven aan hoe lang een bytearray is en hoeveel bytes er aanwezig zijn vanaf de huidige positie tot het einde. In het volgende voorbeeld ziet u hoe u deze eigenschappen kunt gebruiken. In het voorbeeld wordt een tekenreeks met tekst naar de bytearray geschreven en worden vervolgens alle bytes in de array een voor een gelezen totdat het teken ‘a’ of het einde (bytesAvailable <= 0) wordt aangetroffen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 160 Werken met bytearrays
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 }
De eigenschap endian Getallen die uit meerdere bytes bestaan (getallen die in meer dan 1 byte geheugen worden opgeslagen), kunnen op verschillende manieren op computers worden opgeslagen. Een geheel getal kan bijvoorbeeld 4 bytes (32 bits) geheugen in beslag nemen. Op sommige computers wordt de meest significante byte van het getal eerst opgeslagen, op het laagste geheugenadres, en op andere wordt de minst significante byte eerst opgeslagen. Dit kenmerk van een computer (de bytevolgorde) wordt big endian (meest significante byte eerst) of little endian (minst significante byte eerst) genoemd. Het getal 0x31323334 wordt bijvoorbeeld als volgt opgeslagen bij de bytevolgorde big endian en little endian, waarbij a0 het laagste geheugenadres van de 4 bytes is en a3 het hoogste: Big Endian
Big Endian
Big Endian
Big Endian
a0
a1
a2
a3
31
32
33
34
Little Endian
Little Endian
Little Endian
Little Endian
a0
a1
a2
a3
34
33
32
31
Met de eigenschap endian van de klasse ByteArray kunt u deze bytevolgorde aangeven voor getallen die uit meerdere bytes bestaan. De geaccepteerde waarden voor deze eigenschap zijn "bigEndian" en "littleEndian" en in de klasse Endian zijn de constanten BIG_ENDIAN en LITTLE_ENDIAN gedefinieerd om deze tekenreeksen in te stellen voor de eigenschap endian.
De methoden compress() en uncompress() Met de methode compress() kunt u een bytearray comprimeren volgens een compressiealgoritme die u opgeeft als een parameter. Met de methode uncompress() kunt u een bytearray decomprimeren volgens een compressiealgoritme. Nadat u compress() en uncompress() hebt opgeroepen, wordt de lengte van de bytearray ingesteld op de nieuwe lengte en wordt de eigenschap position ingesteld op het einde. In de klasse CompressionAlgorithm zijn constanten gedefinieerd waarmee u de compressiealgoritme kunt opgeven. In AIR worden zowel de Deflate- als de ZLIB-algoritme ondersteund. De Deflate-compressiealgoritme wordt gebruikt in diverse compressie-indelingen, zoals ZLIB, GZIP en enkele ZIP-implementaties. De gecomprimeerde ZLIBgegevensindeling wordt beschreven in http://www.ietf.org/rfc/rfc1950.txt en de Deflate-compressiealgoritme wordt beschreven in http://www.ietf.org/rfc/rfc1951.txt. In het volgende voorbeeld wordt een bytearray met de naam bytes gecomprimeerd met de Deflate-algoritme:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 161 Werken met bytearrays
bytes.compress(CompressionAlgorithm.DEFLATE);
In het volgende voorbeeld wordt een gecomprimeerde bytearray gedecomprimeerd met de Deflate-algoritme: bytes.uncompress(CompressionAlgorithm.DEFLATE);
Objecten lezen en schrijven Met de methoden readObject() en writeObject() leest u een object in een bytearray en schrijft u een object naar een bytearray, gecodeerd in geserialiseerde AMF-indeling (Action Message Format). AMF is een berichtenprotocol dat door Adobe is gemaakt en wordt gebruikt door diverse ActionScript 3.0-klassen, zoals Netstream, NetConnection, NetStream, LocalConnection en Shared Objects. Een typemarkering van één byte bevat de beschrijving van het type van de gecodeerde gegevens die volgen. AMF gebruikt de volgende 13 gegevenstypen: 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
De gecodeerde gegevens volgen op de typemarkering, tenzij de markering één mogelijke waarde bevat, zoals null of true of false, zodat verder niets wordt gecodeerd. Er zijn twee versies van AMF: AMF0 en AMF3. AMF 0 ondersteunt het verzenden van complexe objecten via verwijzingen en staat eindpunten toe voor het herstellen van objectrelaties. AMF 3 is verbeterd ten opzichte van AMF 0 doordat naast objectverwijzingen ook objectkenmerken en tekenreeksen kunnen worden verzonden en nieuwe gegevenstypen worden ondersteund die in ActionScript 3.0 zijn geïntroduceerd. De eigenschap ByteArray.objectEcoding geeft aan welke versie van AMF wordt gebruikt om de objectgegevens te coderen. In de klasse flash.net.ObjectEncoding zijn constanten gedefinieerd waarmee de AMF-versie wordt opgegeven: ObjectEncoding.AMF0 en ObjectEncoding.AMF3. import flash.filesystem.*; import flash.utils.ByteArray; // Label component must be in Library import fl.controls.Label;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 162 Werken met bytearrays
var bytes:ByteArray = new ByteArray(); var myLabel:Label = new Label(); myLabel.move(150, 150); myLabel.width = 200; addChild(myLabel); var myXML:XML =
- <menuName>burger <price>3.95
- <menuName>fries <price>1.45
// 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(); }
Met de methode readObject() wordt een object in geserialiseerde AMF-indeling ingelezen vanuit een bytearray en opgeslagen in een object van het opgegeven type. In het volgende voorbeeld wordt het bestand order vanaf de desktop ingelezen in een bytearray (inBytes). Vervolgens wordt het bestand gedecomprimeerd en wordt readObject() opgeroepen om het op te slaan in het XML-object orderXML. In het voorbeeld wordt elk knooppunt in een lusconstructie for each() toegevoegd aan een tekstgebied voor weergave. In het voorbeeld wordt ook de waarde van de eigenschap objectEncoding weergegeven, evenals een header voor de inhoud van het bestand order. import flash.filesystem.*; import flash.utils.ByteArray; // TextArea component must be in Library import fl.controls.TextArea;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 163 Werken met bytearrays
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(); }
Voorbeeld van een bytearray: een ZIP-bestand lezen In dit voorbeeld ziet u hoe een eenvoudig ZIP-bestand wordt gelezen dat verschillende typen bestanden bevat. Hiervoor worden relevante gegevens uit de metagegevens van elk bestand opgehaald, waarbij elk bestand in een bytearray wordt gedecomprimeerd en naar de desktop wordt geschreven. De algemene structuur van een ZIP-bestand is gebaseerd op de specificatie van PKWARE Inc., die u kunt vinden op http://www.pkware.com/documents/casestudies/APPNOTE.TXT. Eerst staan er een bestandsheader en bestandsgegevens voor het eerste bestand in het ZIP-bestand, gevolgd door een combinatie van een bestandsheader en bestandsgegevens voor elk ander bestand. (De structuur van de bestandsheader wordt later beschreven.) Daarna bevat het ZIP-bestand eventueel een record met een gegevensdescriptor (gewoonlijk wanneer het ZIP-bestand in het geheugen is gemaakt in plaats van opgeslagen op een schijf). Hierna volgen diverse optionele elementen: decoderingsheader van archief, extra gegevensrecord voor archief, centrale mapstructuur, Zip64-einde van centrale maprecord, Zip64-einde van centrale maplocator en het einde van de centrale maprecord. De code in dit voorbeeld is alleen geschreven om ZIP-bestanden te parseren die geen mappen bevatten en er worden geen records met een gegevensdescriptor verwacht. Alle informatie na de laatste bestandsgegevens wordt genegeerd. De bestandsheader voor elk bestand heeft de volgende indeling:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 164 Werken met bytearrays
handtekening van bestandsheader
4 bytes
vereiste versie
2 bytes
algemene bitvlag
2 bytes
compressiemethode
2 bytes (8=DEFLATE; 0=UNCOMPRESSED)
tijd van laatste bestandswijziging
2 bytes
datum van laatste bestandswijziging
2 bytes
crc-32
4 bytes
gecomprimeerde grootte
4 bytes
ongecomprimeerde grootte
4 bytes
lengte van bestandsnaam
2 bytes
lengte van extra veld
2 bytes
bestandsnaam
variabele
extra veld
variabele
Na de bestandsheader volgen de werkelijke bestandsgegevens die gecomprimeerd of niet kunnen zijn, afhankelijk van de vlag voor de compressiemethode. De vlag is 0 (nul) als de bestandsgegevens niet zijn gecomprimeerd, 8 als de gegevens zijn gecomprimeerd met de Deflate-algoritme of een andere waarde voor andere compressiealgoritmen. De gebruikersinterface voor dit voorbeeld bestaat uit een label en een tekstgebied (taFiles). De toepassing schrijft de volgende informatie naar het tekstgebied voor elk bestand dat in het ZIP-bestand wordt aangetroffen: bestandsnaam, gecomprimeerde grootte en niet-gecomprimeerde grootte. Aan het begin van het programma worden de volgende taken uitgevoerd:
• De vereiste klassen worden geïmporteerd. import flash.filesystem.*; import flash.utils.ByteArray; import flash.events.Event;
• De gebruikersinterface wordt gedefinieerd. 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);
• De bytearray bytes wordt gedefinieerd. var bytes:ByteArray = new ByteArray();
• Er worden variabelen gedefinieerd voor het opslaan van metagegevens uit de bestandsheader.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 165 Werken met bytearrays
// 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;
• De objecten File (zfile) en FileStream (zStream) worden gedefinieerd voor het ZIP-bestand en de locatie wordt opgegeven van het ZIP-bestand waaruit de bestanden worden opgehaald: een bestand met de naam “HelloAIR.zip” in de desktopmap. // File variables for accessing .zip file var zfile:File = File.desktopDirectory.resolvePath("HelloAIR.zip"); var zStream:FileStream = new FileStream();
Het programma begint met het openen van het ZIP-bestand in de leesmodus. zStream.open(zfile, FileMode.READ);
Vervolgens wordt de eigenschap endian van bytes op LITTLE_ENDIAN ingesteld om aan te geven dat de minst significante byte eerst wordt aangegeven in de bytevolgorde van numerieke velden. bytes.endian = Endian.LITTLE_ENDIAN;
Vervolgens wordt met de instructie while() een lus gestart die wordt uitgevoerd tot de huidige positie in de bestandsstroom groter is dan of gelijk is aan de grootte van het bestand. while (zStream.position < zfile.size) {
Met de eerste instructie in de lus worden de eerste 30 bytes van de bestandsstroom ingelezen in de bytearray bytes. De eerste 30 bytes bevatten het gedeelte van de eerste bestandsheader dat een vaste grootte heeft. // read fixed metadata portion of local file header zStream.readBytes(bytes, 0, 30);
Vervolgens wordt een geheel getal (signature) gelezen uit de eerste bytes van de header die uit 30 bytes bestaat. In de definitie van de ZIP-indeling is opgegeven dat de handtekening voor elke bestandsheader de hexadecimale waarde 0x04034b50 heeft; als de handtekening anders is, betekent dit dat het einde van het bestandsgedeelte van het ZIPbestand is bereikt en dat er geen bestanden meer zijn om uit te pakken. In dat geval wordt de while-lus onmiddellijk beëindigd en wordt niet gewacht tot het einde van de bytearray is bereikt. bytes.position = 0; signature = bytes.readInt(); // if no longer reading data files, quit if (signature != 0x04034b50) { break; }
In het volgende deel van de code wordt de headerbyte op positie 8 gelezen en wordt de waarde opgeslagen in de variabele compMethod. Deze byte bevat een waarde die aangeeft met welke compressiemethode dit bestand is gecomprimeerd. Er zijn diverse compressiemethoden toegestaan, maar in de praktijk gebruiken bijna alle ZIPbestanden de Deflate-compressiealgoritme. Als het huidige bestand is gecomprimeerd met Deflate-compressie, is compMethod 8; als het bestand niet is gecomprimeerd, is compMethod 0.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 166 Werken met bytearrays
bytes.position = 8; compMethod = bytes.readByte();
// store compression method (8 == Deflate)
Na de eerste 30 bytes volgt een gedeelte van de header met een variabele lengte dat de bestandsnaam en eventueel een extra veld bevat. In de variabele offset is de grootte van dit gedeelte opgeslagen. De grootte wordt berekend door de lengte van de bestandsnaam en de lengte van het extra veld op te tellen. Deze waarden worden ingelezen uit de header op positie 26 en 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
Vervolgens wordt uit het gedeelte van de bestandsheader met variabele lengte het aantal bytes ingelezen dat is opgeslagen in de variabele offset. // read variable length bytes between fixed-length header and compressed file data zStream.readBytes(bytes, 30, offset);
De bestandsnaam wordt ingelezen vanuit het gedeelte van de header met variabele lengte en samen met de gecomprimeerde en niet-gecomprimeerde (oorspronkelijke) grootte van het bestand weergegeven in het tekstgebied. 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');
In het voorbeeld wordt de rest van het bestand vanuit de bestandsstroom ingelezen in bytes voor de lengte die is opgegeven door de gecomprimeerde grootte, waarbij de bestandsheader in de eerste 30 bytes wordt overschreven. De gecomprimeerde grootte is nauwkeurig, zelfs als het bestand niet is gecomprimeerd, omdat de gecomprimeerde grootte in dat geval gelijk is aan de niet-gecomprimeerde grootte van het bestand. // read compressed file to offset 0 of bytes; for uncompressed files // the compressed and uncompressed size is the same zStream.readBytes(bytes, 0, compSize);
Vervolgens wordt het gecomprimeerde bestand gedecomprimeerd en wordt de functie outfile() opgeroepen om het naar de uitvoerstroom te schrijven. De bestandsnaam en de bytearray die de bestandsgegevens bevat, worden doorgegeven aan outfile(). if (compMethod == 8) // if file is compressed, uncompress { bytes.uncompress(CompressionAlgorithm.DEFLATE); } outFile(fileName, bytes); // call outFile() to write out the file
De accolade-sluiten geeft het einde van de while-lus en van de toepassingscode aan, maar niet van de methode outFile(). De while-lus wordt opnieuw gestart en de volgende bytes in het ZIP-bestand worden verwerkt: er wordt een ander bestand uitgepakt of de verwerking van het ZIP-bestand wordt beëindigd als het laatste bestand is verwerkt. } // end of while loop
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 167 Werken met bytearrays
Met de functie outfile() wordt in de schrijfmodus op de desktop een uitvoerbestand geopend dat de naam krijgt die is opgegeven met de parameterfilename. Vervolgens wordt het gegevensbestand vanuit de parameter data naar de uitvoerstroom (outStream) geschreven en wordt het bestand gesloten. 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(); }
168
Hoofdstuk 18: Werken met lokale SQLdatabases Adobe AIR biedt de mogelijkheid om lokale SQL-databases te maken en te gebruiken. De runtime bevat een SQLdatabase-engine met ondersteuning voor vele standaardfuncties van SQL via het open-source databasesysteem SQLite. U kunt een lokale SQL-database gebruiken om lokale, niet-vluchtige gegevens op te slaan, bijvoorbeeld toepassingsgegevens, gebruikersinstellingen voor toepassingen, documenten of een willekeurig ander gegevenstype dat uw toepassing lokaal moet opslaan.
Aanvullende online informatie over lokale SQLdatabases In deze bronnen vindt u meer informatie over het werken met lokale SQL-databases: Snelstarthandleidingen (Adobe AIR Developer Connection) Language Reference • SQLCollationType
• SQLColumnNameStyle • SQLColumnSchema • SQLConnection • SQLError • SQLErrorEvent • SQLErrorOperation • SQLEvent • SQLIndexSchema • SQLMode • SQLResult • SQLSchema • SQLSchemaResult • SQLStatement • SQLTableSchema • SQLTransactionLockType • SQLTriggerSchema • SQLUpdateEvent • SQLViewSchema
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 169 Werken met lokale SQL-databases
Adobe Developer Connection - Artikels en voorbeelden • Adobe AIR Developer Connection for Flash (zoek naar ‘AIR SQL’)
Informatie over lokale SQL-databases Adobe AIR bevat een op SQL gebaseerde engine voor relationele databases die binnen de runtime wordt uitgevoerd. De gegevens worden lokaal opgeslagen in databasebestanden op de computer waarop de AIR-toepassing wordt uitgevoerd (bijvoorbeeld de vaste schijf van de computer). Aangezien de database lokaal wordt uitgevoerd en de gegevensbestanden lokaal worden opgeslagen, kan een database altijd door een AIR-toepassing worden gebruikt, ongeacht of een netwerkverbinding aanwezig is. Dit betekent dat de lokale SQL-database-engine van de runtime een handige manier is om niet-vluchtige, lokale toepassingsgegevens op te slaan, met name als u ervaring hebt met SQLen relationele databases.
Toepassingen voor lokale SQL-databases De AIR-functies voor lokale SQL-databases kunnen worden gebruikt voor willekeurige toepassingen waarbij toepassingsgegevens moeten worden opgeslagen op de lokale computer van de gebruiker. Adobe AIR biedt verschillende manieren om gegevens lokaal op te slaan, waarbij elke manier andere voordelen heeft. Hieronder ziet u een aantal mogelijke toepassingen voor een lokale SQL-database in uw AIR-toepassing:
• Voor een op gegevens gebaseerde toepassing (bijvoorbeeld een adresboek) kunt u een database gebruiken om de hoofdtoepassingsgegevens op te slaan.
• Voor een op documenten gebaseerde toepassing (waarbij gebruikers documenten creëren om ze op te slaan en mogelijk te delen) kan elk document als een databasebestand worden opgeslagen op een door de gebruiker opgegeven locatie. (Let op: aangezien een willekeurige AIR-toepassing het databasebestand kan openen, wordt u aangeraden codering te gebruiken voor mogelijk vertrouwelijke documenten.)
• Voor een toepassing met netwerkverbindingen kunt u een database gebruiken om toepassingsgegevens op te slaan in een lokale cache, of om gegevens tijdelijk op te slaan wanneer er geen netwerkverbinding beschikbaar is. U kunt desgewenst een procedure creëren om de lokale database te synchroniseren met de netwerklocatie voor gegevensopslag.
• Voor alle toepassingen kunt u een database gebruiken om de toepassingsinstellingen van individuele gebruikers op te slaan, bijvoorbeeld gebruikersopties of toepassingsinformatie zoals venstergrootte en -positie.
Informatie over AIR-databases en databasebestanden Een individuele, lokale SQL-database van Adobe AIR wordt als één bestand opgeslagen in het bestandssysteem van de computer. De runtime bevat de SQL-database-engine die het creëren en indelen van databasebestanden, en het bewerken en ophalen van gegevens in een databasebestand beheert. De runtime geeft niet aan hoe of waar de databasegegevens worden opgeslagen in het bestandssysteem - elke database bestaat uit één bestand. U geeft de locatie voor het databasebestand in het bestandssysteem op. Eén AIR-toepassing kan een of meer databases (met andere woorden aparte databasebestanden) benaderen. Aangezien de runtime elke database als één bestand opslaat in het bestandssysteem, kunt u de locatie van uw database afstemmen op het ontwerp van uw toepassing en de toegangsbeperkingen van het besturingssysteem. Iedere gebruiker kan een apart databasebestand voor zijn/haar specifieke gegevens hebben, of u kunt één databasebestand voor alle gebruikers van de toepassing op één computer plaatsen zodat de gegevens kunnen worden gedeeld. Aangezien de gegevens zich lokaal op één computer bevinden, worden de gegevens niet automatisch gedeeld met gebruikers op andere computers. De lokale SQL-database-engine biedt geen mogelijkheid om SQL-instructies uit te voeren in een externe of servergebaseerde database.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 170 Werken met lokale SQL-databases
Informatie over relationele databases Een relationele database is een mechanisme voor het opslaan (en ophalen) van gegevens op een computer. De gegevens zijn verdeeld in tabellen: rijen geven records of items weer, en kolommen (worden ook soms “velden” genoemd) verdelen elke record in individuele waarden. Een adresboektoepassing kan bijvoorbeeld een tabel met de naam “vrienden” bevatten. Elke rij van de tabel is dan één vriend die in de database is opgeslagen. De kolommen van de tabel bevatten gegevens zoals voornaam, achternaam, geboortedatum enzovoort. Voor iedere vriendrij van de tabel slaat de database een aparte waarde voor elke kolom op. Relationele databases zijn ontworpen voor de opslag van complexe gegevens, waarbij een item is gekoppeld of gerelateerd aan items van een ander type. In een relationele database worden gegevens met een één-op-vele-relatie (waarbij één record kan zijn gekoppeld aan meerdere records van een ander type) doorgaans verdeeld over verschillende tabellen. Als u bijvoorbeeld uw adresboektoepassing wilt gebruiken om voor iedere vriend meerdere telefoonnummers op te slaan, is dat een één-op-vele-relatie. De tabel “vrienden” bevat in dat geval alle persoonlijke gegevens van iedere vriend. Een andere tabel, “telefoonnummers”, kan dan alle telefoonnummers van alle vrienden bevatten. In de database worden niet alleen de gegevens van vrienden en telefoonnummers opgeslagen. Elke tabel heeft ook een gegevensitem nodig om de relatie tussen de twee tabellen bij te houden, met andere woorden om individuele vriendrecords te koppelen aan de overeenkomstige telefoonnummers. Dit gegevensitem wordt een primaire sleutel genoemd, een unieke identificator die elke tabelrij verschillend maakt van alle overige rijen uit die tabel. De primaire sleutel kan een “natuurlijke sleutel” zijn, waarbij de sleutel een van de gegevensitems is die elke record uit een tabel op een natuurlijke manier uniek maken. Als u in de tabel “vrienden” bijvoorbeeld weet dat al uw vrienden een andere geboortedatum hebben, kunt u de kolom voor de geboortedatum instellen als primaire sleutel (een natuurlijke sleutel) voor de tabel “vrienden”. Als er geen natuurlijke sleutel is, maakt u een aparte kolom voor de primaire sleutel, zoals “id_vriend”, dit is een kunstmatige waarde die door de toepassing wordt gebruikt om de rijen van elkaar te onderscheiden. Met behulp van een primaire sleutel kunt u relaties tussen meerdere tabellen definiëren. De tabel “vrienden” kan bijvoorbeeld een kolom met de naam “id_vriend” hebben, die voor elke rij (iedere vriend) een uniek nummer bevat. De gerelateerde tabel “telefoonnummers” kan in twee kolommen worden verdeeld, één met de “id_vriend” van de vriend die het desbetreffende telefoonnummer heeft, en één met het daadwerkelijke telefoonnummer. Op die manier kunnen alle telefoonnummers, ongeacht het aantal telefoonnummers per vriend, worden opgeslagen in de tabel “telefoonnummers” en via de primaire sleutel “id_vriend” worden gekoppeld aan de overeenkomstige vriend. Wanneer de primaire sleutel van een tabel wordt gebruikt in een gerelateerde tabel om de relatie tussen de records aan te geven, wordt de waarde in de gerelateerde tabel een externe sleutel genoemd. In tegenstelling tot vele databases biedt de lokale database-engine van AIR niet de mogelijkheid om beperkingen voor externe sleutels in te stellen. Deze beperkingen controleren automatisch of een ingevoegde of bijgewerkte externe-sleutelwaarde overeenkomt met een rij in de tabel met de primaire sleutel. Relaties op basis van externe sleutels vormen echter een belangrijk onderdeel van de structuur van een relationele database, en u wordt aangeraden externe sleutels te gebruiken wanneer u relaties tussen de tabellen van uw database definieert.
Informatie over SQL SQL (Structured Query Language) wordt bij relationele databases gebruikt om gegevens te bewerken en te zoeken. SQL is een beschrijvende en geen proceduretaal. Een SQL-instructie beschrijft de gegevensset die u zoekt maar geeft de computer geen instructies over hoe de gegevens moeten worden gezocht. De database-engine bepaalt hoe de gegevens worden gezocht.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 171 Werken met lokale SQL-databases
De taal SQL is gestandaardiseerd door het ANSI (American National Standards Institute). De lokale SQL-database van Adobe AIR ondersteunt het grootste deel van de standaard SQL-92. Zie de bijlage "SQL support in local databases" (SQL-ondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference voor een specifieke beschrijving van de SQL-onderdelen die worden ondersteund in Adobe AIR.
Informatie over klassen van SQL-databases Als u met lokale SQL-databases wilt werken in ActionScript 3.0, moet u instanties van deze klassen uit het pakket flash.data gebruiken: Klasse
Beschrijving
flash.data.SQLConnection
Biedt de mogelijkheid om databases (databasebestanden) te creëren en te openen, evenals methoden voor het uitvoeren van bewerkingen op databaseniveau en het besturen van databasetransacties.
flash.data.SQLStatement
Vertegenwoordigt één SQL-instructie (één query of opdracht) die op een database wordt uitgevoerd, inclusief het definiëren van de instructietekst en het instellen van parameterwaarden.
flash.data.SQLResult
Biedt een manier om informatie over of het resultaat van de uitvoering van een instructie op te vragen, zoals de resulterende rijen na een SELECT-instructie, het aantal rijen dat wordt beïnvloed door een UPDATE- of DELETE-instructie enzovoort.
Als u schema-informatie met een beschrijving van de structuur van een database wilt verkrijgen, moet u deze klassen uit het pakket flash.data gebruiken: Klasse
Beschrijving
flash.data.SQLSchemaResult
Fungeert als container voor databaseschemaresultaten die worden gegenereerd door het oproepen van de methode SQLConnection.loadSchema().
flash.data.SQLTableSchema
Biedt informatie over één tabel van een database.
flash.data.SQLViewSchema
Biedt informatie over één weergave van een database.
flash.data.SQLIndexSchema
Biedt informatie over één kolom van een tabel of één weergave van een database.
flash.data.SQLTriggerSchema Biedt informatie over één trigger van een database.
Andere klassen uit het pakket flash.data bieden constanten die worden gebruikt met de klassen SQLConnection en SQLColumnSchema: Klasse
Beschrijving
flash.data.SQLMode
Definieert een set van constanten voor de mogelijke waarden van de parameter openMode van de methoden SQLConnection.open() en SQLConnection.openAsync().
flash.data.SQLColumnNameStyle
Definieert een set van constanten voor de mogelijke waarden van de eigenschap SQLConnection.columnNameStyle.
flash.data.SQLTransactionLockType
flash.data.SQLCollationType
Definieert een set van constanten voor de mogelijke waarden van de optieparameter van de methode SQLConnection.begin(). Definieert een set van constanten voor de mogelijke waarden van de eigenschap SQLColumnSchema.defaultCollationType en de parameter defaultCollationType van de constructor SQLColumnSchema().
Daarnaast vertegenwoordigen de volgende klassen uit het pakket flash.events de gebeurtenissen (en ondersteunende constanten) die u gebruikt:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 172 Werken met lokale SQL-databases
Klasse
Beschrijving
flash.data.SQLEvent
Definieert de gebeurtenissen die door een SQLConnection- of SQLStatement-instantie worden verzonden wanneer een of meer bewerkingen uit de instantie met succes zijn uitgevoerd. Voor elke bewerking is een gekoppelde gebeurtenistypeconstante gedefinieerd in de klasse SQLEvent.
flash.data.SQLErrorEvent
Definieert de gebeurtenis die door een SQLConnection- of SQLStatement-instantie wordt verzonden wanneer een of meer bewerkingen uit de instantie een fout opleveren.
flash.data.SQLUpdateEvent
Definieert de gebeurtenis die door een SQLConnection-instantie wordt verzonden wanneer tabelgegevens in een van de gekoppelde databases veranderen door de uitvoering van de SQL-instructie INSERT, UPDATE of DELETE.
Ten slotte bieden de volgende klassen uit het pakket flash.errors informatie over bewerkingsfouten in de database: Klasse
Beschrijving
flash.data.SQLError
Biedt informatie over een bewerkingsfout in de database, zoals de bewerking die is mislukt en de oorzaak van de fout.
flash.data.SQLErrorEvent
Definieert een set van constanten voor de mogelijke waarden van de eigenschap operation van de klasse SQLError, die de databasebewerking aangeeft waarbij de fout is opgetreden.
Informatie over synchrone en asynchrone uitvoeringsmodi Wanneer u code schrijft om met een lokale SQL-database te werken, selecteert u een van de twee beschikbare uitvoeringsmodi voor bewerkingen in de database: synchroon of asynchroon. De codevoorbeelden tonen op algemene manier hoe u elke bewerking op beide manieren kunt uitvoeren zodat u het voorbeeld kunt gebruiken dat het meest geschikt is voor uw behoeften. In asynchrone uitvoeringsmodus geeft u de runtime een instructie, waarna de runtime een gebeurtenis verzendt wanneer de desbetreffende bewerking is voltooid of mislukt. Eerst geeft u de database-engine de opdracht een bewerking uit te voeren. De database-engine werkt op de achtergrond terwijl de toepassing verderwerkt. Wanneer ten slotte de bewerking is voltooid (of mislukt), verzendt de database-engine een gebeurtenis. Uw code, geactiveerd door de gebeurtenis, voert indien nodig daarop volgende bewerkingen uit. Deze procedure heeft een groot voordeel: de runtime voert de databasebewerkingen op de achtergrond uit terwijl de hoofdtoepassingscode verder wordt uitgevoerd. Als de databasebewerking lange tijd duurt, blijft de toepassing verderwerken. En het belangrijkste is dat interactie met de gebruiker mogelijk blijft omdat het scherm niet bevriest. Het nadeel is dat asynchrone bewerkingscode soms complexer is om te schrijven. Dit is doorgaans het geval wanneer meerdere afhankelijke bewerkingen moeten worden verdeeld tussen verschillende gebeurtenislistenermethoden. Conceptueel is het eenvoudiger om bewerkingen als één sequentie van stappen (een set van synchrone bewerkingen) te beschrijven in plaats van als een set van bewerkingen verdeeld in meerdere gebeurtenislistenermethoden. Naast asynchrone databasebewerkingen is met Adobe AIR ook het synchroon uitvoeren van databasebewerkingen mogelijk. In de synchrone uitvoeringsmodus worden de bewerkingen niet op de achtergrond uitgevoerd. In plaats daarvan worden ze uitgevoerd volgens dezelfde uitvoeringssequentie als alle andere toepassingscode. U geeft de databaseengine de opdracht een bewerking uit te voeren. Vervolgens wordt de code op dat punt onderbroken terwijl de database-engine zijn werk doet. Nadat de bewerking is voltooid, gaat de uitvoering verder vanaf de volgende regel van uw code.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 173 Werken met lokale SQL-databases
U bepaalt op SQLConnection-niveau welke uitvoeringsmodus (synchroon of asynchroon) voor bewerkingen wordt gebruikt. Het is niet mogelijk om via één enkele databaseverbinding bepaalde bewerkingen of instructies synchroon en andere asynchroon uit te voeren. U bepaalt welke uitvoeringsmodus (synchroon of asynchroon) voor een SQLConnection wordt gebruikt door een SQLConnection-methode op te roepen om de database te openen. Als u SQLConnection.open() oproept, werkt de verbinding in synchrone uitvoeringsmodus. Roept u SQLConnection.openAsync() op, dan werkt de verbinding in asynchrone uitvoeringsmodus. Nadat een SQLConnection-instantie met een database is verbonden met behulp van open() of openAsync(), wordt deze in synchrone of asynchrone uitvoeringsmodus vergrendeld, tenzij u de verbinding met de database sluit en weer opent. Elke uitvoeringsmodus heeft specifieke voordelen. De meeste aspecten van beide modi zijn identiek. Er zijn echter bepaalde verschillen waarmee u het best rekening houdt terwijl u in een bepaalde modus werkt. Zie “Synchrone en asynchrone databasebewerkingen gebruiken” op pagina 194 voor meer informatie over deze onderwerpen en suggesties voor het werken in elke modus.
Databases creëren en wijzigen Voordat uw toepassing gegevens kan toevoegen of ophalen, moet er een database met gedefinieerde tabellen aanwezig zijn en moet de database toegankelijk zijn voor uw toepassing. Hieronder wordt beschreven hoe u een database creëert en de gegevensstructuur binnen een database definieert. Deze taken zijn weliswaar minder vaak nodig dan het invoegen en ophalen van gegevens maar zijn toch noodzakelijk voor de meeste toepassingen.
Database creëren Voordat u een databasebestand kunt creëren, moet u een SQLConnection-instantie creëren. Roep de methode open() op om de instantie in synchrone uitvoeringsmodus te openen, of roep de methode openAsync() op om de instantie in asynchrone uitvoeringsmodus te openen. De methoden open() en openAsync() worden gebruikt om een verbinding met een database te openen. Als u een File-instantie gebruikt die verwijst naar een niet-bestaande bestandslocatie voor de parameter reference (de eerste parameter), creëert de methode open() of openAsync() een databasebestand op die bestandslocatie en wordt een verbinding met de zojuist gecreëerde database geopend. De naam van het databasebestand mag altijd een willekeurige geldige bestandsnaam met een willekeurige bestandsextensie zijn, ongeacht de methode die u oproept (open() of openAsync()). Als u de methode open() of openAsync() oproept met de instelling null voor de parameterreference, wordt een nieuwe database in het geheugen gecreëerd in plaats van een databasebestand op de vaste schijf. De volgende code illustreert het creëren van een databasebestand (een nieuwe database) via de asynchrone uitvoeringsmodus. In dit geval wordt het databasebestand met de bestandsnaam “DBSample.db” opgeslagen in de opslagdirectory van de toepassing:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 174 Werken met lokale SQL-databases
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); }
Als u bewerkingen synchroon wilt uitvoeren, roept u de methode open() op wanneer u een databaseverbinding opent met de SQLConnection-instantie. In het volgende voorbeeld ziet u hoe u een SQLConnection-instantie creëert en opent die de bewerkingen synchroon uitvoert: import flash.data.SQLConnection; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; 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); }
Databasetabellen creëren Als u een tabel in een database wilt creëren, moet u een SQL-instructie op de desbetreffende database uitvoeren via dezelfde procedure als voor het uitvoeren van een SQL-instructie zoals SELECT, INSERT enzovoort. U creëert een tabel met behulp van de instructie CREATE TABLE, waarbij u kolomdefinities en beperkingen voor de nieuwe tabel opgeeft. Zie “Werken met SQL-instructies” op pagina 177 voor meer informatie over het uitvoeren van SQL-instructies. In het volgende voorbeeld ziet u hoe u een tabel met de naam “employees” in een bestaand databasebestand creëert via de asynchrone uitvoeringsmodus. Let op: deze code gaat ervan uit dat een SQLConnection-instantie met de naam conn al is gedefinieerd en met een database is verbonden.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 175 Werken met lokale SQL-databases
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); }
In het volgende voorbeeld ziet u hoe u een tabel met de naam “employees” in een bestaand databasebestand creëert via de synchrone uitvoeringsmodus. Let op: deze code gaat ervan uit dat een SQLConnection-instantie met de naam conn al is gedefinieerd en met een database is verbonden. 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; try { createStmt.execute(); trace("Table created"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 176 Werken met lokale SQL-databases
Werken met SQL-databasegegevens Bij het werken met lokale SQL-databases voert u regelmatig dezelfde taken uit, zoals het verbinden met een database, en het toevoegen van gegevens aan en ophalen van gegevens uit tabellen in een database. Bij het uitvoeren van deze taken moet u een aantal aspecten in acht nemen, zoals het werken met gegevenstypen en het verhelpen van fouten. Daarnaast zijn er verschillende databasetaken die u niet zo vaak zult uitvoeren maar doorgaans wel voordat u de veel voorkomende taken kunt uitvoeren. U moet bijvoorbeeld een database creëren en de structuur van de tabellen in de database definiëren voordat u kunt verbinden met de database en gegevens uit tabellen kunt ophalen. Deze minder frequente, initiële setuptaken worden besproken in “Databases creëren en wijzigen” op pagina 173. U kunt kiezen om databasebewerkingen asynchroon uit te voeren, wat betekent dat de database-engine op de achtergrond wordt uitgevoerd en deze u meldt wanneer de bewerking is voltooid (of mislukt) door een gebeurtenis te verzenden. U kunt deze bewerkingen echter ook synchroon uitvoeren. In dat geval worden de databasebewerkingen na elkaar uitgevoerd en wacht de hele toepassing (ook het vernieuwen van het scherm) tot de bewerkingen zijn voltooid voordat andere code wordt uitgevoerd. In de voorbeelden in deze sectie ziet u hoe u de bewerkingen synchroon en asynchroon kunt laten uitvoeren. Zie “Synchrone en asynchrone databasebewerkingen gebruiken” op pagina 194 voor meer informatie over het werken in synchrone of asynchrone uitvoeringsmodus.
Verbinden met een database Voordat u databasebewerkingen kunt uitvoeren, moet u een verbinding met het databasebestand tot stand brengen. Er wordt een SQLConnection-instantie gebruikt om de verbinding met een of meer databases te vertegenwoordigen. De eerste database waarmee u via een SQLConnection-instantie verbinding maakt, wordt de “hoofd”database genoemd. Met deze database maakt u verbinding via de methode open() (voor de synchrone uitvoeringsmodus) of openAsync() (voor de asynchrone uitvoeringsmodus). Als u een database opent via de bewerking openAsync(), moet u de gebeurtenis open van de SQLConnectioninstantie registreren zodat u een melding ontvangt wanneer de bewerking openAsync() is voltooid. Deze registratie is nodig als u wilt dat de gebeurtenis error van de SQLConnection-instantie controleert of de bewerking is voltooid/mislukt. In het volgende voorbeeld ziet u hoe u een bestaand databasebestand opent voor asynchrone uitvoering. Het databasebestand heeft de naam “DBSample.db” en bevindt zich in de toepassingsopslagdirectory van de gebruiker. 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); }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 177 Werken met lokale SQL-databases
In het volgende voorbeeld ziet u hoe u een bestaand databasebestand opent voor synchrone uitvoering. Het databasebestand heeft de naam “DBSample.db” en bevindt zich in de toepassingsopslagdirectory van de gebruiker. 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(); 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); }
Let op: bij het oproepen van de methode openAsync() in het asynchrone voorbeeld en het oproepen van de methode open() in het synchrone voorbeeld is het tweede argument de constante SQLMode.UPDATE. Als u SQLMode.UPDATE opgeeft voor de tweede parameter (openMode), treedt een fout op als het opgegeven bestand niet bestaat. Als u SQLMode.CREATE opgeeft voor de parameter openMode (of als u geen waarde opgeeft voor de parameter openMode), probeert de runtime een databasebestand te creëren als het opgegeven bestand niet bestaat. U kunt ook SQLMode.READ opgeven voor de parameter openMode als u een bestaande database in alleen-lezen modus wilt openen. In dat geval kunnen gegevens uit de database worden opgehaald maar niet worden toegevoegd, verwijderd of gewijzigd.
Werken met SQL-instructies Een individuele SQL-instructie (een query of opdracht) wordt in de runtime vertegenwoordigd door een SQLStatement-object. Ga als volgt te werk om een SQL-instructie te creëren en uit te voeren: Creëer een SQLStatement-instantie. Het SQLStatement-object vertegenwoordigt de SQL-instructie in uw toepassing. var selectData:SQLStatement = new SQLStatement();
Geef de database op waarop u de query wilt toepassen. Hiervoor stelt u de eigenschap sqlConnection van het SQLStatement-object in op de SQLConnection-instantie die met de gewenste database is verbonden. // A SQLConnection named "conn" has been created previously selectData.sqlConnection = conn;
Geef de daadwerkelijke SQL-instructie op. Creëer de instructietekst als een tekenreeks (String) en wijs deze toe aan de eigenschap text van de SQLStatementinstantie. selectData.text = "SELECT col1, col2 FROM my_table WHERE col1 = :param1";
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 178 Werken met lokale SQL-databases
Definieer functies om het resultaat van de uitvoeringsbewerking (alleen asynchrone uitvoeringsmodus) te verwerken. Gebruik de methode addEventListener() om functies als listeners voor de gebeurtenissen result en error van de SQLStatement-instantie te registreren. // 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 }
U kunt ook listenermethoden opgeven met behulp van een Responder-object. In dat geval creëert u de Responderinstantie en koppelt u de listenermethoden aan die instantie. // 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 }
Als de instructietekst parameterdefinities bevat, wijst u waarden toe aan de desbetreffende parameters. U wijst parameterwaarden toe via de associatieve-array-eigenschap parameters van de SQLStatement-instantie. selectData.parameters[":param1"] = 25;
Voer de SQL-instructie uit. Roep de methode execute() van de SQLStatement-instantie op. // using synchronous execution mode // or listener methods in asynchronous execution mode selectData.execute();
Als u een Responder in plaats van gebeurtenislisteners gebruikt in asynchrone uitvoeringsmodus, moet u ook de Responder-instantie opgeven voor de methode execute(). // using a Responder in asynchronous execution mode selectData.execute(-1, selectResponder);
Zie de volgende onderwerpen voor specifieke voorbeelden die deze procedurestappen illustreren: “Gegevens ophalen uit een database” op pagina 181 “Gegevens invoegen” op pagina 187 “Gegevens wijzigen of verwijderen” op pagina 190
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 179 Werken met lokale SQL-databases
Parameters gebruiken in instructies Met een SQL-instructieparameter kunt u een herbruikbare SQL-instructie creëren. Bij het gebruik van instructieparameters kunnen waarden binnen de instructie wijzigen (zoals waarden die worden toegevoegd met een instructie van het type INSERT) maar blijft de basistekst van de instructie ongewijzigd. Dit verbetert de prestaties en vergemakkelijkt het schrijven van code voor een toepassing.
Instructieparameters Een toepassing gebruikt vaak dezelfde SQL-instructie meerdere keren, met slechts een kleine wijziging. Bijvoorbeeld: een voorraadbeheertoepassing waarmee een gebruiker nieuwe voorraaditems kan toevoegen aan de database. De toepassingscode die een voorraaditem toevoegt aan de database voert de SQL-instructie INSERT uit, waarmee de gegevens daadwerkelijk worden toegevoegd aan de database. Elke keer dat de instructie wordt uitgevoerd, is er echter een kleine wijziging. Met name de daadwerkelijke waarden die worden ingevoegd in de tabel, verschillen omdat ze specifiek zijn voor het voorraaditem dat wordt toegevoegd. Als een SQL-instructie meerdere keren maar met verschillende waarden wordt gebruikt, wordt u aangeraden een SQLinstructie te gebruiken die met parameters werkt en niet met literale waarden in de SQL-tekst. Een parameter is een placeholder in de instructietekst die door een daadwerkelijke waarde wordt vervangen elke keer dat de instructie wordt uitgevoerd. Als u parameters in een SQL-instructie wilt gebruiken, creëert u de SQLStatement-instantie op de gewone manier. Voor de daadwerkelijke SQL-instructie die aan de eigenschap text wordt toegewezen, gebruikt u parameterplaceholders in plaats van literale waarden. Vervolgens definieert u de waarde voor elke parameter door de waarde van een element in de eigenschap parameters van de SQLStatement-instantie in te stellen. Aangezien de eigenschap parameters een associatieve array is, stelt u een specifieke waarde in met de volgende syntaxis: statement.parameters[parameter_identifier] = value;
parameter_identifier is een tekenreeks als u een benoemde parameter gebruikt, of een index van gehele getallen als u een onbenoemde parameter gebruikt.
Benoemde parameters gebruiken Een parameter kan benoemd zijn. Een benoemde parameter heeft een specifieke naam die door de database wordt gebruikt om de parameterwaarde te koppelen aan de overeenkomstige placeholderlocatie in de instructietekst. De naam van een parameter bestaat uit het teken “:” of “@” gevolgd door een naam, zoals in de volgende voorbeelden wordt geïllustreerd: :itemName @firstName
De volgende code illustreert het gebruik van benoemde parameters: 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();
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 180 Werken met lokale SQL-databases
Onbenoemde parameters gebruiken Als alternatief voor het gebruik van benoemde parameters kunt u ook onbenoemde parameters gebruiken. Als u een onbenoemde parameter wilt gebruiken, geeft u een parameter in een SQL-instructie aan met een “?” (vraagteken). Aan elke parameter wordt een numerieke index toegewezen, afhankelijk van de volgorde van de parameters in de instructie, te beginnen bij index 0 voor de eerste parameter. In het volgende voorbeeld ziet u een variatie van het vorige voorbeeld, nu met onbenoemde parameters: 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();
Voordelen van het gebruik van parameters Het gebruik van parameters in een SQL-instructie biedt verschillende voordelen: Betere prestaties Een SQLStatement-instantie die parameters gebruikt, kan efficiënter werken dan een instantie die
de SQL-tekst dynamisch genereert bij elke uitvoering. De prestatieverbetering is te danken aan het feit dat de instructie één keer wordt voorbereid en vervolgens meerdere keren met verschillende parameterwaarden kan worden uitgevoerd zonder dat de SQL-instructie opnieuw hoeft te worden gecompileerd. Type toewijzen aan expliciete gegevens Parameters worden gebruikt voor het omzetten van waarden in een toegewezen type als de daadwerkelijke waarden niet bekend zijn op het moment dat de SQL-instructie wordt geschreven. Het gebruik van parameters is de enige manier om de opslagklasse te garanderen van een waarde die in de database wordt opgenomen. Als geen parameters worden gebruikt, probeert de runtime alle waarden om te zetten van hun tekstvorm in een opslagklasse op basis van het type van de overeenkomstige kolom. Zie de sectie "Data type support" (Ondersteuning van gegevenstypen) in de bijlage "SQL support in local databases" (SQL-ondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference voor meer informatie over opslagklassen en het type van waarden in een kolom. Betere beveiliging Het gebruik van parameters helpt een schadelijke techniek die SQL-injectieaanval wordt genoemd,
onmogelijk te maken. Bij een SQL-injectieaanval voert de gebruiker SQL-code in via een voor de gebruiker toegankelijke locatie (zoals een gegevensinvoerveld). Als toepassingscode een SQL-instructie genereert door gebruikersinvoer rechtstreeks samen te voegen tot SQL-tekst, wordt de door de gebruiker ingevoerde SQL-code uitgevoerd op de database. De volgende code is een voorbeeld van het samenvoegen van gebruikersinvoer tot SQLtekst. Gebruik deze techniek niet: // 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;
Door instructieparameters in plaats van door de gebruiker ingevoerde waarden samen te voegen tot de tekst voor een instructie, maakt u een SQL-injectieaanval onmogelijk. Er kan geen SQL-injectie plaatsvinden omdat de
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 181 Werken met lokale SQL-databases
parameterwaarden expliciet als vervangen waarden worden verwerkt, en niet als waarden die een onderdeel van de literale instructietekst worden. Dit is het aanbevolen alternatief voor de bovenstaande code: // 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;
Gegevens ophalen uit een database Het ophalen van gegevens uit een database bestaat uit twee stappen. Eerst voert u de SQL-instructie SELECT uit om de gegevensset te beschrijven die u uit de database wilt ophalen. Vervolgens benadert u de opgehaalde gegevens, en geeft u ze weer of bewerkt u ze, afhankelijk van de toepassing.
SELECT-instructies uitvoeren Voor het ophalen van bestaande gegevens uit een database gebruikt u een SQLStatement-instantie. Wijs de juiste SQLinstructie SELECT toe aan de eigenschap text van de instantie en roep vervolgens de methode execute() op. Zie voor meer informatie over de syntaxis van de instructie SELECT de bijlage "SQL support in local databases" (SQLondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference. In het volgende voorbeeld ziet u hoe u de instructie SELECT uitvoert om via de asynchrone uitvoeringsmodus gegevens op te halen uit de tabel “products”: 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();
In het volgende voorbeeld ziet u hoe u de instructie SELECT uitvoert om via de asynchrone uitvoeringsmodus gegevens op te halen uit de tabel “products”:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 182 Werken met lokale SQL-databases
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 }
Nadat in de asynchrone uitvoeringsmodus de uitvoering van de instructie is voltooid, verzendt de SQLStatementinstantie de gebeurtenis result (SQLEvent.RESULT) om aan te geven dat de instructie correct is uitgevoerd. Als u echter een Responder-object hebt opgegeven als argument bij de oproep execute(), wordt de resultaathandlerfunctie van het Responder-object opgeroepen. In de synchrone uitvoeringsmodus wordt de uitvoering onderbroken tot de bewerking execute() is voltooid. Daarna gaat de uitvoering verder vanaf de volgende coderegel.
Resultaatgegevens van SELECT-instructie benaderen Nadat de uitvoering van de instructie SELECT is voltooid, kunnen de opgehaalde gegevens worden benaderd. Elke gegevensrij in de resultaatset SELECT wordt een Object-instantie. Het desbetreffende object heeft eigenschappen waarvan de naam overeenkomt met de naam van de kolommen in de resultaatset. De eigenschappen bevatten de waarden uit de kolommen in de resultaatset. De instructie SELECT geeft bijvoorbeeld een resultaatset met drie kolommen op: “itemId”, “itemName” en “price”. Voor elke rij van de resultaatset wordt een Object-instantie gecreëerd met de eigenschapnamen itemId, itemName en price. Deze eigenschappen bevatten de waarden uit de overeenkomstige kolommen. De volgende code is een vervolg van de vorige code voor het ophalen van gegevens in de asynchrone uitvoeringsmodus. In de code ziet u hoe u de opgehaalde gegevens benadert met de gebeurtenislistenermethode voor resultaatsets. 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. }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 183 Werken met lokale SQL-databases
De volgende code is een uitbreiding van de vorige code voor het ophalen van gegevens in de synchrone uitvoeringsmodus. De code breidt het blok try..catch uit het vorige voorbeeld voor de synchrone uitvoeringsmodus uit om te illustreren hoe u de opgehaalde gegevens benadert. 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. }
Uit de vorige codevoorbeelden blijkt dat de resultaatobjecten zich bevinden in een array die beschikbaar is als de eigenschap data van een SQLResult-instantie. Als u de asynchrone uitvoeringsmodus met een gebeurtenislistener gebruikt, roept u de methode getResult() van de SQLStatement-instantie op om die SQLResult-instantie op te halen. Als u een Responder-argument hebt opgegeven bij de oproep execute(), wordt de SQLResult-instantie opgegeven als argument bij de resultaathandlerfunctie. In de synchrone uitvoeringsmodus roept u de methode getResult() van de SQLStatement-instantie op een willekeurig moment na het oproepen van de methode execute() op. In elk geval hebt u via de array-eigenschap data toegang tot de resultaatrijen nadat u het SQLResultobject hebt verkregen. De volgende code definieert een SQLStatement-instantie waarvan de tekst een SELECT-instructie is. De instructie haalt rijen op die de waarden uit de kolommen firstNamelastName bevatten op alle rijen uit de tabel employees. Dit voorbeeld gebruikt de asynchrone uitvoeringsmodus. Nadat de uitvoering is voltooid, wordt de methode selectResult() opgeroepen en worden de resultaatrijen met gegevens benaderd met SQLStatement.getResult() en weergegeven via de methode trace(). Let op: deze code gaat ervan uit dat een SQLConnection-instantie met de naam conn al is gedefinieerd en met de database is verbonden. De code gaat er ook van uit dat de tabel “employees” al is gecreëerd en gegevens bevat.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 184 Werken met lokale SQL-databases
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); }
De volgende code illustreert dezelfde technieken als de vorige code maar in de synchrone uitvoeringsmodus. Het voorbeeld definieert een SQLStatement-instantie waarvan de tekst een SELECT-instructie is. De instructie haalt rijen op die de waarden uit de kolommen firstNamelastName bevatten op alle rijen uit de tabel employees. De resultaatrijen met gegevens worden benaderd met SQLStatement.getResult() en weergegeven via de methode trace(). Let op: deze code gaat ervan uit dat een SQLConnection-instantie met de naam conn al is gedefinieerd en met de database is verbonden. De code gaat er ook van uit dat de tabel “employees” al is gecreëerd en gegevens bevat.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 185 Werken met lokale SQL-databases
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; 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); }
Het gegevenstype van SELECT-resultaatgegevens definiëren Elke rij die het resultaat is van een SELECT-instructie, wordt standaard gegenereerd als een Object-instantie met eigenschappen die zijn benoemd volgens de naam van de kolommen in de resultaatset en met de waarde van elke kolom als de waarde van de overeenkomstige eigenschap. Voordat u echter de SQL-instructie SELECT uitvoert, kunt u de eigenschap itemClass van de SQLStatement-instantie instellen op een klasse. Als u de eigenschap itemClass instelt, wordt elke rij die het resultaat is van de instructie SELECT gegenereerd als een instantie van de opgegeven klasse. De runtime wijst de waarden van resultaatkolommen aan eigenschapwaarden toe door de naam van de kolommen in de resultaatset van SELECT te baseren op de naam van de eigenschappen in de klasse itemClass. Elke klasse die is toegewezen als een itemClass-eigenschapwaarde, moet een constructor hebben waarvoor geen parameters nodig zijn. Bovendien moet de klasse één eigenschap hebben voor elke kolom die het resultaat is van de instructie SELECT. Als een kolom in de lijst SELECT geen gekoppelde eigenschapnaam in de klasse itemClass heeft, wordt dit als een fout beschouwd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 186 Werken met lokale SQL-databases
SELECT-resultaten in delen ophalen Bij de uitvoering van een SELECT-instructie worden standaard alle rijen van de resultaatset tegelijk opgehaald. Nadat de instructie is voltooid, verwerkt u doorgaans de opgehaalde gegevens, bijvoorbeeld door objecten te creëren of de gegevens op het scherm weer te geven. Als de instructie een groot aantal rijen genereert, kan het verwerken van alle gegevens tegelijk een grote belasting voor de computer zijn, waardoor de gebruikersinterface niet wordt vernieuwd. U kunt de zichtbare prestaties van uw toepassing verbeteren door te zorgen dat de runtime slechts een bepaald aantal resultaatrijen tegelijk weergeeft. Hierdoor worden de initiële resultaatgegevens sneller weergegeven. Op deze manier kunt u ook de resultaatrijen in sets verdelen zodat de gebruikersinterface wordt bijgewerkt telkens wanneer een set rijen is verwerkt. Let op: deze techniek is alleen nuttig in asynchrone uitvoeringsmodus. Als u de resultaten van SELECT in delen wilt ophalen, geeft u een waarde op voor de eerste parameter van de methode SQLStatement.execute() (de parameter prefetch). De parameter prefetch geeft het aantal rijen aan dat u wilt ophalen de eerste keer dat de instructie wordt uitgevoerd. Als u de methode execute() van een SQLStatementinstantie oproept, geeft u een waarde voor de parameter prefetch op zodat alleen dat aantal rijen wordt opgehaald: 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
De instructie verzendt de gebeurtenis result wanneer de eerste set resultaatrijen beschikbaar is. De resultaateigenschap data van de SQLResult-instantie bevat de gegevensrijen en de eigenschap complete ervan geeft aan of er nog op te halen resultaatrijen resteren. Als u de volgende set gegevensrijen wilt ophalen, roept u de methode next() van de SQLStatement-instantie op. Net als bij de methode execute() wordt de eerste parameter van de methode next() gebruikt om aan te geven hoeveel rijen moeten worden opgehaald de volgende keer dat de gebeurtenis result wordt verzonden. 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); } } }
De SQLStatement verzendt de gebeurtenis result elke keer dat de methode next() een volgende set resultaatrijen weergeeft. Dit betekent dat dezelfde listenerfunctie kan worden gebruikt om verder te gaan met het verwerken van resultaten (op basis van next()-oproepen) tot alle rijen zijn opgehaald. Zie de taalverwijzingsbeschrijvingen voor de methode SQLStatement.execute() (de parameterbeschrijving prefetch) en de methode SQLStatement.next().
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 187 Werken met lokale SQL-databases
Gegevens invoegen Voor het ophalen van gegevens uit een database moet de SQL-instructie INSERT worden uitgevoerd. Nadat de instructie is uitgevoerd, hebt u toegang tot de primaire sleutel voor de zojuist ingevoegde rij als de sleutel door de database is gegenereerd.
INSERT-instructies uitvoeren Als u gegevens wilt toevoegen aan een tabel in een database, moet u een SQLStatement-instantie creëren en uitvoeren waarvan de tekst de SQL-instructie INSERT is. In het volgende voorbeeld ziet u hoe u een SQLStatement-instantie gebruikt om een gegevensrij toe te voegen aan de bestaande tabel “employees”. Dit voorbeeld illustreert het invoegen van gegevens in asynchrone uitvoeringsmodus. Let op: deze code gaat ervan uit dat een SQLConnection-instantie met de naam conn al is gedefinieerd en met een database is verbonden. De code gaat er ook van uit dat de tabel “employees” al is gecreëerd. 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); }
In het volgende voorbeeld ziet u hoe u een gegevensrij toevoegt aan de bestaande tabel “employees” in synchrone uitvoeringsmodus. Let op: deze code gaat ervan uit dat een SQLConnection-instantie met de naam conn al is gedefinieerd en met een database is verbonden. De code gaat er ook van uit dat de tabel “employees” al is gecreëerd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 188 Werken met lokale SQL-databases
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; try { // execute the statement insertStmt.execute(); trace("INSERT statement succeeded"); } catch (error:SQLError) { trace("Error message:", error.message); trace("Details:", error.details); }
De door de database gegenereerde primaire sleutel van een ingevoegde rij ophalen Vaak moet uw code na het invoegen van een gegevensrij in een tabel de door de database gegenereerde primaire sleutel of de rij-identificatiewaarde voor de zojuist ingevoegde rij weten. Nadat u een rij in één tabel hebt ingevoegd, wilt u bijvoorbeeld rijen toevoegen aan een gerelateerde tabel. In dat geval kunt u het best de waarde van de primaire sleutel als vreemde sleutel in de gerelateerde tabel invoegen. De primaire sleutel van de zojuist ingevoegde rij kan worden opgehaald via het SQLResult-object dat door het uitvoeren van de instructie is gegenereerd. Dit object wordt ook gebruikt om resultaatgegevens te benaderen nadat de instructie SELECT is uitgevoerd. Net als bij alle andere SQLinstructies creëert de runtime na het voltooien van de instructie INSERT een SQLResult-instantie. U benadert de SQLResult-instantie door de methode getResult() van het SQLStatement-object op te roepen als u een gebeurtenislistener of de synchrone uitvoeringsmodus gebruikt. Als u echter de asynchrone uitvoeringsmodus gebruikt en u een Responder-instantie opgeeft voor de oproep execute(), wordt de SQLResult-instantie opgegeven als argument bij de resultaathandlerfunctie. In elk geval heeft de SQLResult-instantie de eigenschap lastInsertRowID, die de rij-identificator van de laatst ingevoegde rij bevat als de uitgevoerde SQL-instructie de instructie INSERT is. In het volgende voorbeeld ziet u hoe u de primaire sleutel van een ingevoegde rij benadert in asynchrone uitvoeringsmodus: insertStmt.text = "INSERT INTO ..."; insertStmt.addEventListener(SQLEvent.RESULT, resultHandler); insertStmt.execute(); private 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 }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 189 Werken met lokale SQL-databases
In het volgende voorbeeld ziet u hoe u de primaire sleutel van een ingevoegde rij benadert in synchrone uitvoeringsmodus: insertStmt.text = "INSERT INTO ..."; insertStmt.addEventListener(SQLEvent.RESULT, resultHandler); 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 }
Let op: mogelijk heeft de rij-identificator de waarde van de kolom die in de tabeldefinitie is opgegeven als de kolom met de primaire sleutel. Hierbij geldt de volgende regel:
• Als voor de tabel een kolom met de primaire sleutel is gedefinieerd waarbij de kolomgegevens van het type INTEGER zijn, bevat de eigenschap lastInsertRowID de waarde die in de desbetreffende rij is ingevoegd (of de waarde die door de runtime is gegenereerd als het een kolom van het type AUTOINCREMENT betreft).
• Als voor de tabel meerdere kolommen met de primaire sleutel zijn gedefinieerd (een samengestelde sleutel) of één kolom met de primaire sleutel waarbij de kolomgegevens niet van het type INTEGER zijn, genereert de database een onzichtbare rij-identificatiewaarde voor de rij. Die gegenereerde waarde is de waarde van de eigenschap lastInsertRowID.
• De waarde is altijd de rij-identificator van de laatst ingevoegde rij. Als de instructie INSERT een trigger activeert waardoor vervolgens een rij wordt ingevoegd, bevat de eigenschap lastInsertRowID de rij-identificator van de rij die het laatst door de trigger is ingevoegd en niet van de rij die door de instructie INSERT is gecreëerd. Dit betekent dat als u een kolom met een expliciet gedefinieerde primaire sleutel wilt waarvan de waarde beschikbaar is na de opdracht INSERT via de eigenschap SQLResult.lastInsertRowID, u de kolom moet definiëren als een kolom van het type INTEGER PRIMARY KEY. Let op: zelfs als uw tabel geen expliciete kolom van het type INTEGER PRIMARY KEY bevat, is het perfect acceptabel om de door de database gegenereerde rij-identificator als primaire sleutel voor uw tabel te gebruiken voor het definiëren van relaties met gerelateerde tabellen. De waarde van de kolom met de rij-identificator is in alle SQL-instructies beschikbaar door het gebruik van een van de speciale kolomnamen: ROWID, _ROWID_ of OID. U kunt in een gerelateerde tabel een kolom met een vreemde sleutel creëren en de rijidentificatiewaarde gebruiken als waarde voor de kolom met de vreemde sleutel, zoals bij een expliciet gedefinieerde kolom van het type INTEGER PRIMARY KEY. Als u dus een willekeurige primaire sleutel gebruikt in plaats van een natuurlijke sleutel en u het niet erg vindt dat de runtime de waarde van de primaire sleutel voor u genereert, is er geen groot verschil tussen het gebruik van een kolom van het type INTEGER PRIMARY KEY of van de door het systeem gegenereerde rij-identificator als primaire sleutel van de tabel bij het definiëren van een relatie met vreemde sleutel tussen twee tabellen. Zie de secties "CREATE TABLE" en "Expressions" (Expressies) in de bijlage "SQL support in local databases" (SQLondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference voor meer informatie over primaire sleutels en gegenereerde rij-identificatoren.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 190 Werken met lokale SQL-databases
Gegevens wijzigen of verwijderen Voor het uitvoeren van andere gegevensbewerkingen gebruikt u dezelfde procedure als voor het uitvoeren van de SQLinstructie SELECT of INSERT. Vervang gewoon de SQL-instructie in de eigenschap text van de SQLStatementinstantie:
• Als u bestaande gegevens in een tabel wilt wijzigen, gebruikt u de instructie UPDATE. • Als u een of meer gegevensrijen uit een tabel wilt verwijderen, gebruikt u de instructie DELETE. Zie de bijlage "SQL support in local databases" (SQL-ondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference voor een beschrijving van deze instructies.
Werken met meerdere databases Gebruik de methode SQLConnection.attach() om een verbinding met een andere database te openen voor een SQLConnection-instantie waarmee al een open database is verbonden. Geef de verbonden database een naam met behulp van de parameter “name” via het oproepen van de methode attach(). Wanneer u vervolgens instructies voor het bewerken van de desbetreffende database schrijft, kunt u die naam in een voorvoegsel gebruiken (met de syntaxis databasenaam.tabelnaam) om eventuele tabelnamen in uw SQL-instructies te definiëren, zodat de runtime weet dat de tabel zich in de opgegeven database bevindt. U kunt werken met één SQL-instructie die verwijst naar tabellen uit meerdere databases die zijn verbonden met dezelfde SQLConnection-instantie. Als een transactie voor de SQLConnection-instantie wordt gecreëerd, geldt de desbetreffende transactie voor alle SQL-instructies die met behulp van de SQLConnection-instantie worden uitgevoerd. Deze regel geldt altijd, ongeacht de database waarop de instructie wordt uitgevoerd. U kunt echter ook meerdere SQLConnection-instanties in een toepassing creëren, waarbij elke instantie is verbonden met een of meer databases. Als u echter meerdere verbindingen met dezelfde database gebruikt, mag u niet vergeten dat databasetransacties niet worden gedeeld over SQLConnection-instanties. Dit betekent dat als u via meerdere SQLConnection-instanties verbinding maakt met hetzelfde databasebestand, u er niet op mag vertrouwen dat de wijzigingen in de gegevens van beide verbindingen op de verwachte manier worden doorgevoerd. Als bijvoorbeeld twee UPDATE- of DELETE-instructies op dezelfde database maar via verschillende SQLConnection-instanties worden uitgevoerd en er een toepassingsfout optreedt na één bewerking, bevinden de databasegegevens zich mogelijk in een onomkeerbare tussenfase, waardoor de integriteit van de database (en dus ook van de toepassing) in gevaar kan komen.
Databasefouten verhelpen Over het algemeen verloopt het verhelpen van databasefouten zoals het verhelpen van andere runtimefouten. U wordt aangeraden code te schrijven die is voorbereid op het optreden van mogelijke fouten en deze kan verhelpen, in plaats van dit door de runtime te laten doen. Databasefouten worden doorgaans in drie categorieën verdeeld: verbindingsfouten, SQL-syntaxisfouten en beperkingsfouten.
Verbindingsfouten De meeste databasefouten zijn verbindingsfouten. Deze kunnen tijdens alle bewerkingen optreden. Er zijn weliswaar strategieën voor het voorkomen van verbindingsfouten maar er is slechts zelden een eenvoudige manier om zonder problemen van een verbindingsfout te herstellen als de database een belangrijk deel is van uw toepassing.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 191 Werken met lokale SQL-databases
De meeste verbindingsfouten worden veroorzaakt door de manier waarop de runtime interageert met het besturingssysteem, het bestandssysteem en het databasebestand. Er treedt bijvoorbeeld een verbindingsfout op als de gebruiker geen toestemming heeft om een databasebestand te creëren op een bepaalde locatie van het bestandssysteem. De volgende strategieën helpen verbindingsfouten te voorkomen: Gebruik gebruikersspecifieke databasebestanden Geef iedere gebruiker zijn of haar eigen databasebestand, in plaats van één databasebestand te gebruiken voor alle gebruikers die de toepassing op één computer gebruiken. Plaats het bestand in een directory die aan de account van de gebruiker is gekoppeld. Dit kan bijvoorbeeld de opslagdirectory van de toepassing, de documentenmap van de gebruiker of het bureaublad van de gebruiker zijn. Houd rekening met verschillende soorten gebruikers Test uw toepassing met verschillende soorten gebruikersaccounts in verschillende besturingssystemen. Ga er niet van uit dat de gebruiker beheerdersrechten heeft voor de computer. Ga er ook niet van uit dat de persoon die de toepassing heeft geïnstalleerd, de gebruiker is die de toepassing uitvoert. Houd rekening met verschillende bestandslocaties Als u een gebruiker toestaat de opslaglocatie van een
databasebestand te bepalen of het te openen bestand te selecteren, moet u rekening houden met de mogelijke bestandslocaties die de gebruikers kunnen selecteren. Bovendien kunt u het best de lijst van mogelijke opslaglocaties (of bronlocaties voor het openen) voor databasebestanden beperken. U kunt bijvoorbeeld gebruikers alleen toestaan bestanden te openen die zich binnen de opslaglocatie van hun gebruikersaccount bevinden. Als een verbindingsfout optreedt, is dit doorgaans bij de eerste poging om de database te creëren of te openen. Dit betekent dat de gebruiker geen enkele databasegerelateerde bewerking in de toepassing kan uitvoeren. Voor bepaalde soorten fouten, zoals alleen-lezen of toegangsrechtfouten, is een van de mogelijke hersteltechnieken het kopiëren van het databasebestand naar een andere locatie. De toepassing kan het databasebestand kopiëren naar een locatie waarvoor de gebruiker wel toegangsrechten heeft om bestanden te creëren en te wijzigen, en vervolgens die nieuwe locatie gebruiken.
Syntaxisfouten Een syntaxisfout treedt op als de toepassing een SQL-instructie probeert uit te voeren die niet goed is geformuleerd. Aangezien SQL-instructies voor lokale databases als tekenreeksen zijn gecreëerd, is het niet mogelijk om de SQLsyntaxis tijdens het compileren te controleren. Alle SQL-instructies moeten worden uitgevoerd om hun syntaxis te controleren. Pas de volgende strategieën toe om SQL-syntaxisfouten te voorkomen: Voer een grondige test uit van alle SQL-instructies Indien mogelijk moet u uw SQL-instructies tijdens de
ontwikkeling van uw toepassing apart testen voordat u ze als instructietekst in de toepassingscode codeert. Bovendien wordt u aangeraden een codetestfase in te plannen (zoals het testen per eenheid) om een set van tests te creëren die elke mogelijke optie en codevariatie testen. Gebruik instructieparameters en vermijd het samenvoegen (dynamisch genereren) van SQL Parameters gebruiken,
en dynamisch gegenereerde SQL-instructies vermijden, betekent dat dezelfde SQL-instructietekst wordt gebruikt elke keer dat een instructie wordt uitgevoerd. Hierdoor is het veel eenvoudiger om uw instructies te testen en de mogelijke variaties te beperken. Als u een SQL-instructie dynamisch moet genereren, moet u de dynamische delen van de instructie tot het minimum beperken. Ga ook zorgvuldig te werk bij het valideren van gegevensinvoer om te zorgen dat deze geen syntaxisfouten veroorzaakt. Een toepassing die van een syntaxisfout moet herstellen, heeft complexe logica nodig om een SQL-instructie te controleren en de syntaxis te corrigeren. Door de volgende richtlijnen voor het voorkomen van syntaxisfouten in acht te nemen, kan uw code mogelijke runtimebronnen van SQL-syntaxisfouten (zoals gebruikersinvoer in een instructie) identificeren. Zorg dat de gebruiker over richtlijnen beschikt als een syntaxisfout optreedt. Geef aan wat de gebruiker moet corrigeren om te zorgen dat de instructie correct wordt uitgevoerd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 192 Werken met lokale SQL-databases
Beperkingsfouten Beperkingsfouten treden op wanneer de instructie INSERT of UPDATE gegevens aan een kolom probeert toe te voegen. De fout treedt op als de nieuwe gegevens een van de vooraf gedefinieerde beperkingen voor de tabel of kolom schenden. U kunt onder andere de volgende beperkingen instellen: Beperking ‘uniek’ Geeft aan dat geen enkele rij van de tabel een al bestaande waarde mag bevatten binnen een
bepaalde kolom. Of u kunt aangeven dat wanneer meerdere kolommen worden gecombineerd in één beperking, de combinatie van waarden in de desbetreffende kolommen niet mag worden gedupliceerd. Met andere woorden, elke rij moet verschillend zijn op het gebied van de opgegeven unieke kolom(men). Beperking ‘primaire sleutel’ Wat de gegevens betreft die een beperking (niet) toestaat, is een beperking ‘primaire
sleutel’ hetzelfde als een beperking ‘uniek’. Beperking ‘niet leeg’ Geeft aan dat een bepaalde kolom niet de waarde NULL mag bevatten, met andere woorden, dat
alle rijen in de desbetreffende kolom een waarde moeten hebben. Beperking ‘controle’ Biedt u de mogelijkheid om een willekeurige beperking in te stellen voor een of meer tabellen.
Een veel voorkomende beperking van het ‘controle’ is een regel die bepaalt dat de waarde in een kolom zich binnen een bepaald bereik moet bevinden (bijvoorbeeld dat de waarde in een numerieke kolom groter moet zijn dan 0). Een andere veel voorkomende beperking van het type ‘controle’ definieert relaties tussen kolomwaarden (bijvoorbeeld dat de waarde in een kolom moet verschillen van de waarde in een andere kolom op dezelfde rij). Beperking ‘gegevenstype’ De runtime legt het gegevenstype voor de kolomwaarden op en er treedt een fout op als
wordt geprobeerd om een waarde op te slaan die niet het juiste type heeft voor de kolom. In vele situaties worden waarden echter omgezet zodat ze het gegevenstype hebben dat is ingesteld voor de kolom. Zie “Werken met gegevenstypen” op pagina 193 voor meer informatie. De runtime legt geen beperkingen op voor vreemde-sleutelwaarden. Met andere woorden, vreemde-sleutelwaarden hoeven niet overeen te komen met een bestaande primaire-sleutelwaarde. Naast de vooraf gedefinieerde typen beperkingen ondersteunt de SQL-runtime-engine het gebruik van triggers. Een trigger is vergelijkbaar met een gebeurtenishandler. Het is een vooraf gedefinieerde instructieset die worden uitgevoerd wanneer zich een bepaalde actie voordoet. U kunt bijvoorbeeld een trigger definiëren die worden geactiveerd wanneer gegevens worden ingevoegd in of verwijderd uit een bepaalde tabel. Een voorbeeld van het gebruik van een trigger is het controleren van wijzigingen in gegevens en het weergeven van een foutmelding als niet wordt voldaan aan de opgegeven voorwaarden. Dit betekent dat een trigger hetzelfde doel kan hebben als een beperking, en dat de strategieën voor het voorkomen en herstellen van beperkingsfouten ook gelden voor fouten die door een trigger worden gegenereerd. De fout-id voor fouten die door een trigger worden gegenereerd, verschilt echter van de fout-id voor beperkingsfouten. De set van beperkingen die gelden voor een bepaalde tabel wordt gedefinieerd terwijl u een toepassing ontwikkelt. Door goed na te denken bij het definiëren van beperkingen vergemakkelijkt u het voorkomen en herstellen van beperkingsfouten in uw toepassingen. Beperkingsfouten zijn echter moeilijk systematisch te voorspellen en te voorkomen. Het voorspellen is moeilijk omdat beperkingsfouten pas optreden wanneer toepassingsgegevens worden toegevoegd. Beperkingsfouten treden op wanneer gegevens aan een database worden toegevoegd nadat deze is gecreëerd. Deze fouten zijn vaak het resultaat van de relatie tussen nieuwe gegevens en gegevens die al in de database aanwezig zijn. De volgende strategieën kunnen u helpen veel voorkomende beperkingsfouten te voorkomen: Plan de databasestructuur en de beperkingen zorgvuldig Het doel van beperkingen is toepassingsregels op te leggen en te helpen de integriteit van de databasegegevens te beschermen. Denk tijdens het plannen van uw toepassing na over de structuur van uw database zodat deze uw toepassing kan ondersteunen. Hierbij identificeert u regels voor de gegevens, zoals of bepaalde waarden vereist zijn, een waarde een standaardinstelling heeft, dubbele waarden zijn toegestaan enzovoort. Deze regels helpen u bij het definiëren van databasebeperkingen.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 193 Werken met lokale SQL-databases
Geef expliciet kolomnamen op U kunt de instructie INSERT gebruiken zonder expliciet de kolommen op te geven
waarin waarden zullen worden ingevoegd. Dit is echter een onnodig risico. Door expliciet de kolommen te benoemen waarin waarden zullen worden ingevoegd, kunt u automatisch gegenereerde waarden, kolommen met standaardwaarden en kolommen met de waarde NULL gebruiken. Bovendien zorgt u hierdoor dat in alle kolommen van het type NOT NULL een expliciete waarde wordt ingevoegd. Gebruik standaardwaarden Wanneer u de beperking NOT NULL voor een kolom opgeeft, geeft u wanneer mogelijk een
standaardwaarde in de kolomdefinitie op. Ook toepassingscode kan in standaardwaarden voorzien. Uw code kan bijvoorbeeld controleren of een tekenreeksvariabele de waarde null heeft en er een waarde aan toewijzen voordat de variabele wordt gebruikt om de waarde van een instructieparameter in te stellen. Valideer gebruikersinvoer Controleer gebruikersinvoer voordat de gegevens daadwerkelijk in de database worden ingevoegd om te zorgen dat de invoer aan de beperkingen voldoet, met name in het geval van de beperkingen NOT NULL en CHECK. De beperking UNIQUE is uiteraard moeilijker te controleren omdat een SELECT-query moet worden uitgevoerd om te bepalen of de gegevens uniek zijn. Gebruik triggers U kunt een trigger schrijven die ingevoegde gegevens verifieert (en mogelijk vervangt) of andere
acties uitvoert om ongeldige gegevens te corrigeren. Deze verificatie- en correctieacties kunnen beperkingsfouten voorkomen. In vele opzichten zijn beperkingsfouten moeilijker te voorkomen dan andere fouttypen. Gelukkig zijn er verschillende strategieën om van beperkingsfouten te herstellen zonder dat de toepassing instabiel of onbruikbaar wordt: Gebruik conflictalgoritmen Als u een beperking voor een kolom definieert en als u de instructie INSERT of UPDATE
creëert, kunt u desgewenst een conflictalgoritme opgeven. Een conflictalgoritme definieert de actie die de database uitvoert als een beperkingsfout optreedt. De database-engine kan verschillende mogelijke acties uitvoeren. De database-engine kan één instructie of een complete transactie beëindigen. De engine kan de fout negeren. Of zelfs oude gegevens verwijderen en deze vervangen door de gegevens die de code probeert op te slaan. Zie de sectie "ON CONFLICT (conflict algorithms)" (Conflictalgoritmen) in de bijlage "SQL support in local databases" (SQL-ondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference voor meer informatie. Geef feedback met een oplossing De set van beperkingen die een bepaalde SQL-opdracht kunnen beïnvloeden, kan
van tevoren worden geïdentificeerd. Dit betekent dat u beperkingsfouten die door een instructie kunnen worden veroorzaakt, kunt voorspellen. Op die kennis kunt u toepassingslogica baseren die op een beperkingsfout reageert. Een toepassing bevat bijvoorbeeld een formulier voor het invoeren van nieuwe producten. Als de kolom met de productnaam in de database is gedefinieerd met een beperking van het type UNIQUE, kan het invoegen van een nieuwe productrij in de database een beperkingsfout veroorzaken. Daarom wordt de toepassing zo ontwikkeld dat deze van tevoren rekening houdt met een beperkingsfout. Als de fout optreedt, waarschuwt de toepassing de gebruiker dat de opgegeven productnaam al bestaat en dat een andere naam moet worden gekozen. Een andere mogelijke reactie is dat informatie over het andere product met dezelfde naam wordt weergegeven.
Werken met gegevenstypen Bij het creëren van een tabel in een database definieert de SQL-instructie voor het creëren van de tabel het gegevenstype voor elke kolom van de tabel. Het toewijzen van typen is weliswaar niet vereist maar u wordt toch aangeraden het kolomtype expliciet op te geven in uw SQL-instructies CREATE TABLE. Normaliter wordt elk object dat u in een database opslaat met de instructie INSERT, weergegeven als een instantie van hetzelfde gegevenstype wanneer u de instructie SELECT uitvoert. De opgehaalde waarde kan echter een ander gegevenstype hebben, afhankelijk van de toewijzing van het type aan de databasekolom waarin de waarde is opgeslagen. Als het gegevenstype van een waarde die in een kolom wordt opgeslagen, niet overeenkomt met het type dat aan de kolom is toegewezen, probeert de database de waarde om te zetten in het type dat aan de kolom is
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 194 Werken met lokale SQL-databases
toegewezen. Als bijvoorbeeld het gegevenstype NUMERIC aan een databasekolom is toegewezen, probeert de database ingevoegde gegevens om te zetten in een numerieke opslagklasse (INTEGER of REAL) voordat de gegevens worden opgeslagen. De database genereert een foutmelding als de gegevens niet kunnen worden omgezet. Als de tekenreeks “12345” wordt ingevoegd in een kolom van het type NUMERIC, zet de database op basis van deze regel de tekenreeks automatisch om in het geheel getal 12345 voordat de waarde in de database wordt opgeslagen. Wanneer de waarde wordt opgehaald met de instructie SELECT, wordt deze weergegeven als een instantie van een numeriek gegevenstype (bijvoorbeeld Number) in plaats van een tekenreeksinstantie. De beste manier om ongewenste omzetting van het gegevenstype te voorkomen, is het in acht nemen van twee regels. Ten eerste: definieer elke kolom met het type dat overeenkomt met het type gegevens dat u wilt opslaan. Ten tweede: voeg alleen waarden in waarvan het gegevenstype overeenkomt met het toegewezen type. Het in acht nemen van deze regels biedt twee voordelen. Wanneer u de gegevens invoegt, worden deze niet onbedoeld omgezet (waardoor mogelijk de bedoelde betekenis verloren zou gaan). Bovendien worden de gegevens bij het ophalen weergegeven met het oorspronkelijke gegevenstype. Zie de sectie "Data type support" (Ondersteuning van gegevenstypen) in de bijlage "SQL support in local databases" (SQL-ondersteuning in lokale databases) in ActionScript 3.0 Language and Components Reference voor meer informatie over de beschikbare gegevenstypen voor kolommen en het gebruik van gegevenstypen in SQL-instructies.
Synchrone en asynchrone databasebewerkingen gebruiken In de vorige secties zijn veel voorkomende databasebewerkingen besproken, zoals het ophalen, invoegen, updaten en verwijderen van gegevens, evenals het creëren van een databasebestand en tabellen en andere objecten binnen een database. In de voorbeelden hebt u gezien hoe u deze bewerkingen synchroon en asynchroon kunt laten uitvoeren. Ter herinnering: in asynchrone uitvoeringsmodus geeft u de database-engine de opdracht om een bewerking uit te voeren. De database-engine werkt vervolgens op de achtergrond terwijl de toepassing verderwerkt. Nadat de bewerking is voltooid, verzendt de database-engine een gebeurtenis om u dit te melden. Het belangrijkste voordeel van asynchrone uitvoering is dat de runtime de databasebewerkingen op de achtergrond uitvoert terwijl de hoofdtoepassingscode verder wordt uitgevoerd. Dit is vooral belangrijk wanneer het uitvoeren van de bewerking lang duurt. In de synchrone uitvoeringsmodus echter worden de bewerkingen niet op de achtergrond uitgevoerd. U geeft de database-engine de opdracht een bewerking uit te voeren. De code wordt op dat punt onderbroken terwijl de databaseengine zijn werk doet. Nadat de bewerking is voltooid, gaat de uitvoering verder vanaf de volgende regel van uw code. Het is niet mogelijk om via één enkele databaseverbinding bepaalde bewerkingen of instructies synchroon en andere asynchroon uit te voeren. U bepaalt welke uitvoeringsmodus (synchroon of asynchroon) voor een SQLConnection wordt gebruikt wanneer u verbinding maakt met de database. Als u SQLConnection.open() oproept, werkt de verbinding in synchrone uitvoeringsmodus. Roept u SQLConnection.openAsync() op, dan werkt de verbinding in asynchrone uitvoeringsmodus. Nadat een SQLConnection-instantie met een database is verbonden met behulp van open() of openAsync(), wordt deze in synchrone of asynchrone uitvoeringsmodus vergrendeld.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 195 Werken met lokale SQL-databases
Synchrone databasebewerkingen gebruiken Op het gebied van de daadwerkelijke code die u gebruikt om bewerkingen uit te voeren en erop te reageren, is er niet veel verschil tussen de synchrone en asynchrone uitvoeringsmodus. De belangrijkste verschillen tussen beide modi liggen in twee gebieden. Het eerste verschil is de uitvoering van een bewerking die afhankelijk is van een andere bewerking (bijvoorbeeld rijen die het resultaat zijn van SELECT of de primaire sleutel van de rij die is toegevoegd door de instructie INSERT). Het tweede verschil is de verwerking van fouten.
Code schrijven voor synchrone bewerkingen Het belangrijkste verschil tussen synchrone en asynchrone uitvoering is dat u in de synchrone modus de code als één reeks van stappen schrijft. In de asynchrone modus registreert u gebeurtenislisteners en verdeelt u vaak bewerkingen over verschillende listenermethoden. Als een database in de synchrone uitvoeringsmodus is verbonden, kunt u een reeks van opeenvolgende databasebewerkingen binnen één codeblok laten uitvoeren. Deze techniek wordt in het volgende voorbeeld getoond: 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();
Zoals u ziet, roept u dezelfde methoden op om databasebewerkingen uit te voeren, ongeacht de modus die u gebruikt (synchroon of asynchroon). De belangrijkste verschillen tussen beide modi zijn de uitvoering van een bewerking die afhankelijk is van een andere bewerking, en de verwerking van fouten.
Bewerkingen uitvoeren die afhankelijk zijn van een andere bewerking In de synchrone uitvoeringsmodus hoeft u geen code te schrijven die op een gebeurtenis wacht om te bepalen wanneer een bewerking is voltooid. U mag ervan uitgaan dat als een bewerking op een bepaalde regel van de code is voltooid, de uitvoering verdergaat met de volgende regel. Dit betekent dat als u een bewerking wilt uitvoeren die afhankelijk is van de voltooiing van een andere bewerking, u gewoon de afhankelijke code onmiddellijk na de bewerking schrijft waarvan deze afhankelijk is. Als u bijvoorbeeld wilt dat een toepassing een transactie start, de instructie INSERT uitvoert, de primaire sleutel van de ingevoegde rij ophaalt, die primaire sleutel op een andere rij van een andere tabel invoegt en ten slotte de transactie bevestigt, kunt u de complete code als een reeks van instructies schrijven. In het volgende voorbeeld ziet u het gebruik van deze bewerkingen:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 196 Werken met lokale SQL-databases
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();
Fouten verwerken in synchrone uitvoeringsmodus In de synchrone uitvoeringsmodus wacht u niet op een foutgebeurtenis om te bepalen of een bewerking is mislukt. In plaats daarvan plaatst u code die fouten kan veroorzaken in een set codeblokken van het type try..catch..finally. Plaats de code die de fout kan genereren in het blok try. Schrijf de acties die als reactie op de verschillende fouttypen moeten worden uitgevoerd in aparte blokken van het type catch. Plaats eventuele code die u altijd wilt uitvoeren ongeacht het resultaat (bijvoorbeeld het sluiten van een databaseverbinding die u niet meer nodig hebt) in een blok van het type finally. In het volgende voorbeeld ziet u hoe u blokken van het type try..catch..finally voor foutverwerking gebruikt. Dit voorbeeld is gebaseerd op het vorige voorbeeld maar voegt code voor foutverwerking toe:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 197 Werken met lokale SQL-databases
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(); }
De asynchrone uitvoeringsmodus Veel ontwikkelaars gebruiken de asynchrone uitvoeringsmodus liever niet omdat ze denken dat de uitvoering van een SQLStatement-instantie niet kan worden gestart als al een andere SQLStatement wordt uitgevoerd via dezelfde databaseverbinding. Dit is niet juist. U kunt de eigenschap text van een SQLStatement-instantie niet wijzigen terwijl de instructie wordt uitgevoerd. Als u echter een aparte SQLStatement-instantie gebruikt voor elke verschillende SQLinstructie die u wilt uitvoeren, kunt u de methode execute() van een SQLStatement oproepen terwijl een andere SQLStatement-instantie wordt uitgevoerd, zonder dat een fout optreedt. Wanneer u databasebewerkingen uitvoert in de asynchrone uitvoeringsmodus, heeft elke databaseverbinding (elke SQLConnection-instantie) een eigen interne wachtrij of lijst van bewerkingen die de verbinding moet uitvoeren. De runtime voert de bewerkingen één voor één uit in de volgorde waarin ze aan de wachtrij zijn toegevoegd. Wanneer u een SQLStatement-instantie creëert en de overeenkomstige methode execute() oproept, wordt de desbetreffende bewerking voor het uitvoeren van de instructie toegevoegd aan de wachtrij van de verbinding. Als er momenteel geen bewerking wordt uitgevoerd voor de desbetreffende SQLConnection-instantie, wordt de uitvoering van de instructie op de achtergrond gestart. U kunt bijvoorbeeld binnen hetzelfde codeblok een andere SQLStatement-instantie creëren
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 198 Werken met lokale SQL-databases
en ook de methode execute() van de desbetreffende methode oproepen. Die tweede bewerking voor het uitvoeren van de instructie wordt na de eerste instructie in de wachtrij geplaatst. Zodra de eerste instructie is voltooid, voert de runtime de volgende bewerking uit de wachtrij uit. De verwerking van daarop volgende bewerkingen uit de wachtrij vindt op de achtergrond plaats, zelfs wanneer de gebeurtenis result voor de eerste bewerking wordt verzonden in de hoofdtoepassingscode. In de volgende code wordt deze techniek geïllustreerd: // 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.
Er is een belangrijk neveneffect: de database voert automatisch daarop volgende instructies uit de wachtrij uit. Als een instructie afhankelijk is van het resultaat van een andere bewerking, kunt u de instructie niet toevoegen aan de wachtrij (met andere woorden, u kunt de methode execute() van de instructie niet oproepen) voordat de eerste bewerking is voltooid. De reden hiervoor is dat nadat u de methode execute() van de tweede instructie hebt opgeroepen, u de eigenschap text of parameters van de instructie niet meer kunt wijzigen. In dat geval kunt u de volgende bewerking pas starten nadat de gebeurtenis is verzonden die aangeeft dat de eerste bewerking is voltooid. Als u bijvoorbeeld een instructie in het kader van een transactie wilt uitvoeren, is de uitvoering van de instructie afhankelijk van het openen van de transactie. Nadat u de methode SQLConnection.begin() hebt opgeroepen om de transactie te openen, moet u wachten tot de SQLConnection-instantie de gebeurtenis begin verzendt. Pas daarna kunt u de methode execute() van de SQLStatement-instantie oproepen. In dit voorbeeld is de eenvoudigste manier om de toepassing zo te structureren dat de bewerkingen correct worden uitgevoerd, het creëren van een methode die als listener voor de gebeurtenis begin is geregistreerd. De code die de methode SQLStatement.execute() oproept, wordt binnen die listenermethode geplaatst.
Strategieën voor het werken met SQL-databases Er zijn verschillende manieren waarop een toepassing een lokale SQL-database kan benaderen en ermee kan werken. Het ontwerp van de toepassing kan variëren op het gebied van de structuur van de toepassingscode, de sequentie en timing van de uitvoering van de bewerkingen enzovoort. De technieken die u kiest, kunnen een invloed hebben op het gemak waarmee uw toepassing kan worden ontwikkeld. Ze kunnen een invloed hebben op het gemak waarmee de toepassing in de toekomst kan worden aangepast. Ze kunnen ook een invloed hebben op de prestaties van de toepassing voor de gebruiker.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 199 Werken met lokale SQL-databases
Niet-lege databases distribueren Als u een lokale SQL-database van AIR in uw toepassing gebruikt, verwacht de toepassing een database met een bepaalde structuur (tabellen, kolommen enzovoort). Sommige toepassingen verwachten ook bepaalde gegevens in het databasebestand. U kunt op verschillende manieren zorgen dat de database de juiste structuur heeft, onder andere door de database binnen de toepassingscode te creëren. Wanneer de toepassing wordt geladen, controleert deze of het gekoppelde databasebestand zich op een bepaalde locatie bevindt. Als dat niet het geval is, voert de toepassing een reeks opdrachten uit om het databasebestand te creëren, de databasestructuur toe te passen en de tabellen te vullen met de initiële gegevens. De code die de database en de overeenkomstige tabellen creëert, is vaak complex. Hoewel deze code doorgaans slechts één keer tijdens de levensduur van de geïnstalleerde toepassing wordt gebruikt, wordt de toepassing er groter en complexer door. Een alternatief voor het programmamatig creëren van de database, structuur en gegevens is uw toepassing te distribueren met een niet-lege database. Hiervoor neemt u het databasebestand op in het AIR-pakket van de toepassing. Net als alle bestanden die in een AIR-pakket worden opgenomen, wordt een gebundeld databasebestand geïnstalleerd in de toepassingsmap (de map die wordt ingesteld door de eigenschap File.applicationDirectory). Bestanden in die map zijn echter alleen-lezen. Gebruik het bestand uit het AIR-pakket als “sjabloon”database. De eerste keer dat een gebruiker de toepassing uitvoert, kopieert u het oorspronkelijke databasebestand naar de toepassingsopslagdirectory van de gebruiker (of een andere locatie). Vervolgens wordt die database in de toepassing gebruikt.
Databaseprestaties verbeteren Adobe AIR biedt meerdere technieken om de prestaties van databasebewerkingen in uw toepassing te verbeteren. Naast de hier beschreven technieken kan ook de manier waarop een SQL-instructie is geschreven, de databaseprestaties beïnvloeden. Er zijn doorgaans meerdere manieren om de SQL-instructie SELECT te schrijven om een specifieke resultaatset op te halen. In sommige gevallen is de belasting op de database-engine afhankelijk van de techniek die u gebruikt. Dit aspect van het verbeteren van de databaseprestaties (het ontwerpen van SQL-instructies voor prestatieverbetering) wordt niet besproken in de documentatie bij Adobe AIR.
Gebruik één SQLStatement-instantie per SQL-instructie Voordat een SQL-instructie wordt uitgevoerd, wordt deze door de runtime voorbereid (gecompileerd) om de stappen te bepalen die intern moeten worden uitgevoerd om de instructie uit te voeren. Als u SQLStatement.execute() oproept voor een SQLStatement-instantie die nog niet heeft uitgevoerd, wordt de instructie automatisch voorbereid voordat deze wordt uitgevoerd. De volgende keren dat u de methode execute() oproept, is de instructie al voorbereid mits de eigenschap SQLStatement.text niet is gewijzigd. Als gevolg daarvan wordt deze sneller uitgevoerd. Als u maximaal wilt profiteren van het opnieuw gebruiken van instructies maar waarden moeten worden gewijzigd vóór of na de uitvoering van een instructie, gebruikt u instructieparameters om uw instructie aan te passen. (U geeft instructieparameters op via de associatieve-array-eigenschap SQLStatement.parameters.) Bij het wijzigen van de eigenschap text van de SQLStatement-instantie moet de runtime de instructie opnieuw voorbereiden. Als u de waarden van instructieparameters wijzigt, is dit niet het geval. Zie “Parameters gebruiken in instructies” op pagina 179 voor meer informatie over het gebruik van parameters in instructies. Aangezien het voorbereiden en uitvoeren van een instructie voor een grote belasting van de database-engine kan zorgen, wordt u aangeraden de initiële gegevens vooraf te laden en vervolgens andere instructies op de achtergrond uit te voeren. Laad de gegevens die de toepassing het eerst nodig heeft. Nadat het initiële opstarten van uw toepassing is voltooid, of tijdens een andere periode van inactiviteit binnen de toepassing, voert u andere instructies uit. Als uw toepassing bijvoorbeeld de database helemaal niet nodig heeft om het beginscherm weer te geven, wacht u tot het
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 200 Werken met lokale SQL-databases
beginscherm verschijnt, opent u vervolgens de databaseverbinding, en creëert u ten slotte de SQLStatement-instanties en voert u alle mogelijke instanties uit. Het is echter ook mogelijk dat uw toepassing bij het opstarten onmiddellijk bepaalde gegevens weergeeft, zoals het resultaat van een query. In dat geval voert u de SQLStatement-instantie voor de desbetreffende query uit. Nadat de initiële gegevens zijn geladen en weergegeven, creëert u SQLStatement-instanties voor andere databasebewerkingen en voert u indien mogelijk later andere instructies uit die nodig zijn. Als u een SQLStatement-instantie opnieuw gebruikt, moet uw toepassing een verwijzing naar de SQLStatementinstantie bijhouden nadat deze is voorbereid. Hiervoor definieert u de variabele als een variabele van het type ‘klasse’ en niet van het type ‘functie’. Een goede manier hiervoor is uw toepassing zo te structureren dat een SQL-instructie aan één klasse wordt toegewezen. U kunt ook een groep van instructies die gecombineerd worden uitgevoerd, toewijzen aan één klasse. Wanneer u de SQLStatement-instantie(s) als lidvariabelen van de klasse definieert, blijven ze bestaan zolang de instantie van de klasse waaraan ze zijn toegewezen, in de toepassing bestaat. Als minimale oplossing kunt u gewoon een variabele definiëren die de SQLStatement-instantie buiten een functie bevat zodat de instantie in het geheugen blijft bestaan. Definieer de SQLStatement-instantie bijvoorbeeld als een lidvariabele in een ActionScriptklasse of als een niet-functievariabele in een JavaScript-bestand. Vervolgens kunt u de parameterwaarden van de instructie instellen en de methode execute() van de instructie oproepen wanneer u de query daadwerkelijk wilt uitvoeren.
Meerdere bewerkingen in een transactie groeperen U voert bijvoorbeeld een groot aantal SQL-instructies uit die gegevens toevoegen of wijzigen (instructies van het type INSERT of UPDATE). U kunt een aanzienlijke prestatieverbetering verkrijgen door alle instructies binnen een expliciete transactie uit te voeren. Als u niet expliciet een transactie begint, wordt elke instructie binnen zijn eigen, automatisch gegenereerde transactie uitgevoerd. Nadat elke transactie (elke instructie) is voltooid, schrijft de runtime de resultaatgegevens naar het databasebestand op de schijf. Anderzijds moet u rekening houden met wat er gebeurt als u expliciet een transactie genereert en de instructies in het kader van die transactie uitvoert. De runtime voert alle wijzigingen in het geheugen uit en schrijft ze vervolgens alle tegelijk naar het databasebestand wanneer de transactie wordt bevestigd. Het naar schijf schrijven van gegevens is doorgaans het meest tijdsintensieve deel van de bewerking. Dit betekent dat u de prestaties aanzienlijk kunt verbeteren door de gegevens alle tegelijk naar schijf te schrijven in plaats van één keer per SQL-instructie.
Runtimeverwerking tot het minimum beperken Met behulp van de volgende technieken kunt u onnodige belasting van de database-engine voorkomen en toepassingen sneller maken:
• Geef altijd expliciet database- en tabelnamen op in een instructie. (Gebruik ‘main’ voor de hoofddatabase.) Gebruik bijvoorbeeld SELECT id_werknemer FROM main.werknemers in plaats van SELECT id_werknemer FROM werknemers. Door de databasenaam expliciet op te geven zorgt u dat de runtime niet elke database hoeft te
doorzoeken om de vereiste tabel te vinden. Bovendien kan de runtime niet de verkeerde database kiezen. Neem altijd deze regel in acht, zelfs als een SQLConnection met maar één database is verbonden. De SQLConnection is namelijk op de achtergrond ook verbonden met een tijdelijke database die toegankelijk is via SQL-instructies.
• Geef altijd expliciet kolomnamen op in een instructie van het type SELECT of INSERT. • Verdeel de rijen die worden weergegeven door een instructie van het type SELECT die een groot aantal rijen ophaalt. Zie “SELECT-resultaten in delen ophalen” op pagina 186 voor meer informatie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 201 Werken met lokale SQL-databases
Wijzig het schema niet Wijzig indien mogelijk het schema (de tabelstructuur) van een database niet meer nadat u gegevens hebt toegevoegd aan de tabellen van de database. In een databasebestand bevinden de tabeldefinities zich doorgaans aan het begin van het bestand. Wanneer u verbinding maakt met een database, worden deze definities door de runtime geladen. Wanneer u gegevens toevoegt aan databasetabellen, worden deze gegevens na de tabeldefinitiegegevens geplaatst. Als u echter schemawijzigingen aanbrengt, zoals het toevoegen van een kolom aan een tabel of het toevoegen van een nieuwe tabel, worden de nieuwe tabeldefinitiegegevens gemengd met de tabelgegevens in het databasebestand. Als niet alle tabeldefinitiegegevens zich aan het begin van het databasebestand bevinden, duurt het langer om verbinding te maken met de database omdat de runtime de tabeldefinitiegegevens op verschillende plaatsen in het bestand moet zoeken. Roep voor het uitvoeren van schemawijzigingen de methode SQLConnection.compact() op nadat de wijzigingen zijn voltooid. Hierdoor wordt het databasebestand opnieuw ingedeeld zodat alle tabeldefinitiegegevens zich aan het begin van het bestand bevinden. Het uitvoeren van de bewerking compact() kan echter lang duren, met name bij grote databasebestanden.
Aanbevolen procedures voor het werken met lokale SQL-databases Hieronder volgt een lijst van suggesties voor technieken die u kunt toepassen om de prestaties, de beveiliging en het onderhoudsgemak van uw toepassingen te verhogen bij het werken met lokale SQL-databases. Zie “Databaseprestaties verbeteren” op pagina 199 voor nog meer technieken voor het verbeteren van uw databasetoepassingen.
Creëer vooraf databaseverbindingen Zelfs als uw toepassing geen instructies uitvoert wanneer deze wordt geladen, maakt u een instantie van een SQLConnection-object en roept u de methode open() of openAsync() van de instantie zo vroeg mogelijk op (bijvoorbeeld onmiddellijk nadat de toepassing is gestart) om vertraging bij het uitvoeren van instructies te voorkomen. Zie “Verbinden met een database” op pagina 176.
Gebruik databaseverbindingen opnieuw Als u tijdens de uitvoering van uw toepassing een bepaalde database benadert, zorgt u voor een verwijzing naar de SQLConnection-instantie en gebruikt u deze altijd opnieuw in de hele toepassing zodat u de verbinding niet elke keer hoeft te sluiten en weer te openen. Zie “Verbinden met een database” op pagina 176.
Gebruik bij voorkeur de asynchrone uitvoeringsmodus Bij het schrijven van code voor het benaderen van gegevens kan het verleidelijk zijn om bewerkingen synchroon in plaats van asynchroon te laten uitvoeren omdat het gebruik van synchrone bewerkingen vaak kortere en minder complexe code vereist. Zoals is beschreven in “Synchrone en asynchrone databasebewerkingen gebruiken” op pagina 194 kunnen synchrone bewerkingen de prestaties echter zo verminderen dat de gebruiker dit merkt, zodat het werken met uw toepassing minder aantrekkelijk wordt. De tijd die nodig is om één bewerking uit te voeren, is afhankelijk van de bewerking en met name van de hoeveelheid gegevens die moet worden verwerkt. Bijvoorbeeld: een SQL-instructie van het type INSERT die maar één rij aan de database toevoegt, heeft minder tijd nodig dan een instructie van het type SELECT die duizenden rijen gegevens moet ophalen. Wanneer u echter de synchrone modus gebruikt om meerdere bewerkingen uit te voeren, worden de bewerkingen doorgaans samengeperst. Zelfs als elke bewerking slechts een korte uitvoeringstijd heeft, blokkeert de toepassing tot alle synchrone bewerkingen zijn voltooid. Hierdoor is de totale uitvoeringstijd van meerdere samengeperste bewerkingen mogelijk lang genoeg om uw toepassing onbruikbaar te maken.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 202 Werken met lokale SQL-databases
Gebruik daarom standaard de asynchrone modus, met name voor bewerkingen met een groot aantal rijen. Er bestaat een techniek om de verwerking van grote resultaatsets van de instructie SELECT te verdelen. Zie hiervoor “SELECTresultaten in delen ophalen” op pagina 186. Deze techniek kan echter alleen in de asynchrone uitvoeringsmodus worden gebruikt. Gebruik synchrone bewerkingen alleen wanneer u bepaalde functies niet kunt uitvoeren met asynchrone programmering, wanneer u de nadelen op het gebied van prestaties voor de gebruikers van uw toepassing in acht hebt genomen en wanneer u uw toepassing hebt getest zodat u weet hoe de prestaties van uw toepassing worden beïnvloed. Het gebruik van de asynchrone uitvoeringsmodus kan het coderen van de toepassing complexer maken. Vergeet echter niet dat u de code maar één hoeft te schrijven maar de gebruikers van uw toepassing deze vele keren moeten gebruiken, traag of snel. In vele gevallen kan een groot aantal SQL-bewerkingen tegelijk in de wachtrij worden geplaatst wanneer u een aparte SQLStatement-instantie voor elke uit te voeren SQL-instructie gebruikt, waardoor asynchrone code op ongeveer dezelfde manier als synchrone code wordt geschreven. Zie “De asynchrone uitvoeringsmodus” op pagina 197 voor meer informatie.
Gebruik aparte SQL-instructies en wijzig de eigenschap ‘text’ van de SQLStatement niet Creëer voor elke SQL-instructie die meer dan één keer in de toepassing wordt uitgevoerd, een aparte SQLStatementinstantie voor elke SQL-instructie. Gebruik die SQLStatement-instantie elke keer dat de overeenkomstige SQLopdracht wordt uitgevoerd. Als u bijvoorbeeld een toepassing schrijft met vier verschillende SQL-bewerkingen die meerdere keren worden uitgevoerd. In dat geval creëert u vier aparte SQLStatement-instanties en roept u de methode execute() van elke instructie op om deze uit te voeren. U kunt ook één SQLStatement-instantie voor alle SQLinstructies gebruiken, waarbij de eigenschap text van de instantie elke keer opnieuw wordt gedefinieerd voordat de instructie wordt uitgevoerd. Deze techniek wordt echter afgeraden. Zie “Gebruik één SQLStatement-instantie per SQL-instructie” op pagina 199 voor meer informatie.
Gebruik instructieparameters Gebruik SQLStatement-parameters en voeg gebruikersinvoer niet samen tot instructietekst. Het gebruik van parameters maakt uw toepassing veiliger omdat het SQL-injectieaanvallen onmogelijk maakt. Hierdoor kunt u objecten gebruiken in query’s (in plaats van alleen literale SQL-waarden). Bovendien worden de instructies efficiënter uitgevoerd omdat ze opnieuw kunnen worden gebruikt zonder dat ze opnieuw hoeven te worden gecompileerd elke keer dat ze worden uitgevoerd. Zie “Parameters gebruiken in instructies” op pagina 179 voor meer informatie.
Gebruik constanten voor kolom- en parameternamen Als u geen itemClass voor een SQLStatement opgeeft, moet u om spelfouten te voorkomen tekenreeksconstanten definiëren die de naam van de kolommen in een tabel bevatten. Gebruik deze constanten in de instructietekst en voor de eigenschapnamen bij het ophalen van waarden van resultaatobjecten. Gebruik ook voor parameternamen constanten.
203
Hoofdstuk 19: Gecodeerde gegevens opslaan De Adobe® AIR™-runtime beschikt over een permanente gecodeerde lokale opslag voor elke AIR-toepassing die op de computer van een gebruiker is geïnstalleerd. Hier kunt u gegevens opslaan en ophalen die op de lokale vaste schijf van de gebruikers zijn opgeslagen in een gecodeerde indeling die niet gemakkelijk kan worden ontcijferd door andere toepassingen of gebruikers. Voor elke AIR-toepassing wordt een afzonderlijke gecodeerde lokale opslag gebruikt en elke AIR-toepassing gebruikt een afzonderlijke gecodeerde lokale opslag voor elke gebruiker. In de gecodeerde lokale opslag kunt u informatie opslaan die moet worden beveiligd, zoals aanmeldingsgegevens voor webservices. AIR maakt in Windows van DPAPI en in Mac OS van KeyChain gebruik om de gecodeerde lokale opslag te koppelen aan elke toepassing en gebruiker. De gecodeerde lokale opslag gebruikt AES-CBC 128-bits codering. Informatie in de gecodeerde lokale opslag is alleen beschikbaar voor de inhoud van een AIR-toepassing in de toepassingsbeveiligingssandbox. Gebruik de statische methoden setItem() en removeItem() van de klasse EncryptedLocalStore om gegevens in de lokale opslag op te slaan en op te halen. De gegevens worden opgeslagen in een hashtabel, waarbij tekenreeksen worden gebruikt als sleutels en de gegevens worden opgeslagen als bytearrays. Met de volgende code wordt bijvoorbeeld een tekenreeks opgeslagen in de gecodeerde lokale opslag: 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"
De derde parameter van de methode setItem(), de parameter stronglyBound, is optioneel. Wanneer deze parameter op true is ingesteld, is de gecodeerde lokale opslag beter beveiligd doordat het opgeslagen item wordt gebonden aan de digitale handtekening en bits van de opslaande AIR-toepassing en aan de uitgevers-id van de toepassing, wanneer: var str:String = "Bob"; var bytes:ByteArray = new ByteArray(); bytes.writeUTFBytes(str); EncryptedLocalStore.setItem("firstName", bytes, true);
Voor een item dat is opgeslagen terwijl stronglyBound op true is ingesteld, zullen volgende oproepen van getItem() alleen slagen als de oproepende AIR-toepassing identiek is aan de opslaande toepassing (als er geen gegevens in bestanden in de toepassingsmap zijn gewijzigd). Als de oproepende AIR-toepassing niet identiek is aan de opslaande toepassing, genereert de toepassing een uitzonderingsfout wanneer u getItem() oproept voor een sterk gebonden item. Als u uw toepassing bijwerkt, kan deze geen sterk gebonden gegevens lezen die eerder in de gecodeerde lokale opslag zijn geschreven.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 204 Gecodeerde gegevens opslaan
Standaard kan een AIR-toepassing de gecodeerde lokale opslag van een andere toepassing niet lezen. Met de instelling stronglyBound zijn items extra sterk gebonden (aan de gegevens in de toepassingsbits) waardoor wordt voorkomen dat een schadelijke toepassing gegevens in de gecodeerde lokale opslag van uw toepassing kan lezen door de uitgeversid van uw toepassing te kapen. Als u een toepassing bijwerkt voor het gebruik van een ander handtekeningcertificaat (met een migratiehandtekening), heeft de bijgewerkte versie geen toegang tot de items in de oorspronkelijke opslag, zelfs niet als de parameter stronglyBound op false was ingesteld. Zie “Certificaten wijzigen” op pagina 309 voor meer informatie. U kunt een waarde uit de gecodeerde lokale opslag verwijderen met de methode EncryptedLocalStore.removeItem(), zoals in het volgende voorbeeld: EncryptedLocalStore.removeItem("firstName");
U kunt alle gegevens in de gecodeerde lokale opslag wissen door de methode EncryptedLocalStore.reset() op te roepen, zoals in het volgende voorbeeld: EncryptedLocalStore.reset();
Bij het opsporen van fouten in een toepassing in ADL (AIR Debug Launcher) gebruikt de toepassing een andere gecodeerde lokale opslag dan de opslag die wordt gebruikt in de geïnstalleerde versie van de toepassing. De gecodeerde lokale opslag kan langzamer werken als de opgeslagen hoeveelheid gegevens groter is dan 10 MB. Wanneer u een AIR-toepassing verwijdert, worden de gegevens die in de gecodeerde lokale opslag zijn opgeslagen, niet verwijderd. De gegevens van de gecodeerde lokale opslag worden in een submap van de map met toepassingsgegevens van de gebruiker geplaatst; het pad van deze submap is Adobe/AIR/ELS/ gevolgd door de toepassings-id.
205
Hoofdstuk 20: Informatie over de HTMLomgeving Adobe®AIR™ maakt gebruik van WebKit (www.webkit.org), dat ook wordt gebruikt door de webbrowser Safari, om HTML- en JavaScript-inhoud te parseren, in te delen en weer te geven. Het gebruik van de AIR API's in HTML-inhoud is optioneel. U kunt de inhoud van een HTMLLoader-object of HTML-venster geheel in HTML en JavaScript programmeren. De meeste bestaande HTML-pagina's en -toepassingen kunnen normaal gesproken met weinig wijzigingen worden uitgevoerd (mits ze gebruikmaken van HTML-, CSS-, DOM- en JavaScript-functies die compatibel zijn met WebKit). Aangezien AIR-toepassingen rechtstreeks op de desktopcomputer worden uitgevoerd, met volledige toegang tot het bestandssysteem, is het beveiligingsmodel voor HTML-inhoud strenger dan het beveiligingsmodel van een typische webbrowser. In AIR wordt alleen inhoud die wordt geladen uit de installatiemap van de toepassing geplaatst in de toepassingssandbox. De toepassingssandbox heeft het hoogste machtigingsniveau en biedt toegang tot de AIR API's. AIR plaatst andere inhoud in geïsoleerde sandboxen op basis van de locatie waar deze inhoud vandaan komt. Bestanden die zijn geladen uit het bestandssysteem, gaan naar een lokale sandbox. Bestanden die zijn geladen van het netwerk met behulp van het protocol http: of https:, gaan naar een sandbox op basis van het domein van de externe server. Inhoud in deze niet-toepassingssandboxen krijgt geen toegang tot AIR API's en wordt uitgevoerd op dezelfde manier als bij een normale webbrowser. AIR maakt gebruik van WebKit (www.webkit.org), dat ook wordt gebruikt door de webbrowser Safari, om HTML- en JavaScript-inhoud te parseren, in te delen en weer te geven. De ingebouwde hostklassen en -objecten van AIR bieden een API voor functies die traditioneel worden gekoppeld aan desktoptoepassingen. Het gaat hierbij bijvoorbeeld over het lezen en schrijven van bestanden en het beheer van vensters. Adobe AIR neemt ook de API's over van Adobe® Flash® Player. Het gaat hierbij bijvoorbeeld over functies als geluid en binaire sockets. HTML-inhoud in AIR geeft geen SWF- of PDF-inhoud weer wanneer alfa-, schaal- of transparantie-instellingen worden toegepast. Meer informatie kunt u vinden in Belangrijke opmerkingen voor het laden van SWF- of PDFinhoud in een HTML-pagina en “Venstertransparantie” op pagina 62.
Overzicht van de HTML-omgeving Adobe AIR biedt een volledige browserachtige JavaScript-omgeving met een HTML-renderer, documentobjectmodel en JavaScript-interpreter. De JavaScript-omgeving wordt vertegenwoordigd door de AIR-klasse HTMLLoader. In HTML-vensters bevat een HTMLLoader-object alle HTML-inhoud. Dit object bevindt zich op zijn beurt weer in een NativeWindow-object. In SWF-inhoud kan de klasse HTMLLoader, die een uitbreiding vormt van de klasse Sprite, worden toegevoegd aan de weergavelijst van een stage, net als ieder ander weergaveobject. De ActionScript™eigenschappen van de klasse worden beschreven in “Scripts schrijven voor de HTML-container” op pagina 246 en ook in Flex 3 ActionScript Language Reference.
Informatie over de JavaScript-omgeving en de relatie met AIR In het volgende diagram wordt de relatie geïllustreerd tussen de JavaScript-omgeving en de AIR-runtimeomgeving. Er wordt maar één native venster weergegeven. Een AIR-toepassing kan echter meerdere vensters bevatten. (En een venster kan meerdere HTMLLoader-objecten bevatten.)
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 206 Informatie over de HTML-omgeving
AIR-runtime-omgeving
NativeWindow
HTMLLoader venster JavaScriptomgeving venster
venster
hoofdtekst
htmlLoader
kop
native4Window
runtime h1
div
tabel
p
De JavaScript-omgeving heeft zijn eigen Document- en Window-objecten. JavaScript-code kan interageren met de AIR-runtimeomgeving via de eigenschappen runtime, nativeWindow en htmlLoader. ActionScript-code kan interageren met de JavaScript-omgeving via de eigenschap window van een HTMLLoader-object, dat een referentie vormt naar het JavaScript Window-object. Verder kunnen zowel ActionScript- als JavaScript-objecten luisteren naar gebeurtenissen die zijn verzonden door zowel AIR- als JavaScript-objecten.
De eigenschap runtime geeft toegang tot AIR API-klassen zodat u nieuwe AIR-objecten en ook toegangsklasseleden (statische leden) kunt maken. Als u een AIR API wilt openen, voegt u de naam van de klasse (met pakket) toe aan de eigenschap runtime. Als u bijvoorbeeld een File-object wilt maken, gebruikt u de volgende opdracht: var file = new window.runtime.filesystem.File();
Opmerking: De AIR SDK bevat een JavaScript-bestand, AIRAliases.js, waarin aanvullende handige aliassen voor de meestgebruikte AIR-klassen worden gedefinieerd. Als u dit bestand importeert, kunt u de korte vorm air.Class gebruiken in plaats van window.runtime.package.Class. U kunt bijvoorbeeld het File-object maken met new air.File(). Het NativeWindow-object bevat eigenschappen voor het beheer van het bureaubladvenster. Vanuit een HTMLpagina kunt u toegang krijgen tot het omvattende NativeWindow-object met behulp van de eigenschap window.nativeWindow. Het HTMLLoader-object bevat eigenschappen, methoden en gebeurtenissen voor het beheer van de manier waarop inhoud wordt geladen en weergegeven. Vanuit een HTML-pagina kunt u toegang krijgen tot het bovenliggende HTMLLoader-object met behulp van de eigenschap window.htmlLoader.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 207 Informatie over de HTML-omgeving
Belangrijk: Alleen pagina's die zijn geïnstalleerd als onderdeel van een toepassing, hebben de eigenschap htmlLoader, nativeWindow of runtime. Ze hebben deze eigenschappen alleen wanneer ze zijn geladen als document van het hoogste niveau. Deze eigenschappen worden niet toegevoegd wanneer een document wordt geladen in een frame of iframe. (Een onderliggend document kan toegang krijgen tot deze eigenschappen van het bovenliggende document, zolang het onderliggende document zich bevindt in dezelfde beveiligingssandbox. Een document dat bijvoorbeeld is geladen in een frame, kan toegang krijgen tot de eigenschap runtime van het bovenliggende document met behulp van parent.runtime.)
Informatie over beveiliging AIR voert alle code binnen een beveiligingssandbox uit op basis van het brondomein. Toepassingsinhoud, die beperkt is tot inhoud die is geladen uit de installatiemap van de toepassing, wordt geplaatst in de toepassingssandbox. Toegang tot de runtimeomgeving en de AIR API's is alleen beschikbaar voor HTML en JavaScript die worden uitgevoerd binnen deze sandbox. Tegelijkertijd wordt de meeste dynamische evaluatie en uitvoering van JavaScript geblokkeerd in de toepassingssandbox nadat alle handlers voor de paginagebeurtenis load zijn geretourneerd. U kunt een toepassingspagina toewijzen in een niet-toepassingssandbox door de pagina te laden in een frame of iframe en de AIR-specifieke kenmerken sandboxRoot en documentRoot van het frame in te stellen. Door de waarde sandboxRoot in te stellen op een werkelijk extern domein, kunt u de sandboxinhoud inschakelen zodat u inhoud in dat domein kunt cross-scripten. Het toewijzen van pagina's op deze manier kan nuttig zijn bij het laden en scripten van externe inhoud, bijvoorbeeld in een mash-up-toepassing. Een andere manier om toepassings- en niet-toepassingsinhoud in staat te stellen om elkaar te cross-scripten, en de enige manier om niet-toepassingsinhoud toegang te geven tot AIR API's, is het maken van een sandboxbridge. Een bovenliggende-onderliggende bridge maakt het mogelijk voor inhoud in een onderliggend frame, iframe of venster om toegang te krijgen tot speciaal aangewezen methoden en eigenschappen die zijn gedefinieerd in de toepassingssandbox. Een onderliggende-bovenliggende bridge daarentegen maakt het toepassingsinhoud mogelijk om toegang te krijgen tot bepaalde methoden en eigenschappen die zijn gedefinieerd in de sandbox van de onderliggende. Sandboxbridges worden gecreëerd door de eigenschappen parentSandboxBridge en childSandboxBridge van het Window-object in te stellen. Zie “Beveiliging in HTML” op pagina 31 en “Frame- en iframe-elementen in HTML” op pagina 215 voor meer informatie.
Informatie over invoegtoepassingen en ingesloten objecten AIR ondersteunt de invoegtoepassing Adobe ® Acrobat®. Gebruikers moeten beschikken over Acrobat of Adobe® Reader® 8.1 (of hoger) om PDF-inhoud te kunnen weergeven. Het HTMLLoader-object biedt een eigenschap waarmee kan worden gecontroleerd of het systeem van een gebruiker PDF kan weergeven. SWF-bestandsinhoud kan ook worden weergegeven binnen de HTML-omgeving. Deze functie is echter ingebouwd in AIR en maakt geen gebruik van een externe invoegtoepassing. Er worden geen andere Webkit-invoegtoepassingen ondersteund in AIR.
Zie ook “Beveiliging in HTML” op pagina 31 “Sandboxen in HTML” op pagina 208 “Frame- en iframe-elementen in HTML” op pagina 215 “JavaScript-object Window” op pagina 214 “XMLHttpRequest-objecten” op pagina 209 “PDF-inhoud toevoegen” op pagina 260
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 208 Informatie over de HTML-omgeving
AIR- en Webkit-extensies Adobe AIR maakt gebruik van de open source Webkit-engine, die ook wordt gebruikt in de webbrowser Safari. AIR voegt verschillende extensies toe waarmee toegang tot de runtimeklassen en -objecten mogelijk is. Deze extensies hebben ook een functie bij de beveiliging. Verder voegt Webkit zelf functies toe die niet zijn opgenomen in de W3Cstandaarden voor HTML, CSS en JavaScript. Alleen de AIR-toevoegingen en de belangrijkste Webkit-extensies worden hier behandeld. Documentatie over nietstandaard HTML, CSS en JavaScript vindt u in www.webkit.org en developer.apple.com. Informatie over standaarden vindt u op de W3C-website. Mozilla biedt ook een waardevolle algemene referentie over HTML-, CSS- en DOMonderwerpen (de Webkit-engine is niet identiek aan de Mozilla-engine). Opmerking: AIR ondersteunt niet de volgende standaard en uitgebreide WebKit-functies: de JavaScript Window objectmethode print(), invoegtoepassingen, behalve Acrobat of Adobe Reader 8.1+, SVG (Scalable Vector Graphics) en de CSS-eigenschap opacity.
JavaScript in AIR AIR brengt een aantal wijzigingen aan in het normale gedrag van veelgebruikte JavaScript-objecten. Veel van deze wijzigingen worden aangebracht om het gemakkelijker te maken veilige toepassingen in AIR te schrijven. Deze verschillen in gedrag betekenen echter ook dat bepaalde veelgebruikte JavaScript-coderingspatronen en bestaande webtoepassingen die gebruikmaken van die patronen, niet altijd zoals verwacht zullen worden uitgevoerd in AIR. Zie “JavaScript-beveiligingsfouten voorkomen” op pagina 222 voor meer informatie over het corrigeren van dit soort problemen.
Sandboxen in HTML AIR plaatst inhoud in geïsoleerde sandboxen afhankelijk van de oorsprong van de inhoud. De sandboxregels zijn consistent met het zelfde-oorsprongbeleid dat wordt geïmplementeerd door de meeste webbrowsers. Ze zijn ook consistent met de regels voor sandboxen die worden geïmplementeerd door Adobe Flash Player. Verder biedt AIR het nieuwe sandboxtype toepassing, waarmee toepassingsinhoud kan worden opgeslagen en beveiligd. Zie “Sandboxen” op pagina 28 voor meer informatie over de typen sandboxen die u kunt tegenkomen bij de ontwikkeling van AIRtoepassingen. Toegang tot de runtimeomgeving en de AIR API's is alleen beschikbaar voor HTML en JavaScript die worden uitgevoerd binnen de toepassingssandbox. Tegelijkertijd wordt dynamische evaluatie en uitvoering van de verschillende vormen van JavaScript uit veiligheidsoverwegingen voor een groot deel beperkt binnen de toepassingssandbox. Deze beperkingen gelden altijd, ongeacht of de toepassing rechtstreeks informatie van een server laadt. (Zelfs bestandsinhoud, geplakte tekenreeksen en gegevens die rechtstreeks door de gebruiker worden ingevoerd, kunnen onbetrouwbaar zijn.) De oorsprong van de inhoud in een pagina bepaalt de sandbox waaraan deze wordt toegewezen. Alleen inhoud die is geladen vanuit de toepassingsmap (de installatiemap waarnaar wordt verwezen door het URL-schema app:) wordt in de toepassingssandbox geplaatst. Inhoud die wordt geladen vanuit het bestandssysteem, wordt in de lokaal-metbestandssysteem of lokaal-vertrouwde sandbox geplaatst, waarmee toegang tot en interactie met het lokale bestandssysteem mogelijk is, maar niet met externe inhoud. Inhoud die wordt geladen vanaf het netwerk, wordt in een externe sandbox geplaatst die correspondeert met het brondomein.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 209 Informatie over de HTML-omgeving
Als een toepassingspagina toestemming moet hebben om desgewenst te interageren met inhoud in een externe sandbox, kan die pagina worden toegewezen aan hetzelfde domein als de externe inhoud. Als u bijvoorbeeld een toepassing schrijft waarin kaartgegevens uit een internetservice worden weergegeven, kan de pagina van deze toepassing waarin inhoud van de service wordt geladen en weergegeven, worden toegewezen aan het servicedomein. De kenmerken voor het toewijzen van pagina's aan externe sandboxen en domeinen zijn nieuwe kenmerken die worden toegevoegd aan de frame- en iframe-elementen in HTML. Als u inhoud in een niet-toepassingssandbox wilt toestaan om veilig AIR-functies te gebruiken, kunt u een bovenliggende sandboxbridge instellen. Als u toepassingsinhoud wilt toestaan om veilig methoden en toegangseigenschappen van inhoud in andere sandboxen te benaderen, kunt u een onderliggende sandboxbridge instellen. Veilig betekent hier dat externe inhoud niet per ongeluk verwijzingen kan ophalen naar objecten, eigenschappen of methoden die niet expliciet beschikbaar zijn gemaakt. Alleen eenvoudige gegevenstypen, functies en anonieme objecten kunnen via de bridge worden doorgegeven. U moet echter nog steeds voorkomen dat potentieel gevaarlijke functies expliciet beschikbaar worden gemaakt. Als u bijvoorbeeld een interface beschikbaar hebt gemaakt waarmee externe inhoud bestanden op iedere willekeurige locatie in het systeem van een gebruiker kan lezen en schrijven, biedt u externe inhoud mogelijk kans om uw gebruikers grote schade te berokkenen.
De JavaScript-functie eval() Het gebruik van de functie eval() is beperkt binnen de toepassingssandbox als een pagina eenmaal is geladen. Sommige vormen van gebruik zijn toegestaan, zodat gegevens met JSON-indeling veilig kunnen worden geparseerd. Een evaluatie die uitvoerbare instructies als gevolg heeft, resulteert echter altijd in een fout. “Codebeperkingen voor de inhoud van verschillende sandboxen” op pagina 33 beschrijft het toegestane gebruik van de functie eval().
Functieconstructors In de toepassingssandbox kunnen functieconstructors worden gebruikt voordat een pagina geheel is geladen. Nadat alle handlers voor de paginagebeurtenis load zijn voltooid, kunnen geen nieuwe functies meer worden gemaakt.
Externe scripts laden HTML-pagina's in de toepassingssandbox kunnen geen scripttags gebruiken om JavaScript-bestanden te laden van buiten de toepassingsmap. Als een pagina in uw toepassing een script van buiten de toepassingsmap moet laden, moet die pagina worden toegewezen aan een niet-toepassingssandbox.
XMLHttpRequest-objecten AIR is voorzien van een XHR-object (XMLHttpRequest), waarmee toepassingen gegevens kunnen aanvragen. In het volgende voorbeeld ziet u een eenvoudige gegevensaanvraag: 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);
In tegenstelling tot een browser is het bij AIR mogelijk dat inhoud die wordt uitgevoerd in de toepassingssandbox, gegevens uit elk willekeurig domein aanvraagt. Het resultaat van een XHR die een JSON-tekenreeks bevat, kan worden geëvalueerd in gegevensobjecten, behalve als het resultaat ook uitvoerbare code bevat. Als het XHR-resultaat ook uitvoerbare instructies bevat, treedt er een fout op en mislukt de evaluatiepoging.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 210 Informatie over de HTML-omgeving
Om te voorkomen dat code uit externe bronnen per ongeluk wordt ingebracht, retourneren synchrone XHR's een leeg resultaat als ze zijn gemaakt voordat een pagina geheel is geladen. Asynchrone XHR's worden altijd geretourneerd nadat een pagina is geladen. AIR blokkeert standaard domeinoverschrijdende XMLHttpRequests in niet-toepassingssandboxen. Een bovenliggend venster in de toepassingssandbox kan ervoor kiezen domeinoverschrijdende aanvragen in een onderliggend frame dat inhoud in een niet-toepassingssandbox bevat, toe te staan door het kenmerk allowCrossDomainXHR, dat wordt toegevoegd door AIR, in te stellen op true in het omvattende frame- of iframe-element: <iframe id="mashup" src="http://www.example.com/map.html" allowCrossDomainXHR="true"
Opmerking: Desgewenst kan de AIR-klasse URLStream ook worden gebruikt om gegevens te downloaden. Als u een XMLHttpRequest naar een externe server stuurt vanuit een frame of iframe dat toepassingsinhoud bevat die is toegewezen aan een externe sandbox, moet u ervoor zorgen dat de toewijzende URL het serveradres dat in de XHR wordt gebruikt, niet maskeert. Bekijk bijvoorbeeld de volgende iframe-definitie, die toepassingsinhoud toewijst in een externe sandbox voor het domein example.com: <iframe id="mashup" src="http://www.example.com/map.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/" allowCrossDomainXHR="true"
Omdat het kenmerk sandboxRoot de basis-URL van het adres www.example.com opnieuw toewijst, worden alle aanvragen geladen vanuit de toepassingsmap en niet vanaf de externe server. Aanvragen worden altijd opnieuw toegewezen, ongeacht of ze afkomstig zijn van paginanavigatie of een XMLHttpRequest. Om te voorkomen dat gegevensaanvragen naar de externe server per ongeluk worden geblokkeerd, wijst u sandboxRoot toe aan een submap van de externe URL en niet aan de hoofdmap. Die map hoeft niet echt te bestaan.
Als u bijvoorbeeld wilt toestaan dat aanvragen naar www.example.com gegevens laden vanaf de externe server en niet uit de toepassingsmap, verandert u het vorige iframe-element in de volgende: <iframe id="mashup" src="http://www.example.com/map.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/" allowCrossDomainXHR="true"
In dit geval wordt alleen de inhoud van de submap air lokaal geladen. Zie “Frame- en iframe-elementen in HTML” op pagina 215 en “Beveiliging in HTML” op pagina 31 voor meer informatie over de toewijzing van sandboxen.
Canvas-objecten Het Canvas-object definieert een API voor het tekenen van geometrische vormen zoals lijnen, bogen, ellipsen en veelhoeken. Als u de API voor Canvas wilt gebruiken, voegt u eerst een Canvas-element toe aan het document en tekent u daar vervolgens in met behulp van de JavaScript-API voor Canvas. In de meeste andere opzichten gedraagt het Canvas-object zich als een afbeelding. In het volgende voorbeeld ziet u hoe u een driehoek tekent met behulp van een Canvas-object:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 211 Informatie over de HTML-omgeving
<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();
Zie de Safari JavaScript Reference van Apple voor meer informatie over de API voor Canvas. Het Webkit-project is onlangs begonnen met het aanpassen van de API voor Canvas ten einde deze te standaardiseren volgens de HTML 5 Working Draft die is voorgesteld door WHATWG (Web Hypertext Application Technology Working Group) en W3C. Als gevolg daarvan kan een deel van de documentatie in de Safari JavaScript Reference inconsistent zijn met de Canvas-versie die wordt gepresenteerd in AIR.
Cookies In AIR-toepassingen kan alleen inhoud in externe sandboxen (inhoud die is geladen vanaf bronnen van het type http: en https:) gebruikmaken van cookies (de eigenschap document.cookie). In de toepassingssandbox bieden AIR API's andere manieren om permanente gegevens op te slaan (zoals de klassen EncryptedLocalStore en FileStream).
Clipboard-objecten De WebKit-API voor Clipboard wordt aangestuurd door de volgende gebeurtenissen: copy, cut en paste. Het gebeurtenisobject dat bij deze gebeurtenissen wordt doorgegeven, geeft via de eigenschap clipboardData toegang tot het klembord. Gebruik de volgende methoden van het object clipboardData om klembordgegevens te lezen of te schrijven: Methode
Beschrijving
clearData(mimeType)
Hiermee wist u de klembordgegevens. Stel de parameter mimeType in op het MIME-type van de gegevens die u wilt wissen.
getData(mimeType)
Hiermee haalt u de klembordgegevens op. Deze methode kan alleen worden opgeroepen in een handler voor de gebeurtenis paste. Stel de parameter mimeType in op het MIME-type van de gegevens die u wilt retourneren.
setData(mimeType, data)
Hiermee kopieert u gegevens naar het klembord. Stel de parameter mimeType in op het MIME-type van de gegevens.
JavaScript-code buiten de toepassingssandbox kan alleen via deze gebeurtenissen toegang krijgen tot het klembord. Inhoud in de toepassingssandbox kan echter rechtstreeks toegang krijgen tot het systeemklembord via de AIR-klasse Clipboard. U kunt bijvoorbeeld de volgende opdracht gebruiken om gegevens over tekstopmaak op het klembord te krijgen: var clipping = air.Clipboard.generalClipboard.getData("text/plain", air.ClipboardTransferMode.ORIGINAL_ONLY);
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 212 Informatie over de HTML-omgeving
De volgende MIME-typen zijn geldig voor gegevens: MIME-type
Waarde
Tekst
"text/plain"
HTML
"text/html"
URL
"text/uri-list"
Bitmap
"image/x-vnd.adobe.air.bitmap"
Bestandenlijst
"application/x-vnd.adobe.air.file-list"
Belangrijk: Alleen inhoud in de toepassingssandbox kan toegang krijgen tot bestandsgegevens die aanwezig zijn op het klembord. Als niet-toepassingsinhoud probeert toegang te krijgen tot een bestandsobject vanaf het klembord, wordt een beveiligingsfout veroorzaakt. Zie “kopiëren en plakken” op pagina 147 en Using the Pasteboard from JavaScript (Apple Developer Center) voor meer informatie over het gebruik van het klembord.
Slepen en neerzetten: Het slepen en neerzetten in en uit HTML produceert de volgende DOM-gebeurtenissen: dragstart, drag, dragend, dragenter, dragover, dragleave en drop. Het gebeurtenisobject dat bij deze gebeurtenissen wordt doorgegeven, geeft via de eigenschap dataTransfer toegang tot de gesleepte gegevens. De eigenschap dataTransfer verwijst naar een object dat dezelfde methoden biedt als het clipboardData-object dat is gekoppeld aan een gebeurtenis van het type clipboard. U kunt bijvoorbeeld de volgende functie gebruiken om tekstopmaakgegevens van de gebeurtenis drop te krijgen: function onDrop(dragEvent){ return dragEvent.dataTransfer.getData("text/plain", air.ClipboardTransferMode.ORIGINAL_ONLY); }
Het dataTransfer-object heeft de volgende belangrijke leden: Lid
Beschrijving
clearData(mimeType)
Hiermee wist u de gegevens. Stel de parameter mimeType in op het MIME-type van de gegevensrepresentatie die u wilt wissen.
getData(mimeType)
Hiermee haalt u de gesleepte gegevens op. Deze methode kan alleen worden opgeroepen in een handler voor de gebeurtenis drop. Stel de parameter mimeType in op het MIME-type van de gegevens die u wilt ophalen.
setData(mimeType, data)
Hiermee stelt u de gegevens in die moeten worden gesleept. Stel de parameter mimeType in op het MIMEtype van de gegevens.
types
Een array van tekenreeksen die de MIME-typen bevat van alle gegevensrepresentaties die nu beschikbaar zijn in het dataTransfer-object.
effectsAllowed
Hiermee geeft u aan of de gesleepte gegevens kunnen worden gekopieerd, verplaatst, gekoppeld of een combinatie daarvan. Stel de eigenschap effectsAllowed in de handler voor de gebeurtenis dragstart in.
dropEffect
Hiermee geeft u aan welke van de toegestane neerzeteffecten (drop) worden ondersteund door een sleepdoel (drag). Stel de eigenschap dropEffect in de handler voor de gebeurtenis dragEnter in. Tijdens het slepen verandert de cursor van vorm. Deze geeft aan wat voor effect er zou optreden als de gebruiker de muis loslaat. Als er geen dropEffect is opgegeven, wordt een eigenschapseffect uit effectsAllowed gekozen. Het kopieereffect (copy) heeft prioriteit over het verplaatsingseffect (move), en dat heeft weer prioriteit over het koppelingseffect (link). De gebruiker kan de standaardprioriteit wijzigen met behulp van het toetsenbord.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 213 Informatie over de HTML-omgeving
Zie “Slepen en neerzetten” op pagina 131 en Using the Drag-and-Drop from JavaScript (Apple Developer Center) voor meer informatie over het toevoegen van ondersteuning voor slepen en neerzetten aan een AIR-toepassing.
De eigenschappen innerHTML en outerHTML AIR stelt beveiligingsbeperkingen in voor het gebruik van de eigenschappen innerHTML en outerHTML voor het uitvoeren van inhoud in de toepassingssandbox. Voordat de paginagebeurtenis load optreedt en terwijl eventuele gebeurtenishandlers voor load worden uitgevoerd, gelden er geen beperkingen voor het gebruik van de eigenschappen innerHTML en outerHTML. Als de pagina echter is geladen, kunt u de eigenschap innerHTML of outerHTML alleen gebruiken om statische inhoud toe te voegen aan het document. Eventuele opdrachten die zich bevinden in de tekenreeks die is toegewezen aan innerHTML of outerHTML en die worden geëvalueerd naar uitvoerbare code, worden genegeerd. Als u bijvoorbeeld een kenmerk om een gebeurtenis terug te roepen (callback) opneemt in een elementdefinitie, wordt de gebeurtenislistener niet toegevoegd. Op dezelfde manier worden ingesloten tags van het type <script> niet geëvalueerd. Zie “Beveiliging in HTML” op pagina 31 voor meer informatie.
De methoden Document.write() en Document.writeln() Het gebruik van de methoden write()en writeln() is niet beperkt in de toepassingssandbox vóór de paginagebeurtenis load. Als de pagina echter is geladen, wordt bij het oproepen van een van deze methoden de pagina niet gewist en wordt er ook geen nieuwe pagina gemaakt. In een niet-toepassingssandbox wordt, net zoals bij de meeste webbrowsers, door het oproepen van document.write() of writeln() nadat een pagina geheel is geladen, de huidige pagina gewist en wordt een nieuwe lege pagina geopend.
De eigenschap Document.designMode Hiermee stelt u de eigenschap document.designMode in op de waarde on als u alle elementen in het document bewerkbaar wilt maken. Met de ingebouwde editor kunt u tekst bewerken, kopiëren, plakken, slepen en neerzetten. Het instellen van designMode op on is equivalent met het instellen van de eigenschap contentEditable van het element body op true. U kunt de eigenschap contentEditable voor de meeste HTML-elementen gebruiken om te definiëren welke secties van een document kunnen worden bewerkt. Zie “Het HTML-kenmerk contentEditable” op pagina 218 voor meer informatie.
unload-gebeurtenissen (voor body- en frameset-objecten) In de tag frameset of body van het bovenste niveau van een venster (inclusief het hoofdvenster van de toepassing), mag u de gebeurtenis unload niet gebruiken om te reageren op het venster dat of de toepassing die wordt gesloten. In plaats daarvan gebruikt u de gebeurtenis exiting van het NativeApplication-object (om te bepalen wanneer een toepassing wordt gesloten). U kunt ook de gebeurtenis closing van het NativeApplication-object gebruiken (om te bepalen wanneer een toepassing wordt gesloten). De volgende JavaScript-code geeft bijvoorbeeld het bericht "Goodbye" weer wanneer de gebruiker de toepassing sluit: var app = air.NativeApplication.nativeApplication; app.addEventListener(air.Event.EXITING, closeHandler); function closeHandler(event) { alert("Goodbye."); }
Scripts kunnen echter wel succesvol reageren op de gebeurtenis unload die wordt veroorzaakt door navigatie van een frame, iframe of vensterinhoud van het bovenste niveau. Opmerking: In een volgende versie van Adobe AIR worden deze beperkingen mogelijk verwijderd.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 214 Informatie over de HTML-omgeving
JavaScript-object Window Het Window-object blijft het globale object binnen de JavaScript-uitvoeringscontext. In de toepassingssandbox voegt AIR nieuwe eigenschappen toe aan het JavaScript-object Window ten einde toegang te geven tot de ingebouwde AIRklassen en belangrijke hostobjecten. Verder vertonen bepaalde methoden en eigenschappen binnen de toepassingssandbox ander gedrag dan daarbuiten. De eigenschap Window.runtime De eigenschap runtime stelt u in staat om de ingebouwde runtimeklassen te
instantiëren en te gebruiken vanuit de toepassingssandbox. Deze klassen omvatten de AIR- en Flash Player-API's (maar bijvoorbeeld niet het Flex-framework). Met de volgende opdracht maakt u bijvoorbeeld een AIRbestandsobject: var preferencesFile = new window.runtime.flash.filesystem.File();
Het bestand AIRAliases.js, dat zich bevindt in de AIR SDK, bevat aliasdefinities waarmee u dergelijke verwijzingen kunt verkorten. Als AIRAliases.js bijvoorbeeld in een pagina wordt geïmporteerd, kan een File-object worden gemaakt met de volgende opdracht: var preferencesFile = new air.File();
De eigenschap window.runtime is alleen gedefinieerd voor inhoud binnen de toepassingssandbox en alleen voor het bovenliggende document van een pagina met frames of iframes. Zie “Het bestand AIRAliases.js gebruiken” op pagina 227. De eigenschap Window.nativeWindow De eigenschap nativeWindow biedt een verwijzing naar het onderliggende
native Window-object. Met deze eigenschap kunt u vensterfuncties en eigenschappen zoals schermpositie, grootte en zichtbaarheid in een script opnemen. Ook kunt u venstergebeurtenissen zoals sluiten, grootte wijzigen en verplaatsen hiermee verwerken. Met de volgende opdracht sluit u bijvoorbeeld het venster: window.nativeWindow.close();
Opmerking: De functies voor vensterbesturing die worden geboden door het NativeWindow-object, overlappen de functies die worden geboden door het JavaScript-object Window. In dergelijke gevallen kunt u de methode gebruiken die u het handigst vindt. De eigenschap window.nativeWindow is alleen gedefinieerd voor inhoud binnen de toepassingssandbox en alleen voor het bovenliggende document van een pagina met frames of iframes. De eigenschap Window.htmlLoader De eigenschap htmlLoader biedt een referentie voor het AIR-object
HTMLLoader dat de HTML-inhoud bevat. Met deze eigenschap kunt u het uiterlijk en het gedrag van de HTMLomgeving in een script opnemen. U kunt bijvoorbeeld de eigenschap htmlLoader.paintsDefaultBackground gebruiken om te bepalen of het besturingselement een standaard witte achtergrond gebruikt: window.htmlLoader.paintsDefaultBackground = false;
Opmerking: Het HTMLLoader-object zelf heeft een eigenschap window die verwijst naar het JavaScript-object Window van de HTML-inhoud die het bevat. U kunt deze eigenschap gebruiken om toegang te krijgen tot de JavaScript-omgeving via een verwijzing naar de bevattende HTMLLoader. De eigenschap window.htmlLoader is alleen gedefinieerd voor inhoud binnen de toepassingssandbox en alleen voor het bovenliggende document van een pagina met frames of iframes. De eigenschappen Window.parentSandboxBridge en Window.childSandboxBridge Met de eigenschappen parentSandboxBridge en childSandboxBridge kunt u een interface definiëren tussen een bovenliggend en een onderliggend frame. Zie “Cross-scripting van inhoud in verschillende beveiligingssandboxen” op pagina 235 voor meer informatie.
De functies Window.setTimeout() en Window.setInterval() AIR past beveiligingsbeperkingen toe op het gebruik van
de functies setTimeout() en setInterval() binnen de toepassingssandbox. U kunt de code die moet worden
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 215 Informatie over de HTML-omgeving
uitgevoerd, niet definiëren als tekenreeks bij het oproepen van setTimeout() of setInterval(). U moet hiervoor een functieverwijzing gebruiken. Zie “setTimeout() en setInterval()” op pagina 225 voor meer informatie. De functie Window.open() Wanneer de methode open() wordt opgeroepen door code die wordt uitgevoerd in een niet-toepassingssandbox, wordt er als gevolg van gebruikersinteractie (bijvoorbeeld een muisklik of het indrukken van een toets) alleen een venster geopend. Verder staat de toepassingstitel vóór de venstertitel (om te verhinderen dat vensters die worden geopend door externe inhoud, zich voordoen als vensters die worden geopend door de toepassing). Zie “Beperkingen betreffende het oproepen van de JavaScript-methode window.open()” op pagina 36 voor meer informatie.
Het object air.NativeApplication Het NativeApplication-object biedt informatie over de toepassingsstatus, verzendt verschillende belangrijke gebeurtenissen op toepassingsniveau en biedt nuttige functies voor het beheer van het gedrag van de toepassing. Er wordt automatisch één instantie van het NativeApplication-object gemaakt. Deze kan worden benaderd via de door de klasse gedefinieerde eigenschap NativeApplication.nativeApplication. Om vanuit JavaScript-code toegang te krijgen tot het object, kunt u het volgende gebruiken: var app = window.runtime.flash.desktop.NativeApplication.nativeApplication;
Als het script AIRAliases.js is geïmporteerd, kunt u ook de kortere vorm gebruiken: var app = air.NativeApplication.nativeApplication;
U kunt het NativeApplication-object alleen benaderen vanuit de toepassingssandbox. Interactie met het besturingssysteem: “Werken met runtime- en besturingssysteeminformatie” op pagina 284 beschrijft het NativeApplication-object in detail.
Het JavaScript URL-schema Uitvoering van code die is gedefinieerd in een JavaScript URL-schema (zoals in href="javascript:alert('Test')"), wordt geblokkeerd binnen de toepassingssandbox. Er treedt geen fout op.
Extensies voor HTML AIR en WebKit definiëren een aantal niet-standaard HTML-elementen en -kenmerken, zoals: “Frame- en iframe-elementen in HTML” op pagina 215 “Het HTML-element Canvas” op pagina 217 “Gebeurtenishandlers voor HTML-elementen” op pagina 218
Frame- en iframe-elementen in HTML AIR voegt nieuwe kenmerken toe aan de frame- en iframe-elementen van inhoud in de toepassingssandbox: Het kenmerk sandboxRoot Het kenmerk sandboxRoot geeft een alternatief, niet-toepassingsbrondomein op voor het
bestand dat wordt opgegeven door het framekenmerk src. Het bestand wordt geladen in de niet-toepassingssandbox die correspondeert met het opgegeven domein. Inhoud in het bestand en inhoud die wordt geladen van het opgegeven domein, kan onderling cross-scripten. Belangrijk: Als u de waarde van sandboxRoot instelt op de basis-URL van het domein, worden alle aanvragen voor inhoud van dat domein geladen uit de toepassingsmap en niet vanaf de externe server (of die aanvraag nu resulteert uit paginanavigatie, uit een XMLHttpRequest of uit een andere manier om inhoud te laden).
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 216 Informatie over de HTML-omgeving
Het kenmerk documentRoot Het kenmerk documentRoot geeft de lokale map op waaruit URL's moeten worden
geladen die worden omgezet in bestanden in de locatie die wordt opgegeven door sandboxRoot. Bij het omzetten van URL's, of dit nu gebeurt bij het framekenmerk src dan wel in inhoud die in het frame wordt geladen, wordt het deel van de URL dat overeenkomt met de waarde die wordt opgegeven in sandboxRoot, vervangen door de waarde die wordt opgegeven in documentRoot. Bij de volgende frametag geldt dus: <iframe
src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/"/>
child.html wordt geladen uit de submap sandbox van de toepassingsinstallatiemap. Relatieve URL's in child.html
worden omgezet op basis van de map sandbox. Merk op dat bestanden op de externe server op www.example.com/airniet toegankelijk zijn in het frame, omdat AIR zou proberen ze te laden uit de map
app:/sandbox/. Het kenmerk allowCrossDomainXHR Neem de code allowCrossDomainXHR="allowCrossDomainXHR" op in de
openingsframetag als u wilt toestaan dat inhoud in het frame XMLHttpRequests uitvoert naar een willekeurig extern domein. Standaard kan niet-toepassingsinhoud dergelijke aanvragen alleen uitvoeren binnen het eigen brondomein. Het toestaan van XHR's naar andere domeinen heeft ernstige gevolgen voor de beveiliging. Code in de pagina kan gegevens uitwisselen met een willekeurig domein. Als er op de een of andere manier kwaadaardige inhoud in de pagina wordt ingebracht, kunnen alle gegevens die toegankelijk zijn voor code in de huidige sandbox, worden aangetast. Schakel alleen XHR's die andere domeinen kunnen bereiken in voor pagina's die u zelf maakt en beheert, en alleen als het laden van gegevens uit andere domeinen absoluut noodzakelijk is. Ook moet u alle externe gegevens die door de pagina worden geladen zorgvuldig valideren om te voorkomen dat code wordt ingebracht of dat andere aanvallen worden uitgevoerd. Belangrijk: Als het kenmerk allowCrossDomainXHR is opgenomen in een frame- of iframe-element, zijn XHR's naar andere domeinen ingeschakeld (behalve als de toegewezen waarde "0" is of begint met de letter "f" of "n"). Als u bijvoorbeeld allowCrossDomainXHR instelt op "deny" (weigeren), zijn XHR's naar andere domeinen nog steeds toegestaan. Laat het kenmerk helemaal weg uit de elementdeclaratie als u aanvragen naar andere domeinen niet wilt inschakelen. ondominitialize, kenmerk Geeft een gebeurtenishandler op voor de framegebeurtenis dominitialize. Dit is een
AIR-specifieke gebeurtenis die wordt geactiveerd wanneer de window- en document-objecten van het frame zijn gemaakt, maar voordat er scripts zijn geparseerd of documentelementen zijn gemaakt. Het frame verzendt de gebeurtenis dominitialize zo vroeg tijdens de uitvoering van de laadsequentie, dat eventuele scripts in de onderliggende pagina kunnen verwijzen naar objecten, variabelen en functies die door de handler dominitialize zijn toegevoegd aan het onderliggende document. De bovenliggende pagina kan alleen rechtstreeks objecten toevoegen aan of toegang krijgen tot objecten in een onderliggend document, als de bovenliggende pagina zich bevindt in dezelfde sandbox als de onderliggende. Een bovenliggende pagina in de toepassingssandbox kan echter wel een sandboxbridge tot stand brengen voor communicatie met inhoud in een niet-toepassingssandbox. In de volgende voorbeelden ziet u hoe u de iframe-tag in AIR gebruikt: Plaats child.html in een externe sandbox zonder toewijzing aan een werkelijk domein op een externe server: <iframe
src="http://localhost/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://localhost/air/"/>
Plaats child.html in een externe sandbox, waarbij XMLHttpRequests alleen zijn toegestaan voor www.example.com: <iframe
src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/"/>
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 217 Informatie over de HTML-omgeving
Plaats child.html in een externe sandbox, waarbij XMLHttpRequests zijn toegestaan voor een willekeurig extern domein: <iframe
src="http://www.example.com/air/child.html" documentRoot="app:/sandbox/" sandboxRoot="http://www.example.com/air/" allowCrossDomainXHR="allowCrossDomainXHR"/>
Plaats child.html in een lokaal-met-bestandssysteem sandbox: <iframe
src="file:///templates/child.html" documentRoot="app:/sandbox/" sandboxRoot="app-storage:/templates/"/>
Plaats child.html in een externe sandbox waarbij de gebeurtenis dominitialize wordt gebruikt om een sandboxbridge tot stand te brengen. <script> var bridgeInterface = {}; bridgeInterface.testProperty = "Bridge engaged"; function engageBridge(){ document.getElementById("sandbox").parentSandboxBridge = bridgeInterface; } <iframe id="sandbox" src="http://www.example.com/air/child.html" documentRoot="app:/" sandboxRoot="http://www.example.com/air/" ondominitialize="engageBridge()"/>
Het volgende document, child.html, illustreert hoe onderliggende inhoud de bovenliggende sandboxbridge kan benaderen: <script> document.write(window.parentSandboxBridge.testProperty);
Zie “Cross-scripting van inhoud in verschillende beveiligingssandboxen” op pagina 235 en “Beveiliging in HTML” op pagina 31 voor meer informatie.
Het HTML-element Canvas Hiermee definieert u een tekengebied voor gebruik met de Webkit-API voor Canvas. Opdrachten met betrekking tot afbeeldingen kunnen niet worden opgegeven in de tag zelf. Als u op het canvas wilt tekenen, roept u de canvastekenmethoden aan via JavaScript.
Zie “Canvas-objecten” op pagina 210 voor meer informatie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 218 Informatie over de HTML-omgeving
Gebeurtenishandlers voor HTML-elementen DOM-objecten in AIR en Webkit verzenden bepaalde gebeurtenissen die niet aanwezig zijn in het standaard DOMgebeurtenismodel. In de volgende tabel worden de verwante gebeurteniskenmerken aangegeven die u kunt gebruiken om handlers voor deze gebeurtenissen op te geven: Naam callbackkenmerk
Beschrijving
oncontextmenu
Wordt opgeroepen wanneer een contextmenu wordt opgeroepen, bijvoorbeeld door met de rechtermuisknop op geselecteerde tekst te klikken of de Command-toets ingedrukt te houden tijdens het klikken.
oncopy
Wordt opgeroepen wanneer een selectie in een element wordt gekopieerd.
oncut
Wordt opgeroepen wanneer een selectie in een element wordt geknipt.
ondominitialize
Wordt opgeroepen wanneer het DOM wordt gemaakt van een document dat is geladen in een frame of iframe, maar voordat eventuele DOM-elementen worden gemaakt of scripts geparseerd.
ondrag
Wordt opgeroepen wanneer een element wordt gesleept.
ondragend
Wordt opgeroepen wanneer een gesleept element wordt losgelaten.
ondragenter
Wordt opgeroepen wanneer een sleepbeweging de grenzen van een element bereikt.
ondragleave
Wordt opgeroepen wanneer een sleepbeweging de grenzen van een element verlaat.
ondragover
Wordt continu opgeroepen zolang een sleepbeweging zich binnen de grenzen van een element bevindt.
ondragstart
Wordt opgeroepen wanneer een sleepbeweging begint.
ondrop
Wordt opgeroepen wanneer een sleepbeweging wordt losgelaten boven een element.
onerror
Wordt opgeroepen wanneer er een fout optreedt bij het laden van een element.
oninput
Wordt opgeroepen wanneer er tekst wordt ingevoerd in een formulierelement.
onpaste
Wordt opgeroepen wanneer een item wordt geplakt in een element.
onscroll
Wordt opgeroepen wanneer de inhoud van een schuifbaar element wordt geschoven.
onsearch
Wordt opgeroepen wanneer een element wordt gekopieerd (? Apple docs correct ?)
onselectstart
Wordt opgeroepen wanneer een selectie begint.
Het HTML-kenmerk contentEditable U kunt het kenmerk contentEditable aan een willekeurig HTML-element toevoegen om gebruikers toe te staan de inhoud van het element te bewerken. Met de volgende HTML-voorbeeldcode wordt het gehele document ingesteld als bewerkbaar, behalve het eerste p-element:
Sed ut perspiciatis unde omnis iste natus error.
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 219 Informatie over de HTML-omgeving
Opmerking: Als u de eigenschap document.designMode instelt op on, zijn alle elementen in het document bewerkbaar, ongeacht de instelling van contentEditable voor een individueel element. Als u echter designModeinstelt op off, kunnen elementen waarvoor contentEditable is ingesteld op true, nog steeds worden bewerkt. Zie “De eigenschap Document.designMode” op pagina 213 voor meer informatie.
Extensies voor CSS WebKit ondersteunt verschillende uitgebreide CSS-eigenschappen. In de volgende tabel worden de uitgebreide eigenschappen aangegeven die worden ondersteund. Aanvullende niet-standaardeigenschappen zijn beschikbaar in WebKit maar worden niet volledig ondersteund in AIR omdat ze in WebKit nog worden ontwikkeld of omdat het experimentele functies zijn die mogelijk in de toekomst worden verwijderd. Naam CSS-eigenschap
Geeft de horizontale component van de randafstand op.
Geeft de verticale component van de randafstand op.
Geeft de regel voor het afbreken van tekst op die moet worden gebruikt voor CJK-tekst (Chinees, Japans en Koreaans).
Bepaalt hoe de ondermarge van een tabelcel wordt samengevouwen.
Bepaalt hoe de boven- en ondermarge van een tabelcel worden samengevouwen.
Een willekeurige lengte-eenheid.
De breedte van de beginmarge. Voor tekst die van links naar rechts wordt geschreven, overschrijft deze eigenschap de linkermarge. Voor tekst die van rechts naar links wordt geschreven, overschrijft deze eigenschap de rechtermarge.
Bepaalt hoe de bovenmarge van een tabelcel wordt samengevouwen.
Bepaalt het gedrag van vaste spaties binnen de ingesloten inhoud.
Een willekeurige lengte-eenheid.
Geeft aan met welke breedte de opvulling moet worden gestart. Voor tekst die van links naar rechts wordt geschreven, overschrijft deze eigenschap de linkeropvulling. Voor tekst die van rechts naar links wordt geschreven, overschrijft deze eigenschap de rechteropvulling.
Overschrijft de standaardverwerking van tekst die gedeeltelijk van links naar rechts en gedeeltelijk van rechts naar links wordt geschreven.
Geeft de tekstvulkleur op.
Geeft de vervangende vorm op die moet worden gebruikt in een invoerveld voor wachtwoorden.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 220 Informatie over de HTML-omgeving
Overschrijft het gedrag dat automatisch wordt toegepast bij slepen.
Geeft aan of de inhoud van een element kan worden bewerkt.
Geeft aan of een gebruiker de inhoud van een element kan selecteren.
Zie de handleiding Apple Safari CSS Reference (http://developer.apple.com/documentation/AppleApplications/Reference/SafariCSSRef/) voor meer informatie.
Hoofdstuk 21: Programmeren in HTML en JavaScript Een aantal programmeeraspecten zijn uniek voor de ontwikkeling van Adobe® AIR™-toepassingen met HTML en JavaScript. De volgende informatie is belangrijk, ongeacht of u een HTML-gebaseerde AIR-toepassing programmeert, of dat u een SWF-gebaseerde AIR-toepassing programmeert die HTML en JavaScript uitvoert met behulp van de klasse HTMLLoader (of de Flex™-component mx:HTML).
Informatie over de klasse HTMLLoader De klasse HTMLLoader van Adobe AIR definieert het weergaveobject dat HTML-inhoud kan weergeven in een AIRtoepassing. SWF-gebaseerde toepassingen kunnen een HTMLLoader-besturingselement aan een bestaand venster toevoegen of een HTML-venster maken dat automatisch een HTMLLoader-object bevat met HTMLLoader.createRootWindow(). Het HTMLLoader-object kan vanuit de geladen HTML-pagina worden opgeroepen met de JavaScript-eigenschap window.htmlLoader.
HTML-inhoud laden vanuit een URL De volgende code laadt een URL in een HTMLLoader-object en stelt het object in als een onderliggend object van een Sprite-object: var container:Sprite; var html:HTMLLoader = new HTMLLoader; html.width = 400; html.height = 600; var urlReq:URLRequest = new URLRequest("http://www.adobe.com/"); html.load(urlReq); container.addChild(html);
De eigenschappen width en height van een HTMLLoader-object zijn standaard allebei ingesteld op 0. U wordt aangeraden deze afmetingen in te stellen als u een HTMLLoader-object aan het Stage-object toevoegt. De HTMLLoader verstuurt verschillende gebeurtenissen terwijl een pagina wordt geladen. Op basis van deze gebeurtenissen kunt u bepalen wanneer het veilig is om met de geladen pagina te interageren. Deze gebeurtenissen worden beschreven in “HTML-gerelateerde gebeurtenissen afhandelen” op pagina 240. U kunt HTML-tekst ook renderen met behulp van de klasse TextField, maar de mogelijkheden hiervan zijn beperkt. De klasse TextField van Adobe® Flash® Player ondersteunt een subset van de HTML-markeringen, maar vanwege de groottebeperkingen zijn de mogelijkheden hiervan beperkt. (De klasse HTMLLoader die in Adobe AIR is opgenomen, is niet beschikbaar in Flash Player.)
HTML-inhoud laden vanuit een tekenreeks De methode loadString() van een HTMLLoader-object laadt een tekenreeks met HTML-inhoud in het HTMLLoader-object: var html:HTMLLoader = new HTMLLoader(); var htmlStr:String = "Hello
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 222 Programmeren in HTML en JavaScript
Inhoud die is geladen met de methode loadString(), wordt in de toepassingsbeveiligingssandbox geplaatst, zodat deze volledige toegang heeft tot de API's van AIR.
Belangrijke veiligheidsregels bij gebruik van HTML in AIR-toepassingen De bestanden die u met de AIR-toepassing installeert, hebben toegang tot de API's van AIR. Om veiligheidsredenen heeft de inhoud van andere bronnen geen toegang tot deze API's. Voorbeeld: deze beperking voorkomt dat inhoud van een extern domein (bijvoorbeeld http://example.com) de inhoud van de bureaubladmap van de gebruiker (of nog erger) kan lezen. Omdat beveiligingshiaten kunnen worden gebruikt door de functie eval() (en verwante API's) op te roepen, kan inhoud die met de toepassing wordt geïnstalleerd, deze methoden standaard niet gebruiken. Bepaalde Ajaxframeworks gebruiken echter de functie eval() en verwante API's. Om inhoud goed te structureren zodat deze kan werken in een AIR-toepassing, moet u rekening houden met de beveiligingsbeperkingen voor inhoud van verschillende bronnen. Inhoud van verschillende bronnen wordt geplaatst in afzonderlijke beveiligingsclassificaties, die sandboxen worden genoemd (zie “Sandboxen” op pagina 28). Inhoud die met de toepassing wordt geïnstalleerd, wordt standaard in een sandbox geïnstalleerd die de toepassingssandbox wordt genoemd. Deze verleent toegang tot de API's van AIR. De toepassingssandbox is de veiligste sandbox, aangezien beperkingen voorkomen dat niet-vertrouwde code wordt uitgevoerd. U kunt inhoud die met uw toepassing is geïnstalleerd, ook in een andere sandbox plaatsen. Inhoud in niettoepassingssandboxen werkt in een beveiligde omgeving, zoals in een webbrowser. Voorbeeld: code in niettoepassingssandboxen kan eval() en verwante methoden gebruiken (maar anderzijds heeft deze code geen toegang tot de API's van AIR). De runtime voorziet in manieren om inhoud in verschillende sandboxen veilig te laten communiceren (zonder bijvoorbeeld API's van AIR toegankelijk te maken voor niet-toepassingsinhoud). Zie “Crossscripting van inhoud in verschillende beveiligingssandboxen” op pagina 235 voor meer informatie. Als u code oproept die niet in een sandbox kan worden gebruikt vanwege beveiligingsbeperkingen, geeft de runtime de foutmelding weer dat er in de runtime van Adobe AIR een beveiligingsfout betreffende JavaScript-code in de toepassingsbeveiligingssandbox is opgetreden. Om deze fout te voorkomen, volgt u de coderingsrichtlijnen in de volgende sectie, “JavaScript-beveiligingsfouten voorkomen” op pagina 222. Zie “Beveiliging in HTML” op pagina 31 voor meer informatie.
JavaScript-beveiligingsfouten voorkomen Als u code oproept die niet in een sandbox kan worden gebruikt vanwege deze beveiligingsbeperkingen, geeft de runtime de foutmelding weer dat er in de runtime van Adobe AIR een beveiligingsfout betreffende JavaScript-code in de toepassingsbeveiligingssandbox is opgetreden. Ga als volgt te werk om deze fout te voorkomen.
Oorzaken van JavaScript-beveiligingsfouten Code die wordt uitgevoerd in de toepassingssandbox, is uitgesloten van de meeste bewerkingen waarbij tekenreeksen worden geëvalueerd en uitgevoerd nadat de documentgebeurtenis load is geactiveerd en eventuele handlers voor de gebeurtenis load zijn afgesloten. Als u de volgende typen JavaScript-instructies gebruikt die potentieel onveilige tekenreeksen evalueren en uitvoeren, worden JavaScript-fouten gegenereerd:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 223 Programmeren in HTML en JavaScript
• Functieconstructor Bovendien mislukken de volgende typen JavaScript-instructies zonder een Javascript-fout voor onveilige inhoud te genereren:
• javascript: URL's • Gebeurteniscallbacks die via onevent-kenmerken in innerHTML- en outerHTML-instructies zijn toegewezen • JavaScript-bestanden laden van buiten de installatiemap van de toepassing • document.write() en document.writeln() • Synchrone XMLHttpRequests vóór de gebeurtenis load of tijdens de gebeurtenishandler load • Dynamisch gecreëerde scriptelementen Opmerking: In enkele beperkte gevallen is de evaluatie van tekenreeksen toegestaan. Zie “Codebeperkingen voor de inhoud van verschillende sandboxen” op pagina 33 voor meer informatie. Adobe houdt een lijst bij van Ajax-frameworks die de toepassingsbeveiligingssandbox ondersteunen. Deze lijst vindt u op http://www.adobe.com/go/airappsandboxframeworks_nl. In de volgende secties vindt u informatie om scripts zo aan te passen, dat deze JavaScript-fouten voor onveilige inhoud en stille defecten worden voorkomen voor code die in de toepassingssandbox wordt uitgevoerd.
Toepassingsinhoud toewijzen aan een andere sandbox In de meeste gevallen kunt u een toepassing aanpassen of opnieuw structureren, zodat JavaScript-beveiligingsfouten worden voorkomen. Als aanpassen of opnieuw structureren echter niet mogelijk is, kunt u de inhoud van de toepassing in een andere sandbox laden met de techniek die is beschreven in “Toepassingsinhoud laden in een niettoepassingssandbox” op pagina 236. Als deze inhoud ook toegang moet hebben tot de API's van AIR, kunt u een sandboxbridge maken, zoals beschreven in “Sandboxbridge-interface instellen” op pagina 237.
De functie eval() In de toepassingssandbox kunt u de functie eval() alleen gebruiken vóór de gebeurtenis load van de pagina of tijdens de gebeurtenishandler load. Nadat de pagina is geladen, wordt geen code uitgevoerd als eval() wordt opgeroepen. In de volgende gevallen kunt u uw code echter aanpassen om het gebruik van eval() te voorkomen.
Eigenschappen toewijzen aan een object In plaats van een tekenreeks te parseren om de eigenschapsaccessor te bouwen: eval("obj." + propName + " = " + val);
Functies maken met variabelen die beschikbaar zijn in de context Vervang instructies zoals deze: function compile(var1, var2){ eval("var fn = function(){ this."+var1+"(var2) }"); return fn; }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 224 Programmeren in HTML en JavaScript
function compile(var1, var2){ var self = this; return function(){ self[var1](var2) }; }
Objecten maken met de naam van de klasse als tekenreeksparameter Bekijken we een hypothetische JavaScript-klasse die met de volgende code is gedefinieerd: var CustomClass = { Utils: { Parser: function(){ alert('constructor') } }, Data: { } }; var constructorClassName = "CustomClass.Utils.Parser";
De eenvoudigste manier om een instantie te maken, is met behulp van eval(): var myObj; eval('myObj=new ' + constructorClassName +'()')
U kunt het oproepen van eval() echter voorkomen door elke component van de klassenaam te parseren en het nieuwe object op te bouwen met behulp van de haakjesnotering: function getter(str) { var obj = window; var names = str.split('.'); for(var i=0;i
Om de instantie te maken, gebruikt u: try{ var Parser = getter(constructorClassName); var a = new Parser(); }catch(e){ alert(e); }
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 225 Programmeren in HTML en JavaScript
setTimeout() en setInterval() Vervang de tekenreeks die als handlerfunctie is opgegeven, door een functieverwijzing of een object. Voorbeeld: vervang een instructie zoals: setTimeout("alert('Timeout')", 10);
Of, als de functie vereist dat het object this wordt ingesteld door de oproeper, vervangt u een instructie zoals: this.appTimer = setInterval("obj.customFunction();", 100);
door het volgende: var _self = this; this.appTimer = setInterval(function(){obj.customFunction.apply(_self);}, 100);
Functieconstructor Oproepen van new Function(param, body) kunnen worden vervangen door een inline functiedeclaratie of alleen worden gebruikt voordat de gebeurtenis load van de pagina is afgehandeld.
javascript: URL's De code die in een koppeling met behulp van het URL-schema javascript: is gedefinieerd, wordt in de toepassingssandbox genegeerd. Er wordt geen JavaScript-fout voor onveilige inhoud gegenereerd. U kunt koppelingen vervangen die gebruikmaken van URL's van het type javascript:, zoals:
Gebeurteniscallbacks die via onevent-kenmerken in innerHTML- en outerHTML-instructies zijn toegewezen Als u innerHTML of outerHTML gebruikt om elementen toe te voegen aan de DOM van een document, worden gebeurteniscallbacks die in de instructie zijn toegewezen, zoals onclick of onmouseover, genegeerd. Er wordt geen beveiligingsfout gegenereerd. In plaats daarvan kunt u het kenmerk id aan de nieuwe elementen toewijzen en de callbackfuncties van de gebeurtenishandler instellen met de methode addEventListener(). U hebt bijvoorbeeld een doelelement in een document, zoals:
'; document.getElementById('smith').addEventListener("click", function() { code(); });
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 226 Programmeren in HTML en JavaScript
JavaScript-bestanden laden van buiten de installatiemap van de toepassing Scriptbestanden kunnen niet van buiten de toepassingssandbox worden geladen. Er wordt geen beveiligingsfout gegenereerd. Alle scriptbestanden die in de toepassingssandbox worden uitgevoerd, moeten in de toepassingsmap zijn geïnstalleerd. Als u externe scripts in een pagina wenst te gebruiken, moet u de pagina toewijzen aan een andere sandbox. Zie “Toepassingsinhoud laden in een niet-toepassingssandbox” op pagina 236.
document.write() en document.writeln() Oproepen van document.write() of document.writeln() worden genegeerd nadat de gebeurtenis load van de pagina is afgehandeld. Er wordt geen beveiligingsfout gegenereerd. Als alternatief kunt u een nieuw bestand laden of de hoofdtekst van het document vervangen met behulp van DOM-manipulatietechnieken.
Synchrone XMLHttpRequests vóór de gebeurtenis load of tijdens de gebeurtenishandler load Synchrone XMLHttpRequests die worden gestart vóór de gebeurtenis load van de pagina of tijdens de handler voor de gebeurtenis load, retourneren geen inhoud. Asynchrone XMLHttpRequests kunnen worden gestart maar retourneren pas na de gebeurtenis load. Nadat de gebeurtenis load is afgehandeld, gedragen synchrone XMLHttpRequests zich op de normale manier.
Dynamisch gecreëerde scriptelementen Scriptelementen die dynamisch zijn gecreëerd, bijvoorbeeld met innerHTML of de methode document.createElement(), worden genegeerd.
API-klassen van AIR oproepen vanuit JavaScript Naast de standaardelementen en de uitgebreide elementen van Webkit, heeft HTML- en JavaScript-code toegang tot de hostklassen die door de runtime worden geboden. Met deze klassen hebt u toegang tot de geavanceerde functies van AIR, zoals:
• Toegang tot het bestandssysteem • Gebruik van lokale SQL-databases • Besturing van toepassings- en venstermenu's • Toegang tot netwerksockets • Gebruik van door de gebruiker gedefinieerde klassen en objecten • Geluidsmogelijkheden Voorbeeld: de AIR API voor het bestandssysteem bevat de klasse File, die in het pakket flash.filesystem is opgenomen. U kunt als volgt een File-object in JavaScript maken: var myFile = new window.runtime.flash.filesystem.File();
Het runtime-object is een speciaal JavaScript-object, dat beschikbaar is voor HTML-inhoud die in AIR in de toepassingssandbox wordt uitgevoerd. Hiermee hebt u vanuit JavaScript toegang tot runtimeklassen. De eigenschap flash van het runtime-object biedt toegang tot het pakket flash. De eigenschap flash.filesystem van het runtime-object biedt toegang tot het pakket flash.filesystem (dit pakket bevat de klasse File). Pakketten zijn een manier om klassen te organiseren die in ActionScript worden gebruikt.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 227 Programmeren in HTML en JavaScript
Opmerking: De eigenschap runtime wordt niet automatisch toegevoegd aan de vensterobjecten van pagina's die in een frame of iframe zijn geladen. Zolang het onderliggende document zich echter in de toepassingssandbox bevindt, heeft het onderliggende element toegang tot de eigenschap runtime van het bovenliggende element. Vanwege de pakketstructuur van de runtimeklassen zou een ontwikkelaar lange reeksen JavaScript-code moeten typen om toegang te krijgen tot elke klasse (bijvoorbeeld window.runtime.flash.desktop.NativeApplication). Daarom omvat de SDK van AIR het bestand AIRAliases.js, waarmee u veel makkelijker toegang hebt tot runtimeklassen (door bijvoorbeeld gewoon air.NativeApplication te typen). De API-klassen van AIR worden in deze handleiding besproken. Andere klassen van de API voor Flash Player die interessant kunnen zijn voor HTML-ontwikkelaars, worden beschreven in Adobe AIR Language Reference for HTML Developers. ActionScript is de taal die wordt gebruikt in SWF-inhoud (Flash Player). De syntaxis van JavaScript en die van ActionScript zijn echter bijna identiek. (Ze zijn allebei gebaseerd op versies van de taal ECMAScript.) Alle ingebouwde klassen zijn zowel in JavaScript (in HTML-inhoud) als in ActionScript (in SWFinhoud) beschikbaar. Opmerking: JavaScript-code kan geen gebruik maken van de klassen Dictionary, XML en XMLList, die wel beschikbaar zijn in ActionScript. Opmerking: Zie Klassen, pakketten en naamruimten in ActionScript 3.0 en Basisinformatie over ActionScript voor JavaScript-ontwikkelaars voor meer informatie.
Het bestand AIRAliases.js gebruiken De runtimeklassen zijn georganiseerd in een pakketstructuur, zoals hierna wordt geïllustreerd:
In de SDK van AIR is ook het bestand AIRAliases.js opgenomen, dat "alias"-definities bevat waarmee u runtimeklassen kunt oproepen zonder omslachtig typewerk. Voorbeeld: u kunt de klassen die hierboven zijn vermeld, oproepen door gewoon het volgende te typen:
Deze lijst is slechts een kort fragment van de klassen in het bestand AIRAliases.js. De volledige lijst van klassen en functies op pakketniveau vindt u in Adobe AIR Language Reference for HTML Developers. Naast de vaak gebruikte runtimeklassen bevat het bestand AIRAliases.js ook aliassen voor vaak gebruikte functies op pakketniveau: window.runtime.trace(), window.runtime.flash.net.navigateToURL() en window.runtime.flash.net.sendToURL(), met als alias air.trace(), air.navigateToURL() en air.sendToURL(). Als u het bestand AIRAliases.js wilt gebruiken, neemt u de volgende script-verwijzing op in uw HTML-pagina: <script src="AIRAliases.js">
Pas indien nodig het pad aan in de src-verwijzing.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 228 Programmeren in HTML en JavaScript
Belangrijk: Tenzij anders is aangegeven, gaat de JavaScript-voorbeeldcode in deze documentatie ervan uit dat u het bestand AIRAliases.js hebt opgenomen in uw HTML-pagina.
Informatie over URL's in AIR In HTML-inhoud die in AIR wordt uitgevoerd, kunt u een van de volgende URL-schema's gebruiken om srckenmerken te definiëren voor de tags img, frame, iframe en script, in het kenmerk href van de tag link, of op een willekeurige plaats waar u een URL kunt opgeven. URL-schema
Het pad op basis van de hoofdmap van het bestandssysteem. file:///c:/AIR Test/test.txt
Het pad op basis van de hoofdmap van de geïnstalleerde toepassing.
Het pad op basis van de opslagmap van de toepassing. Voor elke geïnstalleerde toepassing definieert AIR een unieke opslagmap. Dit is de plaats waar gegevens worden opgeslagen die eigen zijn aan die toepassing.
Een standaard HTTP-aanvraag.
Een standaard HTTPS-aanvraag.
Zie “URL-schema's van AIR gebruiken in URL's” op pagina 292 voor meer informatie over het gebruik van URLschema's in AIR. API's van AIR, zoals de klassen File, Loader, URLStream en Sound, maken vaak gebruik van een URLRequest-object in plaats van een tekenreeks waarin de URL is opgenomen. Het URLRequest-object zelf wordt geïnitialiseerd met een tekenreeks, die dezelfde URL-schema's kan gebruiken. Voorbeeld: de volgende instructie creëert een URLRequestobject waarmee de startpagina van Adobe kan worden opgevraagd: var urlReq = new air.URLRequest("http://www.adobe.com/");
Zie “URL-aanvragen en netwerken” op pagina 290 voor meer informatie over URLRequest-objecten.
ActionScript-objecten beschikbaar maken voor JavaScript JavaScript in de HTML-pagina die door een HTMLLoader-object is geladen, kan de klassen, objecten en functies oproepen die in de ActionScript-uitvoeringscontext zijn gedefinieerd. Daartoe wordt gebruikgemaakt van de eigenschappen window.runtime, window.htmlLoader en window.nativeWindow van de HTML-pagina. U kunt ook ActionScript-objecten en -functies beschikbaar maken voor JavaScript-code door verwijzingen naar die objecten en functies op te nemen in de JavaScript-uitvoeringscontext.
Basisvoorbeeld om JavaScript-objecten op te roepen vanuit ActionScript In het volgende voorbeeld ziet u hoe u eigenschappen kunt toevoegen die ActionScript-objecten verwijzen naar het algemene vensterobject van een HTML-pagina:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 229 Programmeren in HTML en 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; }
De HTML-inhoud (in een bestand met de naam test.html), die in het vorige voorbeeld in het HTMLLoader-object is geladen, kan de eigenschap foo oproepen, evenals de methode helloFromJS(), die in het bovenliggende SWFbestand is gedefinieerd: <script> function alertFoo() { alert(foo); }
Als u de JavaScript-context oproept van een document dat op dat moment wordt geladen, kunt u met de gebeurtenis htmlDOMInitialize al vroeg in de constructiesequentie van de pagina objecten maken, zodat ze toegankelijk zijn voor scripts die in de pagina zijn gedefinieerd. Als u wacht op de gebeurtenis complete, kunnen alleen scripts die na de gebeurtenis load van de pagina worden uitgevoerd, toegang krijgen tot de toegevoegde objecten.
Klassedefinities beschikbaar maken voor JavaScript Als u de ActionScript-klassen van uw toepassing beschikbaar wilt maken in JavaScript, kunt u de geladen HTMLinhoud toewijzen aan het toepassingsdomein waarin zich de klassedefinities bevinden. Het toepassingsdomein van de JavaScript-uitvoeringscontext kan worden ingesteld met de eigenschap runtimeApplicationDomain van het HTMLLoader-object. Als u het toepassingsdomein bijvoorbeeld wilt instellen op het primaire toepassingsdomein, stelt u runtimeApplicationDomain in op ApplicationDomain.currentDomain, zoals in de volgende code: html.runtimeApplicationDomain = ApplicationDomain.currentDomain;
Nadat de eigenschap runtimeApplicationDomain is ingesteld, deelt de JavaScript-context klassedefinities met het toegewezen domein. Als u een instantie van een aangepaste klasse in JavaScript wilt maken, verwijst u naar de klassedefinitie via de eigenschap window.runtime en gebruikt u de operator new: var customClassObject = new window.runtime.CustomClass();
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 230 Programmeren in HTML en JavaScript
De HTML-inhoud moet afkomstig zijn van een compatibel beveiligingsdomein. Als de HTML-inhoud afkomstig is van een ander beveiligingsdomein dan dat van het toepassingsdomein dat u toewijst, gebruikt de pagina in plaats daarvan een standaard toepassingsdomein. Voorbeeld: als u een externe pagina van internet laadt, kunt u ApplicationDomain.currentDomain niet toewijzen als het toepassingsdomein van de pagina.
Gebeurtenislisteners verwijderen Als u gebeurtenislisteners voor JavaScript toevoegt aan objecten buiten de huidige pagina, inclusief runtimeobjecten, objecten in de geladen SWF-inhoud en zelfs JavaScript-objecten die in andere pagina's worden uitgevoerd, moet u deze gebeurtenislisteners altijd verwijderen als de pagina niet meer is geladen. Anders verzendt de gebeurtenislistener de gebeurtenis naar een handlerfunctie die niet meer bestaat. In dit geval wordt er een foutmelding weergegeven dat de toepassing heeft geprobeerd te verwijzen naar een JavaScript-object in een HTML-pagina die niet meer is geladen. Wanneer u overbodige gebeurtenislisteners verwijdert, kan AIR ook het overeenkomstige geheugen opnieuw gebruiken. Zie “Gebeurtenislisteners verwijderen in HTML-pagina's die navigeren” op pagina 244 voor meer informatie.
HTML DOM- en JavaScript-objecten oproepen vanuit ActionScript Nadat het HTMLLoader-object de gebeurtenis complete heeft verzonden, hebt u toegang tot alle objecten in het HTML DOM (Document Object Model) voor de pagina. Toegankelijke objecten zijn onder andere weergaveelementen (zoals de objecten div en p in de pagina), evenals JavaScript-variabelen en -functies. De gebeurtenis complete komt overeen met de JavaScript-gebeurtenis load van de pagina. Vóór complete wordt verzonden, mogen variabelen, functies en DOM-elementen niet zijn geparseerd of gecreëerd. Indien mogelijk wacht u op de gebeurtenis complete vóór u het HTML DOM benadert. Bekijken we als voorbeeld de volgende HTML-pagina: <script> foo = 333; function test() { return "OK."; }
Hi.
Deze eenvoudige HTML-pagina definieert een JavaScript-variabele met de naam foo en een JavaScript-functie met de naam test(). Beide zijn eigenschappen van het algemene object window van de pagina. Bovendien bevat het object window.document een element met de naam P (met de id p1), dat u kunt oproepen met de methode getElementById(). Nadat de pagina is geladen (wanneer het HTMLLoader-object de gebeurtenis complete verzendt), kunt u al deze objecten benaderen vanuit ActionScript, zoals wordt geïllustreerd met de volgende ActionScript-code:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 231 Programmeren in HTML en JavaScript
var html:HTMLLoader = new HTMLLoader(); html.width = 300; html.height = 300; html.addEventListener(Event.COMPLETE, completeHandler); var xhtml:XML = <script> foo = 333; function test() { return "OK."; }
Hi.
; 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. }
Als u de inhoud van een HTML-element wilt oproepen, gebruikt u de eigenschap innerHTML. De vorige code gebruikt bijvoorbeeld html.window.document.getElementById("p1").innerHTML om de inhoud van het HTML-element p1 op te halen. U kunt ook eigenschappen voor de HTML-pagina instellen vanuit ActionScript. Het volgende voorbeeld stelt de inhoud van het element p1 en de waarde van de JavaScript-variabele foo op de pagina in met behulp van een verwijzing naar het bevattende HTMLLoader-object: html.window.document.getElementById("p1").innerHTML = "Goodbye"; html.window.foo = 66;
SWF-inhoud insluiten in HTML In een AIR-toepassing kunt u SWF-inhoud insluiten in HTML-inhoud, net zoals in een browser. Sluit de SWF-inhoud in met behulp van de tag object, de tag embed of beide. Opmerking: Vaak wordt zowel de tag object als de tag embed gebruikt om SWF-inhoud weer te geven in een HTMLpagina. Deze techniek biedt echter geen voordelen in AIR. U kunt de W3C-standaard tag object op zichzelf gebruiken in inhoud die in AIR moet worden weergegeven. U kunt ook desgewenst de tags object en embed samen blijven gebruiken voor HTML-inhoud die ook in een browser wordt weergegeven. In het volgende voorbeeld ziet u hoe u de HTML-tag object gebruikt om een SWF-bestand in HTML-inhoud weer te geven. Het SWF-bestand wordt vanuit de toepassingsmap geladen maar u kunt een willekeurig URL-schema gebruiken dat door AIR wordt ondersteund. (De bronlocatie van het SWF-bestand bepaalt de beveiligingssandbox waarin AIR de inhoud plaatst.)
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 232 Programmeren in HTML en JavaScript
U kunt ook een script gebruiken om inhoud dynamisch te laden. In het volgende voorbeeld ziet u hoe u een objectknooppunt maakt om het SWF-bestand weer te geven dat is opgegeven in de parameter urlString. Het voorbeeld voegt het knooppunt toe als onderliggend element van het pagina-element met de id die is opgegeven met de parameter 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; }
ActionScript-bibliotheken in een HTML-pagina gebruiken AIR breidt het HTML-scriptelement uit, zodat een pagina ActionScript-klassen kan importeren in een gecompileerd SWF-bestand. Stel dat de bibliotheek myClasses.swf zich in de submap lib van de hoofdtoepassingsmap bevindt. Als u deze bibliotheek wilt importeren, neemt u de volgende scripttag op in een HTML-bestand: <script src="lib/myClasses.swf" type="application/x-shockwave-flash">
Belangrijk: Het kenmerk type moet type="application/x-shockwave-flash" zijn, anders wordt de bibliotheek niet goed geladen. De map lib en het bestand myClasses.swf moeten ook worden opgenomen wanneer het AIR-bestand in een pakket wordt geplaatst. Benader de geïmporteerde klassen via de eigenschap runtime van het JavaScript-object Window: var libraryObject = new window.runtime.LibraryClass();
Als de klassen in het SWF-bestand zijn verdeeld in pakketten, moet u ook de pakketnaam opnemen. Als de definitie LibraryClass zich bijvoorbeeld in een pakket met de naam utilities bevindt, maakt u met de volgende instructie een instantie van de klasse: var libraryObject = new window.runtime.utilities.LibraryClass();
Opmerking: Als u in AIR een ActionScript SWF-bibliotheek wilt compileren als onderdeel van een HTML-pagina, gebruikt u de compiler acompc. Het hulpprogramma acompc maakt deel uit van de SDK van Flex 3 en wordt beschreven in de Flex 3 SDK-documentatie.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 233 Programmeren in HTML en JavaScript
HTML DOM- en JavaScript-objecten oproepen vanuit een geïmporteerd ActionScript-bestand Als u objecten in een HTML-pagina wenst op te roepen vanuit ActionScript in een SWF-bestand dat in de pagina is geïmporteerd met behulp van de tag <script>, geeft u een verwijzing naar een JavaScript-object zoals window of document op aan een functie die in de ActionScript-code is gedefinieerd. Gebruik de verwijzing binnen de functie om het JavaScript-object op te roepen (of andere objecten die toegankelijk zijn via de doorgegeven verwijzing). Bekijken we als voorbeeld de volgende HTML-pagina: <script src="ASLibrary.swf" type="application/x-shockwave-flash"> <script> num = 254; function getStatus() { return "OK."; } function runASFunction(window){ var obj = new runtime.ASClass(); obj.accessDOM(window); }
Body text.
Deze eenvoudige HTML-pagina heeft een JavaScript-variabele met de naam num en een JavaScript-functie met de naam getStatus(). Beide zijn eigenschappen van het object window van de pagina. Bovendien bevat het object window.document een element met de naam P (met de id p1). De pagina laadt het ActionScript-bestand "ASLibrary.swf", waarin zich de klasse ASClass bevindt. ASClass definieert de functie accessDOM(), die de waarden van deze JavaScript-objecten bijhoudt. De methode accessDOM() gebruikt het JavaScript-object Window als argument. Op basis van deze Window-verwijzing kunnen andere objecten in de pagina worden benaderd, zoals variabelen, functies en DOM-elementen, zoals wordt geïllustreerd in de volgende definitie: public class ASClass{ public function accessDOM(window:*):void { trace(window.num); // 254 trace(window.document.getElementById("p1").innerHTML); // Body text.. trace(window.getStatus()); // OK. } }
U kunt eigenschappen van de HTML-pagina ophalen en instellen op basis van een geïmporteerde ActionScript-klasse. De volgende functie stelt bijvoorbeeld de inhoud van het element p1 op de pagina in, evenals de waarde van de JavaScript-variabele foo op de pagina: public function modifyDOM(window:*):void { window.document.getElementById("p1").innerHTML = "Bye"; window.foo = 66;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 234 Programmeren in HTML en JavaScript
Date- en RegExp-objecten converteren De talen JavaScript en ActionScript definiëren allebei de klassen Date en RegExp, maar objecten van deze typen worden niet automatisch geconverteerd tussen de twee uitvoeringscontexten. U moet de Date- en RegExp-objecten naar het equivalente type converteren vóór u ze gebruikt om eigenschappen of functieparameters in de andere uitvoeringscontext in te stellen. Voorbeeld: de volgende ActionScript-code converteert het JavaScript-object Date met de naam jsDate naar het ActionScript-object Date: var asDate:Date = new Date(jsDate.getMilliseconds());
De volgende ActionScript-code converteert het JavaScript-object RegExp met de naam jsRegExp naar het ActionScript-object RegExp: 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);
HTML-opmaakmodellen bewerken vanuit ActionScript Nadat het HTMLLoader-object de gebeurtenis complete heeft verzonden, kunt u CSS-stijlen in een pagina onderzoeken en bewerken. Bekijken we als voorbeeld het volgende eenvoudige HTML-document: <style> .style1A { font-family:Arial; font-size:12px } .style1B { font-family:Arial; font-size:24px } <style> .style2 { font-family:Arial; font-size:12px }
Nadat een HTMLLoader-object deze inhoud heeft geladen, kunt u de CSS-stijlen in de pagina als volgt bewerken via de array cssRules van de array window.document.styleSheets:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 235 Programmeren in HTML en 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"; }
Deze code past de CSS-stijlen zo aan, dat het resulterende HTML-document er als volgt uitziet:
Let op: code kan stijlen aan de pagina toevoegen nadat het HTMLLoader-object de gebeurtenis complete heeft verzonden.
Cross-scripting van inhoud in verschillende beveiligingssandboxen Het beveiligingsmodel van de runtime isoleert code op basis van de oorsprong. Door cross-scripting van de inhoud in verschillende beveiligingssandboxen kunt u inhoud in een bepaalde beveiligingssandbox toegang bieden tot bepaalde eigenschappen en methoden in een andere sandbox.
AIR-beveiligingssandboxen en JavaScript-code AIR past een zelfde-oorsprongbeleid toe, dat voorkomt dat code in een bepaald domein kan interageren met inhoud in een ander domein. Alle bestanden worden in een sandbox geplaatst op basis van hun oorsprong. Inhoud in de toepassingssandbox kan normaal gesproken niet het zelfde-oorsprongprincipe schenden en inhoud die van buiten de installatiemap van de toepassing is geladen, cross-scripten. AIR biedt echter een aantal technieken waarmee u crossscripting kunt toepassen op niet-toepassingsinhoud. Eén techniek maakt gebruik van frames of iframes om toepassingsinhoud aan een andere beveiligingssandbox toe te wijzen. Pagina's die vanaf de sandboxzone van de toepassing zijn geladen, gedragen zich alsof ze vanaf het externe domein zijn geladen. Voorbeeld: als u toepassingsinhoud toewijst aan het domein example.com, kan die inhoud pagina's cross-scripten die vanaf example.com zijn geladen. Deze techniek plaatst de toepassingsinhoud in een andere sandbox, zodat code binnen die inhoud niet langer is onderworpen aan de uitvoeringsbeperkingen voor code in geëvalueerde tekenreeksen. U kunt deze techniek van sandboxtoewijzing gebruiken om deze beperkingen te verminderen, zelfs als u geen cross-scripting van externe inhoud hoeft uit te voeren. Inhoud op die manier toewijzen, kan met name interessant zijn als u met een van de vele JavaScriptframeworks werkt, of met bestaande code die is gebaseerd op de evaluatie van tekenreeksen. Neem echter het extra risico in acht dat onvertrouwde inhoud kan worden geïnjecteerd en uitgevoerd als inhoud buiten de toepassingssandbox wordt uitgevoerd. Pas hiervoor de nodige voorzorgsmaatregelen toe.
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 236 Programmeren in HTML en JavaScript
Anderzijds verliest toepassingsinhoud die aan een andere sandbox is toegewezen, de toegangsrechten voor de API's van AIR, zodat de techniek van sandboxtoewijzing niet kan worden gebruikt om AIR-functionaliteit toegankelijk te maken voor code die buiten de toepassingssandbox wordt uitgevoerd. Met een andere cross-scriptingtechniek kunt u een interface (sandboxbridge) maken tussen inhoud in een niettoepassingssandbox en het bovenliggende document in de toepassingssandbox. Dankzij deze bridge heeft de onderliggende inhoud toegang tot eigenschappen en methoden die door de bovenliggende inhoud worden gedefinieerd, en omgekeerd. Beide situaties kunnen zich ook tegelijk voordoen. Ten slotte kunt u ook domeinoverschrijdende XMLHttpRequests uitvoeren vanuit de toepassingssandbox en optioneel vanuit andere sandboxen. Zie “Frame- en iframe-elementen in HTML” op pagina 215, “Beveiliging in HTML” op pagina 31 en het “XMLHttpRequest-objecten” op pagina 209 voor meer informatie.
Toepassingsinhoud laden in een niet-toepassingssandbox Om toepassingsinhoud veilig te cross-scripten met inhoud die van buiten de installatiemap van de toepassing is geladen, kunt u het element frame of iframe gebruiken om toepassingsinhoud in dezelfde beveiligingssandbox als de externe inhoud te laden. Als u geen cross-scripting van de externe inhoud nodig hebt maar toch een pagina van uw toepassing buiten de toepassingssandbox wilt laden, kunt u dezelfde techniek gebruiken, waarbij u http://localhost/ of een andere onschuldige waarde opgeeft als het domein of de oorsprong. AIR voegt de nieuwe kenmerken sandboxRoot en documentRoot toe aan het element frame, zodat u kunt bepalen of een toepassingsbestand dat in het frame is geladen, moet worden toegewezen aan een niet-toepassingssandbox. Bestanden met een pad onder de URL sandboxRoot worden in plaats daarvan geladen vanuit de map documentRoot. Om veiligheidsredenen wordt de toepassingsinhoud die op die manier wordt geladen, behandeld alsof deze vanaf de URL sandboxRoot is geladen. De eigenschap sandboxRoot geeft de URL op die moet worden gebruikt om de sandbox en het domein te bepalen waarin de frame-inhoud moet worden geplaatst. Het URL-schema file:, http: of https: moet worden gebruikt. Als u een relatieve URL opgeeft, blijft de inhoud in de toepassingssandbox. De eigenschap documentRoot bepaalt de map waaruit de frame-inhoud moet worden geladen. Het URL-schema file:, app: of app-storage: moet worden gebruikt. In het volgende voorbeeld ziet u hoe u inhoud die in de submap sandbox van de toepassing is geïnstalleerd, toewijst voor uitvoering in de externe sandbox en het domein www.example.com: <iframe src="http://www.example.com/local/ui.html" sandboxRoot="http://www.example.com/local/" documentRoot="app:/sandbox/">
De pagina ui.html kan met behulp van de volgende scripttag een JavaScript-bestand laden vanuit de lokale map sandbox: <script src="http://www.example.com/local/ui.js">
Deze pagina kan ook inhoud laden vanuit een map op de externe server met bijvoorbeeld de volgende scripttag: <script src="http://www.example.com/remote/remote.js">
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 237 Programmeren in HTML en JavaScript
De URL sandboxRoot maskeert alle inhoud op dezelfde URL op de externe server. In het vorige voorbeeld hebt u geen toegang tot externe inhoud op www.example.com/local/ (of een van de submappen) omdat AIR de aanvraag omleidt naar de lokale toepassingsmap. Alle aanvragen worden omgeleid, ongeacht of ze afkomstig zijn van paginanavigatie, een XMLHttpRequest of een andere manier om inhoud te laden.
Sandboxbridge-interface instellen U kunt een sandboxbridge gebruiken als inhoud in de toepassingssandbox toegang moet hebben tot eigenschappen of methoden die zijn gedefinieerd door inhoud in een niet-toepassingssandbox, of als niet-toepassingsinhoud toegang moet hebben tot eigenschappen en methoden die zijn gedefinieerd door inhoud in de toepassingssandbox. Creëer een bridge met de eigenschappen childSandboxBridge en parentSandboxBridge van het object window van een willekeurig onderliggend document.
Onderliggende sandboxbridges creëren Met de eigenschap childSandboxBridge kan het onderliggende document een interface toegankelijk kan maken voor inhoud in het bovenliggende document. Als u een interface toegankelijk wilt maken, moet u de eigenschap childSandbox instellen op een functie of object in het onderliggende document. Vervolgens hebt u toegang tot het object of de functie vanuit de inhoud van het bovenliggende document. In het volgende voorbeeld ziet u hoe een script dat in een onderliggend document wordt uitgevoerd, een object dat een functie en eigenschap bevat, toegankelijk kan maken voor het bovenliggende document: var interface = {}; interface.calculatePrice = function(){ return ".45 cents"; } interface.storeID = "abc" window.childSandboxBridge = interface;
Als deze onderliggende inhoud wordt geladen in een iframe met de id "child", kunt u de interface vanuit de bovenliggende inhoud benaderen door de eigenschap childSandboxBridge van het frame te lezen: var childInterface = document.getElementById("child").contentWindow.childSandboxBridge; air.trace(childInterface.calculatePrice()); //traces ".45 cents" air.trace(childInterface.storeID)); //traces "abc"
Bovenliggende sandboxbridges creëren Met de eigenschap parentSandboxBridge kan het bovenliggende document een interface toegankelijk kan maken voor inhoud in een onderliggend document. Als u een interface toegankelijk wilt maken, stelt het bovenliggende document de eigenschap parentSandbox van een onderliggend document in op een functie of object dat in het bovenliggende document wordt gedefinieerd. Vervolgens hebt u toegang tot het object of de functie vanuit de inhoud van het onderliggende document. In het volgende voorbeeld ziet u hoe een script dat in een bovenliggend document wordt uitgevoerd, een object dat een functie bevat, toegankelijk kan maken voor een onderliggend document: var interface = {}; interface.save = function(text){ var saveFile = air.File("app-storage:/save.txt"); //write text to file } document.getElementById("child").contentWindow.parentSandboxBridge = interface;
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 238 Programmeren in HTML en JavaScript
Via deze interface kan inhoud in het onderliggende frame tekst opslaan in een bestand met de naam save.txt. Er is echter geen andere toegang tot het bestandssysteem. De onderliggende inhoud kan bijvoorbeeld de functie Save als volgt oproepen: var textToSave = "A string."; window.parentSandboxBridge.save(textToSave);
De toepassingsinhoud moet de kleinst mogelijke interface toegankelijk maken voor andere sandboxen. Niettoepassingsinhoud moet standaard als onbetrouwbaar worden beschouwd omdat deze inhoud kan blootstaan aan toevallige of kwaadwillige injectie van code. U moet de nodige veiligheidsmaatregelen nemen om misbruik te voorkomen van de interface die u via de bovenliggende sandboxbridge toegankelijk maakt.
Bovenliggende sandboxbridges benaderen tijdens het laden van een pagina Als een script in een onderliggend document toegang moet hebben tot een bovenliggende sandboxbridge, moet de bridge worden ingesteld voordat het script wordt uitgevoerd. Window-, frame- en iframe-objecten verzenden de gebeurtenis dominitialize nadat een nieuw pagina-DOM is gemaakt maar voordat scripts zijn geparseerd of DOMelementen zijn toegevoegd. U kunt de gebeurtenis dominitialize gebruiken om de bridge al vroeg in de constructiesequentie van de pagina te creëren, zodat alle scripts in het onderliggende document toegang hebben tot de bridge. In het volgende voorbeeld ziet u hoe u een bovenliggende sandboxbridge kunt maken als reactie op de gebeurtenis dominitialize die vanuit het onderliggende frame is verzonden: <script> var bridgeInterface = {}; bridgeInterface.testProperty = "Bridge engaged"; function engageBridge(){ document.getElementById("sandbox").contentWindow.parentSandboxBridge = bridgeInterface; } <iframe id="sandbox" src="http://www.example.com/air/child.html" documentRoot="app:/" sandboxRoot="http://www.example.com/air/" ondominitialize="engageBridge()"/>
Het volgende document, child.html, illustreert hoe onderliggende inhoud de bovenliggende sandboxbridge kan benaderen: <script> document.write(window.parentSandboxBridge.testProperty);
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 239 Programmeren in HTML en JavaScript
Om zeker te zijn dat u naar de gebeurtenis dominitialize in een onderliggend venster luistert en niet naar een frame, moet u de listener aan het nieuwe onderliggende Window-object toevoegen, dat u creëert met de functie window.open(): var childWindow = window.open(); childWindow.addEventListener("dominitialize", engageBridge()); childWindow.document.location = "http://www.example.com/air/child.html";
In dit geval bestaat er geen mogelijkheid om toepassingsinhoud toe te wijzen aan een niet-toepassingssandbox. Deze techniek is alleen nuttig als child.html van buiten de toepassingsmap wordt geladen. U kunt toepassingsinhoud in het venster nog altijd aan een niet-toepassingssandbox toewijzen, maar in dat geval moet u eerst een tussenpagina laden die zelf frames gebruikt om het onderliggende document te laden, en deze pagina toewijzen aan de gewenste sandbox. Als u de functie createRootWindow() van de klasse HTMLLoader gebruikt om een venster te maken, is het nieuwe venster geen onderliggend element van het document waaruit createRootWindow() wordt opgeroepen. U kunt dus geen sandboxbridge maken tussen het oproepende venster en niet-toepassingsinhoud die in het nieuwe venster is geladen. In plaats daarvan moet u in het nieuwe venster een tussenpagina laden die zelf frames gebruikt om het onderliggende document te laden. U kunt vervolgens de bridge creëren tussen het bovenliggende document van het nieuwe venster en het onderliggende document dat in het frame is geladen.
Hoofdstuk 22: HTML-gerelateerde gebeurtenissen afhandelen Met een systeem voor gebeurtenisafhandeling kunnen programmeurs op een gemakkelijke manier reageren op gebruikersinvoer en systeemgebeurtenissen. Het Adobe® AIR™-gebeurtenismodel is heel handig in het gebruik en voldoet aan alle standaarden. Het gebeurtenismodel is gebaseerd op de DOM (Document Object Model) Level 3 Events Specification, een industriestandaard voor de gebeurtenisafhandelingsarchitectuur, en bevat een krachtig en toch intuïtief gebeurtenisafhandelingsmechanisme voor programmeurs.
HTMLLoader-gebeurtenissen Een HTMLLoader-object verzendt de volgende ActionScript™-gebeurtenissen: Gebeurtenis
Wordt verzonden wanneer het HTML-document wordt gemaakt, maar voordat scripts worden geparseerd of DOM-knooppunten worden toegevoegd aan de pagina.
Wordt verzonden wanneer het HTML DOM is gemaakt als reactie op een laadbewerking onmiddellijk na de gebeurtenis onload in de HTML-pagina.
Wordt verzonden wanneer een van de eigenschappen contentWidth of contentHeight (of allebei) is gewijzigd.
Wordt verzonden wanneer de eigenschap location van de HTMLLoader is gewijzigd.
Wordt altijd verzonden wanneer de HTML-engine de scrollpositie wijzigt. Scroll-gebeurtenissen kunnen plaatsvinden vanwege navigatie naar ankerkoppelingen (#-koppelingen) op de pagina of vanwege het oproepen van de methode window.scrollTo(). De gebeurtenis scroll kan ook worden veroorzaakt door het invoeren van tekst in een tekstinvoergebied of tekstgebied.
Wordt verzonden wanneer in de HTMLLoader een JavaScript-uitzondering optreedt waarvoor geen voorziening is getroffen in de JavaScript-code.
U kunt ook een ActionScript-functie registreren voor een JavaScript-gebeurtenis (zoals onClick). Zie “DOMgebeurtenissen afhandelen met ActionScript” op pagina 240 voor meer informatie.
DOM-gebeurtenissen afhandelen met ActionScript U kunt ActionScript-functies registreren zodat ze reageren op JavaScript-gebeurtenissen. Kijk bijvoorbeeld naar de volgende HTML-inhoud:
U kunt een ActionScript-functie registreren als handler voor een willekeurige gebeurtenis in de pagina. Met de volgende code voegt u bijvoorbeeld de functie clickHandler() toe als listener voor de gebeurtenis onclick van het element testLink in de HTML-pagina:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 241 HTML-gerelateerde gebeurtenissen afhandelen
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!"); }
U kunt ook de methode addEventListener() gebruiken om te registreren voor deze gebeurtenissen. U kunt bijvoorbeeld de methode completeHandler() in het vorige voorbeeld vervangen door de volgende code: function completeHandler(event:Event):void { var testLink:Object = html.window.document.getElementById("testLink"); testLink.addEventListener("click", clickHandler); }
Wanneer een listener verwijst naar een specifiek DOM-element, is het aan te raden te wachten totdat de bovenliggende HTMLLoader de gebeurtenis complete heeft verzonden alvorens de gebeurtenislisteners toe te voegen. HTMLpagina's laden vaak meerdere bestanden en het HTML DOM wordt pas volledig samengesteld als alle bestanden zijn geladen en geparseerd. De HTMLLoader verzendt de gebeurtenis complete wanneer alle elementen zijn gemaakt.
Reageren op niet-onderschepte JavaScriptuitzonderingen Bekijk de volgende HTML-code: <script> function throwError() { var x = 400 * melbaToast; }
Deze bevat de JavaScript-functie throwError(), die verwijst naar de onbekende variabele melbaToast: var x = 400 * melbaToast;
Als een JavaScript-bewerking een ongeldige bewerking tegenkomt die niet in de JavaScript-code wordt onderschept via een try/catch-structuur, verzendt het HTMLLoader-object dat de pagina bevat, de gebeurtenis HTMLUncaughtScriptExceptionEvent. U kunt een handler voor deze gebeurtenis registreren, zoals in de volgende code:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 242 HTML-gerelateerde gebeurtenissen afhandelen
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); } }
Binnen JavaScript kunt u dezelfde gebeurtenis afhandelen via de eigenschap window.htmlLoader: <script language="javascript" type="text/javascript" src="AIRAliases.js"> <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);
De gebeurtenishandler htmlErrorHandler() annuleert het standaardgedrag van de gebeurtenis (dat wil zeggen, het verzenden van een JavaScript-foutbericht naar de AIR trace-output) en genereert een eigen outputbericht. Deze output bevat de waarde van de exceptionValue van het HTMLUncaughtScriptExceptionEvent-object. De output bevat de eigenschappen van ieder object in de stackTrace-array:
ONTWIKKELING VAN ADOBE AIR 1.1-TOEPASSINGEN MET FLASH CS4 PROFESSIONAL 243 HTML-gerelateerde gebeurtenissen afhandelen
exceptionValue: ReferenceError: Can't find variable: melbaToast sourceURL: app:/test.html line: 5 function: throwError sourceURL: app:/test.html line: 10 function: onclick
Runtimegebeurtenissen afhandelen met JavaScript De runtimeklassen ondersteunen het toevoegen van gebeurtenishandlers met de methode addEventListener(). Om een handlerfunctie voor een gebeurtenis toe te voegen, roept u de methode addEventListener() op van het object dat de gebeurtenis verzendt. U geeft hierbij het gebeurtenistype en de afhandelingsfunctie op. Als u bijvoorbeeld wilt luisteren naar de gebeurtenis closing die wordt verzonden wanneer een gebruiker op het sluitvak van een venster op de titelbalk klikt, gebruikt u de volgende opdracht: window.nativeWindow.addEventListener(air.NativeWindow.CLOSING, handleWindowClosing);
Gebeurtenishandlerfuncties maken Met de volgende code maakt u een eenvoudig HTML-bestand dat informatie weergeeft over de positie van het hoofdvenster. Een handlerfunctie met de naam moveHandler() luistert naar een verplaatsingsgebeurtenis (gedefinieerd door de klasse NativeWindowBoundsEvent) van het hoofdvenster. <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(); }