Adobe AIR for JavaScript Developers Pocketguide

English, 1.0

APIs : Markdown | HTML

Chapter 3 : Working with JavaScript and HTML Within Adobe AIR

This chapter provides an overview of the HTML and JavaScript environments within Adobe AIR. It discusses:

  • The use of the open source WebKit HTML-rendering engine within Adobe AIR
  • JavaScript functionality within Adobe AIR
  • Security Model
  • Working with Adobe AIR, Flash Player and ActionScript APIs from JavaScript
  • Troubleshooting AIR Applications written with HTML and JavaScript

Once you have completed this chapter, you should have a solid understanding of the HTML and JavaScript environments within Adobe AIR. You should also understand how to work with AIR and ActionScript APIs within HTML and JavaScriptbased applications.

WebKit Within Adobe AIR

Adobe AIR leverages the open source WebKit-rendering engine to add support for rendering HTML content to the runtime.

In addition to HTML rendering, WebKit also provides support for associated web technologies, such as (but not limited to):

  • JavaScript
  • XMLHttpRequest
  • CSS
  • XHTML
  • W3C DOM Level 2 support

Essentially, Adobe AIR has a full HTML rendering engine, and includes support for all of the same technologies that can be used when developing web applications and content targeting the web browser. Developers can build full- featured AIR applications that leverage these technologies.

NOTE

You can find more information on the WebKit project at: http://www.webkit.org.

Why WebKit?

Adobe spent a considerable amount of time researching which HTML engine to use within Adobe AIR and used a number of criteria that ultimately led them to settle on WebKit.

Open project

Adobe knew from the very beginning that it did not want to create and maintain its own HTML rendering engine. Not only would this be an immense amount of work, but it would also make it difficult for developers, who would then have to become familiar with all of the quirks of yet another HTML engine.

WebKit provides Adobe AIR with a full-featured HTML engine that is under continuous development by a robust development community that includes individual developers as well as large companies such as Nokia and Apple. This allows Adobe to focus on bug fixes and features, and also means that Adobe can actively contribute back to WebKit, while also taking advantage of the contributions made by other members of the WebKit community.

Proven technology that web developers know

As discussed earlier, one of the biggest problems with complex web application development is ensuring that content works consistently across browsers. While something may work perfectly in Firefox on the Mac, it may completely fail in Internet Explorer on Windows. Because of this, testing and debugging browser- based content can be a nightmare for developers.

Adobe wanted to ensure that developers were already familiar with the HTML engine used within Adobe AIR so they did not have to learn all of the quirks and bugs of a new engine. Since Safari (which is built on top of WebKit) is the default browser for Mac OS X (and is also available on Windows), developers should be familiar with developing for WebKit.

Minimum effect on AIR runtime size

The size of Adobe AIR is approximately 11 MB on Windows and approximately 16 MB on MAC. The WebKit code base was well written and organized and has had a minimal impact on the final AIR runtime size.

Proven ability to run on mobile devices

While the first release of Adobe AIR runs only on personal computers, the long-term vision is to extend Adobe AIR from the desktop to cell phones and other devices. WebKit has a proven ability to run on such devices and has been ported to cell phones by both Nokia and Apple.

WebKit version used within Adobe AIR

The version of WebKit included in Adobe AIR 1.0 is based off the WebKit mainline version 523.15.

Some changes were applied to this version in order to support AIR's own rendering pipeline and enforce some security restrictions (please check the "AIR Implementation of Functionality" and the "Security" subchapters to find more details about the differences).

The User Agent reported when running in Adobe AIR in Windows is:

Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, like Gecko) AdobeAIR/1.0

and on Mac:

Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWeb Kit/420+ (KHTML, like Gecko) AdobeAIR/1.0

Overall, developers should expect code running in Safari 3 to also work in Adobe AIR, with the exceptions of the differences discussed in this chapter.

JavaScript within Adobe AIR

Adobe AIR has full support for JavaScript within HTML content. JavaScript 1.5, which corresponds to ECMA-262 is supported.

The JavaScript engine is implemented via WebKit, and works the same as it does within WebKit-based browsers. In addition to having access to the HTML DOM, JavaScript can also access AIR and Flash Player APIs directly via the window.runtime property. This will be discussed in more detail later.

NOTE

For an in-depth introduction and discussion of Java-Script, check out JavaScript: the Definitive Guide: 5th Edition, published by O'Reilly:

http://www.oreilly.com/catalog/jscript5/

AIR Implementation of Functionality

HTML and JavaScript functionality is consistent with that found in other WebKit-based projects and browsers, such as Apple's Safari browser. When exploring documentation on HTML engine / browser functionality, you can use references to the Safari 3 browser as an indicator of the functionality available within the HTML environment within AIR.

However, because the HTML engine is running within Adobe AIR, and not a browser, there are a few differences that are useful to understand before beginning development with HTML and JavaScript within Adobe AIR.

URI Schemes

Working with Universal Resource Identifiers (URIs) within HTML content in AIR applications is largely the same as working with URIs within the browser. This section gives a quick overview of working with URIs within HTML content in AIR applications, and introduces some new URIs made available by the runtime.

Supported URI schemes

Adobe AIR provides support for the most common URI schemes available within the browser

Table 3-1. Supported URI schemes

URI Description Example
http:// URI that points to a resource accessed via the standard HTTP protocol. http://www.adobe.com
https:// URI that points to a resource accessed via a protocol encrypted with SSL/TLS. https://secure.example.com
file:// URI that points to a resource on the local or a networked file system. file:///c:/Test/test.txt
mailto: URI that opens the default email ap-mailto:john.doe@example.com plication. mailto:john.doe@example.com

Unsupported URI schemes

The feed:// and data:// URI schemes are not supported by Adobe AIR 1.0, and there is only partial support for the ftp:// scheme.

Finally, the javascript: URI scheme is not supported within applications running within the Adobe AIR application sandbox. Please check the Security model section later is this chapter for more details.

AIR URI Schemes

Adobe AIR also provides a number of additional URIs that makes it easy to reference files and content within specific areas of the users system.

Table 3-2. Adobe AIR URI schemes

URI Description Example
app:/ Provides a reference to the root content directory of the application. This should be used when referencing content included within the AIR file. app:/images
app-storage:/ Provides a reference to an application-specific storage area on the user’s system. This area is useful for storing user-specific application settings and content. app-storage:/settings/pref.xml

NOTE

The AIR-specific URIs take only a single slash, versus two slashes in the other URIs.

Within HTML content, these URI schemes can be used anywhere within HTML and JavaScript content where regular HTTP URIs are used.

Relative URLs

You're not restricted to using just absolute URLs within AIR applications. You can also use relative URLs, but it is important to remember that relative URLs within AIR applications are relative to the application, and not to a server (as they would be when doing traditional browser-based client/server development).

Relative URLs will be relative to the root of the application, and will resolve to the app:/ URI.

For example:

<img src="foo/image.png" />

will resolve to:

<img src="app:/foo/image.png" />

You should keep this in mind when moving web and browser-based content and code into an AIR application.

Cookies

Adobe AIR has full support for setting and getting cookies from HTML-based content in remote sandboxes (content loaded from http:// and https:// sources) that is bound to a specific domain. Content loaded from the installed directory of the application (referenced via app:/ scheme) cannot use cookies (the document.cookie property).

Cookie support is implemented via the operating system's networking stack. This means that AIR applications can share cookies set by any browser or application that also leverage the operating system stack.

For example, AIR applications can share cookies set through Internet Explorer on Windows, and Safari on Mac, as they both also use the operating system's cookie storage functionality. Firefox implements its own cookie storage and thus cookies set within Firefox cannot be shared with AIR applications

NOTE

In addition to cookies, AIR applications have a number of other APIs that can be used to persist data, including the file API, as well as the embedded database API.

Windowing

Windows

You can create new windows via JavaScript just as you can within the browser.

myWindow = window.open("Window.html", "myWindow", "height=400,width=400");

However, the runtime property that provides access to AIR and Flash Player APIs is not automatically available within the new window. In order to make it available, you must explicitly place it within the scope of the new window like so:

window.runtime = window.opener.runtime;

You can also create native windows using apis provided by AIR. The HTMLLoader class includes a static method, HTMLLoader.createRootWindow(), which lets you open a new window (represented by a NativeWindow object) that contains an HTMLLoader object and define some user interface settings for that window. The method takes four parameters, which allow you to define the user interface.

var initOptions = new runtime.flash.display.NativeWindowInitOptions();
var bounds = new runtime.flash.geom.Rectangle (10, 10, 600, 400);
var myHtml= runtime.flash.html.HTMLLoader.createRootWindow(true, 
                                                    initOptions, true,bounds); 
var urlReq = new runtime.flash.net.URLRequest("http://www.example.com");
myHtml.load(urlReq);

Windows created by calling createRootWindow() directly in JavaScript remain independent from the opening HTML window. The JavaScript window opener and parent properties, for example, are null.

Dialogs

The alert, confirm and prompt HTML dialogs are also supported within Adobe AIR.

In addition, the file-browse dialog created via:

<input type="file" />

is also supported in Adobe AIR 1.0.

XMLHttpRequest and Ajax

The XMLHttpRequest object, which enables the use of Ajax techniques for sending and loading data, is completely supported within AIR applications.

One advantage to developing Ajax applications within Adobe AIR versus the browser is that because you have a consistent runtime to target across operating systems, you do not have to worry about cross-browser, platform inconsistencies in how the API is implemented.

The primary benefit of this is that you have to write only one version of the code.

Here is a simple example of an XMLHttpRequest object call within an AIR application that works regardless of which operating system the application is running on:

<script type="text/javascript">
    var xmlhttp;
    function appLoad()
    {
        //replace with URL to resource being loaded var url = "http://www.mikechambers.com/blog/"; 
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", url,true);
        xmlhttp.onreadystatechange=function()
        {
            if (xmlhttp.readyState==4) 
            {
                runtime.trace(xmlhttp.responseText);
            } 
        }
        xmlhttp.send(null)  
    } 
</script>

When called, this function uses the XMLHttpRequest object to load the specified URL and prints its contents out to the command line. The main thing to note in this example is that because the runtime is known and it is consistent across operating systems, you do not have to detect the existence of, or in the implementation of XMLHttpRequest as you would when deploying in the browser.

Both synchronous and asynchronous XMLHttpRequest calls are supported, as is loading data across domains.

Canvas object

The canvas element is supported by WebKit and also by AIR. It defines APIs for drawing geometric shapes, but in most respects it behaves like an image.

The result of a drop operation when dragging images can be among other types (e.g.: a file reference) a canvas element; it can be displayed by appending the element to the DOM.

Clipboard object

The WebKit Clipboard API is driven with the following events: copy, cut, and paste. The event object passed in these events provides access to the clipboard through the clipboardData property.

You can use the methods of the clipboardData object to read or write clipboard data.

For more details on how to do these operations, please check the cookbook chapter.

Drag and drop

Drag-and-drop gestures into and out of HTML produce the following DOM events: dragstart, drag, dragend, dragenter, dragover, dragleave, and drop. The event object passed in these events provides access to the dragged data through the data Transfer property. The dataTransfer property references an object that provides the same methods as the clipboardData object associated with a clipboard event.

For more details on how to work with drag and drop, please check the cookbook chapter.

Supported plug-ins

Adobe AIR does not support other plug-ins except Acrobat or Adobe Reader 8.1+ for displaying PDF content and Flash Player plug-in for displaying SWF content.

In order to load Flash content into HTML, you use the same embed element syntax that you use when embedding Flash content within a browser page.

<embed
    src="content.swf"
    quality="high"
    bgcolor="#FFFFFF"
    width="400"
    height="200"
    name="content"
    swLiveConnect="true"
    align="bottom"
    allowScriptAccess="always"
    type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />

NOTE

You can load both relative and absolute URLs, with relative URLs being relative to the application install directory.

You can use the same techniques that you use in the browser, such as the ExternalInterace API, to facilitate Flash to HTML and HTML to Flash communication within HTML content.

For the SWF content, the Flash Player plug-in is built into AIR and doesn't need to use an external plug-in.

Unsupported functionality

The window.print() method is not supported within Adobe AIR 1.0. There are other methods available via the exposed AIR APIs that give you access to printing within the runtime, but these might feel different from what is available at the browser level.

In addition, support for Scalable Vector Graphics (SVG) is not included in AIR 1.0.

Security Model

This section discusses a number of differences in the security model implementations when running content within Adobe AIR, versus running it in the browser.

Why a different security model?

Adobe AIR enables Ajax and Flash/Flex developers to use their existing skills to build and deploy desktop applications. Although these applications are built using web technologies, the key thing to keep in mind is that the end result is targeted for running on desktop, and thus the security model for AIR is much closer to that of a desktop application than of a web application.

A desktop application has high privileges compared to a web application as it is installed by the user on a specific machine, implying a degree of trust that is greater than that of arbitrary web content. Unfortunately there are design and implementation patterns common to web applications that can be dangerous when combined with the local system access or other AIR APIs available.

Adobe AIR Sandboxes

The runtime provides a comprehensive security architecture that defines permissions according to each file in an AIR application. Permissions are granted to files according to their origin, and are assigned into logical security groupings called sandboxes.

Application sandbox

The application sandbox provides access to all Adobe AIR APIs, including those that provide access to the user's system.

When an application is installed, all files included within an AIR installer file are copied onto the user's computer into an application directory. Developers can reference this directory in code through the app:/ URI scheme. All files within the application directory tree are assigned to the application sandbox when the application is run.

When running within the application sandbox, some potentially dangerous patterns that are allowed in the browser, are restricted. The things that are disabled revolve around the importing of remote JavaScript content and the dynamic execution/evaluation of JavaScript strings.

NOTE

Please see the Adobe AIR documentation for a complete list of what is and is not allowed within the application sandbox.

Non-application sandbox

The non-application sandbox contains all content that is not loaded directly into the application sandbox. This may include both local and remote content loaded into the application at runtime. Such content does not have direct access to AIR APIs and obeys the same rules that it would have to obey in the browser when loaded from the same location (for example HTML from a remote domain behaves like it would behave in the browser). Because this content doesn't gain direct access to AIR APIs it can call into any code evaluation technique that works in browser, such as eval, loading remote scripts, etc.

Developing within the Sandboxes

Access to the runtime environment and AIR APIs are only available to HTML and JavaScript running within the application sandbox. At the same time, dynamic evaluation and execution of JavaScript, in its various forms, is largely restricted within the application sandbox. These restrictions are in place whether or not your application actually loads information directly from a remote server.

Developing within the application sandbox

Here's an overview of the differences you may run into when coding for application sandbox.

In general, code evaluation restrictions do not apply while code is initializing prior to the onload event. Strings can be turned into executable code via the use of eval or the Function constructor, and attributes are turned into actual event handlers such as:

<input type="button" onclick="doClickBtn();"/>

NOTE

If code execution is prevented due to sandbox security restrictions, the following JavaScript error will be thrown : "Adobe AIR runtime security violation for JavaScript code in the application security sandbox."

Loading remote JavaScript files. HTML files running in application sandbox (loaded from the installed directory of the application) can only import JavaScript files located in the same installed directory via

<script src="file.js" type="text/javascript"></script>

If you must load remote JavaScript, you must either install the file(s) with the application or load it into the non-application sandbox.

Cross-domain content loading. Code running in the application sandbox can load data from any remote domain via XMLHttpRequest. There is no cross domain policy enforced for the code loaded from the application install directory, as there is no domain associated with this code (it uses the AIR specific app:/ scheme to load the files from the installation directory). However, the tradeoff is that the content loaded via XHR can only be used as data; it cannot be transformed into executable code (with one exception explained below).

APIs which allow dynamically generated code to execute are prohibited after the onload event. The table below shows which APIs are restricted when running within the application sandbox:

eval() Prohibited after onload. After the parsing time, you cannot use eval() to transform strings (such as those imported via XHR) into JavaScript code. The exception from this rule is eval() used with a string parameter of type JSON— pure JSON strings can be transformed into actual objects, although JSON code that contains call back functions are not supported.
Function Constructor Prohibited after onload.
setTimeout() Prohibited after onload when using string parameters.
setInterval() Prohibited after onload when using string parameters.
javascript:URLs Prohibited
document.write Prohibited after onload.
innerHTML Code attributes on elements inserted via innerHTML or outerHTML are not transformed into executable code, such as container.innerHTML = '<input type="button" onclick="doClickBtn();"/>';
script.src Setting the src tag of a script element to load remote data / content is prohibited.
XMLHttpRequest

Synchronous calls outside of the application sandbox prohibited prior to onload.

Asynchronous calls initiated in onload always finish after onload, and code evaluation restrictions will be applied to loaded content.

Developing within the non-application sandbox

Everything that is not loaded from the application install directory is loaded into the non-application sandbox.

Code in the non-application sandbox does not have direct access to AIR APIs, and thus does not have the JavaScript code evaluation restrictions applied to it.

Creating a non-application sandbox.

When a file loaded from the application sandbox loads a file from a non-application sandbox (either via the iframe or frametags, or from opening a new window) the loaded content will be placed within the non-application security sandbox, with no direct access to AIR apis.

Adobe AIR also provides a way to load application content into the non- application sandbox. This is done via the sandboxRoot and documentRootproperties on the iframe and frame tags.

<iframe
    src="ui.html"
    sandboxRoot="http://www.example.com/airapp/"
    documentRoot="app:/sandbox/">
</iframe>

This example maps content installed in the "sandbox" subdirectory of the application to run in the remote sandbox bound to www.example.com (http://www.example.com) domain.

The sandboxRoot property specifies the URL to use for determining the sandbox and domain in which to place the iframe content. The file:, http:, or https: URL schemes must be used.

The documentRoot property specifies the directory from which to load the iframe content. The file:, app:, or app-storage: URL schemes must be used.

Differences on code running under non-application sandbox.
  • XMLHttpRequest

    Code in the non-application sandbox is bound by a same-origin policy and, by default, cannot do cross-domain data loading via XMLHttpRequest from any remote URL.

    However, this behavior can be overwritten by setting the allowCrossDomaininXHR attribute to true on the iframe or frame element loading the content.

  • window.open

    The window.open() api only works if it's a direct result of user interaction (such as mouse click or keypress).

  • Window term

    The title of a window opened by non-application content is prefixed with the application title (to prevent windows opened by remote content from spoofing windows opened by the application).

Scripting between sandboxes

The runtime lets you create an interface called Sandbox Bridge between content in a non-application sandbox and its parent document in the application sandbox. This is a bi-directional serialization API designed to allow domains/sandboxes that otherwise cannot trust each other entirely to interact.

Using the Sandbox Bridge.

It is possible for the developer to provide a bridge between application sandboxed content (parent) that loads content (child) into the non-application sandbox. Essentially, the parent can explicitly allow the child to access specific properties and methods that it defines.

The application sandbox content (parent) can set up a property called parentSandboxBridge on the frame or iframe tag, and expose functions by attaching them to this property. These functions can be accessed by the non- application content inside the iframe or frame.

In a similar way, the non-application sandbox-the child-can set up a property called childSandboxBridge on its window object and expose functions to the application sandbox.

In order for a script in a child document to access a function attached to the parentSandboxBridge property, the bridge must be set up before the script is run. A new AIR-specific event called dominitialize is fired when the DOM has been created, but before any scripts have been parsed, or DOM elements added. You can use the dominitialize event to establish the bridge early enough in the page construction sequence that all scripts in the child document can access it. Here is an example:

parent.html

<html>
<head> 
    <script type="text/javascript">

    var bridgeInterface = {}; 
    bridgeInterface.testProperty = "Bridge engaged";
    bridgeInterface.testFunction = function()
    { 
        alert ('testFunction')
    };

    function setupBridge()
    { 
        document.getElementById("sandbox").contentWindow.parentSandboxBridge =bridgeInterface;
    } 

    </script> 
</head>
<body> 

    <iframe id="sandbox"
        src="http://www.example.com/airapp/child.html" 
        documentRoot="app:/"
        sandboxRoot="http://www.example.com/airapp/"
        ondominitialize="setupBridge ()">
    </iframe>
</body> 
</html>

child.html

<html>
<head>
    <script type="text/javascript">

    alert(window.parentSandboxBridge.testProperty);

    </script>
</head>
<body>
</body>
</html>

As a general rule, you should not directly expose AIR apis to content running in the non-application sandbox, but rather should encapsulate the access via a function. This ensures that only specific AIR APIs can be called, and when they are called, are only executed in the manner that you allow.

Table 3-3. Sandboxes capabilities overview

Capability Application sandbox Non-application sandbox
Direct access to AIR APIs Yes No
Access to application sandbox functions that use AIR APIs via the SandboxBridge N/A Yes
Loading remote JavaScript files No Yes
Can, by default, execute cross-domain requests (XHR) Yes No
Supports transforming strings into executable code after the onload event No Yes
Ajax frameworks work by default Noa No

a a Frameworks must add support for Adobe AIR.

For more details on working with the Sandbox Bridge see: http://www.adobe.com/devnet/air/ajax/quickstart/sandbox_bridge.html

Using JavaScript Frameworks

Because of the differences of the security models between content running within the browser, and content running within Adobe AIR, most JavaScript frameworks must explicitly add support for Adobe AIR in order for them to running correctly within an Adobe AIR application.

At the time that the book was authored, all major JavaScript frameworks have added (or are adding) support for Adobe AIR.

JavaScript Frameworks and Libraries supporting AIR application sandbox

Ajax frameworks and libraries compatible with AIR application sandbox at the time of authoring this book

For a complete and up to date list of frameworks that support Adobe AIR please check the AIR product page http://www.adobe.com/products/air/ or the AIR Developer Center for Ajax: http://www.adobe.com/devnet/air/ajax/.

Accessing AIR APIs from JavaScript

In addition to the standard JavaScript and HTML DOM APIs, JavaScript code running within the application sandbox in an AIR application can also take advantage of APIs provided by the runtime, as well as Flash Player APIs and even ActionScript 3 libraries. This greatly extends the capabilities of JavaScript over the APIs available in the browser, and includes functionality such as:

  • Playing sounds
  • Manipulating images and bitmaps
  • Reading and writing files to and from the local file system
  • Reading and writing to and from an encrypted local store
  • Access to a relational local database
  • Creating, controlling and manipulating native windows
  • Creating and working with native menus
  • Making direct socket connections (both binary and text based)
  • Network detection
  • Accessing the clipboard
  • Dragging data between AIR applications and OS or another application
  • File extension registration and running at startup
  • Support for dock and tray icons

NOTE

You can find examples of how to leverage these features in the cookbook section.

This section discusses how to leverage AIR and Flash Player APIs from JavaScript, as well as how to load and leverage compiled ActionScript libraries from within JavaScript.

The JavaScript environment and its relationship with AIR

The following diagram shows the relationship between the two environments.

Only a single native window is shown but an AIR application can contain multiple windows. Also, a single window can contain multiple HTMLLoader objects.

The JavaScript environment has its own document and window objects. JavaScript code can interact with the AIR runtime environment through the runtime, nativeWindow, and htmlLoader properties of window.

The runtime property provides access to AIR API classes; it allows you to create new AIR objects as well as access static members.

The nativeWindow gives you access to the current instance of the NativeWindow that controls the current application window.

The htmlLoader gives you access to the current instance of the HTMLLoader that controls how content is loaded and rendered.

NOTE

Only content that is part of the application sandbox has access to these three properties.

ActionScript code can interact with the JavaScript environment through the window property of an HTMLLoader object, which is a reference to the JavaScript window object.

In addition, both ActionScript and JavaScript objects can listen for events dispatched by both AIR and JavaScript objects.

Figure 3-1

Figure 3-1. JavaScript environment in an AIR application

There is also another important object instance available in any AIR application that is not shown in the diagram. The NativeApplication object provides information about the application state, dispatches several important application-level events, and provides useful functions for controlling application behavior. A single instance of the NativeApplication object is created automatically and can be accessed through the class-defined NativeApplication.nativeApplication property.

To access the object from JavaScript code you could use:

var app = window.runtime.flash.desktop.NativeApplication.nativeApplication;

Accessing AIR and Flash Player APIs

Most AIR and Flash Player APIs are contained within packages (similar to how many Ajax frameworks leverage namespaces and packages). This helps organize the APIs, and also reduces the possibility of naming conflicts. When accessing AIR and Flash Player APIs directly from JavaScript, you must do so via their complete package path and name.

As discussed earlier, all AIR and Flash Player APIs are made available via the window.runtime property. The runtime property is at the root of the runtime environment, and all APIs are relative to this root.

For example, to access an API which is not contained within a package, such as trace you reference it directly from the runtime property, like so:

window.runtime.trace("foo");

However, if you want to access an API that is contained within a package, you must prepend the package path to the API. For example, to access the amount of memory currently used by the application, you can call the totalMemory Flash Player property that is in the flash.system.System class. To call this API from JavaScript:

var mem = window.runtime.flash.system.System.totalMemory;

This also applies when creating new instances of an API class from within JavaScript:

var file = new window.runtime.flash.filesystem.File();

This code creates a new File instance that can be used to work with the file system.

Here is a complete example that shows how to write a file named output.txt to the user's desktop:

//call a static property var desktop =
window.runtime.flash.filesystem.File.desktopDirectory;

//call a function on an instance of a class var file =
desktop.resolvePath("output.txt");

//create a new instance of a class using new var fileStream = new
window.runtime.flash.filesystem.FileStream();

//call a function, passing arguments fileStream.open(file,
window.runtime.flash.filesystem.FileMode.WRITE);

fileStream.writeUTFBytes("Hello World");

fileStream.close();

Don't worry too much about what the code is doing in this example, but rather focus on how the AIR APIs are called from JavaScript.

This allows you to leverage virtually any AIR or Flash Player API from within JavaScript.

By remembering how to use the package structure to call APIs, you can leverage all AIR, Flash Player and ActionScript APIs even if JavaScript-specific documentation is not provided.

Working with AIR and Flash Player Events

Many of the AIR and Flash Player APIs make extensive use of events. Event handling in ActionScript-based APIs is based on the W3C DOM Level 3 event model. This is similar to the W3C DOM Level 2 event model available within JavaScript, but is very different from the callback mechanism often deployed in JavaScript.

In order to be notified when an event from an AIR or Flash Player API occurs, you must register to listen for it. The best way to understand this is to look at an example. The following example registers for a NETWORK_CHANGE event that is broadcast by the NativeApplication instance:

function onNetworkChange(event)
{
    runtime.trace("Network status changed");
}

function onAppLoad()
{
    window.runtime.flash.desktop.NativeApplication.nativeApplication.addEventListener(
    window.runtime.flash.events.Event.NETWORK_CHANGE,
    onNetworkChange
    );
}

As you can see from the example, you register for events broadcast by a class instance by calling the addEventListener function on the class instance. This API requires two arguments.

The first argument is the event name of the event being broadcast. For all AIR and Flash Player APIs, there will be a constant for the event name, which you can find in the documentation.

The second argument is a reference to the function that will handle the event. In this case, the function is named onNetworkChange. Looking at the function, you can see that it is passed an argument with information about the event. Again, all AIR and Flash Player APIs will pass an object to the event handler function, which provides information about the event. You can find the exact type of event object passed to the handler, and the information it provides, by referencing the API documentation.

Using AIRAliases.js file

As the previous examples show, being able to leverage AIR and Flash Player APIs from directly within JavaScript can be very powerful. However, because you must reference the APIs via the runtime property and the complete API package path, it can lead to very verbose code.

In order to make it easier to use some of the more common AIR and Flash Player APIs from within JavaScript, Adobe has created a JavaScript include file, named AIRAliases.js. This file, which can be found in the frameworks directory of the SDK, provides aliases for commonly used APIs to make them more convenient to use from within JavaScript.

To use the aliases file, copy it from the SDK to your application directory (make sure to also package it in your AIR file). You then include it within your application using the script tag in each HTML document that you want to leverage the aliases in.

For example, let's look at the earlier example that writes a file to the desktop, but uses the JavaScript aliases provided in the AIRAliases.js file instead of typing out the complete package paths:

<script src="AIRAliases.js" type="text/javascript"></script>
<script type="text/javascript">
function writeFile()
{
    var desktop = air.File.desktopDirectory;
    var file = desktop.resolvePath("output.txt");
    var fileStream = new air.FileStream();

    fileStream.open(file, air.FileMode.WRITE);
    fileStream.writeUTFBytes("Hello World");
    fileStream.close();
}
</script>

First, notice that the code is much less verbose. This is because instead of having to reference APIs via window.runtime and then the complete package path, we can use the aliases within the include file.

For example, this reduces:

var desktop = window.runtime.flash.filesystem.File.desktopDirectory;

to:

var desktop = air.File.desktopDirectory;

Second, the AIR and Flash Player APIs are placed in a name-space called air. If you open the AIRAliases.js file, you can see how the aliases actually work. For example, here is the code that sets up the File API aliases:

var air; if (!air) air = {};

// file
air.File = window.runtime.flash.filesystem.File;
air.FileStream = window.runtime.flash.filesystem.FileStream;
air.FileMode = window.runtime.flash.filesystem.FileMode;

To see a complete list of APIs included, open up the AIRAliases.js file with a text editor. While not all APIs are included, you can easily add additional APIs by following the existing examples in the file.

Leveraging Compiled ActionScript Libraries

Not only can AIR applications leverage Flash Player APIs directly from JavaScript, they can also access compiled Action-Script 3 libraries from within JavaScript.

In addition to loading external JavaScript files, the HTML script tag within an AIR application also has support for loading compiled ActionScript 3 libraries and providing access to the ActionScript classes included within the file. Once the SWF is loaded, the APIs can be referenced in the same manner as the AIR and Flash Player APIs are referenced via the API package path and API name.

NOTE

This technique works only with ActionScript 3 libraries.

Let's look at an example. Included in the Adobe AIR SDK is a SWF that contains the ActionScript 3 Adobe AIR service connectivity API. While this example won't show how to use that API, it will show how to access those APIs from within Java-Script.

NOTE

An example of how to use the Service Connectivity API is provided in the cookbook section.

In order for the example to work, you must copy the frameworks/servicemonitor.swf file from the AIR SDK to your application directory.

Any classes and APIs available within the compiled SWF will be made available via the window.runtime property. The API we want to reference is in a class named ServiceMonitor in the air.net package.

Here's the code:

<script src="servicemonitor.swf" type="application/xshockwave-flash"></script>

<script type="text/javascript">
function onAppLoad()
{
    var monitor = new runtime.air.net.ServiceMonitor();
}
</script>

If AIRAliases.js is included in the page you can use the short version:

var monitor = new air.ServiceMonitor();

This is a very simple example that shows how to load compiled ActionScript libraries, and then access them from JavaScript. In this case, we include the servicemonitor.swf file via the HTML script tag using the special type "application/x-shock wave-flash". This file contains the compiled ActionScript 3 APIs for the air.net.ServiceMonitor class.

Using this technique allows you to leverage third party ActionScript APIs from within AIR applications via JavaScript.

NOTE

Most ActionScript 3 libraries are distributed as zip-based SWC files. In order to use the libraries within JavaScript, change the extension of the library from SWC to ZIP, unzip them using a zip program, and then remove the library's SWF file contained within the SWC.

You can then include the SWF within your application in the same manner as demonstrated earlier.

Troubleshooting AIR Applications

The process of developing an AIR application is much the same as that of developing an HTML-based web application.

The same thing is true when it comes to debugging an AIR application. One difference is that the JavaScript error messages go to the console (when running the application with AIR Debug Launcher) and not in a separate window as you might be used to in the browser world.

This section covers some of the new messages you might come across that are introduced by the runtime and also gives you a quick overview of an AIR SDK tool that can be used to make your life easier when working with HTML/JavaScript.

New JavaScript error messages

Security violation for Javascript code

If you call code that is restricted from use in the application sandbox due to security restrictions, the runtime dispatches a JavaScript error: "Adobe AIR runtime security violation for JavaScript code in the application security sandbox."

Referencing a JavaScript object no longer available

When an object dispatches an event to a handler that has already been unloaded, you see the following error message: "The application attempted to reference a JavaScript object in an HTML page that is no longer loaded."

To avoid this error, remove JavaScript event listeners in an HTML page before it goes away. In the case of page navigation (within an HTMLLoader object), remove the event listener during the unload event of the window object.

// In this example the event listener for an uncaught // Script Exception event is removed when unload event fires

window.onunload = cleanup; window.htmlLoader.addEventListener('uncaughtScriptException', uncaughtScriptException);

function cleanup() { window.htmlLoader.removeEventListener('uncaughtScriptException', uncaughtScriptExceptionHandler); }

Missing event listeners for error events

Exceptions, rather than events, are the primary mechanism for error handling in the runtime classes. However, because exceptions don't work for asynchronous operations, the runtime dispatches an error event object.

If you do not create a listener for the error event (such as when loading files asynchronously), the AIR Debug Launcher presents a dialog box with information about the error.

Most error events are based on the ErrorEvent class, and have a property named text that is used to store a descriptive error message.

An error event does not cause an application to stop executing. It manifests only as a dialog box when launched via ADL and is not presented when running in an installed application.

AIR Introspector

The Adobe AIR SDK includes a JavaScript based tool called AIR Introspector that makes it easier to develop HTML based applications for Adobe AIR. The tool can be used to introspect the content (such as the DOM) of HTML content running within an AIR application.

Figure 3-2

Figure 3-2 AIR Introspector Window

In order to use the AIR Introspector with your application, copy the AIRIntrospector.js file from the frameworks directory of the SDK into to your application project directory and then load the file into your application via the script tag:

<script src="AIRIntrospector.js" type="text/javascript"> </script>

The tool provides a number of features and functionality:

  • A tool that allows you to point to a user interface element in the application and see its markup and DOM properties.
  • Ability to edit the attributes and text nodes for DOM elements.
  • A console for introspecting, and adjusting objects references, properties and code. This includes the ability to execute JavaScript code.
  • View of DOM properties and functions.
  • Lists of links, CSS styles, images, and JavaScript files loaded into the application.
  • Ability to view the initial HTML source and the current markup source for the user interface.
  • A viewer for XMLHttpRequest objects and their properties, including responseText and responseXML properties (when available).
  • Ability to search for matching text in the source code and files.

At this point, you should have a good understanding of the HTML and JavaScript environments within Adobe AIR, as well as how to leverage AIR, Flash Player and third-party Action-Script 3 APIs directly from JavaScript.

The rest of the book will use this knowledge to show how to accomplish specific tasks from HTML and JavaScript applications running within Adobe AIR.

Table of Contents

Leave a Comment

(required)
(required)

Comments

# Manuel R. Ciosici (Aug 15, 2008  8:04 a.m.)

I would like to translate this chapter into Romanian.