Air Devappsflex
Air Devappsflex
Contents
Installation instructions
Installing Adobe AIR
Getting started
Introducing Adobe AIR
Screens
Screen basics
Enumerating the screens
URL requests
Using the URLRequest class
Changes to the URLStream class
Opening a URL in the default system web browser
Index
5
• On Mac OS, double-click the application's icon, which is installed in the Applications sub-directory of your user
directory (for example, in Macintosh HD/Users/JoeUser/Applications/) by default.
The application opens in the runtime environment.
Note: Check the AIR Beta 2 release notes for updates to these instructions, which are located here:
http://labs.adobe.com/wiki/index.php/AIR:Release_Notes.
2 Copy and paste the application code from your old Apollo project’s main MXML file into the new AIR project
MXML file. Note that the AIR application container (ApolloApplication) has been changed to WindowedAppli-
cation.
3 Add your project’s assets into the new project using the Flex Builder project navigator.
4 Update any remaining code that refers to the ApolloApplication container.
Use the Flex SDK to port AIR applications to the new version
1 Recreate the application.xml file. For details of this file format, see “Setting application properties” on page 62.
2 Update your code with the new name for the AIR application container (WindowedApplication).
See also
• “Creating your first Flex AIR application in Flex Builder” on page 15
• “Developing AIR applications with Flex Builder” on page 25
• “Using the Flex AIR components” on page 40
10
The only difference between the Flex and the AIR versions of the utilities is that the AIR versions load the configu-
ration options from the air_config.xml file instead of the flex_config.xml file.
The Flex SDK tools and their command-line options are fully described in Building and Deploying Flex 3
Applications (http://www.adobe.com/go/learn_flex3_building) in the Flex 3 documentation library. The Flex SDK
tools are described here at a basic level to help you get started and to point out the differences between building Flex
and building AIR applications.
Compiler setup
You typically specify compilation options both on the command line and with one or more configuration files. The
global Flex SDK configuration file contains default values that are used whenever the compilers are run. You can edit
this file to suit your own development environment. There are two global Flex configuration files located in the
frameworks directory of your Flex 3 SDK installation. The air_config.xml file is used when you run the amxmlc
compiler. This file configures the compiler for AIR by including the AIR libraries. The flex_config.xml file is used
when you run mxmlc.
ADOBE PRODUCT X.0 11
User Guide
The default configuration values are suitable for discovering how Flex and AIR work, but you should examine the
available options more closely when you embark on a full-scale project. You can supply project-specific values for
the compiler options in a local configuration file that will take precedence over the global values for a given project.
For a full list of the compilation options and for the syntax of the configuration files, see About configuration
files (http://livedocs.macromedia.com/flex/2/docs/00001490.html) in the Flex 2 documentation library.
Note: No compilation options are used specifically for AIR applications, but you do need to reference the AIR libraries
when compiling an AIR application. Typically, these libraries are referenced in a project-level configuration file, in a tool
for a build tool such as Ant, or directly on the command line.
Debugger setup
AIR supports debugging directly, so you do not need a debug version of the runtime (as you would with Flash
Player). To conduct command-line debugging, you use the Flash Debugger and, optionally, the AIR Debug
Launcher.
The Flash Debugger is distributed in the Flex 3 SDK directory. The native versions, for example fdb.exe on Windows,
are in the bin subdirectory. The Java version is in the lib subdirectory. The AIR Debug Launcher, adl.exe or ADL, is
in the bin directory of your Flex SDK installation (there is no separate Java version).
Note: You cannot start an AIR application directly with FDB, because FDB attempts to launch it with Flash Player.
Instead, you must let the AIR application connect to a running FDB session.
See also
• “Creating your first AIR application with the Flex SDK” on page 19
• “Creating an AIR application using the command line tools” on page 28
• “Debugging using the AIR Debug Launcher” on page 30
• “Exporting an AIR installation file using the AIR Developer Tool” on page 32
12
Since AIR is an application runtime, it has little or no visible user interface and you have complete control over the
application and the experience it provides to users. The runtime provides a consistent cross-operating system
platform and framework for deploying applications and therefore eliminates cross-browser testing by ensuring
consistent functionality and interactions across desktops. Instead of developing for a specific operating system, you
target the runtime. This has a number of benefits:
• Applications developed for AIR run across multiple operating systems without any additional work by you. The
runtime ensures consistent and predictable presentation and interactions across all the operating systems supported
by AIR.
• Applications can be built faster by enabling you to leverage existing web technologies and design patterns. This
allows you to extend your web based applications to the desktop without learning traditional desktop development
technologies or the complexity of native code. This is easier than using lower level languages such as C and C++, and
does away with the need to learn complex low-level APIs specific to each operating system.
When developing applications for AIR, you can leverage a rich set of frameworks and APIs:
• APIs specific to AIR provided by the runtime and the AIR framework
• ActionScript APIs used in SWF files and Flex framework (as well as other ActionScript based libraries and
frameworks)
ADOBE PRODUCT X.0 14
User Guide
AIR delivers a new paradigm that dramatically changes how applications can be created, deployed, and experienced.
You gain more creative control and can extend your Flash, Flex, HTML, and Ajax-based applications to the desktop,
without learning traditional desktop development technologies.
15
</mx:WindowedApplication>
2 Add a Label component to the application (place it inside the WindowedApplication tag), set the text property
of the Label component to "Hello AIR", and set the layout constraints to keep it centered, as shown here:
<?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
title="Hello World">
<mx:Label text="Hello AIR" horizontalCenter="0" verticalCenter="0"/>
</mx:WindowedApplication>
3 Add the following style block immediately after the opening WindowedApplication tag and before the label
component tag you just entered:
<mx:Style>
Application
{
background-image:"";
background-color:"";
background-alpha:"0.5";
}
</mx:Style>
These style settings apply to the entire application and render the window background a slightly transparent gray.
The entire application code should now look like the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
title="Hello World">
<mx:Style>
Application
{
background-image:"";
background-color:"";
background-alpha:"0.5";
}
</mx:Style>
<mx:Label text="Hello AIR" horizontalCenter="0" verticalCenter="0"/>
</mx:WindowedApplication>
CLOSE PROCEDURE
2 Using the horizontalCenter and verrticalCenter properties of the Label control, the text is placed in the center of
the window. Move or resize the window as you would any other desktop application.
Note: If the application does not compile, fix any syntax or spelling errors that you may have inadvertently entered into
the code. Errors and warnings are displayed in the Problems view in Flex Builder.
CLOSE PROCEDURE
You can now run the application from the Project Navigator in Flex Builder or from the file system, as your users
would, by double-clicking the AIR file.
CLOSE PROCEDURE
See also
• “Developing AIR applications with Flex Builder” on page 25
• “Using the Flex AIR components” on page 40
19
4 Set the following elements in <initialWindow> to specify how your application window will be displayed:
<visible>true</true> Makes the window visible when it opens. In some cases, you might want to initialize
the visible element to false so that you can alter the window before showing it to your user.
<content>HelloAIR.html</content> Identifies the root html file for AIR to load.
5 Save the file. Your complete application descriptor file should look like this:
<?xml version="1.0" encoding="UTF-8"?>
ADOBE PRODUCT X.0 20
User Guide
<application xmlns="http://ns.adobe.com/air/application/1.0.M5"
appId="samples.HelloWeb" version="0.1">
<name>Hello AIR!</name>
<initialWindow>
<content>HelloAIR.html</content>
<visible>true</visible>
</application>
See also
• “Setting application properties” on page 62
2 Next, add a Label component to the application (place it inside the WindowedApplication tag) and set the text
property of the Label component to "Hello AIR" and set the layout constraints to always keep it centered, as shown
here:
<?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
title="Hello World">
<mx:Label text="Hello AIR" horizontalCenter="0" verticalCenter="0"/>
</mx:WindowedApplication>
These style settings apply to the entire application and render the window background a slightly transparent gray.
The entire application code now looks like this:
<?xml version="1.0" encoding="utf-8"?>
ADOBE PRODUCT X.0 21
User Guide
Note: If the application does not compile, fix syntax or spelling errors. Errors and warnings are displayed in the console
window used to run the amxmlc compiler.
See also
• “Compiling an AIR application with the amxmlc compiler” on page 28
The resulting AIR application looks something like this (the green background is the user's desktop):
ADOBE PRODUCT X.0 22
User Guide
Using the horizontalCenter and verticalCenter properties of the Label control, the text is placed in the center of the
window. Move or resize the window as you would any other desktop application.
See also
• “Debugging using the AIR Debug Launcher” on page 30
This example uses the minimum number of attributes that can be set for a certificate. You can use any values for the
parameters in italics. The key type must be either 1024-RSA or 2048-RSA.
The HelloAIR.air argument is the AIR file that ADT produces. HelloAIR-app.xml is the application descriptor
file. The subsequent arguments are the files used by your application. This example only uses a single file, but you
can include any number of files and directories.
After the AIR package is created, you can double-click, ctrl-click, or type the AIR filename as a command in the shell
to install and run the application.
See also
• “Exporting an AIR installation file using the AIR Developer Tool” on page 32
24
See also
• “Setting up for Flex Builder 3” on page 8
• “The application descriptor file structure” on page 62
ADOBE PRODUCT X.0 26
User Guide
See also
• “Debugging using the AIR Debug Launcher” on page 30
Digital certificates provided by VeriSign and Thwate give your users some assurance as to your identity as a publisher
and verification that the installation file has not been altered since you signed it. Self-signed digital certificates serve
the same purpose but they are not validated by a third-party.
You also have the option of packaging your AIR application without a digital signature by creating an intermediate
AIR file (.airi). An intermediate AIR file is not valid in that it cannot be installed. It is instead used for testing (by the
developer) and can be launched using the AIR ADT command line tool. This capability is provided because in some
development environments signing is handled by a particular developer or team, which insures an additional level
of security in managing digital certificates.
For more information about signing applications, see “Digitally signing an AIR file” on page 206.
See also
• “Exporting an AIR installation file using the AIR Developer Tool” on page 32
where [compiler options] specifies the command-line options used to compile your AIR application.
The amxmlc command invokes mxmlc with an additional parameter, +configname=air, which instructs the
compiler to use the air-config.xml file instead of the flex_config.xml file. Using amxmlc is otherwise identical to
using mxmlc. The mxmlc compiler and the configuration file format are described in Building and Deploying Flex
2 Applications in the Flex 2 documentation library.
The compiler loads the air-config.xml configuration file specifying the AIR and Flex libraries typically required to
compile an AIR application. You can also use a local, project-level configuration file to override or add additional
options to the global configuration. Typically the easiest way to create a local configuration file is to edit a copy of
the global version. You can load the local file with the -load-config option:
-load-config=project-config.xml Overrides global options.
-load-config+=project-config.xml Adds additional values to those global options that take more than value,
such as the -library-path option. Global options that only take a single value are overridden.
You can also use a special naming convention for the file and the amxmlc compiler will load the local configuration
file automatically. For example, if your application’s main MXML file is RunningMan.mxml, then name the config-
uration file: RunningMan-config.xml. To compile the application you only need to type:
amxmlc RunningMan.mxml
Note: The compiler commands use relative paths to find configuration files and executables. See “Setting up the Flex 3
SDK” on page 10
ADOBE PRODUCT X.0 29
User Guide
Examples
The following examples demonstrate use of the amxmlc compiler. (Only the ActionScript and MXML assets of your
application need to be compiled.)
Compile an AIR MXML file:
amxmlc myApp.mxml
Add an additional libraries on the command line (to those already in the configuration file):
amxmlc –library-path+=/libs/libOne.swc,/libs/libTwo.swc -- myApp.mxml
Compile an AIR MXML file without using a configuration file (Mac OS X):
mxmlc -library-path [AIR SDK]/frameworks/libs/air/airframework.swc, \
[AIR SDK]/frameworks/libs/air/airframework.swc, \
-library-path [Flex 2 SDK]/frameworks/libs/framework.swc \
-- myApp.mxml
The flexlib option identifies the location of your Flex SDK frameworks directory, enabling the compiler to locate the
flex_config.xml file.
Compiling from Java (without the class path set):
java -jar [Flex SDK 2]/lib/mxmlc.jar +flexlib [Flex SDK 2]/frameworks +configname=air
[additional compiler options] -- myApp.mxml
• acompc does not look for a local configuration file automatically. To use a project configuration file, you must
use the –load-config option.
acompc is identical to compc, except that it loads configuration options from the air-config.xml file instead of the
flex_config.xml file.
(Type the entire command on one line, or use the line continuation character for your command shell.)
Examples
(Note, the folder lib must exist and be empty before running the command.)
Reference a runtime-shared library:
acompc -load-config myLib-config.xml -output lib/myLib.swc
The debugging support provided by ADL is limited to the printing of trace statements. If you're developing a Flex-
based application, use the Flash Debugger (or Flex Builder) for complex debugging issues in SWF-based applica-
tions.
-runtime runtime-directory Specify the directory containing the runtime to use. If not specified, the runtime
directory in the same SDK as the ADL program will be used. (If ADL is moved out of its SDK folder, then the runtime
directory must always be specified.) On Windows, the directory to specify is typically Adobe AIR. On Mac OSX, the
directory to specify is typically Adobe AIR.framework.
-nodebug Turns off debugging support. If used, the AIR application cannot connect to the Flash debugger and
dialogs for unhandled exceptions will be suppressed. Trace statements are still printed to the console window.
Turning off debugging will allow your application to run a little faster and will also more closely match the execution
mode of an installed application.
application.xml The application descriptor file.
root-directory The root directory of the application to run. If not specified, the directory containing the appli-
cation descriptor file is used.
-- arguments Any character strings appearing after "--" are passed to the application as command-line arguments.
Note: When you launch an AIR application that is already running, a new instance of that application is not started.
Instead, an invoke event is dispatched to the running instance. In this case, the ADL root-directory and runtime param-
eters used for the subsequent launches must match those of the initial launch or the command-line arguments cannot be
delivered to the running instance of the application.
ADL Examples
Run an application and pass in two command-line arguments, "tick" and "tock":
adl myApp-app.xml -- tick tock
Every AIR application must, at a minimum, have an application descriptor file and a main SWF or HTML file. Any
other application assets to be installed with the application must be packaged in the AIR file as well.
All AIR installer files must be signed using a digital certificate. You can use a code signing certificate from the
VeriSign or Thawte certificate authorities, or a self-signed certificate. A VeriSign or Thawte certificate provides users
of your application with some assurance as to your identity as publisher and verification that the installation file has
not been altered since you signed it. A self-signed certificate verifies that the AIR file has not been altered since it
was signed, but cannot verify the identity of the signer.
You can package and sign an AIR file in a single step, or you can create an intermediate, unsigned package in one
step, and sign the intermediate package to produce an installation file in a separate step.
Note: The settings in the application descriptor file determine the identity of an AIR application and its default instal-
lation path. See “The application descriptor file structure” on page 62 for more information.
pfx_file the certificate file. (You can use the adt -certificate option to generate a self-signing certificate before
creating an AIR file). If no certifcate is provided, then ADT will look for a file named air.pfx in the user directory
password the certificate password.
app_xml The path to the application descriptor file. No matter what name is assigned to the application descriptor
file, it will be renamed to “application.xml” in the package. The path can be specified relative to the current directory
or as an absolute path.
file_or_dir The files and directories to package in the AIR file. Any number of files and directories can be
specified, delimited by whitespace. If you list a directory, all files and subdirectories within, except hidden files, are
added to the package. (In addition, if the application descriptor file is specified, either directly, or through wildcard
or directory expansion, it is ignored and not added to the package a second time.) The files and directories specified
must be in the current directory or one of its subdirectories. Use the -C option to change the current directory.
Important: Wildcards cannot be used in the file_or_dir arguments following the –C option. (The command shell
expands wildcards before passing the arguments to ADT, which results in ADT looking for files in the original working
directory instead of the directory specified by the –C option.)
-C dir Changes the working directory to dir before processing subsequent files and directories added to the appli-
cation package. The files or directories are added to the root of the application package. The –C option can be used
any number of times to include files from multiple points in the file system. If a relative path is specified for dir, the
path is always resolved from the original working directory.
As ADT process the files and directories to be included in the package, the relative paths between the current
directory and the target files are stored. These paths are expanded into the application directory structure when the
package is installed. Thus specifying "-C release/bin lib/feature.swf" would place the file
"release/bin/lib/feature.swf " in the "lib" subdirectory of the root application folder.
Note: You must make sure that the <content> element of the application descriptor file specifies the final path to the
main application file relative to the root application directory. This may be an issue if the main application file is not
located in the current directory when you run ADT.
ADT Examples
Package the application.xml file and main SWF located in a working directory (release\bin):
adt –package -certificate cert.pfx -password password myApp.air release\bin\myApp.xml –C
release\bin myApp.swf
The following example shows how to package assets from more than one place in your build file system.
Suppose the application assets are located in the following folders prior to packaging:
/devRoot
/myApp
/release
/bin
myApp.xml
myApp.swf
/artwork
/myApp
/images
image-1.png
...
ADOBE PRODUCT X.0 34
User Guide
image-n.png
/libraries
/release
/libs
lib-1.swf
...
lib-n.swf
Run ADT as a Java program (with the Java classpath set to include the ADT.jar package):
java com.adobe.air.ADT –package -certificate cert.pfx -password password myApp.air myApp.xml
myApp.swf
To create an unsigned AIR intermediate file, use the adt -prepare command. (See Creating an unsigned AIR inter-
mediate file with ADT.)
pfx_file the certificate file. (You can use the adt -certificate option to generate a self-signing certificate before
creating an AIR file). If no certifcate is provided, then ADT will look for a file named air.pfx in the user directory
password the certificate password.
ADT Examples
adt –sign -certificate code_cert.pfx -password secretPassword unsignedMyApp.airi myApp.air
-cn name the string assigned as the common name of the new certificate.
-ou org_unit a string assigned as the organizational unit issuing the certificate. (Optional.)
-o org_name a string assigned as the organization issuing the certificate. (Optional.)
-c country a two-letter ISO-3166 country code. A certificate will not be generated if an invalid code is supplied.
(Optional.)
key_type the type of key to use for the certificate, either “1024-RSA” or “2048-RSA”.
pfx_file the path for the certificate file to be generated.
password the password for the new certificate. The password is required when signing AIR files with this certificate.
ADOBE PRODUCT X.0 36
User Guide
The second set of properties are project specific. These properties assume the naming convention that application
descriptor and AIR files are named based on the root source file, but other conventions are easily supported. The
properties also define the MXMLC debug parameter as true (by default).
<property name="APP_NAME" value="ExampleApplication"/>
<property name="APP_ROOT" value="."/>
<property name="MAIN_SOURCE_FILE" value="${APP_ROOT}/${APP_NAME}.mxml"/>
<property name="APP_DESCRIPTOR" value="${APP_ROOT}/${APP_NAME}-app.xml"/>
<property name="AIR_NAME" value="${APP_NAME}.air"/>
<property name="DEBUG" value="true"/>
<property name="CERT" value="ExampleCert.pfx"/>
<property name"CERT_PASSWORD" value="39#wnetx3tl"/>
To invoke the compiler, the example uses a Java task to run mxmlc.jar:
<target name="compile">
<java jar="${MXMLC.JAR}" fork="true" failonerror="true">
<arg value="-debug=${DEBUG}"/>
<arg value="+flexlib=${SDK_HOME}/frameworks"/>
<arg value="+configname=air"/>
<arg value="-file-specs=${MAIN_SOURCE_FILE}"/>
</java>
</target>
When invoking mxmlc using Java, you must specify the +flexlib parameter. The +configname=air parameter
instructs mxmlc to load the supplied AIR configuration file along with the normal Flex config file.
To package the application use a Java task to run the adt.jar tool:
<target name="package" depends="compile">
<java jar="${ADT.JAR}" fork="true" failonerror="true">
<arg value="-package"/>
<arg value="-certificate"/>
<arg value="${CERT}"/>
<arg value="-password"/>
<arg value="${CERT_PASSWORD}"/>
<arg value="${AIR_NAME}"/>
<arg value="${APP_DESCRIPTOR}"/>
<arg value="${APP_NAME}.swf"/>
<arg value="*.png"/>
</java>
</target>
If your application has more files to package, you could add additional <arg> elements.
Important: You can leave the certificate password parameter out of the build file. If no password is provided, ADT will
prompt you for one on the command line. Since the certificate is only as secure as the password, you should not put a
valued password in a plain-text build file.
The AIR tools require the use of some additional options when operating on files outside the current working
directory:
Compiling The -output option of the mxmlc compiler allows you to specify where to put the compiled file, in this
case, in the build or debug subdirectories. To specify the output file, the line:
<arg value="-output=${debug}/${APP_ROOT_FILE}"/>
is added to the compilation task.
Testing The second argument passed to adl specifies the root directory of the AIR application. To specify the appli-
cation root directory, the line:
<arg value="${debug}"/>
is added to the testing task.
ADOBE PRODUCT X.0 38
User Guide
Packaging Packaging files from subdirectories that should not be part of the final package structure (such as the src
directory) requires using the -C directive to change the adt working directory. When you use the -C directive, files
in the new working directory are packaged at the root level of the air file. Thus "-C build file.png" places file.png at
the root, and "-C assets icons" places the icon folder at the root level, and packages all the files within the icons folder
as well. For example, the following sequence of lines in the package task adds the icons directory directly to the root
level of the application package file:
<arg value="-C"/>
<arg value="${assets}"/>
<arg value="icons"/>
<?xml version="1.0" ?>
<project>
<!-- SDK properties -->
<property name="SDK_HOME" value="C:/FlexSDK"/>
<property name="MXMLC.JAR" value="${SDK_HOME}/lib/mxmlc.jar"/>
<property name="ADL" value="${SDK_HOME}/bin/adl.exe"/>
<property name="ADT.JAR" value="${SDK_HOME}/lib/adt.jar"/>
</target>
FileSystemComboBox control
A FileSystemComboBox defines a combo box control for selecting a location in a file system. The control always
displays the selected directory in the combo box’s text field. When the combo box’s drop-down list is displayed, it
shows the ancestor directories of the selected directory—the hierarchy of directories that contain the selected
directory, up to the computer root directory. This allows a user to select a higher-level directory, providing an alter-
native to the FileSystemTree, FileSystemList, and FileSystemDataGrid controls that display (and allow selection of)
a directory that’s contained by the current directory.
For more information on the FileSystemComboBox control, see the Flex 3 Language Reference.
</mx:Script>
<mx:FileSystemComboBox id="fcb"/>
<mx:FileSystemComboBox id="fcbNoIcons" showIcons="false"/>
<mx:FileSystemComboBox id="fcbIndent" indent="20"/>
<mx:FileSystemComboBox id="fcbChange" directoryChange="setOutput();"/>
<mx:TextArea id="output" width="200" height="50"/>
</mx:WindowedApplication>
FileSystemTree control
A FileSystemTree control displays the contents of a file system directory as a tree. The tree can display the directory’s
files, its subdirectories, or both. For files, file names can be displayed with or without extensions.
For more information on the FileSystemTree control, see the Flex 3 Language Reference.
FileSystemList control
A FileSystemList control displays the contents of a file system directory as selectable items in a scrolling list (a Flex
List control). The displayed contents can include subdirectories and files, with additional filtering options as well.
A FileSystemList control can be linked to a FileSystemHistoryButton control, meaning that the button can be used
to move to a previously displayed directory.
For more information on the FileSystemList control, see the Flex 3 Language Reference.
FileSystemDataGrid control
A FileSystemDataGrid displays file information in a data-grid format. The file information displayed can include
the file name, creation date, modification date, type, and size. These are automatically created as columns in the
underlying DataGrid control, and can be removed or customized in the same way that you customize DataGrid
columns. The displayed contents can include subdirectories and files, with additional filtering options as well. A
FileSystemList control can be linked to a FileSystemHistoryButton control, meaning that the button can be used to
move to a previously displayed directory.
For more information on the FileSystemDataGrid control, see the Flex 3 Language Reference.
ADOBE PRODUCT X.0 44
User Guide
FileSystemHistoryButton control
The FileSystemHistoryButton control works in conjunction with a FileSystemList or FileSystemDataGrid control
(or similar control with a property containing an array of File objects) to let the user move backwards or forwards
through the navigation history of the control. The FileSystemHistoryButton is a PopUpMenuButton with a button
for navigating back or forward one step in the history and a list of history steps from which one step can be chosen
as well.
To link a FileSystemHistoryButton to a control, the button’s dataProvider property should be bound to a property
containing an array of File objects representing a sequence of directories in a file system browsing history. For
instance, the dataProvider property can be bound to the forwardHistory or backHistory property of a FileSys-
temList or FileSystemDataGrid control in order to use the button to navigate the display history of that control.
Then you set the click and itemClick event handlers of the button to call the navigateForward() or
navigateBack() method of the control.
For more information on the FileSystemHistoryButton control, see the Flex 3 Language Reference.
ADOBE PRODUCT X.0 45
User Guide
The window that a WindowedApplication or Window component defines conforms to the standard behavior of the
operating system. The user can move the window by dragging the title bar and resize the window by dragging on
any side or corner of the window. The components also include a set of properties that allow you control over
window sizing, including minimumHeight, minimumWidth, maximumHeight, and maximumWidth.
WindowedApplication container
The WindowedApplication container defines an application container that you use to create Flex applications for
AIR that use the native operating system chrome. The WindowedApplication container adds window-related
functionality and desktop application-specific functionality to the Flex Application container, which you can use
when you build AIR applications.
By default, the WindowedApplication component creates an application window for which windowMode is set to
systemChrome, and visibility is set to true. These settings are made in the application.xml file for the AIR appli-
cation. To eliminate the system chrome and window controls that the WindowedApplication component creates by
default, use a standard Flex Application container instead of a WindowedApplication container as the root MXML
tag for the application and, in the application.xml file, set systemChrome to none.
The following simple application shows a simple use of the WindowedApplication container:
ADOBE PRODUCT X.0 48
User Guide
For more information about the WindowedApplication container, see the Flex 3 Language Reference.
Window container
The Window component is a Flex container that is used to define the content and layout of operating system
windows that are opened after an application launches—in other words, windows other than the initial or main
window of the application (which is a WindowedApplication component or Application component). In addition
to the common functionality that is common with the WindowedApplication component, a Window component
allows you to define characteristics of the window, such as the type of window, the type of chrome, whether certain
actions (such as resizing and maximizing) are permitted for the window, and more. These characteristics are
accessed as properties that can be set when the component is initially created (at which point the actual operating
system window is not yet displayed). However, once the actual window is opened, the properties can no longer be
set and can only be read.
Once the window’s initial properties are set, you call the Window component’s open() method to actually cause the
operating system window to appear on the user’s display.
The following example shows a basic use of the Window component. The example includes two MXML files: the
first uses an Application container and is the initial window of the application, while the second uses the Window
container to define a secondary window for the application. In this example, the main window simulates a “splash
screen” for the application, and after a set time (3 seconds) it closes the splash screen and opens the second window.
Thee following code defines the main application MXML file, which contains the initial window (the splash screen)
that opens automatically when the application is run:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="init();">
<mx:Script>
<![CDATA[
private const LOAD_DELAY:int = 3;
private var timeElapsed:int = 0;
private var loadTimer:Timer;
{
// center the window on the screen
splashScreen = Shell.shell.openedWindows[0];
var screenBounds:Rectangle = Screen.mainScreen.bounds;
splashScreen.x = (screenBounds.width - splashScreen.width) / 2;
splashScreen.y = (screenBounds.height - splashScreen.height) / 2;
updateStatus();
}
updateStatus();
splashScreen.close();
The incrementTime() method is called each second and when the appropriate time is reached, a
DocumentWindow instance is created and its open() method is called. The DocumentWindow class is defined in
a separate MXML document; its base MXML tag is the <mx:Window> tag so it is a subclass of the Window class (the
Window component). Here is the source code for the DocumentWindow MXML file:
<?xml version="1.0" encoding="utf-8"?>
<mx:Window xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
title="Document window"
width="550" height="450">
<mx:Text text="This is a document window." horizontalCenter="0" verticalCenter="0"/>
ADOBE PRODUCT X.0 50
User Guide
</mx:Window>
For more information about the Window container, see the Flex 3 Language Reference.
51
Manual install
Alternatively, the user can manually download and install the runtime before opening an AIR file. The developer can
then distribute an AIR file by a number of means (e-mail, an HTML link on a website, etc.) When the AIR file is
opened, the runtime is activated and begins to process the application install.
For more information on this process, see “Distributing AIR applications” on page 206.
Application Destination
The installation directory of an AIR applications is determined by the first of three possible options:
1 The user customizes the destination during installation. The application installs to wherever the user specifies.
2 If the user does not change the install destination, the application installs to the default path as determined by
the runtime:
• Mac OS X: ~/Applications/
• Windows XP and earlier: C:\Program Files\
• Windows Vista: ~/Apps/
If the developer specifies an installFolder setting in the application descriptor file, the application is installed to
a subpath of this directory.
ADOBE PRODUCT X.0 54
User Guide
You can access the application storage directory via the air.File.applicationStorageDirectory property. You can access
its contents using the resolvePath() method of the File class. For details, see “Working with the file system”
on page 100.
Note: Developers can specify the version of an application by setting the version property of the application descriptor
file. AIR does not interpret the version string in any way. Thus version “3.0” is not assumed to be more current than
version “2.0.” It is up to the developer to maintain meaningful versioning. For details, see “Defining properties in the
application descriptor file” on page 63.
Sandboxes
AIR provides a comprehensive security architecture that defines permissions accordingly to each file in an AIR
application, both internal and external. Permissions are granted to files according to their origin, and are assigned
into logical security groupings called sandboxes.
The AIR runtime security model of sandboxes is composed of the Flash Player security model with the addition of
the application sandbox. Files that are not in the application sandbox have security restrictions similar to those
specified by the Flash Player security model.
A chart of each sandbox and their characteristics is below:
application The file resides in the application directory and operates with
the full set of AIR privileges
remote The file is from an Internet URL, and operates under domain-
based sandbox rules analogous to those of remote files in the
Flash Player.
local-trusted The file is a local file and has been trusted by the user, using
either the Settings Manager or a Flash Player trust
configuration file. The file can both read from local data
sources and communicate with the Internet, but does not
have the full set of AIR privileges.
local-with-networking The file is a local SWF file published with a networking
designation, but has not been explicitly trusted by the user.
The file can communicate with the Internet but cannot read
from local data sources.
ADOBE PRODUCT X.0 56
User Guide
local-with-filesystem The file is a local scripting file that was not published with a
networking designation and has not been explicitly trusted by
the user. This includes JavaScript files that have not been
trusted. The file can read from local data sources but cannot
communicate with the Internet.
The runtime uses these security sandboxes to define the range of data that a file may access and the operations it may
execute. To maintain local security, the files in each sandbox are isolated from the files of other sandboxes. For
example, a SWF file loaded into an AIR application from an external Internet website is placed into the remote
sandbox, and does not by default have permission to script into files that reside in the application directory, which
are assigned to the application sandbox.
This topic focuses primarily on the application sandbox and its relationship to other sandboxes in the AIR appli-
cation. Developers that use content that will be assigned to other sandboxes should read further documentation on
the Flash Player security model. See the “Flash Player Security” chapter in the Programming ActionScript 3.0
documentation and the Adobe Flash Player 9 Security white paper.
}
catch (e)
{
alert(e);
}
The exception type is TypeError (undefined value), because content in the non-application sandbox does not
recognize the window.runtime object, so it is seen as an undefined value.
Writing to disk
Applications running in a web browser have only limited interaction with the user's local file system. This is because
web browsers implement security policies that ensure that a user's computer cannot be compromised by web content.
For example, SWF files running through Flash Player in a browser cannot directly interact with files already on a
user's computer. Shared objects can be written to a user's computer for the purpose of maintaining user preferences
and other data, but this is the limit of file system interaction. Because AIR applications are natively installed, they
have a different security contract, one which includes the capability to read and write across the local file system.
This freedom comes with high responsibility for developers. Accidental application insecurities jeopardize not only
the functionality of the application, but the integrity of the user's machine. For this reason, developers are strongly
advised to read this section as well as the “Best security practices for developers” on page 59 section.
An alias to the application directory. Files accessed from this path will be assigned the application sandbox and
have the full privileges granted by the runtime.
app-storage:/
An alias to the local storage directory, standardized by the runtime. Files accessed from this path will be assigned a
non-application sandbox.
file:///
An alias that represents the root of the user's hard disk. Files accessed from this path are assigned an application
sandbox if it exists in the application directory, and a non-application sandbox otherwise.
Note: AIR applications cannot modify content in the app-resource:/ directory, due to security concerns and because
administrator settings may not allow it.
Unless there are administrator restrictions to the user's computer, AIR applications are privileged to write to any
location on the user's hard drive. Developers are advised to use the app-storage:/ path for local storage related to
their application. Files written to app-storage:/ from an application will be located in a standard location
depending on the user's operating system:
• On Mac OS X: the storage directory of an application is <appData>/<appId>/Local Store/ where <appData>
is the user's preferences folder. This is typically /Users/<user>/Library/Preferences
ADOBE PRODUCT X.0 58
User Guide
If an application is designed to interact with existing files in the user's file system, the developer is advised to read
the “Best security practices for developers” on page 59 section.
Security.allowDomain()
AIR applications restrict scripting access for non-application content more stringently than the Flash Player 9
browser plug-in restricts scripting access for untrusted content. For example, in Flash Player in the browser, when a
SWF file that is assigned to the local-trusted sandbox calls the System.allowDomain() method, scripting access
is granted to any SWF loaded from the specified domain, reassigning this remote file from the remote sandbox to
the local-trusted sandbox. The analogous approach is not permitted from application content in AIR applica-
tions, since it would grant unreasonable access unto the non-application file into the user's file system. Remote files
cannot directly access the application sandbox, regardless of calls to the Security.allowDomain() method.
Code Signing
All AIR installer files are required to be code signed. Code signing is a cryptographic process of confirming that the
specified origin of software is accurate. AIR applications can be signed either by linking a certificate from an external
certificate authority (CA) or by constructing your own certificate. Certificates are created using adt from the SDK
or using either Flash, Flex Builder, or another graphical front-end that uses adt for certificate generation.
For more general information about digitally signing AIR applications, see “Digitally signing an AIR file” on
page 206.
<pfx-file> is the path and name to the existing file that contains the certificate to be associated with the application
The other options are unrelated to security and are described in “Creating an AIR application using the command
line tools” on page 28.
The following options are available to adt in the construction of a self-signed certificate:
<name> is the name of the application
ADOBE PRODUCT X.0 61
User Guide
<org-unit> (optional) is the department within an organization that is creating the installer file
<org-name> (optional) is the name of the organization that is creating the installer file.
<country> (optional) is the two-letter country code that represents the installer file’s country of origin
<key-type> is the type of encryption used to create the certificate. Acceptable options include “1024-RSA” and
“2048-RSA”
<pfx-file> is the path and name, including extension, of the file created that will contain the certificate
<password> is the password associated with the certificate. this password is later required when using adt to
associate an installer file to a certificate.
Note: When choosing a password, it is best to use a password that is a combination of uppercase letters, lowercase letters,
punctuation characters, and numbers. It is also safest to never store the password on the same computer that contains
the certificate, or to not store a password on a machine at all. One way to pick a long password is to thing of a memorable
short sentence or long phrase and then add some personally memorable numbers and punctuation (such as “3665
MELba !@# toast”).
See also
• “Scripting between content in different domains” on page 202
62
</fileType>
</fileTypes>
</application>
• 0–9
• a–z
• A–Z
• . (dot)
• - (hyphen)
The value must contain 1 to 212 characters.
The appId string typically uses a dot-separated hierarchy, in alignment with a reversed DNS domain address, a Java
package or class name, or an OS X Universal Type Identifier. The DNS-like form is not enforced, and AIR does not
create any association between the name and actual DNS domains.
version Specifies the version information for the application. (It has no relation to the version of the runtime). The
version string is an application-defined designator. AIR does not interprete the version string in any way. Thus
version “3.0” is not assumed to be more current than version “2.0.” Examples: "1.0", ".4", "0.5", "4.9", "1.3.4a".
xmlns The AIR namespace, which you must define as the default XML namespace. The namespace will change with
each release of AIR. The last segment of the namespace, such as “1.0.M5,” indicates the AIR runtime version required
by the application.
minimumPatchLevel Together with the AIR namespace, determines the version of the AIR runtime required by the
application. Typically, the user will be prompted to download and install the required version or patch, if necessary.
name The name of the application. You must define this element.
<name>TestApp</name>
In Windows, this is displayed in the application’s title bar and in the Windows Start menu. On Mac OS, it is displayed
in the menu bar when the application is running.
title (Optional) The title displayed by the AIR application installer.
<installFolder>Acme</installFolder>
On Windows, the default installation subdirectory is the Program Files directory. On Mac OS, it is the ./Applications
directory. For example, if the installFolder property is set to "Acme" and an application is named "ExampleApp",
then the application will be installed in C:\Program Files\Acme\Example on Windows and in ./Applica-
tions/Acme/Example.app on MacOS.
Use the forward-slash (/) character as the directory separator character if you want to specify a nested subdirectory,
as in the following:
<installFolder>Acme/Power Tools</installFolder>
The installFolder property can contain any Unicode (UTF-8) character except the following, which are
prohibited from use as folder names on various file systems:
" x22
: x3A
> x3C
< x3E
? x3F
\ x5C
| x7C
The installFolder property is optional. If you specify no installFolder property, the application is installed in
a subdirectory of the default installation directory, based on the name property.
programMenuFolder (Optional) Identifies the location in which to place shortcuts to the application in the
Windows All Programs menu. (Ignored on other operating systems.) The restrictions on the characters that are
allowed in the value of the property are the same as those for the installFolder property.
<programMenuFolder>Acme/Applications</programMenuFolder>
<visible>true</visible>
<minimizable>true</minimizable>
<maximizable>true</maximizable>
<resizable>true</resizable>
<width>400</width>
<height>600</height>
<x>150</x>
<y>150</y>
<minSize>300 300</minSize>
<maxSize>800 800</maxSize>
</initialWindow>
The children of the initialWindow element set the properties of the window into which the root content file will be
loaded.
content The value specified for the content element is the URL for the main content file of the application. This
may be either a SWF file or an HTML file. The URL is specified relative to the root of the application.xml file.
title The window title.
systemChrome If you set this attribute to standard, the standard system chrome supplied by the operating system
is displayed. If you set it to none, no system chrome is displayed. When using the Flex mx:WindowedApplication
component, the component applies its custom chrome if standard system chrome is not set. The system chrome
setting cannot be changed at run time.
transparent Set this to "true" if you want the application window to support alpha blending. The transprent
property of a window cannot be changed after the window has been created. A window with transparency may draw
more slowly and require more memory than otherwise. The transparent setting cannot be changed at run time.
Important: You can only set transparent="true" when systemChrome="none".
visible Set this to "true" if you want to have the main window be visible as soon as it is created. The default value
is "false". Note that the Flex mx:WindowedApplication component will automatically set the window to visible
immediately prior to the applicationComplete event, unless the showWindow attribute is set to false in the
MXML definition.
You may want to leave the main window hidden initially, so that changes to the window ‘s position, size, and the
layout of its contents are not shown. You can then display the window by setting the
stage.nativeWindow.visible property (for the main window) to true. For details, see “Working with windows”
on page 69.
width, height, x, y The initial bounds of the main window of the application. If you do not set these values,
the window size is determined by the settings in the root SWF file or, in the case of HTML, by the operating system.
minSize, maxSize The minimum and maximum sizes of the window. If you do not set these values, they will be
determined by the operating system.
minimizable, maximizable, resizable Specifies whether the window can be minimized, maximized, and
resized. By default, these settings default to true.
Note: On operating systems, such as Mac OS X, for which maximizing windows is a resizing operation, both maximi-
zable and resizable must be set to false to prevent the window from being zoomed or resized.
See also
• “Working with windows” on page 69
ADOBE PRODUCT X.0 66
User Guide
If an image is specified, it must be the size specified. If all sizes are not provided, the closest size will be scaled to fit
for a given use of the icon by the operating system.
Note: The icons specified are not automatically added to the AIR package. The icon files must be included in their correct
relative locations when the application is packaged.
When the installed version of your application includes the handleUpdates element in the application descriptor
file and the user then double-clicks on the AIR file for a new version (the appId attributes must match), the runtime
opens the installed version of the application, rather than the default AIR application installer. Your application logic
can then determine how to proceed with the update operation.
Note: The handleUpdates mechanism only works when the application is already installed and the user double-clicks
the AIR file.
For more information, see “Updating AIR applications programmatically” on page 214.
The fileTypes element is optional. If present, you can specify any number of file type registrations.
The name and extension elements are required for each fileType definition that you include. Note that the
extension is specified without the preceding period. The description element is optional. The contentType
property is also optional.
Icons can be specified for the file extension, using the same format as the application icon element.
When a file type is registered with an AIR application, the application will be invoked whenever a user opens a file
of that type. If the application is already running, AIR will dispatch the invoke event to the running instance.
Otherwise, AIR will launch the application first. In both cases, the file name and location can be retrieved from the
InvokeEvent object dispatched by the application Shell object.
See also
• “Capturing command line arguments” on page 187
68
GETTING STARTED
• “AIR window basics” on page 69
• “Interacting with a window” on page 21
• “Creating a transparent window application” on page 26
• “Launching native windows” on page 31
• “Creating toast-style windows” on page 51
• “Creating resizable, non-rectangular windows” on page 60
• “Controlling the display order of windows” on page 56
DEVELOPMENT TASKS
• “Creating windows” on page 73
• “Manipulating windows” on page 76
• “Listening for window events” on page 81
• “Using full-screen window mode” on page 82
LANGUAGE REFERENCE
• NativeWindow
• NativeWindowInitOptions
MORE INFORMATION:
You may be able to find more information about working the AIR File API in the AIR Developer Center
(http://www.adobe.com/devnet/air/flex/). Search the site using the keywords ‘AIR windows’.
Window string constants are defined in the following classes: NativeWindowDisplayState, NativeWindowResize,
NativeWindowSystemChrome, NativeWindowType
AIR provides an easy-to-use, cross-platform window API for creating native operating system windows using Flash,
Flex, and HTML programming techniques.
ADOBE PRODUCT X.0 70
User Guide
Important: When you are building an application with the Flex framework, you should generally create windows using
the mx:WindowedApplication and mx:Window components. These components are designed as Flex containers and so
can accept Flex components directly whereas NativeWindow objects cannot. When necessary, NativeWindow properties
and methods can be accessed through the WindowedApplication and Window objects using the stage.nativeWindow
property. See About window containers for more information about the Flex components.
With AIR, you have a wide latitude in developing the look-and-feel of your application. The windows you create can
look like a standard desktop application, matching Apple style when run on the Mac, and conforming to Microsoft
conventions when run on Windows. Or you can use the skinnable, extendible chrome provided by the Flex
framework to establish your own style no matter where your application is run. You can even draw your own
windows with vector and bitmap artwork with full support for transparency and alpha blending against the desktop.
Tired of rectangular windows? Draw a round one.
AIR supports two distinct APIs for working with windows: the Flash-oriented NativeWindow class and the HTML-
oriented JavaScript Window class. Windows created with the NativeWindow class use the Flash stage and display list
directly. To add a visual object to a NativeWindow, you add the object to the display list of the window’s stage.
Windows created with JavaScript use HTML, CSS, and JavaScript to display content. To add a visual object to an
HTML window, you add that content to the HTML DOM.
Note: HTML windows are a special category of NativeWindow. The AIR host adds a nativeWindow property to HTML
windows that provides access to the underlying NativeWindow instance.
The first window of your application is automatically created for you by AIR based on the parameters specified in
the initialWindow element of the application descriptor file. If the root content is a SWF file, a NativeWindow
instance is created and the SWF is loaded into the window. If the root content is an HTML file, an HTML window
is created and the HTML page is loaded.
Native windows use an event-based programming model. Changing any properties or calling methods on the
window object that may affect the display or behavior of application components dispatches notification events to
which interested components can listen. For example, when the system chrome maximize button is clicked by a user
the following sequence of events occurs:
1 The user clicks the maximize button.
2 A displayStateChanging event is dispatched by the window
3 If no registered listeners cancel the event, the window is maximized
4 A displayStateChange event is dispatched by the window to notify listeners that the change has been made.
In addition, events for related changes are dispatched:
5 A move event is dispatched if the top, left corner of the window moved because of the maximize operation.
6 A resize event is dispatched if the window size changed because of the maximize operation
A similar sequence of events is dispatched for minimizing, restoring, closing, moving, and resizing a window.
For detailed information about the window API classes, methods, properties, and events, see the AIR ActionScript
3.0 Language Reference (http://www.adobe.com/go/learn_flex3_aslr). For general information about using the Flash
display list, see the “Display Programming” section of the Programming ActionScript
3.0 (http://www.adobe.com/go/programmingAS3) reference.
See also
• “The application descriptor file structure” on page 62
ADOBE PRODUCT X.0 71
User Guide
Window Type
The type property combines certain chrome and visibility attributes of the native operating system to create three
functional types of window. The type property can only be set when creating a new NativeWindow. AIR supports
the following window types:
Normal A typical window. Normal windows use the full-size chrome and appear on the Windows task bar and the
Mac OS X window menu.
Utility A tool palette. Utility windows use a slimmer version of the system chrome and do not appear on the
Windows task bar and the Mac OS-X window menu.
Lightweight Lightweight windows have little or no chrome and do not appear on the Windows task bar and the Mac
OS X window menu. In addition, lightweight windows do not have the System (Alt-Space) menu on Windows.
Lightweight windows are suitable for notification bubbles and controls such as combo-boxes that open a short-lived
display area. When the lightweight type is used, systemChrome must be set to “none”.
Window chrome
Window chrome is the set of controls that allow users to manipulate a window in the desktop environment. For an
AIR application, you have the following choices for window chrome:
System chrome System chrome displays your window within the set of standard controls created and styled by the
user’s operating system. Use system chrome to make your application look like a standard desktop application for
the operating system in which it is run. System chrome is managed by the system, your application has no direct
access to the controls themselves, but can react to the events dispatched when the controls are used. If system chrome
is used for a window, the transparency property must be set to false.
Note: In this Beta release, the Alternate systemChrome setting is not supported.
Flex chrome When using the Flex WindowedApplication and Window components, your window will be displayed
with chrome provided by the Flex framework. If the Flex components are used along with system chrome, the Flex
chrome is not displayed.
Custom chrome When you create a window with no system chrome and you do not use the Flex mx:WindowedAp-
plication of mxWindow components, then you must add your own controls to handle the interactions between a user
and the window. You are also free to make transparent, non-rectangular windows.
Window transparency
To allow alpha blending of a window with the desktop or other windows, set the window's transparent property to
true. The transparent property must be set before the window is created and cannot be changed. The transparent
property is set in the NativeWindowInitOptions object used to create a window. (For the initial window created for
your application, the initialization options are taken from attributes of the initialWindow element in the appli-
cation descriptor file.)
ADOBE PRODUCT X.0 72
User Guide
A transparent window has no default background. Any window area not occupied by a display object will be
invisible. If a display object has an alpha setting of less than one, then any thing below the object will show through,
including other display objects in the same window, other windows, and the desktop. Rendering large alpha-blended
areas can be slow, so the effect should be used conservatively.
Transparent windows are useful when you want to create:
• Applications with borders that are irregular in shape
• Applications that must “fade out” or appear to be invisible
Transparency cannot be used for windows with system chrome.
If your Flex application uses CSS style properties that set a background image or color, your window will not be
transparent. Likewise, if the Application tag in your MXML file defines a background color, this setting will override
a transparent window mode. To ensure the transparency of your application window, include the following code in
your style sheet or in the <mx:Style> element that is contained in your application MXML file:
Application
{
background-image:"";
background-color:"";
}
These declarations suppress the appearance of background color and image in the application window.
The following window-related features are not supported in this Beta release:
• The windowing API does not currently support the Toolbars|OS X Toolbar or the OS X Proxy Icon.
• Alternate system chrome
Creating windows
AIR provides the following primary means for creating applications windows:
• AIR automatically creates the first window for every application. This window is initialized according to the
settings defined in the application descriptor file. If the root content identified in the descriptor is a SWF file, then
you can access the properties and methods of the window instance through the Stage.nativeWindow property and
the NativeWindow API. In addition, the main class of the SWF file must extend from Sprite or a subclass of Sprite.
(The Flex WindowedApplication and Application components, which are Sprite subclasses, are used as the main
class of Flex applications.) If the root content is an HTML file, then you can access the properties and methods of the
window through the JavaScript Window object’s nativeWindow property.
• You can create a new instance of the NativeWindow class. New NativeWindows are initialized by the NativeWin-
dowInitOptions object passed to the window constructor. You can access the properties and methods directly from
the object reference returned by the constructor.
• You can use the HTMLControl.createRootWindow() method to create a window to display HTML content.
• You can use the JavaScript Window.open() method to open new windows from JavaScript code. The properties
and methods of JavaScript-created windows can only be accessed through JavaScript and the window can only
display HTML. JavaScript-created HTML windows automatically include system chrome.
Note: You can create new NativeWindows from JavaScript code (through the AIR window.runtime property).
This section contains the following topics:
• “Creating a new NativeWindow” on page 74
• “Adding content to a window” on page 74
• “Example: Creating windows with ActionScript” on page 75
ADOBE PRODUCT X.0 74
User Guide
To avoid displaying the intermediate states of the window as you set its bounds, position, and contents, do not set
the NativeWindow.visible property to true or call the activate() method until you have finished initializing
the window. The NativeWindowInitOptions object sets those properties of a window that cannot be changed after
the window has been created.
Note: Setting systemChrome="standard" and transparent="true" is not a supported combination.
Once the window is created, you may initialize its properties and load content into the window using the stage
property and Flash display list techniques.
Note: To determine the maximum and minimum window sizes allowed on the current operating system, use the
following static NativeWindow properties:
var maxOSSize:Point = NativeWindow.systemMaxSize;
var minOSSize:Point = NativeWindow.systemMinSize;
You can load Flash or images into the display list of a native window using the flash.display.Loader class.
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.Loader;
addChild(event.target.loader);
}
}
}
Visual Flash content added to an HTML window must be displayed either on top of the HTML content as an overlay,
or beneath transparent HTML content. Such content must also be positioned and resized separately from the HTML
content.
You can load a SWF file that contains library code for use in an HTML-based application. The simplest way to load
a SWF in an HTML window is to use the script tag, but you can also use the flash.display.Loader API directly.
Note: Older SWF files created using ActionScript 1 or 2 will share global state such as class definitions, singletons, and
global variables if they are loaded into the same window. If such a SWF relies on untouched global state to work correctly,
it cannot be loaded more than once into the same window, or loaded into the same window as another SWF using
overlapping class definitions and variables. This content can be loaded into separate windows.
To load HTML content into a NativeWindow, you can either add an HTMLControl object to the window stage and
load the HTML content into the HTMLControl, or create a new window that already contains an HTMLControl
object by using the HTMLControl.createRootWindow()method. The following example displays HTML content
within a 300 by 500 pixel display area on the stage of a native window:
//newWindow is a NativeWindow instance
var htmlView:HTMLControl = new HTMLControl();
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 );
To load an HTML page into a Flex application, you can use the Flex HTMLComponent.
In this Beta release, displaying Flash content embedded in an HTML page within an instance of a HTMLControl is
not supported. Any Flash objects in the page will be displayed as blank rectangles. You can, however, load or create
Flash content using the AIR APIs and add it to the HTML window as an overlay or underlay to the HTML layer.
See also
• “Adding HTML content to SWF-based applications” on page 162
• “Scripting between content in different domains” on page 202
options.type = NativeWindowType.NORMAL;
Manipulating windows
This section highlights using the properties and methods of the NativeWindow class to manipulate the appearance
and behavior of application windows and includes the following topics:
• “Getting a NativeWindow instance” on page 76
• “Activating, showing and hiding windows” on page 77
• “Maximizing, minimizing, and restoring a window” on page 77
• “Changing the window display order” on page 78
• “Closing a window” on page 78
• “Allowing cancellation of window operations” on page 79
• “Example: Minimizing, maximizing, restoring and closing a window” on page 79
• “Example: Resizing and moving windows” on page 80
To show a hidden window without activating it, set the visible property to true. This will bring the window to the
front, but will not take the keyboard or mouse focus.
To hide a window from view, set the NativeWindow.visible property to false. Hiding a window will suppress the
display of both the window, any related task bar icons, and, on MacOS X, the entry in the Windows menu.
Note: On Mac OS X, it is not possible to completely hide a minimized window that has a dock icon. If the visible
property is set to false on a minimized window, the dock icon for the window will still be displayed. If the user clicks
the icon, the window will be restored to a visible state and displayed.
Restoring a window returns it to the size that it was before it was either minimized or maximized.
To restore the window (that is, return it to the size that it was before it was either minimized or maximized), use the
NativeWindow.restore() method.
myWindow.restore();
Note: The behavior that results from maximizing an AIR window is different than the Mac OS X standard behavior.
Rather than toggling between an application-defined “standard” size and the last size set by the user, AIR windows toggle
between the size last set by the application or user and the full usable area of the screen.
ADOBE PRODUCT X.0 78
User Guide
Closing a window
To close a window, use the NativeWindow.close method.
Closing a window unloads the contents of the window, but if other objects have references to this content, the content
objects will not be destroyed. The NativeWindow.close() method executes asynchronously, the application that is
contained in the window continues to run during the closing process. The close method dispatches a close event
when the close operation is complete. The NativeWindow object is still technically valid, but accessing most
properties and methods on a closed window will generate an IllegalOperationError. You cannot reopen a closed
window. Check the closed property of a window to test whether a window has been closed. To simply hide a window
from view, set the NativeWindow.visible property to false.
If the Shell.autoExit property is true, which is the default, then the application exits when its last window closes.
ADOBE PRODUCT X.0 79
User Guide
Note that the dispatchEvent() method returns false if the event preventDefault() method is called by a
listener. However, it can also return false for other reasons, so it is better to explicitly use the
isDefaultPrevented() method to test whether the change should be canceled.
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical">
<mx:Script>
<![CDATA[
public function minimizeWindow():void
{
this.stage.nativeWindow.minimize();
}
]]>
</mx:Script>
<mx:VBox>
<mx:Button label="Minimize" click="minimizeWindow()"/>
<mx:Button label="Restore" click="restoreWindow()"/>
<mx:Button label="Maximize" click="maximizeWindow()"/>
<mx:Button label="Close" click="closeWindow()"/>
</mx:VBox>
</mx:WindowedApplication>
When an event is dispatched, the target property references the window sending the event.
Most window events have two related messages. The first message signals that a window change is imminent (and
can be canceled), while the second message signals that the change has occurred. For example, when a user clicks the
close button of a window, the closing event message is dispatched. If no listeners cancel the event, the window closes
and the close event is dispatched to any listeners.
Events in the flash.events.Event class:
• ACTIVATE
• DEACTIVATE
• CLOSING
• CLOSE
NativeWindowBoundsEvent:
Use the beforeBounds and afterBounds properties to determine the window bounds before and after the
impending or completed change.
• MOVING
• MOVE
ADOBE PRODUCT X.0 82
User Guide
• RESIZING
• RESIZE
NativeWindowDisplayStateEvent:
Use the beforeDisplayState and afterDisplayState properties to determine the window display state before
and after the impending or completed change.
• DISPLAY_STATE_CHANGING
• DISPLAY_STATE_CHANGE
GETTING STARTED
• “Screen basics” on page 83
• “Measuring the virtual desktop” on page 1
DEVELOPMENT TASKS
• “Enumerating the screens” on page 84
LANGUAGE REFERENCE
• Screen
MORE INFORMATION
You may be able to find more information about working the AIR File API in the AIR Developer Center
(http://www.adobe.com/devnet/air/flex/). Search the site using the keywords ‘AIR screens’.
Screen basics
The screen API contains a single class, Screen, which provides static members for getting system screen information,
and instance members for describing a particular screen.
A computer system may have several monitors or displays attached, which may correspond to several desktop
screens arranged in a virtual space. The AIR Screen class provides information about the screens, their relative
arrangement, and their usable space. If more than one monitor maps to the same screen, only one screen exists. If
the size of a screen is larger than the display area of the monitor, there is no way to determine which portion of the
screen is currently visible.
A screen represents an independent desktop display area. Screens are described as rectangles within the virtual
desktop. The top-left corner of screen designated as the primary display is the origin of the virtual desktop
coordinate system. All values used to describe a screen are provided in pixels.
ADOBE PRODUCT X.0 84
User Guide
In this screen arrangement, two screens exist on the virtual desktop. The coordinates of the top-left corner of the main screen (#1) are always
(0,0). If the screen arrangement is changed to designate screen #2 as the main screen, then the coordinates of screen #1 will become negative.
Menubars, taskbars and docks are excluded when reporting the usable bounds for a screen.
For detailed information about the screen API class, methods, properties, and events, see the Flex ActionScript 3.0
Language Reference (http://www.adobe.com/go/learn_flex3_aslr).
package {
import flash.display.Sprite;
import flash.display.Screen;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey);
}
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 +=
left[i].bounds.left - currentScreen.bounds.left;
stage.nativeWindow.y += left[i].bounds.top - currentScreen.bounds.top;
}
}
}
GETTING STARTED
• “AIR menu basics” on page 88
• “Adding native menus to an AIR application” on page 46
DEVELOPMENT TASKS
• “Creating native menus” on page 92
LANGUAGE REFERENCE
• NativeMenu
• NativeMenuItem
MORE INFORMATION
You may be able to find more information about working the AIR File API in the AIR Developer Center
(http://www.adobe.com/devnet/air/flex/). Search the site using the keywords ‘AIR menus’.
Types of menus
AIR supports the following types of menus:
Application menus Application menus can be accessed through the Shell class on operating systems that support
them. On Mac OS X, an application menu is automatically provided by the operating system. Your application can
use the AIR menu API to add items and submenu s to the standard menus as well as add handlers for the existing
menu commands. You can also replace the standard menu entirely.
Window menus Menus can be added to a window by creating a new NativeMenu object and assigning it to the
NativeWindow.menu property on operating systems that support them. Window menus are supported on the
Windows operating system, but not Mac OS X. Native menus can only be used for windows that have system chrome.
Context menus Context menus can be added to InteractiveObjects and document elements in an HTMLControl.
You would typically use the Webkit API for context menus on an HTML element, but you could also use a context
menu directly on the HTMLControl and modify it based on the element which generated the open menu event.
Dock and system tray icon menus Menus can be added to the dock or system tray icons by creating a new
NativeMenu object and assign it to the Shell.shell.icon.menu property. On Mac OS X, the new menu will be added
above the standard items in the menu. On Windows, there is no default menu.
ADOBE PRODUCT X.0 89
User Guide
Flex menus The Flex framework provides a set of Flex menu classes. The Flex classes can be used for windows that
do not have system chrome and allow you to specify menus declaratively in MXML format. If you are using the Flex
Framework, you may wish to use the Flex menu classes for window menus instead of the native classes.
Custom menus Native menus are drawn by the operating system and as such exist outside the Flash and HTML
rendering models. You are, of course, free to draw your own non-native menus. However, the AIR menu classes do
not provide an “owner draw” facility.
Menu structure
A menu contains one or more menu items. A menu item can be a command, a submenu, or a separator. Normally, a
menu item is a command. A menu item becomes a submenu when you assign a NativeMenu object to the submenu
property of the item. A menu item becomes a separator when you set the isSeparator parameter of the item
constructor to true.
The root-level menu in the structure contains the submenu items that appear on the menu bar. Only submenu items
should be added to the root menu of application and window menus. (Although some operating systems will display
command items on the menu bar, putting commands directly on the menu bar is still unconventional.) Command
and separator items can be used at the root level of pop-up and context menus.
The following diagram illustrates the structure of a typical menu. The root menu contains submenu items for a “File”
menu and an “Edit” menu. The “File” menu contains two commands and a submenu item for opening recent
documents (which has a menu containing three items). The “Edit” menu contains three commands and a separator.
ADOBE PRODUCT X.0 90
User Guide
To view a code example that creates this menu see Example: Window and application menu.
Menu events
Menus and menu items both dispatch displaying and select events:
Displaying: Immediately before a menu is displayed, the menu and its menu items will dispatch a displaying event
to any registered listeners. The displaying event gives you an opportunity to update the menu contents or item
appearance before it is shown to the user. For example, in the handler for the displaying event of an “Open Recent”
menu, you could change the menu items to reflect the current list of recently viewed documents.
ADOBE PRODUCT X.0 91
User Guide
The target property of the event object will always be the menu that is about to be displayed. The currentTarget
will be the object on which the listener is registered, either the menu itself, or one of its items.
Select: When a command item is chosen by the user, the item will dispatch a select event to any registered listeners.
Submenu and separator items cannot be selected and so never dispatch a select event.
Select events bubble up from items to their containing menu, on up to the root menu. You can listen for select events
directly on an item and you can listen higher up in the menu structure. When you listen for the select event on a
menu, you can identify the selected item using the event target property. As the event bubbles up through the menu
hierarchy, the currentTarget property of the event object identifies the current menu object.
Mnemonics
Mnemonics are part of the operating system keyboard interface to menus. Both Mac OS X and Windows allow users
to open menus and select commands with the keyboard, but there are subtle differences. On Mac OS X, the user
types the first letter or two of the menu or command and then types return.
On Windows, only a single letter is significant. By default, the significant letter is the first character in the label, but
if you assign a mnemonic to the menu item, then the designated letter will become the significant character. If two
items in a menu have the same significant character (whether or not a mnemonic has been assigned), then the user’s
keyboard interaction with the menu changes slightly. Instead of pressing a single letter to select the menu or
command, the user must press the letter as many times as necessary to highlight the desired item and then press the
enter key to complete the selection. To maintain a consistent behavior, it is generally advisable to assign a unique
mnemonic to each item in a menu for window menus.
Specify the mnemonic character as an index into the label string. The index of the first character in a label is 0. Thus,
to use “r” as the mnemonic for a menu item labeled, “Format”, you would set the mnemonicIndex property equal to 2.
var item:NativeMenuItem = new NativeMenuItem("Format");
item.mnemonicIndex = 2;
Note: If you are localizing the menu labels, be sure to update the mnemonic indexes as well as the label strings. (AIR
does not provide built-in support for localization. However, localization support is provided by the Flex framework.)
enabled toggle the value between true and false to control whether the command is enabled. Disabled items are
visually “grayed-out” and do not dispatch select events.
var item:NativeMenuItem = new NativeMenuItem("Format");
item.enabled = false;
In the root menu of a window or application, all the items must be submenus. (The root of a context menu can
contain all three types of menu items.) AIR provides two ways to create submenus. You can create the menu item and
assign the submenu in one step with the addSubmenu() method:
var editMenu:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit");
You can also create the menu item and assign the submenu separately:
var editMenu:NativeMenuItem = root.addItem("Edit");
editMenu.submenu = new NativeMenu();
After the menu is created, you can assign it as an application, window, icon, or context menu:
Creating a command:
var copy:NativeMenuItem = new NativeMenuItem("Copy",false);
copy.addEventListener(Event.SELECT,onCopyCommand);
editMenu.addItem(copy);
Creating a submenu:
var editMenu:NativeMenuItem = new NativeMenuItem("Edit", false);
editMenu.submenu = new NativeMenu();
You can also create an item and its submenu in one step using the parent menu’s addSubmenu() method:
var editMenu:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit");
Creating a separator:
var separatorA:NativeMenuItem = new NativeMenuItem("A", true);
editMenu.addItem(separatorA);
To create a menu with this class, pass an XML menu definition as follows:
var menuDefinition:String =
"<root>" +
"<FileMenu label='File'>" +
"<NewMenu label='New'>" +
"<NewTextFile label='Text file'/>" +
"<NewFolder label='Folder'/>" +
"<NewProject label='Project'/>" +
"</NewMenu>" +
"<OpenCommand label='Open'/>" +
"<SaveCommand label='Save'/>" +
"</FileMenu>" +
"<EditMenu label='Edit'/>" +
"<CutCommand label='Cut'/>" +
"<CopyCommand label='Copy'/>" +
"<PasteCommand label='Paste'/>" +
"<EditMenu/>" +
"<FoodItems label='Food Items'>" +
"<Jellyfish/>" +
"<Tripe/>" +
"<Gizzard/>" +
"</FoodItems>" +
"</root>";
var test:DeclarativeMenu = new DeclarativeMenu(new XML(menuDefinition));
To listen for menu events, you could listen at the root menu level and use the event.target.name property to detect
which command was selected. You could also look up items in the menu by name and add individual event listeners.
The menu is designed to work both under Windows, for which only window menus are supported, and under Mac
OS X, for which only application menus are supported. To make the distinction, the MenuExample class constructor
checks the static supportsMenu properties of the NativeWindow and Shell classes. If
NativeWindow.supportsMenu is true, then the constructor creates a new NativeMenu object for the window and
then creates and adds the File and Edit submenus. If Shell.supportsMenu is true, then the constructor creates and
adds the File and Edit menus to the existing menu provided by the OS X operating system.
The example also illustrates menu event handling. The select event is handled at the item level and also at the menu
level. Each menu in the chain from the menu containing the selected item to the root menu will respond to the
selection event. The displaying event is used with the “Open Recent” menu. Just before the menu is opened, the items
in the menu are refreshed from the recent Documents array (which doesn’t actually change in this example).
Although not shown in this example, you can also listen for displaying events on individual items.
package {
import flash.display.NativeMenu;
import flash.display.NativeMenuItem;
import flash.display.NativeWindow;
import flash.display.Sprite;
import flash.events.Event;
import flash.filesystem.File;
import flash.system.Shell;
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();
}
if(Shell.supportsMenu){
Shell.shell.menu.addEventListener(Event.SELECT, selectCommandMenu);
fileMenu = Shell.shell.menu.addItem(new NativeMenuItem("File"));
fileMenu.submenu = createFileMenu();
editMenu = Shell.shell.menu.addItem(new NativeMenuItem("Edit"));
editMenu.submenu = createEditMenu();
}
}
return fileMenu;
}
return editMenu;
}
GETTING STARTED
• “AIR file basics” on page 100
• “Building a text-file editor” on page 9
• “Building a directory search application” on page 13
• “Reading and writing from an XML preferences file” on page 17
• “Compressing files and data” on page 80
DEVELOPMENT TASKS
• “Working with File objects” on page 101
• “Working with directories” on page 107
• “Working with files” on page 109
• “Using the encrypted local store” on page 122
LANGUAGE REFERENCE
• File
• FileStream
• FileMode
MORE INFORMATION
You may be able to find more information about working the AIR File API in the AIR Developer Center
(http://www.adobe.com/devnet/air/flex/). Search the site using the keywords ‘AIR filesystem’.
FileStream A FileStream object is used to open files for reading and writing. Once you’ve created a File object that
points to a new or existing file, you pass that pointer to the FileStream object so that you can open and then manip-
ulate data within the file.
Some methods in the File class have both synchronous and asynchronous versions:
• File.copyTo() and File.copyToAsync()
Also, FileStream operations work synchronously or asynchronously depending on how the FileStream object opens
the file: by calling the open() or by calling openAsync() method.
The asynchronous versions let you initiate processes that run in the background and dispatch events when complete
(or when error events occur). Other code can execute while these asynchronous background processes are taking
place. With asynchronous versions of the operations, you need to set up event listener functions, using the
addEventListener() method of the File or FileStream object that calls the function.
The synchronous versions let you write simpler code that does not rely on setting up event listeners. However, since
other code cannot execute while a synchronous method is executing, important processes, such as display object
rendering and animation, may be paused.
You can point a File object to the user's documents directory. On Windows, this is typically the "My Documents"
directory (for example, "C:\Documents and Settings\userName\My Documents"). On Mac OS, it is the
Users/userName/Documents directory. The following code sets a File object to point to an AIR Test subdirectory of
the documents directory:
var file:File = File.documentsDirectory.resolvePath("AIR Test");
You can point a File object to the desktop. The following code sets a File object to point to an AIR Test subdirectory
of the desktop:
var file:File = File.desktopDirectory.resolvePath("AIR Test");
You can point a File object to the application storage directory. For every AIR application, there is a unique associated
path that defines the application store directory. You may want to use this directory to store application-specific data
(such as user data or preferences files). For example, the following code points a File object to a preferences file,
prefs.xml, contained in the application storage directory:
var file:File = File.applicationStorageDirectory;
file = file.resolvePath("prefs.xml");
You can point a File object to the directory in which the application was installed, known as the application resource
directory. You can reference this directory using the File.applicationResourceDirectory property. You may
use this directory to examine the application descriptor file or other resources installed with the application. For
example, the following code points a File object to a directory named images in the application resource directory:
var file:File = File.applicationResourceDirectory;
file = file.resolvePath("images");
ADOBE PRODUCT X.0 103
User Guide
The File.getRootDirectories() method lists all root volumes, such as C: and mounted volumes, on a Windows
computer. On Mac, this method always returns the unique root directory for the machine (the "/" directory).
You can point the File object to an explicit directory by setting the nativePath property of the File object, as in the
following example (on Windows):
var file:File = new File();
file.nativePath = "C:\\AIR Test\\";
You can use the resolvePath() method to obtain a path relative to another given path. For example, the following
code sets a File object to point to an "AIR Test" subdirectory of the user's home directory:
var file:File = File.userDirectory;
file = file.resolvePath("AIR Test");
You can also use the url property of a File object to point it to a directory based on a URL string, as in the following:
var urlStr:String = "file:///C:/AIR Test/";
var file:File = new File()
file.url = urlStr;
You can also use the nativePath property of a File object to set an explicit path. For example, the following code,
when run on a Windows computer, sets a File object to the AIR Test subdirectory of the C: drive:
var file:File = new File();
file.nativePath = "C:\\AIR Test";
file = file.resolvePath("log.txt");
You can use the url property of a File object to point it to a file or directory based on a URL string, as in the following:
var urlStr:String = "file:///C:/AIR Test/test.txt";
var file:File = new File()
file.url = urlStr;
You can also pass the URL to the File() constructor function, as in the following:
var urlStr:String = "file:///C:/AIR Test/test.txt";
var file:File = new File(urlStr);
Note that url property always returns the URI-encoded version of the URL (for example, blank spaces are replaced
with "%20):
file.url = "file:///c:/AIR Test";
trace(file.url); // file:///c:/AIR%20Test
You can also use the nativePath property of a File object to set an explicit path. For example, the following code,
when run on a Windows computer, sets a File object to the test.txt file in the AIR Test subdirectory of the C: drive:
var file:File = new File();
file.nativePath = "C:/AIR Test/test.txt";
You can also pass this path to the File() constructor function, as in the following:
var file:File = new File("C:/AIR Test/test.txt");
On Windows you can use the forward slash (/) or backslash (\) character as the path delimiter for the nativePath
property. On Mac OS, use the forward slash (/) character as the path delimiter for the nativePath :
var file:File = new File(/Users/dijkstra/AIR Test/test.txt");
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);
ADOBE PRODUCT X.0 105
User Guide
function fileSelected(event:Event):void
{
trace(fileToOpen.nativePath);
}
If the application has another browser dialog box open when you call a browse method, the runtime throws an error.
When using the nativePath property, you use either the forward slash (/) or backslash (\) character as the directory
separator character on Windows; use the forward slash (/) character on Mac OS. On Windows, remember to type
the backslash character twice in a string literal.
file:///c:/AIR Test/test.txt
app-resource Use this to specify a path relative to the root directory of the installed application (the directory that
contains the application.xml file for the installed application). For example, the following path points to an images
subdirectory of the directory of the installed application:
app-resource:/images
app-storage Use this to specify a path relative to the application store directory. For each installed application, AIR
defines a unique application store directory, which is a useful place to store data specific to that application. For
example, the following path points to a prefs.xml file in a settings subdirectory of the application store directory:
app-storage:/settings/prefs.xml
trace(file1.getRelativePath(file2)); // bob/test.txt
The second parameter of the getRelativePath() method, the useDotDot parameter, allows for .. syntax to be
returned in results, to indicate parent directories:
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");
However, documents and directory names do include capitalization. For example, the following assumes that there
is a folder named AIR Test in the documents directory, as in the following examples:
var file:File = File.documentsDirectory.resolvePath("AIR test");
trace(file.nativePath); // ... AIR test
file.canonicalize();
trace(file.nativePath); // ... AIR Test
The canonicalize method converts the nativePath object to use the correct capitalization for the file or directory
name.
You can also use the canonicalize() method to convert short file names ("8.3" names) to long file names on
Windows, as in the following examples:
var path:File = new File();
path.nativePath = "C:\\AIR~1";
path.canonicalize();
trace(path.nativePath); // C:\AIR Test
Capabilities.hasIME Specifies whether the player is running on a system that does (true) or does not (false)
have an input method editor (IME) installed.
Capabilities.language Specifies the language code of the system on which the player is running.
Creating directories
The File.createDirectory() method lets you create a directory. For example, the following code creates a
directory named AIR Test as a subdirectory of the user's home directory:
var dir:File = File.userDirectory.resolvePath("AIR Test");
dir.createDirectory();
The createTempDirectory() method automatically creates a unique temporary directory (saving you the work of
determining a new unique location).
You may use a temporary directory to temporarily store temporary files used for a session of the application. Note
that there is a createTempFile() method, for creating new, unique temporary files in the System temporary
directory.
You may want to delete the temporary directory before closing the application, as it is not automatically deleted.
ADOBE PRODUCT X.0 108
User Guide
Enumerating directories
You can use the getDirectoryListing() method or the getDirectoryListingAsync() method of a File object
to get an array of File objects pointing to files and subfolders in a directory.
For example, the following code lists the contents of the user's documents directory (without examining subdirec-
tories):
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);
}
When using the asynchronous version of the method, the directoryListing event object has a files property that is the
array of File objects pertaining to the directories:
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);
}
}
Note that when you specify true for the overwrite parameter of the copyTo() method, all files and folders in an
existing target directory are deleted and replaced with the files and folders in the source directory (even if the target
file does not exist in the source directory).
For details, see “Copying and moving files” on page 110.
The following code asynchronously deletes the AIR Test subdirectory of the user's documents directory:
var directory:File = File.documentsDirectory.resolvePath("AIR Test");
directory.addEventListener(Event.COMPLETE, completeHandler)
directory.deleteDirectoryAsync(true);
function completeHandler(event:Event):void {
trace("Deleted.")
}
Also included are the moveToTrash() and moveToTrashAsync methods, which you can use to move a directory to
the System trash. For details, see “Moving a file to the trash” on page 111.
creator Obsolete—use the extension property. (This property reports the Macintosh creator type of the file, which
is only used in Mac OS versions prior to Mac OS X.)
extension The file extension, which is the part of the name following (and not including) the final dot ("."). If there is no
dot in the filename, the extension is null.
icon An Icon object containing to the icons defined for the file.
modificationDate The date that the file on the local disk was last modified.
nativePath The full path in the host operating system representation. See “Paths of File objects” on page 102.
parent The folder that contains the folder or file represented by the File object. This property is null if the File object
references a file or directory in the root of the filesystem.
type Obsolete—use the extension property. (On the Macintosh, this property is the four-character file type,
which is only used in Mac OS versions prior to Mac OS X.)
url The URL for the file or directory. See “Paths of File objects” on page 102.
For details on these properties, see the File class entry in the ActionScript 3.0 Language Reference.
Note that in this example, the value of overwrite parameter of the copyTo() method (the second parameter) is set
to true. By setting this to true, an existing target file is overwritten. This parameter is optional. If you set it to false
(the default value), the operation dispatches an IOErrorEvent event if the target file already exists (and the file is not
copied).
The Async versions of the copy and move methods work asynchronously. Use the addEventListener() method to
monitor completion of the task or error conditions, as in the following code:
var original = File.documentsDirectory;
original = original.resolvePath("AIR Test/test.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.");
}
ADOBE PRODUCT X.0 111
User Guide
The File class also includes the File.moveToTrash() and File.moveToTrashAsync() methods, which move a file
or directory to the system trash.
Deleting a file
The File class includes a deleteFile() method and a deleteFileAsync() method. These both delete files, the
first working synchronously, the second working asynchronously (see “AIR file basics” on page 100).
For example, the following code synchronously deletes the test.txt file in the user's documents directory:
var directory:File = File.documentsDirectory.resolvePath("test.txt");
directory.deleteFile();
The following code asynchronously deletes the test.txt subdirectory of the user's documents directory:
var file:File = File.documentsDirectory.resolvePath("test.txt");
file.addEventListener(Event.COMPLETE, completeHandler)
file.deleteFileAsync();
function completeHandler(event:Event):void {
trace("Deleted.")
}
Also included are the moveToTrash() and moveToTrashAsync methods, which you can use to move a file or
directory to the System trash. For details, see “Moving a file to the trash” on page 111.
The createTempFile() method automatically creates a unique temporary file (saving you the work of determining
a new unique location).
You may use a temporary file to temporarily store information used in a session of the application. Note that there
is also a createTempDirectory() method, for creating a new, unique temporary directory in the System temporary
directory.
You may want to delete the temporary file before closing the application, as it is not automatically deleted.
ADOBE PRODUCT X.0 112
User Guide
This example uses the File.documentsDirectory property and the resolvePath() method of a File object to
initialize the File object. However, there are many other ways to point a File object to a file. For more information,
see “Pointing a File object to a file” on page 103.
For more information, see “Initializing a FileStream object, and opening and closing files” on page 113 and
“FileStream open modes” on page 113.
4. If you opened the file asynchronously (using the openAsync() method), add and set up event listeners for
the FileStream object.
These event listener methods will respond to events dispatched by the FileStream object in a variety of situations,
such as when data is read in from the file, when I/O errors are encountered, or when the complete amount of data
to be written has been written.
For details, see “Asynchronous programming and the events generated by a FileStream object opened asynchro-
nously” on page 117.
For details, see “Data formats, and choosing the read and write methods to use” on page 118.
6. Call the close() method of the FileStream object when you are done working with the file.
This makes the file available to other applications.
ADOBE PRODUCT X.0 113
User Guide
For details, see “Initializing a FileStream object, and opening and closing files” on page 113.
The sections that follow provide more details on using the AIR file APIs to read and write files.
For examples of using FileStream object to read and write files, see the following topics:
• “Building a text-file editor” on page 9
• “Reading and writing from an XML preferences file” on page 17
• “Building a directory search application” on page 13
FileMode.WRITE Specifies that the file is open for writing. If the file does not exist, it is created when the FileStream
object is opened. If the file does exist, any existing data is deleted.
FileMode.APPEND Specifies that the file is open for appending. The file is created if it does not exist. If the file
already exists, existing data is not overwritten, and all writing begins at the end of the file.
FileMode.UPDATE Specifies that the file is open for reading and writing. If the file does not exist, it is created.
Specify this mode for random read/write access to the file. You can read from any position in the file, and when
writing to the file, only the bytes written overwrite existing bytes (all other bytes remain unchanged).
myFileStream.open(myFile, FileMode.READ);
The fileMode parameter (the second parameter of the open() and openAsync() methods), specifies the mode in
which to open the file: for read, write, append, or update. For details, see the previous section, “FileStream open
modes” on page 113.
If you use the openAsync() method to open the file for asynchronous file operations, set up event listeners to handle
the asynchronous events:
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 {
// ...
}
The file is opened for synchronous or asynchronous operations, depending upon whether you use the open() or
openAsync() method. For details, see “AIR file basics” on page 100.
If you set the fileMode parameter to FileMode.READ or FileMode.UPDATE in the open method of the FileStream
object, data is read into the read buffer as soon as you open the FileStream object. For details, see “The read buffer
and the bytesAvailable property of a FileStream object” on page 116.
You can call the close() method of a FileStream object to close the associated file, making it available for use by
other applications.
When you first open a FileStream object, the position property is set to 0.
Prior to a read operation, the value of position must be at least 0 and less than the number of bytes in the file (which
are existing positions in the file).
The value of the position property is modified only in the following conditions:
ADOBE PRODUCT X.0 115
User Guide
There is, however, one exception: for a FileStream opened in append mode, the position property is not changed
after a call to a write method. (In append mode, data is always written to the end of the file, independent of the value
of the position property.)
Note that for a file opened for asynchronous operations, the write operation does not complete before the next line
of code is executed. However, you can call multiple asynchronous methods sequentially, and the runtime will execute
them in order:
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.");
}
You can specify the position value immediately after you call a read or write method (or at any time), and the next
read or write operation will take place starting at that position. For example, note that the following code sets the
position property right after a call to the writeBytes() operation, and the position is set to that value (300) even
after the write operation completes:
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
ADOBE PRODUCT X.0 116
User Guide
For a file opened for synchronous operations (using the open() method), you can always set the position pointer
to any valid position (within the bounds of the file) and begin reading any amount of data (within the bounds of the
file), as shown in the following code (which assumes that the file contains at least 100 bytes):
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);
Whether a file is opened for synchronous or asynchronous operations, the read methods always read from the
"available" bytes, represented by the bytesAvalable property. When reading synchronously, all of the bytes of the
file are available all of the time. When reading asynchronously, the bytes become available starting at the position
specified by the position property, in a series of asynchronous buffer fills signalled by progress events.
For files opened for synchronous operations, the bytesAvailable property is always set to represent the number of
bytes from the position property to the end of the file (all bytes in the file are always available for reading).
For files opened for asynchronous operations, you need to ensure that the read buffer has consumed enough data
prior to calling a read method. For a file opened asynchronously, as the read operation progresses, the data from the
file, starting at the position specified when the read operation started, is added to the buffer, and the
bytesAvailable property increments with each byte read. The bytesAvailable property indicates the number of
bytes available starting with the byte at the position specified by the position property to the end of the buffer.
Periodically, the FileStream object sends a progress event.
For a file opened asynchronously, as data becomes available in the read buffer, the FileStream object periodically
dispatches the progress event. For example, the following code reads data into a ByteArray object, bytes, as it is
read into the buffer:
var bytes:ByteArray = new ByteArray();
var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, FileMode.READ);
function progressHandler(event:ProgressEvent):void
{
myFileStream.readBytes(bytes, myFileStream.position, myFileStream.bytesAvailable);
}
For a file opened asynchronously, only the data in the read buffer can be read. Furthermore, as you read the data, it
is removed from the read buffer. For read operations, you will need to ensure that the data exists in the read buffer
prior to calling the read operation. You may do this by setting up a progress handler. For example, the following
code reads 8000 bytes of data starting from position 4000 in the file:
var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.addEventListener(Event.COMPLETE, completed);
ADOBE PRODUCT X.0 117
User Guide
myFileStream.openAsync(myFile, FileMode.READ);
myFileStream.position = 4000;
function progressHandler(event:Event):void
{
if (myFileStream.bytesAvailable > 8000 )
{
str += myFileStream.readMultiByte(8000, "iso-8859-1");
}
}
During a write operation, the FileStream object does not read data into the read buffer. When a write operation
completes (all data in the write buffer is written to the file), the FileStream object starts a new read buffer (assuming
that the associated FileStream object was opened with read capabilities), and starts reading data into the read buffer,
starting from the position specified by the position property. The position property may be the position of the
last byte written, or it may be a different position, if the user specifies a different value for the position object after
the write operation.
Asynchronous programming and the events generated by a FileStream object opened asynchronously
When a file is opened asynchronously (using the openAsync() method), reading and writing files are done
asynchronously. As data is read into the read buffer and as output data is being written, other ActionScript code can
execute.
This means that you will need to register for events generated by the FileStream object opened asynchronously.
By registering for the progress event, you can be notified as new data becomes available for reading, as in the
following 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");
}
You can read the entire data by registering for the complete event, as in the following 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");
}
ADOBE PRODUCT X.0 118
User Guide
In much the same way that input data is buffered to enable asynchronous reading, data that you write on an
asynchronous stream is buffered and written to the file asynchronously. As data is written to a file, the FileStream
object periodically dispatched an OutputProgressEvent object. An OutputProgressEvent object includes a
bytesPending property that is set to the number of bytes remaining to be written. You can register for the
outputProgressEvent to be notified as this buffer is actually written to the file, perhaps in order to display a
progress dialog. However in general it is not necessary to do so. In particular, you may call the close() method
without concern for the unwritten bytes. The FileStream object will continue writing data and the close event will
be delivered after the final byte is written to the file and the underlying file is closed.
Data formats, and choosing the read and write methods to use
Every file is a set of bytes on a disk. In ActionScript, the data from a file can always be represented as a ByteArray.
For example, the following code reads the data from a file into a ByteArray object named bytes:
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);
function completeHandler(event:Event):void
{
myFileStream.readBytes(bytes, 0, myFileStream.bytesAvailable);
}
Similarly, the following code writes data from a ByteArray named bytes to a file:
var myFile:File = File.documentsDirectory.resolvePath("AIR Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.WRITE);
myFileStream.writeBytes(bytes, 0, bytes.length);
However, often you do not want to store the data in an ActionScript ByteArray object. And often the data file will be
in a specified file format.
For example, the data in the file may be in a text file format, and you may want to represent such data in a String
object.
For this reason, the FileStream class includes read and write methods for reading and writing data to and from types
other than ByteArray objects. For example, the readMultiByte() method lets you read data from a file and store it
to a string, as in the following 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");
}
Note that the second parameter of the readMultiByte() method specifies the text format that ActionScript uses to
interpret the data ("iso-8859-1" in the example). ActionScript supports a number of common character set
encodings, and these are listed in the ActionScript Language Reference (see Supported character sets at
http://livedocs.macromedia.com/flex/2/langref/charset-codes.html).
ADOBE PRODUCT X.0 119
User Guide
The FileStream class also includes the readUTFBytes() method, which reads data from the read buffer into a string
using the UTF-8 character set. Since characters in the UTF-8 character set is are of a variable length, you should not
try to use readUTFBytes() in a method that responds to the progress event, since the data at the end of the read
buffer may represent an incomplete character. (This is also true when using the readMultiByte() method with a
variable-length character encoding.) For this reason, you should read the entire data when the FileStream object
dispatches the complete event.
There are also similar write methods, writeMultiByte() and writeUTFBytes(), for working with String objects
and text files.
Note that the readUTF() and the writeUTF() methods (not to be confused with readUTFBytes() and
writeUTFBytes()) also read and write the text data to a file, but they assume that the text data is preceded by data
specifying the length of the text data, which is not a common practice in standard text files.
Some UTF-encoded text files begin with a "UTF-BOM" (byte order mark) character that defines the endianess as
well as the encoding format (such as UTF-16 or UTF-32).
For an example of reading and writing to a text file, see “Example: Reading an XML file into an XML object”
on page 119.
The readObject() and writeObject() are convenient ways to store and retrieve data for complex ActionScript
objects. The data is encoded in AMF (ActionScript Message Format). This format is proprietary to ActionScript.
Applications other than AIR, Flash Player, Flash Media Server, and Flex Data Services do not have built-in APIs for
working with data in this format.
There are a number of other read and write methods (such as readDouble() and writeDouble()). However, if you
use these, make sure that the file format matches the formats of the data defined by these methods.
File formats are often more complex than simple text formats. For example, an MP3 file includes compressed data
that can only be interpreted with the decompression and decoding algorithms specific to MP3 files. MP3 files also
may include ID3 tags that contain metatag information about the file (such as the title and artist for a song). There
are multiple versions of the ID3 format, but the simplest (ID3 version 1) is discussed in the “Example: Reading and
writing data with random access” on page 120 section.
Other files formats (for images, databases, application documents, etc.) have quite different structures, and to work
with their data in ActionScript, you need to understand how the data is structured.
Similarly, writing the data to the file is as easy as setting up an appropriate File and FileStream objects, and then
calling a write method of the FileStream object, passing the string version of the XML data to the write method as in
the following code:
var file:File = File.documentsDirectory.resolvePath("AIR Test/preferences.xml");
fileStream = new FileStream();
ADOBE PRODUCT X.0 120
User Guide
fileStream.open(file, FileMode.WRITE);
fileStream.writeUTFBytes(outputString);
fileStream.close();
Note that these examples use the readUTFBytes() and writeUTFBytes() methods, because they assume that the
files are in UTF-8 format. If this is not the case, you may need to use a different method (see “Data formats, and
choosing the read and write methods to use” on page 118).
The previous examples use FileStream objects opened for synchronous operation. You can also open files for
asynchronous operations (which rely on event listener functions to respond to events). For example, the following
code shows how to read an XML file asynchronously:
var file:File = File.documentsDirectory.resolvePath("AIR Test/preferences.xml");
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.COMPLETE, processXMLData);
fileStream.open(file, FileMode.READ);
var prefsXML:XML;
function processXMLData(event:Event):void
{
prefsXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
}
The processXMLData() method is invoked when the entire file is read into the read buffer (when the FileStream
object dispatches the complete event). It calls the readUTFBytes() method to get a string version of the read data,
and it creates an XML object, prefsXML, based on that string.
To see a sample application that shows these capabilities, see “Reading and writing from an XML preferences file”
on page 17.
We set the position to this location in the file because the ID3 v1.0 format specifies that the ID3 tag data is stored
in the last 128 bytes of the file. The specification also says the following:
• The first 3 bytes of the tag contain the string "TAG".
• The next 30 characters contain the title for the MP3 track, as a string.
• The next 30 characters contain the name of the artist, as a string.
• The next 30 characters contain the name of the album, as a string.
• The next 4 characters contain the year, as a string.
• The next 30 characters contain the comment, as a string.
• The next byte contains a code indicating the track's genre.
• All text data is in ISO 8859-1 format.
The id3TagRead() method checks the data after it is read in (upon the complete event):
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);
}
}
function id3TagRead()
{
if (fileStr.readMultiByte(3, "iso-8859-1").match(/tag/i))
{
var id3Title = fileStr.readMultiByte(30, "iso-8859-1");
var id3Artist = fileStr.readMultiByte(30, "iso-8859-1");
var id3Album = fileStr.readMultiByte(30, "iso-8859-1");
var id3Year = fileStr.readMultiByte(4, "iso-8859-1");
var id3Comment = fileStr.readMultiByte(30, "iso-8859-1");
var id3GenreCode = fileStr.readByte().toString(10);
}
}
You can also perform a random-access write to the file. For example, you could parse the id3Title variable to
ensure that it is correctly capitalized (using methods of the String class), and then write a modified string, called
newTitle, to the file, as in the following:
To conform with the ID3 version 1 standard, the length of the newTitle string should be 30 characters, padded at
the end with the character with the code 0 (String.fromCharCode(0)).
ADOBE PRODUCT X.0 122
User Guide
You may want to use the encrypted local store to store information that must be secured, such as login credentials
for web services.
AIR uses DPAPI on Windows and KeyChain on Mac OS to associate the encrypted local store to each application
and user. The encrypted local store uses AES-CBC 128-bit encryption.
Information in the encrypted local data store is only available to AIR application content in the application security
sandbox.
Use the setItem() and removeItem() static methods of the EncryptedLocalStore class to store and retrieve data
from the local store. The data is stored in a hash table, using strings as keys, with the data stored as byte arrays.
For example, the following code stores a string in the encrypted local store:
var str:String = "Bob";
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(str);
EncryptedLocalStore.setItem("firstName", bytes);
You can delete a value from the encrypted local store by using the EncryptedLocalStore.removeItem() method,
as in the following example:
EncryptedLocalStore.removeItem("firstName");
123
GETTING STARTED
• “Drag and drop basics” on page 123
• “Dragging, copying, and pasting data” on page 35
DEVELOPMENT TASKS
• “Supporting the drag-out gesture” on page 125
• “Supporting the drag-in gesture” on page 127
• “HTML Drag and drop” on page 129
LANGUAGE REFERENCE
• DragManager *
• DragOptions *
• Clipboard
• NativeDragEvent
* The Flex 3 ActionScript Language Reference incorrectly lists these classes as NativeDragManager and NativeDra-
gOptions.
MORE INFORMATION
You may be able to find more information about working the AIR File API in the AIR Developer Center
(http://www.stage.adobe.com/devnet/air/flex/). Search the site using the keywords ‘AIR drag and drop’.
Package Classes
Constants used with the drag-and-drop API are defined in the following classes: DragActions, ClipboardFormat, Clip-
boardTransferModes
flash.events NativeDragEvent
The following example illustrates how to start a drag operation for a bitmap object loaded from a file. The example
loads an image and, on a mouseDown event, starts the drag operation.
import flash.desktop.DragManager;
import mx.core.UIComponent;
import flash.desktop.Clipboard;
import flash.display.Bitmap;
import flash.filesystem.File;
Dragging Sprites
Sprite objects have a separate drag API which allows drag gestures to be used to move sprites around on the stage of
a window. You can use both APIs at the same time to allow moving a sprite around its current stage as well as out of
the stage. However, the DragManager API will take precedence visually — that is, the drag image or mouse pointer
will be shown rather than the live, possibly animated, sprite.
If more than one drag action is specified, or no action is specified, the effective action reported back to the initiating
object will follow precedence: copy, move, link. If none of the actions set by the receiving component matches an
action allowed by the drag gesture, then the receiving component will not be eligible to take the drop.
ondragend dispatched when the user releases the mouse button to end the drag gesture.
ondragleave dispatched when the drag gesture leaves the element boundaries.
ondragdrop dispatched when the user drops the data onto the element. The data being dragged can only be accessed
within the handler for this event.
{
droppedText = evt.dataTransfer.getData("text/plain");
}
Use the dataTransfer.getData() method to read the data onto the clipboard, passing in the mime type of the data
format to read.
copy The data should be copied to the destination, leaving the original in place.
link The data should be shared with the drop destination using a link back to the original.
move The data should be copied to the destination and removed from the original location.
copyMove The data can be copied or moved. This is the default value.
The target of the drag gesture should set the dataTransfer.dropEffect property to indicate the action taken. The
value should be one of the actions allowed by the initiator, but this is not enforced (it is up to the application logic to
take the appropriate action). The dropEffect is typically set in the handler for the ondragenter handler, but can
be set in any of the events dispatched by the drag target (except ondragleave).
function doDragStart(evt) {
evt.dataTransfer.setData("text/plain","Text to drag");
evt.dataTransfer.effectAllowed = "all";
}
function doDragEnter(evt) {
evt.dataTransfer.dropEffect = "move";
}
131
GETTING STARTED
• “Copy-and-paste basics” on page 131
• “Dragging, copying, and pasting data” on page 35
DEVELOPMENT TASKS
• “Reading from and writing to the system clipboard” on page 132
• “Clipboard data formats” on page 132
LANGUAGE REFERENCE
• Clipboard
• ClipboardFormats
• ClipboardTransferMode
MORE INFORMATION
You may be able to find more information about working the AIR clipboard API in the AIR Developer Center
(http://www.stage.adobe.com/devnet/air/flex/). Search the site using the keywords ‘AIR copy and paste’.
Copy-and-paste basics
The copy-and-paste API contains the following classes.
Package Classes
flash.desktop Clipboard, Constants used with the copy-and-paste API are defined in the following classes: ClipboardFormats, Clip-
boardTransferMode
The static Clipboard.generalClipboard property represents the operating system clipboard. Access the system
clipboard through the static Clipboard.generalClipboard property. Clipboard objects are also used to transfer
data through the drag-and-drop API. The Clipboard class provides methods for reading and writing data to
clipboard objects.
ADOBE PRODUCT X.0 132
User Guide
The data on the clipboard is represented by an instance of a Clipboard object. Different representations of the same
information can be made available in a single Clipboard object to increase the ability of other applications to under-
stand and use the data. For example, an image might be included as image data, a serialized Bitmap object, and as a
file. Rendering of the data in a format can be deferred so that the format is not actually created until the data in that
format is read.
An application object can be transferred as a reference and as a serialized object. References are only valid within the
originating application. Serialized object transfers are valid between Adobe AIR applications, but can only be used
with objects that remain valid when serialized and deserialized.
See also
• “Clipboard data formats” on page 132
if(Clipboard.generalClipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)){
var text:String = Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT);
}
To write to the clipboard, add the data to Clipboard.generalClipboard in one or more formats. Any existing data
in the same format will be overwritten automatically. However, it is a good practice to also clear the system clipboard
before writing new data to it to make sure that unrelated data in any other formats is also deleted.
import flash.desktop.Clipboard;
import flash.desktop.ClipboardFormats;
Clipboard.generalClipboard.clear();
var textToCopy:String = "Copy to clipboard.";
Clipboard.generalClipboard.addData(ClipboardFormats.TEXT_FORMAT,textToCopy,false);
TEXT_FORMAT Text-format data is translated to and from the ActionScript String class.
BITMAP_FORMAT Bitmap-format data is translated to and from the ActionScript BitmapData class.
FILE_LIST_FORMAT File-list-format data is translated to and from an array of ActionScript File objects.
URL_FORMAT URL-format data is translated to and from the ActionScript String class.
When copying and pasting data in response to an oncopy, oncut, or onpaste event in HTML content, mime types
must be used instead of the ClipboardFormat strings. The valid data mime types are:
Text •"text/plain"
URL •"text/uri-list"
Bitmap •"image/x-vnd.adobe.air.bitmap"
File list •"application/x-vnd.adobe.air.file-list"
To extract a serialized object from the clipboard object (after a drop or paste operation), use the same format name
and the cloneOnly or clonePreferred transfer modes.
var transfer:Object = clipboard.getData("object", ClipboardTransferMode.CLONE_ONLY);
A reference is always added to the Clipboard object. To extract the reference from the clipboard object (after a drop
or paste operation), instead of the copy, use the originalOnly or originalPreferred transfer modes:
var transferedObject:Object =
clipboard.getData("object", ClipboardTransferMode.ORIGINAL_ONLY);
References are only valid if the Clipboard object originates from the current AIR application. Use the originalPre-
ferred transfer mode to access the reference when it is available, and the serialized clone when the reference is not
available.
Deferred rendering
If creating a data format is computationally expensive, you can use deferred rendering by supplying a function that
supplies the data on demand. The function is only called if a receiver of the drop or paste operation requests data in
the deferred format.
The rendering function is added to a Clipboard object using the setDataHandler() method and must return the
data in the expected format.
If a data format of the same type is added to a Clipboard object with the setData() method, that data will take prece-
dence over the deferred version (the rendering function will never be called).
ADOBE PRODUCT X.0 134
User Guide
About SQL
Structured Query Language (SQL) is used with relational databases to manipulate and retrieve data. SQL is a
descriptive language rather than a procedural language: instead of giving the computer instructions on how it
should retrieve data, a SQL statement describes the set of data you want, and the computer determines how to
retrieve that data.
The SQL language has been standardized by the American National Standards Institute (ANSI). The Adobe AIR
local SQL database supports most of the SQL-92 standard. For specific descriptions of the SQL language supported
in Adobe AIR, see the appendix “SQL support in local databases” in the Adobe AIR language reference.
Other classes in the flash.data package provide constants that are used with the SQLConnection class and the
SQLColumnSchema class:
• flash.data.SQLColumnNameStyle Defines a set of constants representing the possible values for the
SQLConnection.columnNameStyle property.
• flash.data.SQLTransactionLockType Defines a set of constants representing the possible values for the
option parameter of the SQLConnection.begin() method.
• flash.data.SQLCollationType Defines a set of constants representing the possible values for the
SQLColumnSchema.defaultCollationType property and the defaultCollationType parameter of the
SQLColumnSchema() constructor.
In addition, the following classes in the flash.events package represent the events (and supporting constants) that
you will use:
ADOBE PRODUCT X.0 138
User Guide
• flash.events.SQLEvent Defines the events that are dispatched when any of the SQLConnection or
SQLStatement operations execute successfully. Each operation has an associated event type, all of which are defined
by the SQLEvent class.
• flash.events.SQLErrorEvent Defines the event that is dispatched when any of the SQLConnection or
SQLStatement operations results in an error.
• flash.events.SQLUpdateEvent Defines the event that is dispatched by a SQLConnection instance when
table data in one of its connected databases changes as a result of an INSERT, UPDATE, or DELETE SQL statement being
executed.
Finally, the following classes in the flash.errors package provide information about database operation errors:
• flash.errors.SQLError Provides information about a database operation error, including the operation that
was being attempted and the cause of the failure.
• flash.errors.SQLErrorCode Defines a set of constants representing the possible values for the SQLError
class’s code property, which indicates the type of error that led to a failed operation.
• flash.errors.SQLErrorOperation Defines a set of constants representing the possible values for the SQLError
class’s operation property, which indicates the database operation that resulted in an error.
Connecting to a database
Before you can perform any database operations, you need to first open a connection to the database file. A
SQLConnection instance is used to represent a connection to one or more databases. The first database that is
connected using a SQLConnection instance, known as the “main” database, is connected using the open() method.
Opening a database is an asynchronous operation, meaning you must register for the SQLConnection instance’s
open event in order to know when the open() operation completes, and the SQLConnection instance’s error event
to determine if the operation fails. The following example shows how to open an existing database file named
“DBSample.db,” located in the user’s application storage directory.
import flash.data.SQLConnection;
import flash.events.SQLErrorEvent;
ADOBE PRODUCT X.0 139
User Guide
import flash.events.SQLEvent;
import flash.filesystem.File;
conn.open(dbFile, false);
function openHandler(event:SQLEvent):void
{
trace("the database was opened successfully");
}
function errorHandler(event:SQLErrorEvent):void
{
trace("Error code:", event.error.code);
trace("Details:", event.error.message);
}
Notice that in the open() method call, the second argument is false. Specifying false for the second parameter
(autoCreate) causes the runtime to dispatch an error if the specified file doesn’t exist. If you pass true for the
autoCreate parameter (or leave it off and only specify a file location as the first parameter), the runtime will attempt
to create a new database file if the specified file doesn’t exist.
Alternatively, you can specify listener functions by creating a Responder object that refers to the listener functions
and passing it to the execute() method call.
// using a Responder
var selectResponder = new Responder(onResult, onError);
5. If the statement text includes parameter definitions, assign values for those parameters.
To do this, use the SQLStatement instance’s parameters associative array property.
selectData.parameters["param1"] = 25;
// using a Responder
selectData.execute(-1, selectResponder);
For specific examples that demonstrate these steps, see the following sections:
• Retrieving data from a database
• Inserting data
• Changing or deleting data
In cases like the one described here, where you have a SQL statement that’s used multiple times except that it uses
different values in the statement, the best approach is to use a SQL statement that includes parameters rather than
literal values in the SQL text. A parameter is a placeholder in the statement text that is replaced with an actual value
each time the statement is executed. To use parameters in a SQL statement, you create the SQLStatement instance
and assign the SQL statement that uses parameter placeholders rather than literal values to its text property. You
then define the value for each parameter by setting the value of an element in the SQLStatement instance’s
parameters property. The parameters property is an associative array, so you set a particular value using the
following syntax:
statement.parameters[parameter_identifier] = value;
The parameter_identifier is a string if you’re using a named parameter, or an integer index if you’re using an
unnamed parameter.
addItemStmt.execute();
addItemStmt.execute();
ADOBE PRODUCT X.0 142
User Guide
Using statement parameters instead of concatenating user-entered values into a statement's text prevents a SQL
injection attack, because the parameter values are treated explicitly as substituted values, rather than becoming part
of the literal statement text. The following is the recommended alternative to the previous listing:
// 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;
selectStmt.execute();
When the statement finishes executing, the SQLStatement instance dispatches a result event (SQLEvent.RESULT)
indicating that the statement was run successfully. Alternatively, if a Responder object is passed as an argument in
the execute() call, the Responder object’s result handler function is called. Each row of data in the result becomes
an Object instance whose properties’ names match the result set’s column names and whose properties contain the
values from the result set’s columns. For example, if a SELECT statement specifies a result set with three columns
named “itemId,” “itemName,” and “price,” for each row in the result set an Object instance is created with properties
named itemId, itemName, and price, containing the values from their respective columns.
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.
}
As the preceding code listing shows, the result objects are contained in an array that is available as the data property
of a SQLResult instance. If you’re using an event listener, to retrieve that SQLResult instance you call the
SQLStatement instance’s getResult() method. If you specify a Responder argument in the execute() call, the
SQLResult instance is passed to the result handler function as an argument. In either case, once you have the
SQLResult object you can access the result rows using the data array property.
The following code listing defines a SQLStatement instance whose text is a SELECT statement. The statement
retrieves rows containing the firstName and lastName column values of all the rows of a table named employees.
When the execution completes, the selectResult() method is called, and the resulting rows of data are retrieved
using SQLStatement.getResult() and displayed using the trace() method. Note that this listing assumes there
is a SQLConnection instance named conn that has already been instantiated and is already connected to the
database. It also assumes that the “employees” table has already been created and populated with data.
import flash.data.SQLConnection;
import flash.data.SQLResult;
import flash.data.SQLStatement;
import flash.events.SQLErrorEvent;
import flash.events.SQLEvent;
function selectResult(event:SQLEvent):void
{
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 code:", event.error.code);
trace("Details:", event.error.message);
}
You can improve the perceived performance of your application by instructing the runtime to return a specific
number of result rows at a time. Doing so will cause the initial result data to return more quickly. It also allows you
to divide the result rows into sets, so that the user interface is updated after each set of rows is processed. When you
call a SQLStatement instance’s execute() method, specify a value for the prefetch parameter (the execute()
method’s first parameter) to indicate the number of result rows to retrieve when the statement executes:
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) will be returned
The statement dispatches the result event, indicating that the first set of result rows are available. The resulting
SQLResult instance’s data property contains the rows of data, and its complete property indicates whether there are
additional result rows to retrieve. To retrieve subsequent result rows, call the SQLStatement instance’s next()
method. Like the execute() method, the next() method’s first parameter is used to indicate how many rows to
retrieve the next time the result event is dispatched.
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);
}
}
}
The SQLStatement dispatches a result event each time the next() method returns a subsequent set of result rows,
so the same listener function can be used to continue processing results until all the rows are retrieved.
For more information, see the language reference descriptions for the SQLStatement.execute() method (the
prefetch parameter description) and the SQLStatement.next() method.
Inserting data
To add data to a table in a database, you create and execute a SQLStatement instance using a SQL INSERT statement.
The following example uses a SQLStatement instance to add a row of data to the already-existing employees table.
Note that this listing assumes that there is a SQLConnection instance named conn that has already been instantiated
and is already connected to a database. It also assumes that the “employees” table has already been created.
import flash.data.SQLConnection;
import flash.data.SQLResult;
import flash.data.SQLStatement;
import flash.events.SQLErrorEvent;
import flash.events.SQLEvent;
insertStmt.sqlConnection = conn;
function insertResult(event:SQLEvent):void
{
trace("INSERT statement succeeded");
}
function insertError(event:SQLErrorEvent):void
{
trace("Error code:", event.error.code);
trace("Details:", event.error.message);
}
Note that the row identifier may or may not be the value of the column that is designated as the primary key column
in the table structure, according to the following rule:
• If the table is defined with a primary key column whose affinity (column data type) is INTEGER, the
lastInsertRowID property contains the value that was inserted into that row (or the value generated by the
runtime if it’s an AUTOINCREMENT column).
ADOBE PRODUCT X.0 147
User Guide
• If the table is defined with multiple primary key columns (a composite key) or with a single primary key column
whose affinity is not INTEGER , behind the scenes the database generates a row identifier value for the row, and that
generated value is the value of the lastInsertRowID property.
• The value is always the row identifier of the most-recently inserted row. If an INSERT statement causes a trigger
to fire, which in turn inserts a row, the lastInsertRowID property will contain the row identifier of the last row
inserted by the trigger, rather than the row created by the INSERT statement.
Consequently, if you want to have an explicitly defined primary key column whose value available after an INSERT
command through the SQLResult.lastInsertRowID property, the column must be defined as an INTEGER
PRIMARY KEY column. Note, however, that even if your table does not include an explicit INTEGER PRIMARY KEY
column, it is equally acceptable to use the database-generated row identifier as a primary key for your table in the
sense of defining relationships with related tables. The row identifier column value is available in any SQL statement
by using one of the special column names ROWID, _ROWID_, or OID. You can create a foreign key column in a related
table, and use the row identifier value as the foreign key column value, just as you would with an explicitly-declared
INTEGER PRIMARY KEY column. In that sense, if you are using an arbitrary primary key rather than a natural key,
and as long as you don’t mind the runtime generating the primary key value for you, it makes little difference
whether you use an INTEGER PRIMARY KEY column or the system-generated row identifier as a table’s primary key
for defining a foreign key relationship with between two tables.
For more information about primary keys and generated row identifiers, see the sections titled “CREATE TABLE”
and “Expressions” in the appendix “SQL support in local databases” in the Adobe AIR language reference.
Connection errors
Most database errors are connection errors, and they can occur during any operation. Although there are strategies
for preventing connection errors, there is rarely a simple way to gracefully recover from a connection error if the
database is a critical part of your application.
Most connection errors have to do with how the runtime interacts with the operating system, the file system, and
the database file. For example, a connection error will occur if the user doesn’t have permission to create a database
file in a particular location on the file system. The following strategies will help you to prevent connection errors:
ADOBE PRODUCT X.0 148
User Guide
Use user-specific database files Rather than using a single database file for all users who use the application on a
single computer, give each user their own database file, stored in a location that’s associated with the user’s account
such as the application’s storage directory, the user’s documents folder, the user’s desktop, and so forth.
Consider different user types Test your application with different types of user accounts, on different operating
systems. Don’t assume that the user will have administrator permission on the computer, or that the individual who
installed the application is the user who’s running the application.
Consider various file locations If you allow users to specify the location where a database file is saved or the location
of a database file to open, consider the possible file locations that users might specify. In addition, consider defining
limits on where users can store (or from where they can open) database files. For example, you might only allow
users to open files that are within their user account’s storage location.
If a connection error occurs, it most likely happens on the first attempt to create or open the database. This means
that the user will be unable to do any database-related operations in the application. For certain types of errors, such
as read-only or permission errors, one possible recovery technique is to implement application logic that copies the
database file to (or creates a new database file in) a different location where the user does have permission to create
and write to files.
Syntax errors
A syntax error occurs when a SQL statement is incorrectly formed, and the application attempts to prepare or
execute the statement. Because local database SQL statements are created as strings, compile-time SQL syntax
checking is not possible, and all SQL statements must be executed (or prepared) to check their syntax. Use the
following strategies to prevent SQL syntax errors:
Test all SQL statements thoroughly If possible, while developing your application test your SQL statements
separately before encoding them as statement text in the application code. In addition, use a code-testing approach
such as unit testing to create a set of tests that exercise every possible option and variation in the code.
Use statement parameters and avoid concatenating (dynamically generating) SQL Using parameters, and avoiding
dynamically-built SQL statements, means that the same SQL statement text is used each time a statement is
executed. Consequently, it’s much easier to test your statements and limit the possible variation. If you must dynam-
ically generate a SQL statement, keep the dynamic parts of the statement to a minimum, and carefully validate any
user input to make sure it won’t cause syntax errors.
Use prepared SQL statements In many ways this is simply a combination of the two previous strategies. Prepared
statements can’t be dynamically generated. Syntax checking happens when a statement is prepared, so if you use
prepared SQL statements in your application, and explicitly prepare all statements, each statement is tested. For
more on using prepared statements, see “Use prepared statements” on page 157.
To recover from a syntax error, an application would need complex logic to be able to examine a SQL statement and
correct its syntax. By following the previous guidelines for preventing syntax errors, you should also be able to
identify any potential run-time sources of SQL syntax errors (such as user input used in a statement). To recover
from a syntax error, you could provide the user with a specific error message guiding him or her to what needs to
be corrected to make the statement execute correctly.
Constraint errors
Constraint errors occur when an INSERT or UPDATE statement attempts to add data to a column that violates one of
the defined constraints for the table or column. The following constraints can be defined:
Unique constraint Indicates that across all the rows in a table, there cannot be duplicate values in one column (or,
when multiple columns are combined in a unique constraint, the combination of values in those columns must not
be duplicated). In other words, in terms of the specified unique column(s), each row must be distinct.
ADOBE PRODUCT X.0 149
User Guide
Primary key constraint In terms of the data that a constraint allows and doesn’t allow, a primary key constraint is
identical to a unique constraint.
Not null constraint Specifies that a single column cannot store a NULL value and consequently that in every row, that
column must have a value.
Check constraint Allows you to specify an arbitrary constraint on one or more tables. Common examples of check
constraints are a rule that define that a column’s value must be within certain bounds (for example, that a numeric
column’s value must be larger than 0), or one that specifies relationships between column values (for example, that
a column’s value must be different than the value of another column in the same row).
The runtime does not enforce constraints on foreign key values (foreign key values aren’t required to match an
existing primary key value). The runtime also does not enforce the data type of columns’ values (although under
some conditions the runtime converts an inserted values to another data type that matches its column’s specified
type). See the section “Data type support” in the appendix “SQL support in local databases” in the Adobe AIR
language reference for more information.
In addition to the predefined constraint types, the runtime SQL engine supports the use of triggers. A trigger is a
predefined set of instructions that are carried out when a certain action happens, such as when data is inserted into
or deleted from a particular table. One possible use of a trigger is to examine data changes and cause an error to
occur if specified conditions aren’t met. Consequently, a trigger can serve the same purpose as a constraint, and the
strategies for preventing and recovering from constraint errors also apply to trigger-generated errors. However, the
error code for trigger-generated errors (the constant SQLErrorCode.ABORT) is different from the error code for
constraint errors (the constant SQLErrorCode.CONSTRAINT).
Because constraints are specified when a table is created, triggers must be explicitly created, and Adobe AIR doesn’t
specify any additional constraints on tables or columns, the set of constraints that apply to a particular table can be
identified ahead of time and can be taken into account both in preventing and in recovering from constraint errors.
Because constraint errors are dependent on data that is to be added to a database, and often on the relationship
between the new data and other data that already exists in the database, constraint errors are difficult to systemati-
cally predict and prevent. The following strategies can help you avoid many constraint errors:
Carefully plan database structure and constraints The purpose of constraints is to enforce application rules and
help protect the integrity of the database’s data. When you’re planning your application, consider how to structure
your database to support your application. As part of that process, you will want to identify rules about your data,
such as whether certain values are required, whether a value has a default, whether duplicate values are allowed, and
so forth. Those rules will guide you in defining database constraints.
Explicitly specify column names An INSERT statement can be written without explicitly specifying the columns into
which values are to be inserted, but doing so is an unnecessary risk. By explicitly naming the columns into which
values are to be inserted, you can allow for automatically generated values, columns with default values, and
columns that allow NULL values. In addition, by doing so you can ensure that all NOT NULL columns have an explicit
value inserted.
Use default values Whenever you specify a NOT NULL constraint for a column, if at all possible you should also
specify a default value in the column definition. Application code can also provide default values, for example
checking if a String variable is null and assigning it a value before using it to set a statement parameter value.
Validate user-entered data Check user-entered data ahead of time to make sure that it obeys limits specified by
constraints, especially in the case of NOT NULL and CHECK constraints. Naturally, a UNIQUE constraint is more
difficult to check for because doing so would require executing a SELECT query to determine whether the data is
unique.
ADOBE PRODUCT X.0 150
User Guide
Use triggers You can write a trigger that validates (and possibly replaces) inserted data or takes other actions to
correct invalid data. This can prevent a constraint error from occurring.
Fortunately, while constraint errors are perhaps more difficult to prevent than other types of errors, there are several
strategies to recover from constraint errors in ways that don’t make the application unstable or unusable:
Use conflict algorithms When you define a constraint on a column, and when you create an INSERT or UPDATE
statement, you have the option of specifying a conflict algorithm, defining what action the database should take
when a constraint violation occurs. The possible actions can range from ending a single statement or a whole trans-
action, to ignoring the error or even replacing old data with the new data in order to conform to a constraint. For
more information see the section “ON CONFLICT (conflict algorithms)” in the appendix “SQL support in local
databases” in the Adobe AIR language reference.
Provide corrective feedback Since the set of constraints that can affect a particular SQL command can be identified
ahead of time, you can anticipate constraint errors that a statement could cause. With that knowledge, you can build
application logic to respond to a constraint error, such as by showing the user a helpful error message that allows
him or her to correct the error and attempt the operation again. For example, if an application includes a data entry
form for entering new products, and the product name column in the database is defined with a UNIQUE constraint,
the action of inserting a new product row in the database could cause a constraint error. Consequently, if a
constraint error occurs, the application could prompt the user to indicate that the specified product name is already
in use, and encourage the user to choose a different name (or perhaps allow the user to view information about the
other product with the same name).
The following code listing shows the process of creating a new database file (a new database). In this case, the
database file is saved in the application’s storage directory, with the file name “DBSample.db”:
import flash.data.SQLConnection;
import flash.events.SQLErrorEvent;
import flash.events.SQLEvent;
import flash.filesystem.File;
conn.open(dbFile);
function openHandler(event:SQLEvent):void
{
trace("the database was created successfully");
}
function errorHandler(event:SQLErrorEvent):void
{
trace("Error code:", event.error.code);
trace("Details:", event.error.message);
}
A database’s file name can be any valid file name, with any file extension. If you call the open() method with null
for the file parameter, a new in-memory database is created rather than a database file on disk.
The following example demonstrates creating a new table named “employees” in an existing database file. Note that
this code assumes there is a SQLConnection instance named conn that is already instantiated and is already
connected to a database.
import flash.data.SQLConnection;
import flash.data.SQLStatement;
import flash.events.SQLErrorEvent;
import flash.events.SQLEvent;
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 code:", event.error.code);
trace("Details:", event.error.message);
}
In addition to asynchronous database operations, the runtime also allows you to execute database operations
synchronously. The decision to execute operations asynchronously or synchronously isn’t made on an operation-
by-operation basis; instead it’s specified by passing a value for the SQLConnection constructor’s isSync parameter
when you create a SQLConnection instance. (The default value, which is used when no argument is passed, is false,
meaning the connection doesn’t use synchronous execution.) Once a SQLConnection instance is created, its
execution mode (synchronous or asynchronous) is fixed; all database operations that are performed on any database
that’s opened using that SQLConnection instance will execute using the specified mode. This is true regardless of
whether the operation is performed by calling a SQLConnection method (such as opening a connection using
SQLConnection.open() or beginning a transaction using SQLConnection.begin()), or if the operation is a SQL
statement such as a SELECT query that’s executed using a SQLStatement instance whose sqlConnection property
is set to the SQLConnection instance.
By creating it that way, all operations will be performed synchronously for that SQLConnection object. You can
execute a series of database operations in succession within a single code block, as in the following example:
var conn:SQLConnection = new SQLConnection(true);
var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db");
// start a transaction
conn.begin();
insertCustomer.execute();
var customerId:Number = insertCustomer.getResult().lastInsertRowID;
insertPhoneNumber.execute();
As you can see, you call the same methods to perform database operations whether you’re using synchronous or
asynchronous execution. The key differences between the two approaches have to do with executing operations that
depend on other operations (such as SELECT result rows or the primary key of the row added by an INSERT
statement) and handling errors that can occur with any database operation.
// start a transaction
conn.begin();
insertCustomer.execute();
var customerId:Number = insertCustomer.getResult().lastInsertRowID;
insertPhoneNumber.execute();
// 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;
insertPhoneNumber.execute();
A side effect of the database automatically executing subsequent queued statements is that if one statement or
operation depends on the outcome of another operation, when you’re using asynchronous execution mode you won’t
be able to make changes to the second statement once its execute() method is called, so you must wait for the event
indicating the first operation completes before starting the next operation. For instance, if you want to execute a
statement in the context of a transaction, the statement execution depends on the operation of opening the trans-
action. In that case, after calling the SQLConnection.begin() method to open the transaction, you would need to
wait for the SQLConnection instance to dispatch its begin event before calling the SQLStatement instance’s
execute() method. The simplest way to organize your application to ensure that the operations are executed
properly is to create a method that’s registered as a listener for the begin event, and call the
SQLStatement.execute() method within that listener.
In addition to the techniques described in this section, the way a SQL statement is written can also impact database
performance. Frequently, there are multiple ways to write a SQL SELECT statement to retrieve a particular result set,
and in some cases the different approaches will require more or less effort from the database engine. This aspect of
improving database performance—designing SQL statements for better performance—is not covered in the Adobe
AIR documentation.
A key aspect of using a prepared SQLStatement instance is that your application needs to keep a reference to the
SQLStatement instance once it has been prepared, meaning it shouldn’t be declared as a function-scope variable. In
practice, the best way to do this is to structure your application so that a SQL statement (or a group of statements
that are executed in combination) is wrapped in a single class. The SQLStatement instance or instances can be
member variables of the class, meaning they will persist as long as the instance of the wrapper class exists in the
application.
In the most simple case, you can simply define a variable containing the SQLStatement instance outside of a
function, (for example, as a member variable in an ActionScript class, or as a non-function variable in a JavaScript
file) so that the instance persists in memory. You can then call the prepare() method of that instance when you
want to prepare the statement, and later set parameter values and call its execute() method when you want to
actually run the query.
ADOBE PRODUCT X.0 158
User Guide
As an alternative to creating the database, structure, and data programmatically, you can distribute a pre-populated
database with your application by including the database file in the application’s AIR package. This has the benefit
of removing the need for a complex set of program instructions (the code that creates the database and its tables)
that are only used once in the lifetime of the application, but still add to the size and complexity of the application.
One important issue to keep in mind if you’re using the approach of including a pre-created database in your AIR
file has to do with the initial location where the database file is placed when the application is installed. Like all files
that are included in an AIR package, a bundled database file will be installed in the application’s resource directory.
However, because the user who is running the application may not necessarily be the user who installed the appli-
cation, that user may not have the necessary permission from the operating system to write to the file in its default
location. Instead, it is recommended that you use the file that is included in the AIR package as a “template”
database, from which individual users’ databases can be created. The first time a user runs the application, the
original database file can be copied into the user’s application storage directory (or another location), and that
database can be the one that’s actually used by the application, thereby avoiding the issue.
Use prepared SQL statements For any SQL statement that will be executed more than once in an application, create
the SQLStatement instance and call it’s prepare() method ahead of time to reduce processing time later. For
example, your application might load its initial screen or initial set of data to get the user started, then instantiate
the SQLStatement instances and call their prepare() methods. See “Use prepared statements” on page 157 for more
information.
Use statement parameters Use SQLStatement parameters—never concatenate user input into statement text.
Doing so makes your application more secure (it prevents the possibility of SQL injection attacks), makes it possible
to use objects in queries (rather than only SQL literal values), and makes statements run more efficiently (because
they can be reused without needing to be recompiled each time they’re executed).
Use constants for column and parameter names When you don’t specify an itemClass for a SQLStatement, to
avoid spelling errors, define constants for column names and use the constants in the statement text and for the
property names when retrieving values from result objects.
See also
• “Improving database performance” on page 156
161
Note: In the Flex framework, only classes that extend the UIComponent class can be added as children of a Flex
Container components. For this reason, you cannot directly add an HTMLControl as a child of a Flex Container
component; however you can use the Flex HTML control, you can build a custom class that extends UIComponent and
contains an HTMLControl as a child of the UIComponent, or you can add the HTMLControl as a child of a UICom-
ponent and add the UIComponent to the Flex container.
You can also render HTML text by using the TextField class, but its capabilities are limited. The Flash Player’s
TextField class supports a subset of HTML markup, but because size limitations, its capabilities are limited. (The
HTMLControl class included in Adobe AIR is not available in Flash Player.)
See also
• “Using the Flex AIR components” on page 40
• data
• requestHeaders
• method
• url
The corresponding static properties of the URLRequestDefaults class are also used (if the property is not set in the
URLRequest object).
The HTMLControl class includes the following properties for that pertain to all data loads in the HTMLControl
object:
• manageCookies
• userAgent
• userCache
These properties override any settings in the URLRequest or URLRequestDefaults class.
The username and password set with the setLoginCredentials() of the URLRequest object (and with the static
setLoginCredentialsForHost() method of the URLRequestDefaults class) are also used.
Certain headers defined in the requestHeader property, such as the Accept header, are not used.
In defining the url property of a URLRequest object, use any of the following URL schemes:
file A path relative to the root of the file system. For example:
file:///c:/AIR Test/test.txt
ADOBE PRODUCT X.0 164
User Guide
app-resource A path relative to the root directory of the installed application (the directory that contains the appli-
cation.xml file for the installed application). For example, the following path points to an images subdirectory of the
directory of the installed application:
app-resource:/images
You can access the location of the app-resource directory using the File.applicationResourceDirectory
property in ActionScript or the air.File.applicationResourceDirectory property in JavaScript.
app-storage A path relative to the application store directory. For each installed application, AIR defines a unique
application store directory, which is a useful place to store data specific to that application. For example, the following
path points to a prefs.xml file in a settings subdirectory of the application store directory:
app-storage:/settings/prefs.xml
You can access the location of the app-storage directory using the File.applicationStorageDirectory in
ActionScript or the air.File.applicationStorageDirectory property in JavaScript.
http A standard HTTP request:
http://www.adobe.com
https://secure.example.com
In HTML content running in AIR, you can also use any of these URL schemes in defining src attributes for img,
frame, iframe, and script tags, in the href attribute of a link tag, and anywhere you can provide a URL.
For content loaded from sandboxes other than the application security sandbox, as in SWF content running in Flash
Player (not in AIR), only the http: and https: URL schemes are supported.
You can use a URLRequest object that uses any of these URL schemes to define the URL request for a number of
different objects, such as an HTMLControl object, a File object, a Loader object, a URLStream object, or a Sound
object.
If a value is set for neither the userAgent property of the HTMLControl object nor for URLRequestDe-
faults.userAgent, a default value is used as the user agent string. This default value varies depending on the
runtime operating system (such as Mac OS or Windows), the runtime language, and the runtime version, as in the
following two examples:
• "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko)
Apollo/1.0"
• "Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, like Gecko) Apollo/1.0"
Consider using the XML class to represent large amounts of HTML data, and then using the toXMLString()
method of the XML object to convert the data to a string:
var xHTML:XML =
<html>
<head>
<style>
tr { font-family: Verdana }
</style>
<script>
function init() {
alert("Document loaded.");
}
</script>
</head onLoad="init()">
<body>
<table>
<tr>
<th>HTMLControl feature</th>
<th>Description</th>
<tr>
td>Full HTML tag support</td>
<td>Including tables, etc.</td>
</tr>
<tr>
<td>CSS support</td>
<td>As shown here</td>
</tr>
<tr>
<td>JavaScript support</td>
<td>Including cross-script communication to ActionScript.</td>
</tr>
</table>
</body>
</html>;
html.height = 200;
addChild(html);
html.loadString(htmlStr);
Content loaded via the loadString() method is put in the application security sandbox, giving it full access to
AIR APIs.
An HTMLControl object's width and height properties are both set to 0 by default. You will want to set these before
adding an HTMLControl object to the stage.
scrollH The horizontal scroll position of the HTML content within the HTMLControl object.
scrollV The vertical scroll position of the HTML content within the HTMLControl object.
You may want to check the htmlHeight and htmlWidth properties when the HTMLControl object dispatches an
htmlBoundsChanged event. For example, the following code set the scrollV property so that HTML content is
scrolled to the bottom of the content:
function scrollHTML(event:Event):void
{
html.scrollV = html.htmlHeight - SIZE;
}
You could use code like this to control or implement UI controls such as scroll bars. The HTMLControl does not
include horizontal and vertical scroll bars. You can implement these in ActionScript or by using a Flex component.
The Flex HTML component automatically includes scroll bars for HTML content. You can also use the
HTMLControl.createRootWindow() method to create a window that contains an HTMLControl object with scroll
bars (see “Creating windows with scrolling HTML content” on page 180).
htmlBoundsChanged Dispatched when one or both of the htmlWidth and htmlHeight properties have changed.
locationChange Dispatched when the location property of the HTMLControl has changed.
scroll Dispatched anytime the HTML engine changes the scroll position. This can be due to navigation to anchor
links (# links) in the page or to JavaScript calls to the window.scrollTo() method. Typing in a text input or text
area can also cause a scroll.
uncaughtJavaScriptException Dispatched when a JavaScript exception occurs in the HTMLControl and the
exception is not caught in JavaScript code.
You can also register an ActionScript function for a JavaScript event (such as onClick). For details, see “Registering
ActionScript functions to respond to JavaScript events ” on page 171.
historyPosition The current position in the history list. History items before this position represent “back”
navigation, and items after this position represent “forward” navigation.
historyAt() Returns the URLRequest object corresponding to the history entry at the specified position in the
history list.
historyBack() Navigates back in the history list, if possible.
historyGo() Navigates the indicated number of steps in the browser history. Navigates forward if positive,
backward if negative. Navigation by zero forces a reload. Attempts to set position beyond the end will set it to the
end.
Items in the history list are stored as objects of type HistoryListItem. The HistoryListItem class has the following
properties:
isPost Set to true if the HTML page includes POST data
originalUrl The original URL of the HTML page, prior to any redirects
This simple HTML page has a JavaScript variable named "foo" and a JavaScript function named "test()". Both of these
are properties of the window object of the page (the page's DOM). Also, the window.document object includes a
named P element (with the ID "p1"), which you can access using the getElementById() method. Once the page is
loaded (when the HTMLControl object dispatches the complete event), you can access each of these from Action-
Script, as shown in the following ActionScript code:
var html:HTMLControl = new HTMLControl();
html.width = 300;
html.height = 300;
html.addEventListener(Event.COMPLETE, completeHandler);
var xhtml:XML =
<html>
<script>
foo = 333;
function test() {
return "OK.";
}
</script>
<body>
<p id="p1">Hi.</p>
</body>
</html>;
html.loadString(xhtml.toString());
function completeHandler(e:Event):void {
trace(html.window.foo); // 333
trace(html.window.document.getElementById("p1").innerHTML); // Hi.
trace(html.window.test()); // OK.
}
ADOBE PRODUCT X.0 170
User Guide
To access the content of an HTML element, use the innerHTML property. For example, the previous code uses
html.window.document.getElementById("p1").innerHTML to get the contents of the HTML element named
"p1".
You can also set properties of the HTML page from ActionScript. For example, the following sets the contents of the
p1 element on the page and it sets the value of the foo JavaScript variable on the page:
html.window.document.getElementById("p1").innerHTML = "eeee";
html.window.foo = 66;
When you load this content into an HTMLControl object, the date property (defined in the JavaScript script) and
the p element (of the document) are both of type JavaScriptObject (when accessed from ActionScript); however the
primes object is of type JavaScriptArray and the sayHi() function is of type JavaScriptFunction:
After an HTMLControl object loads this content, you can manipulate the CSS styles in the page via the cssRules
array of the window.document.styleSheets array, as shown here:
var html:HTMLControl = new HTMLControl( );
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";
}
This code adjusts the CSS styles so that the resulting HTML document appears like the following:
Keep in mind that code can add styles to the page after the HTMLControl object dispatches the complete event.
</html>
You can register an ActionScript function as a handler for any event in the page. For example, the following code
adds the clickHandler() function as the listener for the onclick event of the testLink element in the HTML
page:
var html:HTMLControl = new HTMLControl( );
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!");
}
You can also use the addEventListener() method to register for these events. For example, you could replace the
completeHandler() method in the previous example with the following code:
function completeHandler(event:Event):void {
var testLink:JavaScriptObject = html.window.document.getElementById("testLink");
testLink.addEventListener("click", clickHandler);
}
It is good practice to wait for the HTMLControl to dispatches the complete event before adding these event
listeners, as shown in the previous example. HTML pages often load multiple files and the HTML DOM is not fully
built until all the files are loaded and parsed, at which point the HTMLControl to dispatches the complete event.
When a JavaScript operation encounters an illegal operation that is not caught in the JavaScript code with a
try/catch structure, the HTMLControl object dispatches an HTMLUncaughtJavaScriptExceptionEvent event. You
can register an ActionScript method to listen for this event, as in the following code:
var html:HTMLControl = new HTMLControl();
var urlReq:URLRequest = new URLRequest("test.html");
html.load(urlReq);
ADOBE PRODUCT X.0 173
User Guide
html.width = container.width;
html.height = container.height;
container.addChild(html);
html.addEventListener(HTMLUncaughtJavaScriptExceptionEvent.UNCAUGHT_JAVASCRIPT_EXCEPTION,
htmlErrorHandler);
function htmlErrorHandler(event:HTMLUncaughtJavaScriptExceptionEvent):void
{
event.preventDefault();
trace("exceptionValue:", event.exceptionValue)
for (var i:uint = 0; i < event.stackTrace.length; i++)
{
trace("___________________");
trace("sourceURL:", event.stackTrace[i].sourceURL);
trace("line:", event.stackTrace[i].line);
trace("function:", event.stackTrace[i].functionName);
}
}
In this example, the htmlErrorHandler() event handler cancels the default behavior of the event (which is to send
the JavaScript error message to the trace output), and generates its own output message. It outputs the value of the
exceptionValue of the HTMLUncaughtJavaScriptExceptionEvent object. It outputs the properties of each object
in the stackTrace array:
exceptionValue: ReferenceError: Can't find variable: melbaToast
___________________
sourceURL: app-resource:/test.html
line: 5
function: throwError
___________________
sourceURL: app-resource:/test.html
line: 10
function: onclick
function loaded(e:Event):void
{
html.window.foo = foo;
html.window.helloFromJS = helloFromJS;
ADOBE PRODUCT X.0 174
User Guide
<html>
<script>
function alertFoo() {
alert(foo);
}
</script>
<body>
<button onClick="alertFoo()">
What is foo?
</button>
<p><button onClick="helloFromJS('Hi.')">
Call helloFromJS() function.
</button></p>
</body>
</html>
To make ActionScript classes defined in a SWF file available in JavaScript, you need to make sure that the loaded
HTML content is in the same application domain as the display object container, by setting the useApplication-
Domain property of the HTMLControl object to ApplicationDomain.currentDomain (the application domain of
the SWF content), as shown in the following code:
html.useApplicationDomain = ApplicationDomain.currentDomain;
Because the package structure of the runtime classes would require you to type long strings of JavaScript code strings
to access each class (as in window.runtime.filesystem.File), the AIR SDK for HTML includes an AIRAliases.js
file that lets you access runtime classes much more easily (for instance, by simply typing air.File), which is
described in the following section.
To use the AIRAliases.js file, include the following script reference in your HTML page:
<script src="AIRAliases.js" />
The AIR SDK and the Flex SDK include thatAIRAliases.js file in a frameworks subdirectory. Copy the file to your
project source directory, and adjust the path in the src reference in the script tag, as needed.
Important: Except where noted, the JavaScript example code in this documentation assumes that you have included
the AIRAliases.js file in your HTML page.
• window.status
• window.document.title
• window.location
Similarly, calling the following methods in JavaScript has no effect, by default:
• window.blur()
• window.close()
• window.focus()
• window.moveBy()
• window.moveTo()
• window.open()
• window.resizeBy()
• window.resizeTo()
The HTMLHost class lets you determine how to handle JavaScript that modifies these properties or calls these
methods.The methods in the HTMLHost class correspond to each of these window settings.
3 In the code that contains the HTMLControl (not the code of the new subclass of HTMLHost) instantiate an
object of the type defined by the new class, and assign that object to the htmlHost property of the HTMLControl.
The following Flex code uses the CustomHost class defined in the previous step:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
applicationComplete="init()">
<mx:Script>
<![CDATA[
import flash.html.HTMLControl;
import CustomHost;
private function init():void
{
var html:HTMLControl = new HTMLControl();
html.width = container.width;
html.height = container.height;
var urlReq:URLRequest = new URLRequest("Test.html");
html.htmlHost = new CustomHost();
html.load(urlReq);
container.addChild(html);
}
]]>
</mx:Script>
<mx:UIComponent id="container" width="100%" height="100%"/>
</mx:WindowedApplication>
To test the code described here, in the application resource directory include an HTML file with the following
content:
<html>
<head>
<title>Test</title>
</head>
<script>
function openWindow()
{
window.runtime.trace("in");
document.title = "foo"
window.open('Test.html');
window.runtime.trace("out");
}
</script>
<body>
<a href="#" onclick="openWindow()">window.open('Test.html')</a>
</body>
</html>
The object passed as a parameter to the createWindow() method is an HTMLWindowCreateOptions object. The
HTMLWindowCreateOptions class includes properties that define values that are set in the features parameter
string in the call to window.open():
fullscreen fullscreen
height height
locationBarVisible location
menuBarVisible menubar
resizeable resizable
scrollBarsVisible scrollbars
statusBarVisible status
toolBarVisible toolbar
width width
x left or screenX
y top or screenY
ADOBE PRODUCT X.0 179
User Guide
JavaScript calls to window.close() do not automatically cause the containing window to close. You may, for
example, want a call to window.close() to remove the HTMLControl from the display list, leaving the window
(which may have other content) open, as in the following code:
override public function closeWindow():void
{
htmlControl.parent.removeChild(htmlControl);
}
bounds A Rectangle object defining the position and size of the new window.
For example, the following code uses the HTMLControl.createRootWindow() method to create a new window
with HTMLControl content that uses scrollbars:
bounds);
html.stage.nativeWindow.orderToFront();
return html
}
}
Then the following defines a subclass of the HTMLControl class that uses the MyHTMLHost class as its htmlHost
property:
package
{
import flash.html.HTMLControl;
import MyHTMLHost;
import MyHTMLControl;
public class MyHTML extends HTMLControl
{
public function MyHTML()
{
super();
htmlHost = new MyHTMLHost();
}
}
}
For details on the HTMLHost class and the HTMLControl.createRootWindow() method used in this example, see
“Defining browser-like user interfaces for HTML content” on page 175.
import flash.html.HTMLControl;
import flash.net.URLRequest;
if(HTMLControl.pdfCapability == HTMLPDFCapability.STATUS_OK) {
trace("PDF content can be displayed");
}
else {
ADOBE PRODUCT X.0 183
User Guide
Forms
PDF files that contain forms will only post correctly if form posting uses a supported link format and returns PDF
or HTML. Adobe discourages the use of forms that return FDF or rely heavily on JavaScript communication. Collab-
orative PDF forms will not function correctly in AIR 1.0.
184
Application invocation
An AIR application is invoked when the user (or the operating system):
• launches the application from the desktop shell
• uses the application as a command on a command-line shell
• opens a type of file for which the application is the default opening application
• (Mac OS X) clicks the application icon in the dock taskbar (whether or not the application is currently running)
• chooses to launch the application from the installer (either at the end of a new installation process, or after
double-clicking the AIR file for an already installed application).
• begins an update of an AIR application when the installed version has signaled that it should handle application
updates itself by including a <handleUpdates/> flag in the application descriptor
Whenever an AIR application is invoked, AIR dispatches an InvokeEvent object through the singleton Shell object.
To allow an application time to initialize itself and register an event listener, invoke events are queued instead of
discarded when there are no registered listeners for the event. As soon as a listener is registered, all the queued events
are delivered.
ADOBE PRODUCT X.0 186
User Guide
When you are using the Flex framework, the WindowedApplication component will listen for the invocation event
and redispatch them. If your Flex application listens for invoke events on the Shell object, it will not receive any such
events dispatched before it has registered its listener, including the initial event, since the events will have already
been delivered to the WindowedApplication’s listener. Flex applications should listen for invoke events on the
WindowedApplication object rather than the Shell object. You add a listener for the invoke event either by setting
the invoke attribute in the <WindowedApplication> element tag:
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
invoke="onInvoke(event)" title="Invocation Event Log">
When you add the listener using the addEventListener function, you must call the method in response to the
initialize event (or earlier) in order to get the first invoke event dispatched when an application is launched, which
will contain any command line arguments.
Only one instance of an AIR application will be started. When an already running application is invoked again, AIR
dispatches a new invocation event to the running instance. It is an AIR application’s responsibility to respond to an
invocation event and take the appropriate action (such as opening a new document window to display the file
contents).
An invocation event object contains any arguments passed to the application, as well as the directory from which the
application has been invoked. If the application was invoked because of a file-type association, then the full path to
the file is included in the command line arguments. Likewise, if the application was invoked because of an appli-
cation update, the full path to the update AIR file is provided. The invocation event object is defined by the AIR
InvokeEvent class.
Your application can handle invocation events by registering a listener with its Shell (or WindowedApplication)
object:
Shell.shell.addEventListener(InvokeEvent.INVOKE,onInvokeEvent);
See also
• “Setting application properties” on page 62
• “Presenting a custom application update user interface” on page 215
ADOBE PRODUCT X.0 187
User Guide
Arguments Array
tick tock {tick,tock}
tick "tick tock" {tick,tick tock}
"tick" “tock” {tick,tock}
\"tick\" \"tock\" {"tick","tock"}
The InvokeEvent.currentDirectory property contains a File object representing the directory from which the
application was launched.
When an application is invoked because a file of a type registered by the application is opened, the native path to the
file is included in the command-line arguments as a string. (It is your application’s responsibility to open or perform
the intended operation on the file.) Likewise, when an application handles updates itself, the native path to the AIR
file will be included when a user double-clicks an AIR file containing an application with a matching application ID.
You can access the file using the resolve() method of the currentDirectory File object:
if((invokeEvent.currentDirectory != null)&&(invokeEvent.arguments.length > 0)){
dir = invokeEvent.currentDirectory;
fileToOpen = dir.resolvePath(invokeEvent.arguments[0]);
}
if(invokeEvent.currentDirectory != null){
logEvent("Current directory=" + invokeEvent.currentDirectory.nativePath);
} else {
logEvent("--no directory information available--");
}
logEvent("--no arguments--");
}
}
More than one <fileType> element can be placed within the <fileTypes> element to register more than one
extension.
For details, see “Registering file types” on page 66.
The Shell object also has an id property, that is the application ID for the file, as illustrated in the following code:
trace(Shell.shell.id);
For more information, see “The application descriptor file structure” on page 62.
ADOBE PRODUCT X.0 189
User Guide
All resources that are not installed with the AIR application are put in the same security sandboxes as they would be
placed in if they were running in Flash Player in a web browser. Remote resources are put in sandboxes according to
their source domains, and local resources are put in the local-with-networking, local-with-filesystem, or local-
trusted sandbox.
Although content outside of the AIR application security sandbox may access AIR runtime APIs, but some function-
ality (such as attempting to read files from the filesystem) will result in a runtime security exception.
You can check if the Capabilities.playerType static property is set to Security.APPLICATION to see if content
is in the runtime (and not running in Flash Player running in a browser).
For more information, see “AIR Security” on page 52.
Shell.shell.idleThreshold = 120;
Shell.shell.addEventListener(Event.USER_IDLE,function(event:Event){
trace(“Idle”);
});
Shell.shell.addEventListener(Event.USER_PRESENT,function(event:Event){
trace(“Present”);
});
Note: Only a single idle event will be dispatched between present events.
Taskbar icons
Many operating systems provide a taskbar, such as the Mac OS X dock, that can contain an icon to represent an appli-
cation. AIR provides an interface for interacting with the application task bar icon through the Shell.shell.icon
property.
AIR creates the Shell.shell.icon object automatically (whether or not the icon is visible). The object type will
always be a subclass of InteractiveIcon, either DockIcon or SystemTrayIcon, depending on the operating system. You
can determine which subclass AIR supports on the current operating system using the Shell.supportsDockIcon
and Shell.supportsSystemTrayIcon properties. The InteractiveIcon base class provides the properties width,
height, and bitmaps, which you can use to change the image used for the icon, but accessing properties specific to
DockIcon or SystemTrayIcon on the wrong operating system will generate runtime exceptions.
To set or change the image used for an icon, create an array containing one or more images and assign it to the
Shell.shell.icon.bitmaps property. The size of taskbar icons is very different on different operating systems.
You can provide multiple sizes of images in the bitmaps array to avoid scaling. If more than one image is supplied in
the array, AIR will select the size closest to the current display size of the taskbar icon, scaling it if necessary. The
following example sets the image for a taskbar icon:
Shell.shell.icon.bitmaps = [bmp16x16.bitmapData, bmp128x128.bitmapData];
You can animate the icon by resetting the bitmaps property with an array containing a different image in response
to the stage enterFrame event or a timer event. (Only one image in a bitmaps array is used.)
To remove the icon from the task bar on Windows, or restore the default icon appearance on Mac OS X, set bitmaps
to an empty array:
Shell.shell.icon.bitmaps = [];
Dock icons
AIR supports dock icons when Shell.supportsDockIcon is true. The Shell.shell.icon property represents the
application icon on the dock (not a window dock icon).
You can add commands to the standard dock menu by creating a new NativeMenu object containing the commands
and assigning it to the Shell.shell.icon.menu property. The items in the menu will be displayed above the
standard dock icon menu items.
ADOBE PRODUCT X.0 191
User Guide
You can bounce the dock icon by calling the Shell.shell.icon.bounce() method. If you set the bounce()
priority parameter to informational, then the icon will bounce once. If you set it to critical, then the icon will
bounce until the user activates the application. Constants for the priority parameter are defined in the Notifica-
tionType class.
Note: The icon will not bounce if the application is already active.
When the dock icon is clicked, the Shell object will dispatch an InvokeEvent. If the application is not running, the
system will launch it; otherwise, the invocation event will be delivered to the running version.
You can add a menu to the system tray icon by creating a new NativeMenu object and assigning it to the
Shell.shell.icon.menu property (no default menu is provided by the operating system) The system tray icon is
accessed by right-clicking the icon.
The system tray icon dispatches ScreenMouseEvents for click, mouseDown, mouseUp, rightClick, right-
MouseDown, and rightMouseUp events. You can use these events, along with a menu, to allow users to interact with
your application when it has no visible windows.
The following example creates an AIR application which has a system tray icon, but no visible windows. The system
tray icon has a menu with a single command for exiting the application.
package {
import flash.display.Loader;
import flash.display.NativeMenu;
import flash.display.NativeMenuItem;
import flash.display.NativeWindow;
import flash.display.Sprite;
import flash.display.SystemTrayIcon;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.Shell;
{
Shell.shell.autoExit = false;
var iconLoader:Loader = new Loader();
var iconMenu:NativeMenu = new NativeMenu();
var exitCommand:NativeMenuItem =
iconMenu.addItem(new NativeMenuItem("Exit"));
exitCommand.addEventListener(Event.SELECT,function(event:Event):void{
Shell.shell.icon.bitmaps = [];
Shell.shell.exit();
});
if(Shell.supportsSystemTrayIcon){
Shell.shell.autoExit = false;
iconLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,
iconLoadComplete);
iconLoader.load(new URLRequest("icons/AIRApp_16.png"));
if(Shell.supportsDockIcon){
iconLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,
iconLoadComplete);
iconLoader.load(new URLRequest("icons/AIRApp_128.png"));
var dock:DockIcon = Shell.shell.icon as DockIcon;
dock.menu = iconMenu;
}
//In this Beta release, you must keep a window open or the icon will be removed
//stage.nativeWindow.close();
stage.nativeWindow.visible = false;
}
When you set the dock icon image, the change will only apply while the application is running. When the user quits,
the icon image will revert to the icon specified in the application descriptor (or the operating system default icon if
no icon image has been provided).
This example assumes that there are image files named AIRApp_16.png and AIRApp_128.png in an icons subdi-
rectory of the application. (Sample icon files are included with the AIR SDK.)
When a window is in the background, you can notify the user that an event of interest related to the window has
occurred. On Mac OS X, you can notify the user by bouncing the application dock icon (as described in “Bouncing
the dock” on page 191). On Windows, you can highlight the window taskbar icon by calling the window’s
notifyUser() method. The type parameter passed to the method determines the urgency of the notification:
• NotificationType.CRITICAL: the window icon will flash until the user brings the window to the foreground.
• NotificationType.INFORMATIONAL: the window icon will highlight by changing color.
var type:String;
if(critical){
type = NotificationType.CRITICAL;
} else{
type = NotificationType.INFORMATIONAL;
}
stage.nativeWindow.notifyUser(type);
Calling the window notifyUser() method on an operating system that does not support window-level notification
will have no affect. Use the NativeWindow.supportsNotification property to determine if window notification
is supported.
On the Windows operating system, you can prevent the window from appearing on the taskbar by creating windows
of type utility or lightweight. Invisible windows also do not appear on the taskbar.
Because the initial window is necessarily of type, normal, in order to create an application without any windows that
appear in the taskbar, you must leave the initial window created at startup invisible. To do this, add
<visible>false</visible> to the <initalWindow> element of the application descriptor file (and don’t set
visible=true or call activate() on the window). In the NativeWindowInitOption object used to create any new
windows, set type to NativeWindowType.UTILITY or NativeWindowType.LIGHTWEIGHT.
On Windows, you can change the icon that is displayed on the window system chrome title bar and in the iconified
representation of the window in the task bar. To change the icon image, assign an array containing the BitmapData
objects for the new image to the window’s icon property. (You can use the Loader class to load image files.) Because
not all windows have an icon, you should check that the property is not null before attempting to assign a value to it.
if(nativeWindow.icon != null){
nativeWindow.icon.bitmaps = new Array(loadedImage.bitmapData);
}
Note: AIR does not support changing window icons on the dock under Mac OS X. (You can only change the dock icon
for a running application.)
Application termination
The quickest way to end it all is to call Shell.shell.exit() and this works fine when your application has no data
to save or resources to clean up. Calling exit() will automatically close all windows and then terminate the appli-
cation. However, to allow windows or other components of your application to interrupt the termination process,
perhaps to save vital data, you must dispatch the proper warning events before calling exit().
ADOBE PRODUCT X.0 194
User Guide
Another consideration in gracefully shutting down an application is providing a single execution path, no matter
how the shut-down process starts. Application termination can be triggered by the user (or OS) in the following
ways:
• Closing the last application window when Shell.shell.autoExit=true.
• Application exit command from the OS, for example, when the user chooses exit application command from the
default menu. This will only happen on Mac OS X; Windows does not provide an application exit command through
system chrome.
• Computer shut down.
When exit command is mediated through the operating system by one of these routes, the Shell object will dispatch
an exiting event. If no listeners cancel the exiting event, any open windows are closed. Each window will dispatch a
closing and then a close event. If any of the windows cancel the closing event, the shut-down process will halt.
If the order of window closure is an issue for your application, then you should listen for the exiting event from the
Shell and close the windows in the proper order yourself. This might be the case, for example, if you have a document
window with tool palettes. It might be inconvenient, or worse, if the system closed the palettes, but the user decided
to cancel the exit command to save some data. On Windows, the only time you will get the exiting event is after
closing the last window (when autoExit=true).
A good practice for exiting the application, which provides consistent behavior on all platforms and whether or not
the exit sequence is initiated via operating system chrome or menu commands, or initiated through application logic,
is to:
1 Always dispatch an exiting event through the Shell object before calling exit() in application code and check
that another component of your application doesn’t cancel the event.
public function applicationExit():void{
var exitingEvent:Event = new Event(Event.EXITING,false,true);
Shell.shell.dispatchEvent(exitingEvent);
if(!exitingEvent.isDefaultPrevented()){
Shell.shell.exit();
}
}
2 Listen for the exiting event and in the handler close any windows (dispatching a closing event first) and then
perform any needed clean up tasks such as saving application data, deleting temporary files, etc. Only synchronous
methods should be used to ensure that they will finish before the application quits.
If the order in which your windows are closed doesn’t matter, then you can loop through the
Shell.shell.openedWindows array and close each window in turn. If order does matter, then you will have to
provide a means of closing the windows in the correct sequence.
private function onExiting(exitingEvent:Event):void{
var winClosingEvent:Event;
for each(var win:NativeWindow in Shell.shell.openedWindows){
winClosingEvent = new Event(Event.CLOSING,false,true);
win.dispatchEvent(winClosingEvent);
if(!winClosingEvent.isDefaultPrevented()){
win.close();
} else{
exitingEvent.preventDefault();
}
}
if(!exitingEvent.isDefaultPrevented()){
//perform cleanup
}
ADOBE PRODUCT X.0 195
User Guide
3 Windows should always handle their own clean up by listening for the window closing event.
4 Only one exiting listener should be used in your application since handlers called earlier cannot know whether
subsequent handlers will cancel the exiting event (and it would be unwise to rely on the order of execution).
196
Service Monitoring
Your AIR application can run in environments with uncertain and changing network connectivity. To help an appli-
cation manage connections to online resources, Adobe AIR sends a network change event whenever a network
connection becomes available or unavailable. The network change event is dispatched by the application’s
flash.system.Shell object. To react to this event, add a listener:
Shell.shell.addEventListener(Event.NETWORK_CHANGE, onNetworkChange);
The Event.NETWORK_CHANGE event does not indicate a change in all network activity, only that a network
connection has changed. AIR does not attempt to interpret the meaning of the network change. A networked
computer may have many real and virtual connections, so losing a connection does not necessarily mean losing a
resource. On the other hand, new connections do not guarantee improved resource availability, either. Sometimes a
new connection can even block access to resources previously available (for example, when connecting to a VPN).
In general, the only way for an application to determine whether it can connect to a remote resource is to try it. To
this end, the service monitoring frameworks in the air.net package provide AIR applications with an event-based
means of responding to changes in network connectivity to a specified host.
Note: The service monitoring framework detects whether a server responds acceptably to a request. This does not
guarantee full connectivity. Scalable web services often use caching and load-balancing appliances to redirect traffic to
a cluster of web servers. In this situation, service providers only provide a partial diagnosis of network connectivity.
The ServiceMonitor class implements the framework for monitoring network services and provides a base function-
ality for service monitors. By default, an instance of the ServiceMonitor class will dispatch events regarding network
connectivity. These events will be dispatched, when the instance is created and whenever a network change is
detected by Adobe AIR. Additionally, you can set the pollInterval property of a ServiceMonitor instance to check
connectivity at a specified interval in milliseconds, regardless of general network connectivity events. An instance of
ServiceMonitor will not check network connectivity until the start() method is called.
The URLMonitor class, subclassing the ServiceMonitor class, detects changes in HTTP connectivity for a specified
URLRequest.
The SocketMonitor class, also subclassing the ServiceMonitor class, detects changes in connectivity to a specified
host at a specified port.
var monitor:URLMonitor;
monitor = new URLMonitor(new URLRequest('http://www.adobe.com'));
monitor.addEventListener(StatusEvent.STATUS, announceStatus);
monitor.start();
function announceStatus(e:StatusEvent):void {
trace("Status change. Current status: " + monitor.available);
}
function announceStatus(e:StatusEvent):void {
trace("Status change. Current status: " + socketMonitor.available);
}
199
URLRequest properties
The URLRequest class includes the following properties which are available to content only in the AIR application
security sandbox:
followRedirects Specifies whether redirects are to be followed (true, the default value) or not (false). This is
only supported in the runtime.
manageCookies Specifies whether the HTTP protocol stack should manage cookies (true, the default value) or not
(false) for this request. This is only supported in the runtime.
shouldAuthenticate Specifies whether authentication requests should be handled (true) for this request. This is
only supported in the runtime. The default is to authenticate requests—this may cause an authentication dialog box
to be displayed if the server requires credentials to be shown. You can also set the user name and password—see
“Setting login credentials for a URLRequest object” on page 200.
shouldCacheResponse Specifies whether successful response data should be cached for this request. This is only
supported in the runtime. The default is to cache the response (true).
useCache Specifies whether the local cache should be consulted before this URLRequest fetches data. This is only
supported in the runtime. The default (true) is to use the local cached version, if available.
userAgent Specifies the user-agent string to be used in the HTTP request.
ADOBE PRODUCT X.0 200
User Guide
The following properties of a URLRequest object can be set by content in any sandbox (not just the AIR application
security sandbox):
contentType The MIME content type of any data sent with the URL request.
method Controls the HTTP request method, such as a GET or POST operation. (Content running in the AIR
application security domain can specify strings other than "GET" or "POST" as the method property. Any HTTP verb
is allowed and "GET" is the default method. See “AIR Security” on page 52.)
requestHeaders The array of HTTP request headers to be appended to the HTTP request.
Note: The HTMLControl class has related properties for settings pertaining to content loaded by an HTMLControl
object. For details, see “Loading HTML content from a URL ” on page 163.
The URLRequestDefaults class lets you define default settings for URLRequest objects. For example, the following
code sets the default values for the manageCookies and useCache properties:
URLRequestDefaults.manageCookies = false;
URLRequestDefaults.useCache = false;
The URLRequestDefaults class includes a setLoginCredentialsForHost() method that lets you specify a default
user name and password to use for a specific host. The host, which is defined in the hostname parameter of the
method, can be a domain, such as "www.example.com", or a domain and a port number, such as
"www.example.com:80". Note that "example.com", "www.example.com", and "sales.example.com" are each
considered unique hosts.
These credentials are only used if the server requires them. If the user has already authenticated (for example, by
using the authentication dialog box) then you cannot change the authenticated user by calling the
setLoginCredentialsForHost() method.
For example, the following code sets the default user name and password to use at www.example.com:
URLRequestDefaults.setLoginCredentialsForHost("www.example.com", "Ada", "love1816$X");
Each property of URLRequestDefaults settings apply to only the application domain of the content setting the
property. However, the setLoginCredentialsForHost() method applies to content in all application domains
within an AIR application. This way, an application can log into a host and have all content within the application be
logged in with the specified credentials.
For more information, see the URLRequestDefaults class in the Flex Language Reference for Apollo.
http: and https: Use these as you would use them in a web browser.
file: Use this to specify a path relative to the root of the file system. For example:
file:///c:/AIR Test/test.txt
app-resource: Use this to specify a path relative to the root directory of the installed application (the directory
that contains the application descriptor file for the installed application). For example, the following path points to
a resources subdirectory of the directory of the installed application:
app-resource:/resources
When running in the ADL application, the application resource directory is set to the directory that contains the
application descriptor file.
app-storage:/ Use this to specify a path relative to the application store directory. For each installed application,
AIR defines a unique application store directory, which is a useful place to store data specific to that application. For
example, the following path points to a prefs.xml file in a settings subdirectory of the application store directory:
app-storage:/settings/prefs.xml
You can use a URLRequest object that uses any of these URL schemes to define the URL request for a number of
different objects, such as a FileStream or a Sound object. You can also use these schemes in HTML content running
in AIR; for example, you can use them in the src attribute of an img tag.
However, you can only use these AIR URL schemes in content in the application resource directory. For more infor-
mation, see “AIR Security” on page 52.
• The Security.allowDomain() method cannot be called from the application security sandbox.
• Importing non-application content into the application sandbox by setting the
LoaderContext.securityDomain or the LoaderContext.applicationDomain property is prevented.
But there are still cases where the main AIR application wants content from a remote domain to have controlled
access to scripts in the main AIR application, or vice versa. To accomplish this, the AIR runtime provides a sandbox
bridge mechanism, which serves as a gateway between the two, providing explicit interaction between remote and
application security sandboxes.
Suppose an AIR music store application wants to allow remote SWF files to broadcast the price of albums, but does
not want the remote SWF file to disclose whether the price is a sale price. To do this, a StoreAPI class provides a
method to acquire the price, but obscures the sale price. An instance of this StoreAPI class is then assigned to the
parentSandboxBridge property of the LoaderInfo object of the Loader object that loads the remote SWF.
ADOBE PRODUCT X.0 203
User Guide
The following code represents an example of a PriceQuoter SWF file that reports the store’s price, but cannot report
the sale price:
package
{
import flash.display.Sprite;
import flash.system.Security;
import flash.text.*;
When exposing sandbox bridges, it's important to expose high-level APIs that limit the degree to which they can be
abused. Keep in mind that the content calling your bridge implementation may be compromised. So, for example,
exposing a "readFile(path:String)" method via a bridge is vulnerable to abuse. It would be better to expose a
"readApplicationSetting()" API that doesn't take a path. The more semantic approach limits the damage that
an application can do once part of it is compromised.
For more information on security, see “AIR Security” on page 52.
205
For information about how to package an application into an AIR file using the AIR SDK see “Exporting an AIR
installation file using the AIR Developer Tool” on page 32.
Once you package an AIR application there are a couple of ways to distribute it:
• You can install it by sending the AIR package to the end user just as you would distribute any file. For example,
you can send the AIR package as an e-mail attachment or as a link in a web page.
• Using a seamless install installation link in a web page.
AIR applications are easy to install and run. The seamless install feature lets users install the latest version of the AIR
runtime (if it is not installed) when clicking the link to install a specific AIR application. Once the AIR application
is installed, users simply double-click the application icon to run it, just like any other desktop application.
This section contains the following topics:
• “Digitally signing an AIR file” on page 206
• “Distributing and installing using the seamless install feature” on page 208
• “Distributing and installing an AIR file without using the seamless install feature” on page 212
Certificate format
The AIR signing tools accept PKCS#12 keystore files (which typically use a .pfx or .p12 file extension). These files
can be generated from a certificate using a variety of third- party tools, including the Java Keytool utility included
with the JDK, and the Microsoft pvk2pfx utility included with Windows development tools. In addition, many
browsers, including Internet Explorer and Firefox, can export or backup keystore files in the proper format.
You can use an existing class-3, high assurance code signing certificate or you can obtain a new one. The certificate
issued by the certificate authority must be one of the following types:
• Verisign:
• Microsoft Authenticode Digital ID
• Sun Java Signing Digital ID
• Thawte:
• Apple Developer Certificate
• JavaSoft Developer Certificate
• Microsoft Authenticode Certificate
Adobe developer certificates will be offered by these CAs in the future. Although there will be Adobe developer
certificates, existing code-signing certificates issued by these CAs will continue to be supported.
Note: You cannot use an SSL certificate to sign AIR files.
Obtaining a certificate
To obtain a certificate, you must typically visit the Verisign or Thawte web site and complete the procurement
process. The tools used to produce the keystore file needed by the AIR tools will depend on the type of certificate
purchased, how the certificate is stored on the receiving computer, and, in some cases, the browser used to obtain
the certificate. For example, to obtain and export a Microsoft Authenticode certificate, Verisign or Thawte will
require you to use Microsoft Internet Explorer. The certificate can then be exported as a .pfx file directly from the
Internet Explorer user interface.
ADOBE PRODUCT X.0 208
User Guide
You can generate a self-signed certificate using the ADT tool used to package AIR installation files. A number of
third-party tools can also be used.
For instructions on how to generate a self-signed certificate, as well as instructions on signing an AIR file, see
“Exporting an AIR installation file using the AIR Developer Tool” on page 32. You can also export and sign AIR files
using Flex Builder, Dreamweaver, and the AIR update for Flash.
Terminology
This section provides a glossary of some of the key terminology you should understand when making decisions
about how to sign your application for public distribution.
Certificate Authority (CA) An entity in a public-key infrastructure network that serves as a trusted third party and
ultimately certifies the identity of the owner of a public key. A CA normally issues digital certificates, signed by its
own private key, to attest that it has verified the identity of the certificate holder.
Certificate Practice Statement (CPS) Sets forth the practices and policies of the certificate authority in issuing and
verifying certificates. The CPS is part of the contract between the CA and its subscribers and relying parties. It also
outlines the policies for identify verification and the level of assurances offered by the certificates they provide.
Certificate Revocation List (CRL) A list of issued certificates that have been revoked and should no longer be relied
upon.
Digital Certificate A digital document that contains information about the identity of the owner, the owner’s public
key, the identity of the certificate itself, and which is signed by the issuing certificate authority.
Digital Signature An encrypted message or digest that can only be decrypted with the public key half of a public-
private key pair. In a PKI, a digital signature will contain one or more digital certificates that are ultimately traceable
to the certificate authority. A digital signature can be used to validate that a message (or computer file) has not been
altered since it was signed (within the limits of assurance provided by the cryptographic algorithm used), and,
assuming one trusts the issuing certificate authority, the identity of the signer.
Private Key The private half of a two-part, public-private key asymmetric cryptography system. The private key
must be kept secret and should never be transmitted over a network. Digitally signed messages are encrypted with
the private key by the signer.
Public Key The public half of a two-part, public-private key asymmetric cryptography system. The public key is
openly available and is used to decrypt messages encrypted with the private key.
Public Key Infrastructure (PKI) A system of trust in which certificate authorities attest to the identity of the owners
of public keys. Clients of the network rely on the digital certificates issued by a trusted CA to verify the identity of
the signer of a digital message (or file).
Note: The instructions in this topic provide information on setting parameters of the badge.swf file provided by Adobe.
We also provide the source code for the badge.swf file, which you can customize.
• appname—The name of the application to display in the badge SWF file text when the runtime is not
installed.
• buttoncolor—The color of the download button (specified as a hex value, such as FFCC00).
• messagecolor—The color of the text message displayed below the button when the runtime is not installed
(specified as a hex value, such as FFCC00).
• imageurl—The URL of the image (optional) to display in the badge.
For details, see “Adjusting the code in the HTML page that contains the badge.swf file” on page 210.
Installing the AIR application from a seamless install link in a web page
Once you have added the seamless install link to a page, you (or any user) can install the AIR application by clicking
the link in the SWF file.
1 Navigate to the HTML page in a web browser that has Flash Player (version 6 or later) installed.
2 In the web page, click the link in the badge.swf file.
• If you have installed the AIR runtime, skip to the next step.
• If you have not installed the AIR runtime, a dialog box is displayed asking whether you would like to install
it. Install the AIR runtime (see “Install the runtime” on page 2), and then proceed with the next step.
3 In the Installation window, leave the default settings selected, and then click Continue.
On a Windows computer, AIR automatically does the following:
• Installs the application into c:\Program Files\
• Creates a desktop shortcut for application
• Creates a Start Menu shortcut
• Adds an entry for application in the Add/Remove Programs Control Panel
On Mac OS, the installer adds the application to the Applications subdirectory of the user directory (for example,
in the /Applications directory in Mac OS).
4 When the installation is complete, click Finish.
5 Select the options you want, and then click the Install button.
ADOBE PRODUCT X.0 210
User Guide
Adjusting the code in the HTML page that contains the badge.swf file
You need to add FlashVars parameter definitions for the URL variable, and modify the path to the badge.swf file (if
needed). SWF files are embedded in a page using the EMBED and OBJECT tags, as in the following:
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="HelloWorld" width="215" height="138"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="badge.swf" />
<param name="FlashVars" value="appUrl=AIRFileURL.air&airversion=1.0.M5" />
<embed src="badge.swf" quality="high" bgcolor="#869ca7"
FlashVars="appUrl=AIRFileURL.air&airversion=1.0.M5"
width="215" height="138" name="HelloWorld" align="middle"
play="true"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
The boldface lines represent code that you need to add and modify to reflect the URL of your AIR file and the
badge.swf file.
However, this is a simplified version of code embedding a SWF file. In most HTML pages, SWF files are embedded
with more complicated code. For example, Flex Builder and Flash CS3 both insert code as described in the Flash
Player Detection Kit (http://www.adobe.com/products/flashplayer/download/detection_kit/), as shown below:
<script language="JavaScript" type="text/javascript">
<!--
// Version check for the Flash Player that has the ability to start Player Product Install
(6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);
// Check to see if a player with Flash Product Install is available and the version does
not meet the requirements for playback
if ( hasProductInstall && !hasRequestedVersion ) {
// MMdoctitle is the stored document.title value used by the installation process to
close the window that started the process
// This is necessary in order to close browser windows that are still utilizing the
older version of the player after installation has completed
// DO NOT MODIFY THE FOLLOWING FOUR LINES
// Location visited after installation is complete if installation is required
var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
var MMredirectURL = window.location;
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
var MMdoctitle = document.title;
AC_FL_RunContent(
"src", "playerProductInstall",
"FlashVars",
"MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"&a
ppUrl=AIRFileURL.air&airversion=1.0.M5",
"width", "215",
"height", "138",
"align", "middle",
"id", "badge",
"quality", "high",
"bgcolor", "#869ca7",
ADOBE PRODUCT X.0 211
User Guide
"name", "badge",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else if (hasRequestedVersion) {
// if we've detected an acceptable version
// embed the Flash Content SWF when all tests are passed
AC_FL_RunContent(
"src", "badge",
"width", "215",
"height", "138",
"align", "middle",
"id", "badge",
"quality", "high",
"bgcolor", "#869ca7",
"name", "badge",
"flashvars",'historyUrl=history.htm%3F&lconid=' + lc_id + '
&appUrl=AIRFileURL.air&airversion=1.0.M5',
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else { // flash is too old or we can't detect the plugin
var alternateContent = 'Alternate HTML content should be placed here. '
+ 'This content requires the Adobe Flash Player. '
+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
document.write(alternateContent); // insert non-flash content
}
// -->
</script>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="badge" width="100%" height="100%"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="badge.swf" />
<param name="FlashVars" value="appInstallUrl=AIRFileURL.air&airversion=1.0.M5" />
<param name="quality" value="high" />
<param name="bgcolor" value="#869ca7" />
<param name="allowScriptAccess" value="sameDomain" />
<embed src="badge.swf" quality="high" bgcolor="#869ca7"
FlashVars="appUrl=AIRFileURL.air&airversion=1.0.M5"
width="215" height="138" name="badge" align="middle"
play="true"
loop="false"
quality="high"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
</noscript>
In this code, there are many more lines to modify, as the code embeds the SWF file in a number of ways (including
via JavaScript calls). Be sure to modify AIRFileURL.air to point to the URL (or relative path) of your AIR file, and
modify it each place it is referenced in the code. If necessary, also modify the path to the badge.swf file, and modify
it each place it is referenced in the code.
ADOBE PRODUCT X.0 212
User Guide
If an Adobe AIR application downloads an AIR file via the web, it is a good practice to have a mechanism by which
the web service can notify the Adobe AIR application of the version being downloaded. The application can then use
this string as the version parameter of the update() method. If the AIR file is obtained by some other means, in
which the version of the AIR file is unknown, the AIR application can examine the AIR file to determine the version
information. (An AIR file is a ZIP-compressed archive, and the application descriptor file is the second record in the
archive.)
For details on the application descriptor file, see “Setting application properties” on page 62.
This interface is always used the first time a user installs a version of an application on a machine. However, you can
define your own interface to use for subsequent instances. To do this specify a handleUpdates element in the appli-
cation descriptor file for the application:
<handleUpdates/>
When the application is installed, when the user opens an AIR file with an application ID matching the installed
application, the runtime opens the application, rather than the default AIR application installer. For more infor-
mation, see “Signaling the inclusion of an update interface” on page 66.
The application can decide, when it is invoked (when the Shell.shell object dispatches an invoke event) whether
to update the application (using the Updater class). If it decides to update, it can present its own installation interface
(which differs from its standard running interface) to the user.
ADOBE PRODUCT X.0 216
User Guide
function loaded(event:Event):void {
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
writeAirFile();
}
function writeAirFile():void {
var file:File = File.applicationStorageDirectory.resolve("My App v2.air");
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.CLOSE, fileClosed);
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeBytes(fileData, 0, fileData.length);
fileStream.close();
}
function fileClosed(event:Event):void {
trace("The AIR file is written.");
}
See also
• “Workflow for reading and writing files” on page 112.
Class Package
Clipboard flash.desktop
ClipboardFormats flash.desktop
CompressionAlgorithm flash.utils
ClipboardTransferMode flash.desktop
DockIcon flash.display
DragActions flash.desktop
DragManager flash.desktop
DragOptions flash.desktop
DRMAuthenticateEvent flash.events
DRMStatusEvent flash.events
EncryptedLocalStore flash.filesystem
File flash.filesystem
FileListEvent flash.events
FileMode flash.filesystem
FileStream flash.filesystem
HTMLControl flash.html
HTMLHistoryItem flash.html
HTMLHost flash.html
ADOBE PRODUCT X.0 2
User Guide
Class Package
HTMLPDFCapability flash.html
HTMLUncaughtJavaScriptExceptionEvent flash.html
HTMLWindowCreateOptions flash.html
Icon flash.desktop
InteractiveIcon flash.display
InvokeEvent flash.events
JavaScriptFunction flash.html
JavaScriptObject flash.html
NativeDragEvent flash.events
NativeMenu flash.display
NativeMenuItem flash.display
NativeWindow flash.display
NativeWindowBoundsEvent flash.events
NativeWindowDisplayState flash.display
NativeWindowDisplayStateEvent flash.events
NativeWindowErrorEvent flash.events
NativeWindowIcon flash.display
NativeWindowInitOptions flash.display
NativeWindowResize flash.display
NativeWindowSystemChrome flash.display
NativeWindowType flash.display
NotificationType flash.display
OutputProgressEvent flash.events
Screen flash.display
Shell flash.system
SQLCollationType flash.data
SQLColumnNameStyle flash.data
SQLColumnSchema flash.data
SQLConnection flash.data
SQLError flash.errors
SQLErrorCode flash.errors
SQLErrorEvent flash.events
SQLErrorOperation flash.errors
ADOBE PRODUCT X.0 3
User Guide
Class Package
SQLEvent flash.events
SQLIndexSchema flash.data
SQLResult flash.data
SQLSchema flash.data
SQLSchemaResult flash.data
SQLStatement flash.data
SQLTableSchema flash.data
SQLTransactionLockType flash.data
SQLTriggerSchema flash.data
SQLUpdateEvent flash.events
SQLViewSchema flash.data
SystemTrayIcon flash.display
Updater flash.system
URLRequestDefaults flash.net
XMLSignatureValidator flash.utils
TransferableTransferMode flash.desktop
URLRequestDefaults flash.net
Updater flash.system
Most of these classes are available only to content in the AIR application security sandbox (see “Introducing Adobe
AIR” on page 13). However, the following classes are also available to content running in other sandboxes:
• Door
• URLRequest.
HTTPStatusEvent HTTP_RESPONSE_STATUS
responseURL
responseHeaders
URLRequest followRedirects
manageCookies
shouldAuthenticate
shouldCacheResponse
userAgent
userCache
setLoginCredentials()
Stage nativeWindow
Security APPLICATION
Most of these new properties and methods are available only to content in the AIR application security sandbox.
However, the new members in the URLRequest classes are also available to content running in other sandboxes.
The ByteArray.compress() and ByteArray.uncompress() methods each include a new algorithm parameter,
allowing you to choose between deflate and zlib compression.
See also
• “Setting up for Flex Builder” on page 4
• “Setting up for Flex SDK” on page 13
Use the Flex SDK and the command-line tools to install sample applications
1 Unzip the sample application files into a folder on your computer. Create a new folder for each, if you like.
2 With the SDK properly installed and configured (the SDK added to your class path), you're ready to test the
samples.
CLOSE PROCEDURE
Next steps
Follow the instructions in the quick-start topics to edit, run, and debug the applications.
See also
Flex Builder users:
• Developing AIR applications with Flex Builder
Flex developers using the Flex SDK:
• Compiling an AIR application with the amxmlc compiler
• Compiling an AIR component or library with the acompc compiler
• Debugging using the AIR Debug Launcher
• Exporting an AIR installation file using the AIR Developer Tool
9
The installer (AIR) file for this sample application is available in the Samples directory included with the documen-
tation at the AIR pre-release site.
The application is a straightforward, but simple, editor of plain text files. The application uses UTF-8 encoding for
reading and writing all text files.
ADOBE PRODUCT X.0 10
User Guide
File Description
TextEditor.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the
code” on page 10.
icons/ApolloApp_32.png
icons/ApolloApp_48.png
icons/ApolloApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/TextEditor.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
This code sets the File object to point to the test.txt file in the user's documents directory. In Windows, this is the My
Documents directory. In Mac OS, it is the /Users/userName/Documents directory.
The defaultFile file is later passed to Open and Save As pop-up windows, if the user has not yet selected a file path.
Reading a file
The openFile() method contains code that opens a file chooser dialog box. When the user selects a file and clicks
the OK button. The fileOpenSelected() method is called. The method first initiates the file File object to point
to the path specified by the user:
currentFile = event.file;
Next the stream FileStream object is closed (in case it currently has a file open) and the stream FileStream object
are initialized:
if (stream != null)
{
ADOBE PRODUCT X.0 11
User Guide
stream.close();
}
stream = new FileStream();
stream.openAsync(currentFile, FileMode.READ);
Note: The fileMode parameter of the openAsync() method is set to FileMode.READ. This lets you read the file.
Event handlers are set up to respond to the complete and ioError events:
stream.addEventListener(Event.COMPLETE, fileReadHandler);
stream.addEventListener(IOErrorEvent.IO_ERROR, readIOErrorHandler);
AIR begins reading the file asynchronously, and the runtime automatically starts reading the file in and firing events.
Note that you can add these event listeners after calling the openAsync() method, because the runtime will complete
executing this ActionScript code (the block of code that includes the calls to addEventListener() methods) before
responding to any events.
Note: This sample application shows how to read a file asynchronously. You can also read the file synchronously by
calling the open() method when opening the file, rather than calling the openAsync() method. For more information,
see “Working with the file system” on page 100.
If the stream object dispatches an ioError event, the readIOErrorHandler() displays an error message for the
end user.
When the file is read in fully, the stream object dispatches the complete event, and the fileReadHandler())
method reads and processes the file.
The readUTFBytes() method of the stream object returns a string by reading UTF-8 characters from specified
number of bytes. Since the stream object just dispatched complete event, the bytesAvailable property represents
the total length of the file, and it is passed as the length property of the call to the readUTFBytes() method:
var str:String = stream.readUTFBytes(stream.bytesAvailable);
The following code replaces the line ending characters from the file with the "\n" newline character, which is used in
a TextField object in a SWF file. It then assigns the string to the text property of the Text control:
var lineEndPattern:RegExp = new RegExp(File.lineEnding, "g");
str = str.replace(lineEndPattern, "\n");
mainTextField.text = str;
The currentFile object is undefined when the user first opens the application, and when the user clicks the New
button. If there is no currentFile defined, then the saveAs() method is called (in the else block), which lets the
user select a file path for saving the file.
Next the stream FileStream object is closed (if it is currently open) and then it is initialized:
if (stream != null)
{
stream.close();
}
stream = new FileStream();
stream.openAsync(currentFile, FileMode.WRITE);
ADOBE PRODUCT X.0 12
User Guide
Note that the mode parameter of the openAsync() method is set to FileMode.WRITE. This lets you write to the file.
An event handlers is set up to respond to the any ioError events:
stream.addEventListener(IOErrorEvent.IO_ERROR, writeIOErrorHandler);
The following code replaces the "\n" newline character, which is used in a TextField object in a SWF file, with the
line ending character used in text files in the file system (File.lineEnding) It then assigns the string to the text
property of the Text control:
var str:String = mainTextField.text;
str = str.replace(/\r/g, "\n");
str = str.replace(/\n/g, File.lineEnding);
The writeUTFBytes() method of the stream object writes a string to the file in UTF-8 format and then closes the
file:
stream.writeUTFBytes(str);
stream.close();
If the stream object dispatches an ioError event, the writeIOErrorHandler() displays an error message to the
end user.
13
File Description
FileSearch.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the code”
on page 14.
icons/ApolloApp_32.png
icons/ApolloApp_48.png
icons/ApolloApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/FileSearch.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
The File.documentsDirectory is a File object pointing to the user's documents directory (such as My Documents
on Windows), and the nativePath property is a string value of the platform-specific path to the directory. For
example, on Windows, this path could be:
C:\Documents and Settings\userName\My Documents
The user can edit this value (in the TextArea component), and when the user clicks the Search button, the search()
method checks to see if the path is valid, and displays an error message if it is not:
var dir:File = new File(folderPath.text);
if (!dir.isDirectory)
{
Alert.show("Invalid directory path.", "Error");
}
ADOBE PRODUCT X.0 15
User Guide
Notice the difference between the nativePath property and the url property of a File, listed here for the same
directory File object:
dir.addEventListener(FileListEvent.DIRECTORY_LISTING, dirListed);
dir.getDirectoryListingAsync();
The dirListed() method processes the list of files in the current directory. This list is represented as the files
property of the dirListing event. The method sets a currentNodes variable to this array:
currentNodes = event.files;
The dirListed() method iterates through each member of this array, to see if it is a directory. If it is a directory, the
object is added to a list of current subdirectories (of the current directory being examined).
node = currentNodes[i];
if (node.isDirectory)
{
currentSubdirectories.push(currentNodes[i]);
}
After the iteration is completed, the members of this array are added to a master array of directories to be searched,
named directoryStack:
for (i = currentSubdirectories.length - 1; i > -1; i--)
{
directoryStack.push(currentSubdirectories[i]);
}
At this point, now that processing of the current directory is complete, the application can call another asynchronous
listing of the next directory in the stack (if there is one):
var dir:File = directoryStack.pop();
if (dir == null) {
progress.visible = false;
// There are no further directories to search. The search is completed.
} else {
dir.addEventListener(FileListEvent.DIRECTORY_LISTING, dirListed);
dir.listDirectoryAsync();
}
Note: The file extension, represented by the fileExtension variable, is extracted from the filename by using the
substr() and lastIndexOf() methods of the name property of the File object. (The file extension is the string portion
of the filename that follows the last occurence of the "." character in the filename.)
17
The preferences are stored in a text file contains XML data. The application converts that data to an XML object,
upon reading, and converts the XML data to text upon writing.
1 Open the application.
2 Resize and reposition the window.
3 Click the Save Preferences button.
The application writes the new data to the XML file.
4 Restart the application to see your preferences take effect.
ADOBE PRODUCT X.0 18
User Guide
File Description
PrefsXMLDemo.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the code”
on page 18.
icons/ApolloApp_32.png
icons/ApolloApp_48.png
icons/ApolloApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/PrefsXMLDemo.zip.
For help on building this quick start sample application,
See also
• “Building the quick-start sample applications with Flex” on page 7.
File.applicationStorageDirectory points to the AIR application store directory, which is uniquely defined for
each AIR application.
The appCompleteHandler() method also sets up an event handler to respond to the window closing (which saves
the preferences data to the file):
stage.nativeWindow.addEventListener(Event.CLOSING, windowClosingHandler);
The readXML() method sets up a File object and a FileStream object. The fileMode parameter of the call to the
open() method is set to FileMode.READ, so that the FileStream object can read data from the file.
stream.open(prefsFile, FileMode.READ);
The open() method of the stream object opens the file synchronously and begins reading data into the read buffer.
The processXMLData() event method processes the XML data and closes the file. The bytesAvailable property
of the FileStream object is the number of bytes in the read buffer, which is all of the bytes from the file (since the file
is read synchronously):
prefsXML = XML(stream.readUTFBytes(stream.bytesAvailable));
stream.close();
Note: This code sample uses E4X notation, which was introduced in ActionScript 3.0. For example,
prefsXML.windowState.@x is the value of the x attribute of the windowState property of the prefsXML XML object.
For more information, see the Working with XML (http://livedocs.adobe.com/flex/2/docs/00001910.html#118717)
chapter of the Programming ActionScript 3.0 book.
The readXML() method makes the window visible after the processXMLData() method returns:
stage.nativeWindow.visible = true;
It then sets up and uses a FileStream object for writing the data. Note that FileMode.WRITE is specified as the
fileMode parameter in the open() method. This specifies that the FileStream object will be able to write to the file
(and will truncate any existing data before writing):
stream = new FileStream();
stream.open(prefsFile, FileMode.WRITE);
Next, the writeUTFBytes() method is called, which writes the string version of the XML data to the file (as UTF-
8 data):
stream.writeUTFBytes(outputString);
ADOBE PRODUCT X.0 20
User Guide
Since this file was opened for synchronous operations (using the open() method) and the write method is included
within the event handler for the Window object's closing event, the file writing will complete before the window
(and application) actually close. This application uses synchronous read and write operations because the XML
preferences file is relatively small. If you were to want to write a file asynchronously, you would want to cancel the
closing event, and explicitly close the application by calling the Shell.shell.exit()) method in an event
handler for the outputProgress event dispatched by the FileStream object.
21
See also
• “Understanding the code” on page 22
• “Building the quick-start sample applications with Flex” on page 7
ADOBE PRODUCT X.0 22
User Guide
Drag the middle to move The mouseDown event triggers application logic to run that calculates the mouse position and, if appro-
priate, makes a call to the NativeWindow.startMove() method.
ADOBE PRODUCT X.0 23
User Guide
Arrow keys move one pixel at a time The keyDown event triggers application logic that detects if an arrow key was pressed. If it was,
the NativeWindow.x or NativeWindow.y property is either increased or decreased by 1, depending on whether the arrow that was
pressed was the DOWN arrow key, the UP arrow key, the LEFT arrow key, or the RIGHT arrow key. This process occurs each time the user presses
an arrow key.
Shift + arrow keys resize one pixel at a time The keyDown event triggers application logic that detects if the SHIFT key was
pressed in combination with an arrow key. If such a key combination was pressed, the NativeWindow.width or Window.height
property is either increased or decreased by 1, depending on whether the arrow that was pressed was the DOWN arrow key, the UP arrow key,
the LEFT arrow key, or the RIGHT arrow key. This process occurs each time the user presses the SHIFT key in combination with an arrow key.
Mouse wheel changes opacity The event listener that was created to detect activity from the mouse wheel makes a call to an event
handler that determines the extent and direction in which the mouse wheel is turned. These values are used to modify the alpha property,
which affects the level of transparency that is applied to the background color.
Double-click to quit The doubleClick event triggers application logic that makes an explicit call to the Window.close()
method.
Press n to create a new window The keyDown event triggers application logic that detects if the N key was pressed. If so, a new
instance of the Ruler class (which extends NativeWindow) is created, displaying a new ruler window.
Creating a Window
To create a window, PixelPerfect instantiates a new Ruler object. The Ruler class extends the NativeWindow class.
In the Ruler constructor, the NativeWindowInitOptions object is created and passed to the NativeWindow super
class constructor:
public function Ruler(width:uint = 300,
height:uint = 300,
x:uint = 50,
y:uint = 50,
alpha:Number = .4){
var winArgs:NativeWindowInitOptions = new NativeWindowInitOptions();
winArgs.systemChrome = NativeWindowSystemChrome.NONE;
winArgs.transparent = true;
super(false, winArgs);
//...
The rest of the constructor initializes the properties of the new window and its members.
else
y -= 1;
drawTicks();
break;
case Keyboard.RIGHT:
if (e.shiftKey)
width += 1;
else
x += 1;
drawTicks();
break;
case Keyboard.LEFT:
if (e.shiftKey)
width -= 1;
else
x -= 1;
drawTicks();
break;
case 78:
createNewRuler();
break;
}
This code snippet also shows the key events used to move the window and to create new windows.
For a window to be transparent against the desktop, the window must be created with transparency enabled by
setting transparent property to true in the NativeWindowsInitOptions object passed to the window
constructor. The transparency state of a window cannot be changed once the window is created.
When a windows's close() method is called, the NativeWindow object does not dispatch a closing event. To allow
cancellation of the close operation, dispatch the closing event in your event handler:
private function onDoubleClick(e:Event):void
var closing:Event = new Event(Event.CLOSING,true,true);
dispatchEvent(closing);
if(!closing.isDefaultPrevented()){
close();
}
}
A close event is dispatched after the window is closed, signaling the completion of the close process. After a window
is closed, it cannot be reopened. Closing the window frees the resources associated with the window (unless they are
referenced elsewhere) so that they can be garbage collected. The application is responsible for closing its windows so
that the associated resources can be freed. When the last window of an application is closed, the application also exits.
This default behavior can be changed by setting the Shell object autoExit property to false.
For more information about the methods and properties of the AIR windowing API, see the AIR ActionScript 3.0
Reference.
See also
• “Working with windows” on page 69
26
File Description
WeatherStation.mxml The main application file in MXML for Flex 2. Details of the code are discussed in the Under-
standing the code section.
assets/minimize_icon.png
icons/AIRApp_32.png
icons/AIRApp_48.png
icons/AIRApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/WeatherStation.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
<systemChrome>none</systemChrome>
<transparent>true</transparent>
Second, the CSS styles that are applied to the Flex 2 Application component can affect how that component's
background is displayed and whether it is opaque or transparent. To make sure the background is transparent, the
WeatherStation.mxml file includes the following CSS style declaration:
<mx:Style>
Application
{
background-color:"";
background-image:"";
padding: 0px;
}
After the application is loaded, the initApp() method sets up mouseDown event listeners on the two visible VBox
components. When the user presses the mouse button while the cursor is over one of these VBox components, the
onMouseDown() method is loaded.
this.bgBox.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.tempBox.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
The onMouseDown() method shows how simple it can be to start the window moving sequence:
private function onMouseDown(evt:MouseEvent):void
{
stage.nativeWindow.startMove();
}
Calling the NativeWindow.startMove() method results in the window moving around the desktop in response to
mouse movements until the mouse button is released. You don't need to write additional code to control the
window moving and stopping sequence; it is handled automatically.
<mx:Button id="closeBtn"
icon="@Embed('assets/close_icon.png')"
width="16"
height="16"
click="onClose(event)" />
When the minimize button is clicked, the onMinimize() method calls the NativeWindow.minimize() method:
private function onMinimize(evt:MouseEvent):void
{
stage.nativeWindow.minimize();
}
When the close button is clicked, the onClose() method calls the NativeWindow.close() method:
private function onClose(evt:MouseEvent):void
{
stage.nativeWindow.close();
}
The NativeWindow.close() method terminates the application. It does so asynchronously, and a close event is
started when the application is about to stop. The application can listen for the close event and perform various
clean-up or housekeeping functions before the application stops.
To achieve this effect, the application first defines an instance of the flash.filters.DropShadowFilter class.
public var shadowFilter:DropShadowFilter;
The initApp() method then sets the parameters of the filter and applies the filter to the bgBox component and a
number of other components, as follows:
// creates a generic drop shadow to use on components that don't accept CSS shadow styles
shadowFilter = new DropShadowFilter();
shadowFilter.color = 0x000000;
shadowFilter.alpha = 0.4;
shadowFilter.blurX = 5;
shadowFilter.blurY = 5;
shadowFilter.distance = 5;
// 'external' shadows
addShadow(this.bgBox);
addShadow(this.largeImage);
// 'internal' shadows
addShadow(this.locationTxt);
addShadow(this.tempTxt);
addShadow(this.conditionTxt);
addShadow(this.additionalTxt);
Because the largeImage Image object extends beyond the boundaries of the bgBox component's background, it
also needs a shadow to make the illusion complete. The other display components are only given shadows because
they seem to stand out better that way.
The same DropShadowFilter instance is applied to each of the components in the addShadow() method:
/**
* Adds a standard drop shadow to a display object.
*/
Each component is passed as an argument to this method and treated as a DisplayObject instance (so the same
method could be used for DisplayObject instances that are not Flex UIComponent instances too). Each object's
filters array is then set to an array containing the one shadowFilter object.
31
The Window Launcher sample application on Microsoft Windows, flanked by four different kinds of native windows.
ADOBE PRODUCT X.0 32
User Guide
File Description
WindowLauncher.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the
code” on page 32.
icons/AIRApp_32.png
icons/AIRApp_48.png
icons/AIRApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/WindowLauncher.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
options.maximizable = maximizableOption.selected;
options.minimizable = minimizableOption.selected;
options.resizable = resizableOption.selected;
options.transparent = transparentOption.selected;
options.systemChrome = Chrome.selectedItem.optionString;
options.type = windowType.selectedItem.optionString;
Note: Transparency is not supported for windows that use system chrome. Likewise, system chrome can not be used for
lightweight windows. These rules are enforced in Window Launcher by validating the settings as they are made.
ADOBE PRODUCT X.0 33
User Guide
newWindow.title = titleString.text;
newWindow.alwaysInFront = alwaysInFrontOption.selected;
newWindow.x = Number(xPosition.text);
newWindow.y = Number(yPosition.text);
newWindow.width = Number(widthValue.text);
newWindow.height = Number(heightValue.text);
These properties of the window can be changed at any time before a window is closed.
The width and height properties set the outer dimensions of the window, including the size of any system chrome.
Thus a window without system chrome has a smaller client area than a window with chrome.
lineStyle(1,0,1);
beginFill(0x234578,.5);
for(var i:int = 0; i <= Math.floor(newWindow.stage.stageWidth/rectSize); i++){
for (var j:int = 0; j <= Math.floor(newWindow.stage.stageHeight/rectSize); j++){
drawRoundRect(i*rectSize,j*rectSize,
rectSize-rectSpace,rectSize-rectSpace,10,10);
}//j loop
}//i loop
endFill();
}
newWindow.stage.addChild(client);
After the window has been created, content added, and event handlers attached, the final step is to make the window
visible:
newWindow.visible = true;
35
To use Scrappy, drag files, bitmaps, URLs, and text to the window. The application accepts dragged items in any of
the standard formats supported by AIR. You can also paste (v) items into the window, as well as cut (x), copy (c) and
delete (Del) existing items.
ADOBE PRODUCT X.0 36
User Guide
Note: Not all applications post bitmap data to the clipboard in a format supported by AIR.
File Description
Scrappy.as The main application file in ActionScript. Details of the code are discussed in “Understanding the
code” on page 36.
scraps/Scrap.as The base class for displaying the dragged or pasted information.
about.html Describes this sample application and provides some items to drag into the main window.
Scrappy-app.xml The AIR application descriptor file (see “The application descriptor file structure” on page 62)
icons/AIRApp_32.png
icons/AIRApp_48.png
icons/AIRApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/Scrappy.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7.
dragTarget.focusRect = false;
addChild(dragTarget);
}
stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
stage.window.addEventListener(NativeWindowBoundsEvent.RESIZE, onResize);
stage.window.addEventListener(Event.CLOSE,onClose);
}
The important events for the drag target are: nativeDragEnter, which tells you when a drag gesture enters within the
display object area; nativeDragExit, which tells you when a drag gesture leaves the display object area; and native-
DragDrop, which tells you that the drop has occurred on the display object. You can also listen for the native-
DragOver event instead of the nativeDragEnter event if you need to track the position of the mouse over the target.
The target will dispatch nativeDragOver events whenever the mouse moves (as well as on a short interval)
The keyDown event on the stage is used to check for the paste command. The event listener is attached to the stage
because a sprite will only receive keyboard events when it has focus.
transferable.hasFormat(ClipboardFormats.FILE_LIST_FORMAT) ||
transferable.hasFormat(ClipboardFormats.TEXT_FORMAT) ||
transferable.hasFormat(ClipboardFormats.URL_FORMAT) ||
transferable.hasFormat("SCRAP")){
DragManager.acceptDragDrop(dragTarget);
}
}
The Scrappy application can accept each of the four standard formats. It also defines a custom format, “SCRAP,”
which contains a reference to a Scrap object created within the Scrappy application itself.
In some situations, you might also want to check the allowedActions property of the event object before accepting
the drop.
HTMLScrap Uses an HTMLControl to load and display URLs (including file URLs).
FileScrap Loads and displays the file contents, or displays the file name and icon. For the handful of file types
Scrappy understands, the FileScrap constructor loads the data and creates one of other types of Scrap object to render
it.
ADOBE PRODUCT X.0 39
User Guide
Scrap Factory
The scrap factory class, Scrap.createScrap(), takes a Clipboard object, checks the data formats available, and
then creates the appropriate type of scrap object to display the data.
public static function createScrap(data:Clipboard,
makeCopy:Boolean,
placeX:int,
placeY:int):Scrap{
var scrap:Scrap;
if(data.hasFormat("SCRAP")){
scrap = Scrap(data.dataForFormat("SCRAP",ClipboardTransferMode.ORIGINAL_ONLY));
} else if(data.hasFormat(ClipboardFormats.BITMAP_FORMAT)){
scrap = new BitmapScrap(BitmapData(data.getData(
ClipboardFormats.BITMAP_FORMAT)));
} else if(data.hasFormat(ClipboardFormats.TEXT_FORMAT)){
scrap = new TextScrap(String(data.getData(
ClipboardFormats.TEXT_FORMAT)));
} else if(data.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)){
var dropfiles:Array =
data.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
for each (var file:File in dropfiles)
{
scrap = new FileScrap(file);
}
} else if(data.hasFormat(ClipboardFormats.URL_FORMAT)){
scrap = new HTMLScrap(String(data.getData(
ClipboardFormats.URL_FORMAT)));
}
Scrappy uses two separate drag APIs. As long as a drag gesture stays within the bounds of the main window, Scrappy
uses the Sprite drag API, which provides a somewhat smoother operation for positioning sprites. When the drag
gesture leaves the window, Scrappy transitions the drag gesture to the DragManager API, which allows data to be
dragged to other applications.
Preparing to drag
When the Scrap object being moved leaves the window, it dispatches a rollOut event. The handler for this event stops
the Sprite-controlled drag and gets a Clipboard object by calling the function, addTransferableData(). The addTrans-
ferableData() function creates a new Clipboard object and adds a reference to the current Scrap object by using a
custom format name. The addTransferableData function is overridden in the Scrap subclasses to add the data appro-
priate to that subclass in addition to the reference format.
protected function onDragOut(event:Event):void{
parent.removeEventListener(MouseEvent.ROLL_OUT,onDragOut);
this.stopDrag();
offset.x = -mouseX;
offset.y = -mouseY;
var transferObject:Clipboard = addTransferableData();
DragManager.doDrag(this,transferObject,getImage(),offset);
}
protected function addTransferableData():Clipboard{
var transfer:Clipboard = new Clipboard();
transfer.setData("SCRAP",this,true);
return transfer;
}
Paste
Scrappy implements a paste command on the main window. In response to a paste command (v), the application
passes the clipboard data to the factory method Scrap.createScrap(), which is also used to create scraps for drop
operations.
public function doPaste():void{
var scrap:Scrap = Scrap.createScrap(Clipboard.generalClipboard,
stage.stageWidth/4,stage.stageHeight/4);
addChild(scrap);
scrap.grabFocus();
}
The pasted scrap is always placed in the same spot on the stage.
Copy
Copy is implemented by the Scrap base class. The function calls the addTransferable() function to get the data from
the Scrap object (this is the same function used for drag-and-drop). You cannot assign a Clipboard object directly to
the Clipboard.generalClipboard property, so you must copy each of the formats individually:
public function doCopy():void{
var transferObject:Clipboard = addTransferableData();
for each( var format:String in Clipboard.generalClipboard.formats){
Clipboard.generalClipboard.setData(format, transferObject.getData(format),true);
}
}
Cut
Cut just copies the scrap object to the clipboard, then deletes it.
42
The installer (AIR) file for this sample application is available in the Samples directory included with the documen-
tation at the AIR pre-release site.
ADOBE PRODUCT X.0 43
User Guide
Before running the application, install the index.php file (included with the source files in the PHP directory) in the
http://localhost/PhotoSyncUpload/ folder of your PHP-enabled web server. Also, make sure that a webcam is
installed on your machine.
To test the application:
1 Install the application (by double-clicking the provided AIR file), and run it.
2 Point your webcam to something that you want to take a picture of.
3 Click the Preview button. Then click the Save button to save the image.
4 Repeat this step to save multiple images.
5 Click the Upload button to upload the files to your web server.
File Description
PhotoUpload.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the
code” on page 43.
com/adobe/images/JPEGEncoder.as A utility class used by the JPEGEncoder class. This class is also available at the ActionScript 3.0
Corelib project.
com/adobe/images/BitString.as A utility class used by the JPEGEncoder class. This class is also available at the ActionScript 3.0
Corelib project.
php/index.php A file to include in the http://localhost/PhotoSyncUpload/ folder of your PHP-enabled web server.
icons/ApolloApp_32.png
icons/ApolloApp_48.png
icons/ApolloApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/PhotoUpload.zip.
See also
“Building the quick-start sample applications with Flex” on page 7
The shoot() method then captures the image in the video VideoDisplay component to a BitmapData object and
writes that BitmapData to the shot Image component (by setting the source property of the Image component):
bmd = new BitmapData(video.width, video.height);
bmd.draw(video);
var bmp:Bitmap = new Bitmap(bmd);
bmp.x = (stage.stageWidth - bmp.width)/2
shot.source = bmp;
Saving a file
The save() method sets up a FileStream object to write the image data to a file. The image data is converted to a
ByteArray containing JPEG-encoded data by calling the encode() method of a JPEGEncoder object:
private function save():void {
file = File.applicationStorageDirectory;
file = file.resolvePath("images/" + new Date().time.toString() + ".jpg");
stream = new FileStream;
stream.open(file, FileMode.WRITE);
var data:ByteArray = getJPEG(bmd);
stream.writeBytes(data, 0, data.length);
stream.close();
}
private function getJPEG(bmd:BitmapData):ByteArray {
var jpg:JPEGEncoder = new JPEGEncoder();
return jpg.encode(bmd);
}
Note that the file object points to a file in the images subdirectory of the application resource directory, and the
name of the file is based on a timestamp provided by a Date object’s time property:
ADOBE PRODUCT X.0 45
User Guide
file = File.applicationStorageDirectory;
file = file.resolvePath("images/" + new Date().time.toString() + ".jpg");
You register event listeners for the complete and progress events of the Uploader object and then call its start()
method, which uploads the files to the URL passed as a parameter:
uploader.addEventListener(Event.COMPLETE, uploadCompleteHandler);
uploader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
uploader.start(UPLOAD_URL);
The Uploader object uploads the files one at a time by calling its upload() method, passing the File object as a
parameter:
private function uploadFile(file:File):void
{
var urlRequest:URLRequest = new URLRequest(url);
urlRequest.method = URLRequestMethod.POST;
file.addEventListener(ProgressEvent.PROGRESS, uploadProgress);
file.addEventListener(Event.COMPLETE, uploadComplete);
file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA , uploadServerData);
file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, uploadError);
file.addEventListener(HTTPStatusEvent.HTTP_STATUS, uploadError);
file.addEventListener(IOErrorEvent.IO_ERROR, uploadError);
file.upload(urlRequest, "uploadfile");
}
The upload() method of the File object uploads the file to the given URL (specified as a URLRequest object):
The PHP page you posted on your web server recognizes the string as its cue to accept the file provided as POST
data as a file to be uploaded (and saved on the web server, in an “uploaded” subdirectory.
46
Pop-up menus A native menu can be displayed anywhere in an application by calling the menu display() method.
File Description
AIRMenus.as The main application file. Details of the code are discussed in the Understanding the code section.
AIRMenuIcon.as Extends the Icon class to embed the images used for the dock and system tray icons (which are
also used for the application icon).
AIRMenus-app.xml The application descriptor file. See “Setting application properties” on page 62.
icons/ApolloApp_32.png
icons/ApolloApp_48.png
icons/ApolloApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/AIRMenus.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
ADOBE PRODUCT X.0 48
User Guide
Creating a menu
To create a menu, you start with a new NativeMenu object and add commands, submenus and separators to it. The
top, or root, level menu of application and window menus should only contain submenus. Command and separator
items in the root level menu will not be displayed by all operating systems, and even on those that do display them,
such items would be non-standard and likely to confuse users.
The AIR Menus example uses a function to create the root menu, which is called for each type of menu supported
by AIR. The function creates three example submenus, labeled File, Edit, and Help. The NativeMenu objects for these
submenus are, in turn, created by other functions:
private function createRootMenu():NativeMenu{
var menu:NativeMenu = new NativeMenu();
menu.addSubmenu(createFileMenu(),"File");
menu.addSubmenu(createEditMenu(),"Edit");
menu.addSubmenu(createHelpMenu(),"Help");
return menu;
}
The functions which create the submenus, use the addItem() method to add commands and separators. Each menu
object contains an items array. Since all of the events dispatched when a menu is selected are handled by the same
function, the items array is used to attach the listener to all the items.
private function createFileMenu():NativeMenu{
var menu:NativeMenu = new NativeMenu();
menu.addItem(new NativeMenuItem("New"));
menu.addItem(new NativeMenuItem("Open"));
menu.addItem(new NativeMenuItem("Save"));
menu.addItem(new NativeMenuItem("",true));//separator
menu.addItem(new NativeMenuItem("Exit"));
When AIR supports dock icons on an operating system, the static Shell.supportsDockIcon will be true. The
dock icon is represented by the Shell.shell.icon property. The icon object is created automatically. You can
change the appearance of the dock icon by setting the icon.bitmaps property.
Mac OS X provides a default menu for the dock icon. You can add additional items to the dock menu by adding the
items to a NativeMenu object and assigning it to the icon.menu property.
if(Shell.supportsDockIcon){
DockIcon(Shell.shell.icon).menu = createRootMenu();
Shell.shell.icon.bitmaps = new AIRMenuIcon().bitmaps;
}
When AIR supports system tray icons on an operating system, the static Shell.supportsSystemTrayIcon will be
true. The system tray icon is represented by the Shell.shell.icon property. The icon object is created automat-
ically. To show the icon in the notification area of the taskbar, you only need to assign an array containing the icon
image to the icon bitmaps property. To remove the icon from the taskbar, set bitmaps to an empty array.
Add a menu to the system tray icon by assigning a NativeMenu object to the icon.menu property. You must cast the
object to the SystemTrayIcon class to access the menu property.
if(Shell.supportsSystemTrayIcon){
Shell.shell.icon.bitmaps = new AIRMenuIcon().bitmaps;
SystemTrayIcon(Shell.shell.icon).tooltip = "AIR Menus";
SystemTrayIcon(Shell.shell.icon).menu = createRootMenu();
}
Be careful about using SystemTrayIcon properties on the wrong operating system. An Mac OS X, for example, the
Shell.shell.icon object is of type, DockIcon. Attempting to set the tooltip would generate a runtime error.
A context menu can have commands, submenus, and separators in the root menu.
A pop-up menu can have commands, submenus, and separators in the root menu.
ADOBE PRODUCT X.0 50
User Guide
Select events also bubble up through the menu hierarchy. Each parent menu in the chain will also dispatch a select
event. The target property of the event object will be the NativeMenuItem object of the selected command; the
currentTarget property will be the NativeMenu object of the current menu.
This example responds to each select event by adding a line describing the event to the TextField in the window.
private function itemSelected(event:Event):void{
textDisplay.appendText(selectCount++ + ". Selected item: "
+ event.target.label + "\n");
}
Also available, but not used in this example are displaying events. Displaying events are dispatched by a menu just
before it is displayed. You can use displaying events to update the menu or items within it to reflect the current state
of the application. For example, if your application used a menu to let users open recently viewed documents, you
could update the menu to reflect the current list inside the handler for the displaying event.
51
File Description
WordUp.as The main application file. Listens for message events from the MessageCenter and passes the
message to the DisplayManager for display.
WordUpIcon.as Extends the Icon class to embed the icon assets for this application.
WordUp-app.xml The application descriptor file. See “Setting application properties” on page 62.
display/MessageWindow.as Extends the NativeWindow class to create a toast-style window displaying a text message.
messages/MessageCenter.as Dispatches message events. (In WordUp the messages are random text strings and dispatched on
a timer interval.)
icons/WordUpIcon16.png Sample icon files used both for the desktop application icon and the system tray or dock icon.
icons/WordUpIcon32.png
icons/WordUpIcon48.png
icons/WordUpIcon128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/WordUp.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
To initialize the application logic, WordUp creates a new DisplayManager object, which manages the pop-up toast
windows, and a new MessageCenter object, which periodically generates an event containing a random message:
displayManager = new DisplayManager();
messageCenter = new MessageCenter();
messageCenter.addEventListener(MessageCenter.NEW_MESSAGE, onMessage);
The onMessage() event handler function passes the message text to the display manager, which creates a new
message window.
Since the initial window created by AIR is not needed, ideally it could be closed. However, there is a defect in this
Beta release of AIR that results in the system tray icon disappearing if the initial window is closed.
Shell.shell.autoExit = false;
//stage.nativeWindow.close();
}
These options define a window with no system chrome and which won’t appear on the Windows taskbar or OS X
windows menu. In addition, the window alwaysInFront property is set to true so that the message will appear
above other windows.
To regulate the life span of a message window, the window listens to custom lifeTick events from the DisplayManager
object:
manager.addEventListener(DisplayManager.LIFE_TICK,lifeTick,false,0,true);
When this event is dispatched, the window decrements its time-to-live counter. When the counter reaches zero, the
window closes itself (removing the event listener to aid garbage collection):
public function lifeTick(event:Event):void{
timeToLive--;
if(timeToLive < 1){
close();
}
}
The MessageWindow class overrides the close() method so that if the message window is closed in response to a
mouse event, the event listener will also be removed.
In response to these events, WordUp suspends or restarts the DisplayManager timer that dispatches lifeTick events
to the message windows:
//When the computer is idle, don't remove the messages
private function onIdle(event:Event):void{
displayManager.pauseExpiration();
trace("Idling.");
ADOBE PRODUCT X.0 55
User Guide
In addition, the activate() method will also order the window to the front.
Changing the value of the alwaysInFront property may also change the ordering of a window. For example,
changing the value from true to false will order the window behind any other “alwaysInFront” windows, but still
in front of other windows. When you use the orderInFrontOf() or orderInBackOf() methods, the window will
take on the alwaysInFront setting of the target window.
The window ordering methods return a boolean value that indicates whether the ordering operation succeeded. The
only reason an ordering operation may fail is if the window being ordered is not visible.
File Description
Z.as The main application file. Details of the code are discussed in the Understanding the code section.
Z-app.xml The application descriptor file. See “Setting application properties” on page 62.
window/ZWindow.as Extends the NativeWindow class to customize the behavior of the example windows in the Z
application.
icons/ZIcon32.png
icons/ZIcon48.png
icons/ZIcon128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/Z.zip.
ADOBE PRODUCT X.0 58
User Guide
See also
• “Building the quick-start sample applications with Flex” on page 7
The makeZOrderMenu() method returns a NativeMenu object containing the menu commands and submenus.
The first two items in the menu show the window alwaysInFront and visible settings. To make sure the state of
the menu matches the state of the window, the menu item checked property is updated in response to the menu
displaying event. The displaying event is dispatched immediately before the menu is made visible.
var stateAlwaysInFront:NativeMenuItem =
menu.addItem(new NativeMenuItem("Always in front"));
stateAlwaysInFront.addEventListener(Event.SELECT, toggleAlwaysInFront);
var stateVisible:NativeMenuItem = menu.addItem(new NativeMenuItem("Visible"));
stateVisible.addEventListener(Event.SELECT, toggleVisibility);
menu.addEventListener(Event.DISPLAYING, function(event:Event):void{
stateAlwaysInFront.checked = alwaysInFront;
stateVisible.checked = visible;
});
Separator items are created by setting the isSeparator parameter to true in the item constructor.
menu.addItem(new NativeMenuItem("",true));//separator
Command items are added by adding an item with the appropriate label and attaching an event listener that carries
out the command. For example, the following statement adds the activate command:
var commandActivate:NativeMenuItem = menu.addItem(new NativeMenuItem("Activate"));
commandActivate.addEventListener(Event.SELECT, activateCommand);
Since the menu is defined in the window itself, there is no need to determine which window the command should
be applied to. However, for the “Order in front of ” and “Order behind” commands, the second window needed for
the command must be identified. To do this, the ZWindow object is assigned to the menu item data property when
a window submenu is populated.
The Z application creates a submenu containing an item for each of the orderable windows:
var submenuOrderInFront:NativeMenuItem =
menu.addSubmenu(createWindowSubmenu(),"Order in front of");
submenuOrderInFront.submenu.addEventListener(Event.SELECT, orderInFrontCommand);
The items in the submenu are added by the displayWindows() method by looping through the static
ZWindow.zWindows array, which contains every instance of a ZWindow.
To make it easier to access the ZWindow object for the windows listed in the menu, the window object is assigned
to the menu item data property. The data property is of type object, so you can assign any object to it. This allows
the assigned object to be accessed through the event object target property when handling the menu item select
event:
private function orderInFrontCommand(event:Event):void{
orderInFrontOf(event.target.data as ZWindow);
}
60
File Description
Launcher.as A stub class that creates the main application window and closes.
Launcher-app.xml The application descriptor file. See “Setting application properties” on page 62.
window/ClippedStage.as Extends the Sprite class to create a content container that clips anything outside the window
client area.
window/GeometryUtils.as A utility class providing some functions for calculating geometric relationships.
icons/!SquareIcon32.png
icons/!SquareIcon48.png
icons/!SquareIcon128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/!Square.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addChild(clippedStage);
addWindowDressing();
addEventListener(NativeWindowBoundsEvent.RESIZE,onBoundsChange);
draw(viewWidth,viewHeight);
activate();
}
ADOBE PRODUCT X.0 62
User Guide
The grippers are arranged around the border at preset angles, so the angle is known. The width and height of the
ellipse is the width and height of the window for the outer edge of the window border (viewWidth and viewHeight),
and the width and height minus the thickness of the border for the inner edge of the window border.
The drawing routine uses this formula to calculate the x and y coordinates of the four corners of the gripper, points
A, B, C, and D:
var A:Point = new Point();
A.x = Math.cos(startAngle) * viewWidth/2;
A.y = Math.sin(startAngle) * viewHeight/2;
var B:Point = new Point();
B.x = Math.cos(startAngle) * (viewWidth-40)/2;
B.y = Math.sin(startAngle) * (viewHeight-40)/2;
var C:Point = new Point();
C.x = Math.cos(stopAngle) * (viewWidth-40)/2;
C.y = Math.sin(stopAngle) * (viewHeight-40)/2;
var D:Point = new Point();
D.x = Math.cos(stopAngle) * viewWidth/2;
D.y = Math.sin(stopAngle) * viewHeight/2;
The start and stop angles are calculated from the preset gripper angle, plus and minus the angular width of the
gripper. Defining these quantities as angles rather than lengths makes the math a bit easier and also provides a more
pleasing effect when the window is resized since the gripper size stays proportional to the border size.
var startAngle:Number = (angleRadians - spreadRadians);
var stopAngle:Number = (angleRadians + spreadRadians);
The routine next draws the shape of the gripper between the four points:
Next, a series of line segments is drawn between B and C. If enough segments are used, then the visual effect is indis-
tinguishable from an actual curve. !Square uses ten segments, which seems sufficient.
for(var i:int = 1; i < 10; i++){
lineTo(Math.cos(startAngle + i * incAngle) * (viewWidth-40)/2,
Math.sin(startAngle + i * incAngle) * (viewHeight-40)/2);
}
Another straight line is drawn from C to D and the shape is closed by drawing a polyline segment from D back to A.
The shape is started with the beginBitmapFill() method so when endFill() is called the area defined by the
drawing commands is filled with a bitmap texture.
ADOBE PRODUCT X.0 64
User Guide
The class also listens for resize events from the parent window and responds by redrawing the clipping mask based
on the new window dimensions.
private function onResize(event:NativeWindowBoundsEvent):void{
setClipMask(event.afterBounds);
}
This type of clipping is not limited to simple shapes, so the technique can be used for any window that has areas
which should be masked.
Don’t forget to clear the graphics before drawing the new border.
Since the content is always animated, it does not need to be redrawn by the resize listener. Redrawing will occur on
the next frame event anyway. For non-animated content, you may need to resize or reposition the window content
objects directly.
66
File Description
Screens.as The main application file. Details of the code are discussed in the Understanding the code section.
Screens-app.xml The application descriptor file. See “Setting application properties” on page 62.
icons/ApolloApp_32.png
icons/ApolloApp_48.png
icons/ApolloApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/.
See also
• “Building the quick-start sample applications with Flex” on page 7
The Screen object for the operating-system designated main screen can be accessed using the static mainScreen
property of the Screen class.
To draw the screens, the drawScreenRepresentation() method loops through the screens and draws a rectangle
for the entire screen and another for the usable area:
with(graphics){
//Draw screen rectangle
beginFill(screenColor,.5);
drawRect(screen.bounds.left,
screen.bounds.top,
screen.bounds.width,
screen.bounds.height);
endFill();
The method also draws several labels. To avoid having to add and remove TextField objects on each animation frame,
The labels are drawn into a bitmap with the BitmapData.draw() method. The resulting label bitmaps are drawn to
the main sprite using a bitmap fill.
ADOBE PRODUCT X.0 69
User Guide
If the window is somehow off any screen, the main screen is returned.
To find the proper screen to which to move the window, the array of screens is vertically or horizontally sorted and
then the relevant coordinates are compared by walking through the sorted array. The following method moves the
window to the left:
/*Moves the window to the next screen to the left*/
private function moveLeft():void{
var currentScreen:Screen = 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;
}
}
}
The sort method called above uses the following sorting function to compare screen coordinates:
ADOBE PRODUCT X.0 70
User Guide
Dock icons
Dock icons provide a means for users to easily access applications. An application icon is shown in the dock
whenever the application is running. At the user’s discretion the icon can be kept in the dock even when the appli-
cation is not running. The image used for the icon in both cases is the icon specified in the application descriptor
file. When your application is running, you can change the icon image by setting the Shell.shell.icon.bitmaps
property. When the application shuts down, the icon, if left in the dock, will revert back to the original image.
In addition to setting the icon image, you can add a menu to the dock icon. When you add a menu, the items are
displayed above the standard, operating-system provided menu.
Although you cannot listen for mouse events on the dock icon directly, an invoke event is dispatched by the Shell
object whenever the user clicks on the dock icon.
System tray icons support a menu, a tooltip, and will dispatch events for mouse events.
File Description
Stopwatch.as The main application file. Details of the code are discussed in the Understanding the code section.
Stopwatch-app.xml The application descriptor file. See “Setting application properties” on page 62.
Clock.as Defines the clock control used to set and display the timer.
icons/StopWatchIcon32.png
icons/StopWatchIcon48.png
icons/StopWatchIcon128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/Stopwatch.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7
• changeIcon() updates the icon to reflect the current visual state of the stopwatch.
The application defines two sets of functions for these operations, one for Windows and one for Mac OS X. When
the application is initialized at run time, the dock, undock, and changeIcon function objects are set to the version
designed for the current operating system.
On Mac OS X, the function references are set and a listener is added to detect when the user clicks on the dock icon:
dock = OSXdock;
undock = OSXundock;
changeIcon = OSXchangeIcon;
Shell.shell.addEventListener(InvokeEvent.INVOKE,onIconClick);
Clicks on the dock icon can be detected by listening to Shell invoke events.
On Windows, the function references are set, a tooltip is added and then a click event listener is added directly to the
system tray icon object:
dock = DOSdock;
undock = DOSundock;
changeIcon = DOSchangeIcon;
SystemTrayIcon(Shell.shell.icon).tooltip = "Stopwatch";
SystemTrayIcon(Shell.shell.icon).addEventListener(MouseEvent.CLICK, onIconClick);
To create a transparent icon image, the new BitmapData object must be created with the transparent parameter of
its constructor set to true. In addition, the fill color should be set using the 32-bit ARGB color value, setting the
alpha component to 0, for example, in hexadecimal format, you could use: 0x00ffffff.
On Windows, the system tray icon is so small that the animation effect is too subtle. To compensate, a color
transform is used to invert the colors of the icon for every other frame.
public function DOSchangeIcon():void{
var matrix:Matrix = new Matrix(16/clock.width,0,0,16/clock.height);
var icon:BitmapData = new BitmapData(16,16,true,0x00ffffff);
if(alternate){
icon.draw(clock.bitmapData,matrix,null,null,null,true);
} else {
icon.draw(clock.bitmapData,matrix,invert,null,null,true);
}
Shell.shell.icon.bitmaps = [icon];
alternate = !alternate;
}
}
75
Once the application’s data displays on the screen, there is no additional user interaction available. This is inten-
tional, in order to focus the application entirely on the database operations.
ADOBE PRODUCT X.0 76
User Guide
File Description
SimpleDBExampleFlex.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the code”
on page 76.
icons/AIRApp_32.png
icons/AIRApp_48.png
icons/AIRApp_128.png
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/SimpleDBExampleFlex.zip.
See also
• “Building the quick-start sample applications with Flex” on page 7.
In this case null is passed as an argument to the open() method, indicating that the runtime will create a new
database in the computer’s memory rather than in a disk location. Alternatively, you could specify a file location
(using a File instance). The runtime would then open the database file at that location (creating it first if it doesn’t
exist). The code to do that would look like this:
var dbFile:File = File.applicationStorageDirectory.resolvePath("DBSample.db");
conn.open(dbFile);
ADOBE PRODUCT X.0 77
User Guide
File.applicationStorageDirectory points to the AIR application store directory, which is uniquely defined for
each AIR application.
Assuming the open() operation succeeds and the database connection opens, the openSuccess() method is called.
That method simply performs the clean-up operation of removing the event listener registrations, and calls the
createTable() method that does the work of creating a table in the database.
2 Specifies that the statement will execute on the database that’s connected through the SQLConnection instance
conn:
createStmt.sqlConnection = conn;
3 Defines the SQL statement text to create a database table. The table is named “employees.” It has four columns:
“empId,” “firstName,” “lastName,” and “salary.”
var sql:String = "";
sql += "CREATE TABLE IF NOT EXISTS employees (";
sql += "empIdINTEGER PRIMARY KEY AUTOINCREMENT,";
sql += "firstNameTEXT,";
sql += "lastNameTEXT,";
sql += "salaryNUMERIC CHECK (salary >= 0) DEFAULT 0";
sql += ")";
createStmt.text = sql;
4 Registers event listeners to specify the methods that are called when the statement finishes executing
(createResult) or fails (createError):
createStmt.addEventListener(SQLEvent.RESULT, createResult);
createStmt.addEventListener(SQLErrorEvent.ERROR, createError);
Assuming the statement runs successfully, the “employees” table is created and the createResult() method is
called. That method removes the registered listeners and calls the addData() method to perform the next step in
the process, adding data into the newly-created table.
insertStmt.text = sql;
insertStmt.addEventListener(SQLEvent.RESULT, insertResult);
insertStmt.addEventListener(SQLErrorEvent.ERROR, insertError);
insertStmt.execute();
insertStmt2.addEventListener(SQLEvent.RESULT, insertResult);
insertStmt2.addEventListener(SQLErrorEvent.ERROR, insertError);
insertStmt2.execute();
Note that because the second statement execution doesn’t depend on the result of the first one, the second
SQLStatement instance is created and its execute() method is called immediately after the first instance’s
execute() method is called. (As opposed to waiting for the result event of the first INSERT statement before
executing the second one.) The runtime queues up these two statements, executing the second one immediately
after the first one completes.
The only complicating factor is that the code needs to determine that both statements have completed before it
moves on to retrieve data from the database. In order to do this, in the insertResult() method (which is called
when either SQLStatement’s result method is triggered) the application determines which statement finished
executing, then checks whether both statements have finished executing. If they have, the getData() method is
called to retrieve the data from the database and display it on the screen:
private function insertResult(event:SQLEvent):void
{
var stmt:SQLStatement = event.target as SQLStatement;
stmt.removeEventListener(SQLEvent.RESULT, insertResult);
stmt.removeEventListener(SQLErrorEvent.ERROR, insertError);
if (stmt == insertStmt)
{
insert1Complete = true;
}
else
{
insert2Complete = true;
}
selectStmt.addEventListener(SQLEvent.RESULT, selectResult);
selectStmt.addEventListener(SQLErrorEvent.ERROR, selectError);
selectStmt.execute();
As specified in the code, when the SELECT statement finishes executing the selectResult() method is called. In
selectResult(), the result data that is retrieved by the SELECT statement is accessed by calling the SQLStatement
instance’s getResult() method. Calling getResult() returns a SQLResult instance that is stored in the variable
result; the actual result rows are contained in an array in its data property. The results are displayed in the Flex
DataGrid control named resultsGrid by setting it (that is, the result.data property) as the resultsGrid data
grid’s dataProvider property:
private function selectResult(event:SQLEvent):void
{
// ... clean up ...
This application uses a specific compressed file format known as the gzip compressed file format. The specification
describing this format is available in IETF RFC 1952 (http://www.ietf.org/rfc/rfc1952).
ADOBE PRODUCT X.0 81
User Guide
File Description
FileCompressionTool.mxml The main application file in MXML for Flex. Details of the code are discussed in “Understanding the code”
on page 81.
controls/CompressScreen.mxml MXML file defining the layout and functionality of the “compress a file” screen
controls/DecompressS- MXML file defining the layout and functionality of the “decompress a file” screen
creen.mxml
icons/AIRApp_32.png
icons/AIRApp_48.png
icons/AIRApp_128.png
Files that perform compression and decompression operations (in folder “GZIPEncoder/com/probertson/utils/”)
GZIPEncoder.as A GZIPEncoder instance can be used to compress a file into a gzip compressed format file or decompress
a gzip compressed format file into a ByteArray or File object.
GZIPFile.as A GZIPFile instance represents a single gzip compressed format file, with properties for the various meta-
data as well as the actual source data in the compressed file.
CRC32Generator.as A CRC32Generator instance is used to generate a CRC-32 value, which is used to verify that the uncom-
pressed data extracted from a gzip compressed file is not modified or damaged from its original, pre-
compression content. The CRC-32 check is used in the gzip compression format.
You can download the source files for this example at http://download.macro-
media.com/pub/labs/air/quickstart_apps/b2/FileCompressionTool.zip.
Note: The files in the “GZIPEncoder/com/probertson/utils/” folder are from the open-source “ActionScript GZIP
compression library” written by H. Paul Robertson and are available at http://probertson.com/projects/gzipencoder/ in
addition to being included as part of the downloadable source file described in the preceding paragraph.
For help on building this quick start sample application,
See also
• “Building the quick-start sample applications with Flex” on page 7.
import flash.utils.ByteArray;
import flash.utils.CompressionAlgorithm;
Although the data is now compressed, only half the process of creating a compressed-format file is complete. In
addition to containing raw compressed data, each compression format (such as zip, gzip, etc.) stores extra infor-
mation about the compressed data within the compressed data file. What makes each compressed file format unique
is the definition of the specific way that a file is structured, including what extra information is stored along with the
compressed data and how the bundle of data and extra information is organized. For instance, the gzip compressed
format specifies that gzip-formatted data (for example, a gzip file) contains certain identifiers indicating the
compression format and compression algorithm used, information about the date and time that the compression
took place, the operating system on which the compression took place, and so forth, in addition to containing the
actual compressed data.
If you are writing code to create or parse files that are structured using a particular compressed file format, you need
to understand the distinction between the actual compressed data (which the runtime can create or extract for you
using ByteArray.compress() and ByteArray.uncompress()) and the structure of the compressed data, which
your code will need to create or read. For examples of how this is done in the File Compression Tool sample, see the
GZIPEncoder.compressToFile() method for creating a file in gzip compression format, and the
GZIPEncoder.parseGZIPFile() method for parsing a gzip compression format file into its parts.
outStream.close();
}
Although the compressToFile() method includes some additional complexity for dealing with creating the output
file and writing the extra information that’s part of the gzip compression format, the core function of compressing
the data and adding it to the gzip file is performed by these two lines:
srcBytes.compress(CompressionAlgorithm.DEFLATE);
outStream.writeBytes(srcBytes, 0, srcBytes.length);
The ByteArray instance named srcBytes contains the data to be compressed (loaded from the user-selected source
file). The compress() method is called with the CompressionAlgorithm.DEFLATE argument, so all the bytes in
srcBytes are compressed using the DEFLATE compression algorithm. At that point srcBytes contains the
compressed version of the data (the original content is replaced). That data is then written to the destination file (the
gzip file that’s being created) in the appropriate part of the file as specified in the gzip compression format. The
entire srcBytes ByteArray is written to the output file stream using the outStream variable’s writeBytes()
method—the three arguments indicate that the data to write comes from srcBytes, starting at position 0 in
srcBytes, and going to the final position of srcBytes (indicated by srcBytes.length).
// call the parseGZIPFile method, which extracts the gzip file into a
// GZIPFile instance with properties representing the parts of the gzip file
var gzipData:GZIPFile = parseGZIPFile(src);
The step of converting the compressed data to uncompressed data takes place in this line:
data.uncompress(CompressionAlgorithm.DEFLATE);
Once the uncompress() method is called, the compressed content of the data ByteArray instance is uncompressed
and the data variable then contains the uncompressed data, ready to be written to the destination file.
1
Index
A D browseForDirectory()
adobe-app URL scheme 105 deleteDirectory() method (File method 103
application storage director 105 class) 108 browseForOpen() method 104
application store directory 102 deleteDirectoryAsync() method browseForSave() method 104
(File class) 108 copyTo() method 110
app-storage URL scheme 105
deleteFile() method (File class) 111 copyToAsync() method 110
appStoreDirectory property (File
class) 102 deleteFileAsync() method (File createDirectory() method 107
class) 111
asynchronous methods 101 createTempDirectory()
deleting directories 108, 111 method 107, 111
deleting files 111 createTempFile() method 111
B
desktop directory 102 creationDate property 109
browseForDirectory() method
(File class) 103 desktopDirectory property (File creator property 109
class) 102
browseForOpen() method (File deleteDirectory() method 108
class) 104 directories 102, 107
deleteDirectoryAsync()
browseForSave() method (File copying 108 method 108
class) 104 creating 107 deleteFile() method 111
browsing to select a directory 103 deleting 108, 111 deleteFileAsync() method 111
browsing to select a file 104 enumerating 108 desktopDirectory property 101
moving 108 documentsDirectory
C referencing 102 property 101
clearing directories 108 directory chooser dialog boxes 103 encoding property 106
copying directories 108 documents directory 102 exists property 109
copying files 110 documentsDirectory property isDirectory property 109
copyTo() method (File class) 110 (File class) 102 lineEnding property 106
copyToAsync() method (File listDirectory() method 108
class) 110 E listDirectoryAsync()
createDirectory() method (File encoding property (File class) 106 method 108
class) 107 enumerating directories 108 listRootDirectories method 101
createTempDirectory() method exists property (File class) 109 modificationDate property 109
(File class) 107, 111
moveTo() method 110
createTempFile() method (File
class) 111 F moveToAsync() method 110
creating directories 107 file API 100 moveToTrash() method 111
creationDate property (File file chooser dialog boxes 104 moveToTrashAsync()
class) 109 File class 100, 101 method 111
creator property (File class) 109 appStoreDirectory property 101 name property 109
2 INDEX
deleting 111 N
moving 110 name property (File class) 109
reading 112 nativePath property (File
class) 102, 109
referencing 103
writing 112
P
FileStream class 100
parent property (File class) 109
path delimiter (file system) 103
H
paths (file and directory) 105
home directory 102
paths, relative 105
I
R
isDirectory property (File
class) 109 reading files 112
relative paths (between files) 105