DLG Software


Rich Internet Applications,

  Flex, AIR, and maybe a little SAS


Abstract

This is a primer for newbie Flex developers.  It covers (and ties together) the topics of Flex app wrappers, SWF file embedding, ActionScript/JavaScript communication, and SWF/SWF communication. It includes numerous references and embedded demo apps.

Introduction

Some Flex applications have no need to communicate with “external” HTML page elements such as <input> fields, Ajax controls, etc.   However, often your Flex app does need to communicate with other page elements, even other SWFs.  This primer provides an introduction to topics related to these occasions,  including:  
Note that this newbie primer doesn’t cover these topics in-depth but it does provide multiple references to resources with usage and syntax details, sample code, videos, and working examples.
  Books referenced in this primer are listed at the bottom of this page. A link for other Adobe docs is also included.



Customizing a wrapper and embedding your SWF(s)

By default, when you generate a Flex app you also generate a wrapper, which is a combination of HTML and Javascript.  This wrapper embeds your SWF and optionally provides player detection, browse history management, etc. The generated .html file serves as the entry point to your application.
  The above is a general case, with exceptions - for example, mxmlc cmdline compiles don't generate a wrapper for you, you’ll need to create it yourself.

Flex3 projects contain a folder named html-template which holds files used to generate the wrapper for your Flex application.  By default this includes:
  • model HTML from which your app’s generated HTML is derived.  There are various model HTML templates available.  All are named index.template.html.
  • various js files, including AC_OETags, which is a JavaScript lib used to detect whether the Flash player is installed on the client and, if so, the player version
  • history files used for history management on non-IE clients
  • playerProductInstall.swf which is used to upgrade the player when required

When you use the Flex-supplied wrapper templates everything needed to embed your SWF is done for you.  The generated HTML deals with different embedding standards,  generating both <object> and <embed> tags so your app will run in both IE and non-IE browsers (e.g., mozilla-based FireFox). 

When the Flex-generated wrapper does not meet your needs (say, you need to embed an Ajax control on the page or you want the page to host multiple SWFs) you’ll need a customized wrapper.  For this you can modify a Flex-supplied wrapper template or create your wrapper from scratch. 

  When modifying your app's wrapper do NOT edit the .html in your project output folders (e.g., bin-debug).  This .html is regenerated each time you compile, so your edits will be overwritten.  Instead, edit index.template.html in the html-template directory.  This is the model from which your wrapper is generated.

Flex supplies a variety of wrapper templates for different needs (stored in the ...installDir.../sdks/3.0.0/templates directory).  For information on the features and usage of each template see the Livedocs page on this topic or refer to the Adobe doc Building and Deploying Adobe Flex 3 Applications (the best single Adobe doc on this topic)

Sometimes you need minimal wrapper functionality and will create a very simple wrapper from scratch.  In this case, an excellent tool for embedding SWFs is SWFObject.  SWFObject is a license-free utility for embedding SWFs with flash player detection.  SWFObject provides a browser-based GUI that generates the tags needed to embed your SWF.  This GUI lets you set numerous embed options and parameters (see the gotoandlearn video mentioned in the references below for a walk-though of this GUI’s usage and features)

  The wrapper for this page was created from scratch and embeds multiple SWFs using SWFObject.  It is a barebones implementation that does not include the files necessary to support deep linking or browser history management.  It does handle Flash player detection through features of SWFObject.

For details on customizing the wrapper and embedding your Flex apps see the references below.

References: Wrapper creation/modification
NOTE: The Livedocs pages listed below come from the Adobe doc Building and Deploying Adobe Flex 3 Applications Chapter 16 “Creating the Wrapper”
References: SWFObject


Communicating with the Wrapper via Javascript

When SWFs communicate with other controls on a page the mechanism is JavaScript.

While you can use navigateToURL and URLRequest to invoke JavaScript functions the preferred method in AS3 is the ExternalInterface class.  One advantage of ExternalInterface is that it is synchronous, allowing the function call to return a value.

ExternalInterface consists primarily of two methods, call() and addCallback().  The former invokes a JavaScript function, the latter is used to expose an AS function to JavaScript.

As usual there are cross-domain security restrictions, and there are some required parameter values that you must set to allow the ActionScript-JavaScript communication (e.g., allowScriptAccess must be set to always or samedomain).  For details on syntax and constraints see the references below for more info, especially Building and Deploying Adobe Flex 3 Applications Chapter 16.

When using ExternalInterface to communicate from ActionScript to JavaScript you simply invoke the JavaScriptfunction using the call() method.   You may pass one or more optional parms.  This call is synchronous and can return a value.  Through the call() function you can perform any action that is normally available via a page’s scripts.

When using ExternalInterface to communicate from JavaScript to ActionScript you need to expose your ActionScript function(s) through the addCallback method.  This makes the function(s) available to JavaScript. 

ExternalInterface is straightforward but does have limitations.  For example, with ExternalInterface the parameters you pass can be simple primitives, arrays, and simple objects, but you cannot pass user-defined classes.  For more advanced ActionScript/JavaScript integration you should consider using the Flex Ajax Bridge, which is a small code library specifically designed for this purpose.  See below for references on FABridge.

Demo for ExternalInterface

Below is a demo of bidirectional communication through ExternalInterface -- the Flex app directly calls the Javascript Alert function, while a custom Javascript function invokes an Alert in the Flex app. While this demo passes a single string you could pass multiple parameters and more complex data types.





References: ExternalInterface
  • Adobe Developer’s guide Chapter 32 “Communicating with the Wrapper”
  • Flex 3 Cookbook Chapter 17 “Browser Communication”
  • ActionScript 3.0 Cookbook Chapter 22 “Building Integrated Applications”
  • Advanced Flex 3 pg 332-338
  • My favorite site for Flex tips, Flex Examples, has several working examples of ExternalInterface usage.
  • The Livedocs classdoc for ExternalInterface has a nice example of dealing with load timing issues. 
  • Building and Deploying Adobe Flex 3 Applications Chapter 16 has info on embed parms that must be set in order to allow AS/JS communication.
References: FABridge


LocalConnection

The LocalConnection class is used for communicating between SWFs.  These SWFs can be embedded on the same page, in different browsers, or running in Adobe AIR.  All communication is done through the Flash player. 

This section is fairly short because LocalConnection is remarkably straightforward.  Key concepts are:
  • In both the sender and receiver you instantiate LocalConnection, providing a common name for the connection they'll use.  When you provide a connection name you may want to use a name with a leading underscore – this bypasses some security/domain restrictions
  • In the receiver SWF you define a LocalConnection handler function.  This function will process incoming “calls” from the sender SWF
  • In the sender SWF you create a function to invoke the receiver SWF’s function, usually passing one or more parms

As usual, there are some cross-domain security restrictions you’ll need to take into account.  For details see the references section below. 

Demo of LocalConnection

A simple demo of two embedded Flex apps that communicate through LocalConnection is below. The first embedded SWF is the sender. Enter text and click SEND to send the message to the receiving SWF using LocalConnection.



Below is the receiving SWF. It displays messages received through LocalConnection.



LocalConnection References:


Persistent storage and communication through SharedObjects

Another method of sharing data between SWFs -- including data that persists between sessions -- is the use of SharedObjects.  SO’s are basically the Flash Player’s version of cookies. However, SO’s have numerous advantages over cookies (they’re not limited to strings, they can be much larger than cookies, they don’t expire, etc.).  In cases where you want to share data between applications and want this data to persist between session SharedObjects is a good option. 

SharedObjects can be either local or remote (LSO versus RSO). This section covers only LSO's because they are simple and easy to use (RSO's require use of an Adobe server-based product such as Flash Media Server). However, storing data locally has its drawbacks -- for more information see the sidebar below on this topic.

Local SharedObjects are ridiculously easy to use. You obtain an SO through the SharedObject class getLocal() method, passing the SO name as a parm. Example:
    mySO:SharedObject = SharedObject.getLocal("userPrefs")
If the SO does not already exist Flex creates it for you (getLocal is a static method, you do not use the new statement). 

Once you have your SO you read/write your data through its data property just as you would any AS object (e.g., mySO.data.username = ”Dan”;). You can store primitives and several other native AS datatypes such as Array, Date, and Object. You can store custom classes but in some cases this requires special handling on your part to deal with serializing/deserializing. You cannot directly store UICs like buttons, sprites, etc.

Note the following re Local SharedObjects:
  • SO's and their data are managed by the Flash Player, not the Browser.
  • When your app terminates any open SO's will automatically be written to disk. However, it's good practice to perform "manual" writes using flush() (see caution note below)
  • You can create as many SO’s as you need but there is a space limitation by domain of 100k.  Users can modify this default size setting.  If you attempt to write data that exceeds this limit the user is prompted to increase the size limitation (but not if your application is terminating -- again, see the caution note below)
  • Access to SO’s are limited to apps running from the same domain; apps running in different domains cannot access each other’s SO’s.
  • It is possible for users to disable SO’s, so for critical data you should verify that they are enabled.  An article on this topic is here 
  • When your SO is written to disk Flex3/AS3 uses AMF3 format to serialize the data. This means that SWFs using AS1 or AS2 cannot access these SO's, since they don't "understand" AMF3 (they use AMF0). However, AS3 can access AMF0 SharedObjects, and you can specify that your AS3 SO's use AMF0 format (use the defaultObjectEncoding property)
  The flash player automatically writes your SO's data to disk when a user exits your application – at least it attempts to.  However, if your SO exceeds its size limit during app termination the player can't prompt the user to increase the SO's size limit.  Because of this it's good practice to perform manual writes of SO data using the flush() method. This ensures that the Flash player can prompt the user to increase the SO's size limit when that limit is exceeded.

Sidebar on persistent storage: Local versus server-side

By default SO’s are associated with the name you provide and a path generated by Flex.   This generated path includes the domain of the SWF and a randomly generated string (for security).  This default usage of an SO makes it unavailable to other SWFs.  However, you can share SO's and their data between SWFs of the same domain.  You do this by specifying the local path parameter when creating and opening the SO.  Be aware that there are limited options for this local path parameter when you want to share an SO between SWFs.  The parm value must be either the root location of the SO storage (ie., “/” or root+SWFs-shared-domain (e.g., “/mydomain”).  A good explanation of this is included in ActionScript 3 Cookbook recipe 17.7.

Below is an example of a SharedObject used by two applications from the same domain.  It illustrates a case where a site serves up multiple Flex apps but wants to provide the user a consistent look and feel based on their preferences.  User preferences are saved between sessions (confirm this by reloading the page) and used by multiple applications (use the “launch second app” button to open another SWF in a new browser window.  The second SWF will honor that user preferences that were in effect at the time of its initialization.   

Demo of SharedObject

The demo apps below illustrate the use of SharedObjects for persistent storage and SWF to SWF data sharing. 

SO Demo App1 is used to create/modify a SO with user preferences.  It honors these preferences between sessions.  To verify this:
    1. in SO Demo App1 set some prefs
    2. use the SAVE PREFERENCES option
    3. refresh the page
Upon refresh you’ll see that SO Demo App 1 “remembers” your prefs between sessions.

SO Demo App 2 reads the same SO to set its own appearance.  This illustrates both persistent storage and sharing of the saved data between SWFs.

SO Demo App 1


The link below launches a second SO demo app in a new browser. This app doesn't do anything except for honoring the prefs you set/saved in SO demoApp1, but that's the point -- SO demoApp2 demonstrates one Flex app making use of SharedObject data set/saved by a different Flex app (i.e., it shows a SharedObject that is truly shared, its data used by multiple Flex apps).
NOTE: SO demoApp 2 honors the prefs you last saved in SO demoApp 1




References: SharedObjects


Books referenced in this primer:

Below are books mentioned in this primer.  More info on these and other books as well as links to Adobe Flex documentation mentioned here are available through my page on Flex documentation.
  • Flex 3 Cookbook by Todd Anderson, Joshua Noble
  • ActionScript 3.0 Cookbook by Joey Lott, Keith Peters, Darron Schall
  • Adobe Flex3 Bible by David Gassner
  • ActionScript 3.0 Bible by Roger Braunstein, Mims H. Wright, and Joshua Noble
  • Advanced Flex3 by Shashank Tiwari, Jack Herrington, Elad Elrom, and Joshua Mostafa