Accessibility

Table of Contents

Using the Adobe AIR update framework

Using the framework in Flash apps built on AIR

If you develop AIR applications using Flash (that is, not using the Flex framework), you can still use the Adobe AIR update framework. With Flash, however, you can't use the library with the default UI, since this library uses the Flex framework. As a result, there is a little more work needed to implement the update logic and the UI.

If you don't want to create the project step by step, you can use the archive (air_update_flash.zip) provided with this article. You'll still need to extract the applicationupdater.swc file from the update framework archive, and add it to the project paths (see the next section).

Creating the project

Choose File > New > Flash File (Adobe AIR) and then click OK. Next, choose File > Save and type air_update_flash.fla as the name.

To add the applicationupdater.swc file to the project:

  1. Choose File > Publish Settings.
  2. Select the Flash tab, and click the Settings button for the "Script" option.
  3. Select the Library path tab (see Figure 10), and click the plus (+) button, then click the "Browse to SWC file" button (the red one) and select the applicationupdater.swc file.
  4. Click OK.

    Adding the applicationupdater.swc file to
the library path

    Figure 10. Adding the applicationupdater.swc file to the library path

To test that the library was added to the project, switch to Source mode and enter the following ActionScript code:

import air.update.ApplicationUpdater;
var appUpdater:ApplicationUpdater = new ApplicationUpdater(); 

Run the application; if the library has been added to the project you won't see any errors.

Adding code for the update

Note: I am not a Flash developer, and it is quite possible that someone more experienced with Flash than I am could write code that is more efficient or more elegant.

  1. Switch to Design mode and add four text boxes to air_update_flash.fla (see Figure 11). Make two of them static text and type Application name:, and Version:. Set the other two as dynamic text, and give them the following IDs: lblName and lblVersion.

    Adding
  the UI components to the main application window

    Figure 11. Adding the UI components to the main application window

    You will use these controls to display the application name the current version.

    As I noted earlier, because you are using the update framework without the default UI, you have to implement the UI yourself. To do this, you can create a custom component (a movie clip) named myWindow. You will use this component to draw the content of the pop-up window that will display the various states while updating the application. Because the logic for updating the application resides in a FLA file, you need a way to control this component's appearance from the main application.

  2. Create a new ActionScript file (myWindow.as) in the same folder as the air_update_flash.fla file. In this file, insert the following code:

    package {
        public class myWindow extends MovieClip {
            
        }
    }
  3. You are ready now to create the movie clip that you will use to draw the content of the pop-up window. Select the Library panel and click New Symbol. For the Name type myWindow, for Type select Movie Clip, and then click Advanced.
  4. Select Export for ActionScript and Export in frame 1 in the Linkage section (see Figure 12). For the Class, type myWindow (this is the class you defined in the myWindow.as file).

    Create the movie clip component

    Figure 12. Create the movie clip component

  5. Click OK.
  6. It is time to add the UI elements to this component. From the Library panel choose the myWindow component, and click Edit. Add a black background, then add a text box (make it dynamic), and select a larger font size. Below this text box, add a text area and a progress bar. Finally, add two buttons aligned bottom-right (see Figure 13). Save the file.

    Adding the UI components to the myWindow
movie clip

    Figure 13. Adding the UI components to the myWindow movie clip

    Basically, you set up all the components needed to draw the windows you will show. When you use the component, you can choose which components to show, which components to hide, what the text and labels will be, and so on.

  7. Add the IDs for these components: title_1 for the first text box, description_1 for the text area, bar_1 for the progress bar, button_1 and button_2 for the two buttons.
  8. You need to make these components available to the main application. For this, open the myWindow.as file and add this code:

    package {
        import flash.display.MovieClip;
        import fl.controls.ProgressBar;
        import fl.controls.Button;
        import fl.controls.TextArea;
        
        //this class sets the type for the myWindow component
        //we use it as a proxy to the UI controls from the myWindow component 
        //(buttons, labels, text area, or progress bar)
        public class myWindow extends MovieClip {
            
            public function set title(text:String):void {
               title_1.text = text;
            }
            
            public function set description(text:String):void {
               description_1.text = text;
            }
            
            public function set enableDescription(enable:Boolean):void {
               description_1.visible = enable;
            }
                   
    
            public function enableBar(enable:Boolean):void {
               bar_1.visible = enable;
            }
            
            public function get bar():ProgressBar {
               return bar_1;
            }
            
            public function get buttonLeft():Button {
               return button_1;
            }
            
            public function get buttonRight():Button {
               return button_2;
            }
        }
    }
              

    Now you can access each component from the main application.

  9. It is time to move back to air_update_flash.fla and add the business logic. Select the file, and then open the Actions Frame and select Scene 1, Layer 1: Frame 1. You should see the code you added before:

    import air.update.ApplicationUpdater;
    var appUpdater:ApplicationUpdater = new ApplicationUpdater();
              

Here is the complete code followed by an explanation:

import air.update.ApplicationUpdater;
import air.update.events.StatusFileUpdateEvent;
import air.update.events.StatusUpdateErrorEvent;
import air.update.events.StatusFileUpdateErrorEvent;
import air.update.events.DownloadErrorEvent;
import air.update.events.StatusUpdateEvent;
import air.update.events.UpdateEvent;
import flash.events.ErrorEvent;
import flash.events.MouseEvent;
import flash.desktop.NativeApplication;
import flash.display.NativeWindow;
import flash.display.NativeWindowInitOptions;
import flash.display.NativeWindowSystemChrome;
import flash.display.NativeWindowType;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import fl.controls.Button;
import Namespace;
import XML;
 
var appUpdater:ApplicationUpdater = new ApplicationUpdater();
var window:NativeWindow;
var windowContent:myWindow = new myWindow();
var existentListeners:Dictionary = new Dictionary();
 
//initialize the updater; gets called when the application is loaded
function initializeUpdater():void {
    setApplicationNameAndVersion();
    appUpdater.updateURL = "http://localhost/updater/update_flash.xml";
    //we set the event handlers for INITIALIZED nad ERROR
   
appUpdater.addEventListener(UpdateEvent.INITIALIZED, onUpdate);
    appUpdater.addEventListener(ErrorEvent.ERROR, onError);
       
appUpdater.addEventListener(StatusUpdateEvent.UPDATE_STATUS, onStatusUpdate);
    appUpdater.addEventListener(StatusUpdateErrorEvent.UPDATE_ERROR, onStatusUpdateError);
   
appUpdater.addEventListener(ProgressEvent.PROGRESS, onDownloadProgress);
   
appUpdater.addEventListener(UpdateEvent.DOWNLOAD_COMPLETE, onDownloadComplete);
    appUpdater.addEventListener(DownloadErrorEvent.DOWNLOAD_ERROR, onDownloadError);
    //initialize the updater
    appUpdater.initialize();
}
//listener for INITIALIZED event of the applicationUpdater;
function onUpdate(event:UpdateEvent):void {
    //start the process of checking for a new update and to install
    appUpdater.checkNow();
}
//Handler function for error events triggered by the ApplicationUpdater.initialize
function onError(event:ErrorEvent):void {
    trace(event);
    createWindow();
    displayWindowError(event.errorID, event.text);
}
//handler function for StatusUpdateEvent.UPDATE_STATUS
//this is called after the update descriptor was downloaded and interpreted successfuly 
function onStatusUpdate(event:StatusUpdateEvent):void {
    trace(event);
    //prevent the default (start downloading the new version)
    event.preventDefault();
    createWindow();
    windowContent.bar.visible = false; //hide the progress bar
    //create the window for displaying Update available
    if (event.available) {
        windowContent.title = "Update Available";
        windowContent.enableDescription = true;
        windowContent.description = event.version + " " + event.details[0][1];
        windowContent.buttonLeft.label = "Update";
        windowContent.buttonRight.label = "Cancel";
        addEventToButton(windowContent.buttonLeft, MouseEvent.CLICK, startDownload);
        addEventToButton(windowContent.buttonRight, MouseEvent.CLICK, closeWindow);
     //we don't have an update, so display this information
    } else {
        windowContent.title = "No Update Available";
        windowContent.enableDescription = false;
        windowContent.buttonLeft.visible = false;
        windowContent.buttonRight.label = "Close";
        addEventToButton(windowContent.buttonRight, MouseEvent.CLICK, closeWindow);
    }
}
//error listener for an error when the updater could not download or
//interpret the update descriptor file.
function onStatusUpdateError(event:StatusUpdateErrorEvent):void
{
    createWindow();
    displayWindowError(event.subErrorID, event.text);
}
//error listener for DownloadErrorEvent. Dispatched if there is an error while connecting or
//downloading the update file. It is also dispatched for invalid HTTP statuses 
//(such as "404 - File not found").
function onDownloadError(event:DownloadErrorEvent):void {
    createWindow();
    displayWindowError(event.subErrorID, event.text);    
}
//start the download of the new version
function startDownload(event:MouseEvent):void {
    appUpdater.downloadUpdate();
    createWindow();
    windowContent.bar.visible = true;
    windowContent.bar.setProgress(0, 100);
}
//listener for the ProgressEvent when a download of the new
version is in progress
function onDownloadProgress(event:ProgressEvent):void {
   windowContent.bar.setProgress(event.bytesLoaded, event.bytesTotal);
}
//listener for the complete event for downloading the application
//just close the window; the downloaded version will be automatically installed,
//and then the application gets restarted
function onDownloadComplete(event:UpdateEvent):void {
    closeWindow(null);
}
//sets the state of the window in error display mode
function displayWindowError(errorId:int, errorText:String):void
{
    windowContent.title = "Error";
    windowContent.enableDescription = true;
    windowContent.description = "Error ID: " + errorId + ". " + errorText;
    windowContent.buttonLeft.visible = false;
    windowContent.buttonRight.label = "Close";
    windowContent.bar.visible = false;
    addEventToButton(windowContent.buttonRight, MouseEvent.CLICK, closeWindow);
}
//create a window using NativeWindow, and as a content myWindow
class
function createWindow():void {
    if (window == null) {
        var options:NativeWindowInitOptions = new NativeWindowInitOptions();
        options.systemChrome = NativeWindowSystemChrome.STANDARD;
        options.type = NativeWindowType.NORMAL;
        
        window = new NativeWindow(options);
        window.x = 300;
        window.y = 200;
        window.stage.stageHeight = 230;
        window.stage.stageWidth = 450;
        window.stage.scaleMode = StageScaleMode.NO_SCALE;
        window.stage.align = StageAlign.TOP_LEFT;
        window.stage.addChild(windowContent);
        windowContent.bar.visible = false;
    }
    window.alwaysInFront = true;
    window.visible = true;
}
//close the window
function closeWindow(event:Event):void {
    window.close();    
}
//hide the window
function hideWindow():void {
    window.visible = false;
}
//sets the application name and version in the main window
function setApplicationNameAndVersion():void {
    var appXML:XML = NativeApplication.nativeApplication.applicationDescriptor;
    var ns:Namespace = appXML.namespace();
    lblVersion.text = appXML.ns::version;
    lblName.text = appXML.ns::name;
}
//add to the given button, the listener for given type (actually we use only the type MouseEvent.CLICK).
//we use a dictionary to store for each button the listener registered.
//when this function gets called, first we remove any registered listener. Next we register the listener 
//on the button, and next we save to dictionary.
function addEventToButton(button:Button, type:String, listener:Function):void
{
    //remove existent listneres
    if (existentListeners[button] != null) {
        var arr:Array = existentListeners[button] as Array;
        button.removeEventListener(type, arr[0]);
    } 
    existentListeners[button] = [];
    button.addEventListener(type, listener);
    existentListeners[button][0] = listener;
    button.visible = true;
}
 
initializeUpdater();
//initialize the updater 

This code does the following:

  • It uses a NativeWindow instance and a myWindow instance (the component you created earlier) to draw the pop-up window (see the function createWidow() in the code).
  • The function initializeUpdater() is called once the application is loaded. This function initializes the update framework object (appUpdater), sets the URL for the update descriptor file (on my machine the path is http://localhost/updater/update_flash.xml), and registers listeners for different events on the update object. While I chose a minimal implementation (I intend to show a window if an update is available or not, to display the window while the update is downloaded, and to display an error window if something goes wrong), you can implement more windows (see the documentation for more details).
  • The code implements each listener registered on the updater object.
  • The function setApplicationNameAndVersion() is called from initializeUpdater() and sets the application name and version in the UI in the main application window.
  • There is also a function for creating the pop-up window (createWindow), and functions to hide and close the window.

Testing the code

You have almost all the bits in place. You have to write the update descriptor file, and set the URL of the applicationUpdater (this is set in the initializeUpdater() function) to point to this file.

  1. Inside of your web server root create a folder called updater. In this folder create the file update_flash.xml, and add the following XML to it:

    <?xml version="1.0" encoding="utf-8"?>
    <update xmlns="http://ns.adobe.com/air/framework/update/description/1.0">
        <version>1.2</version>
        <url>http://localhost/updater/air_update_flash.air</url>
        <description><![CDATA[
             This version has fixes for the following known issues:
             *First issue
             *Second issue   
       ]]></description>
    </update>
  2. Choose File > Publish to create an AIR file for this project. You should see an air_update_flash.air file in the same folder as the air_update_flash.fla file. Install the application.
  3. In Flash CS4 choose File > Publish Settings, select the Flash tab, and click Settings next to the Player option. Increase the version number (see Figure 14), and then click Publish AIR File.

    Increase the version number and publish
the project.

    Figure 14. Increase the version number and publish the project.

  4. Copy the AIR file to your web server, inside the updater folder. Open the update_flash.xml file from the same folder, and set the version to the same number you used for the project you just published. Also, make sure that the URL to the AIR file is correct.
  5. Now you can open the installed application and you should see something like the window shown Figure 15.

    The custom updater UI

    Figure 15. The custom updater UI

  6. Click Update to start the update process. The new version is downloaded and installed, and then the application is restarted (see Figure 16).

    The update was installed successfully.

    Figure 16. The update was installed successfully.

Where to go from here

The Adobe AIR update framework enables you to add a very important and useful feature to your applications: the ability to push updates to your users very easily. The update framework supports Flex, Ajax, and Flash, so you're covered no matter what technology you prefer for developing AIR applications.

For more AIR resources, visit the AIR Developer Center. Also, take time to read the documentation that comes with the framework. You'll discover how flexible it is, and how you can customize it to meet your needs.