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).
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:
Click OK.

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.
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.
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.

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.
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 {
}
}
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).

Figure 12. Create the movie clip component
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.

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.
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.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.
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:
NativeWindow instance and a myWindow instance (the component you created earlier) to draw the pop-up window (see the
function createWidow() in the code).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).setApplicationNameAndVersion() is called from initializeUpdater() and sets the application name and version in the UI in the main application
window.createWindow),
and functions to hide and close the window.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.
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>
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.

Figure 14. Increase the version number and publish the project.
Now you can open the installed application and you should see something like the window shown Figure 15.

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

Figure 16. The update was installed successfully.
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.