Adobe Air ships with a sensational “Application Update” framework that makes deploying new versions of your application a snack. There’s even a fantastic blog post on how to get started using it. Typically it just involves throwing a few lines of ActionScript into your app’s startup:

var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI();
appUpdater.configurationFile = new File("app:/updateConfig.xml");
appUpdater.initialize();

Then throwing together a few lines of updateConfig.xml to set the period of the check and which error dialogs to suppress or show.

But what if you don’t just want the “auto update” feature? Perhaps you want to let your client manually check for updates (for example because your autoupdate frequency was deliberately set to a long time period between checks, or perhaps you put out a patched version to immediately fix a problem for a particular client). For these case, you want some kind of “Check For Updates” button on your About dialog (or wherever). Perhaps something like:

Check For Updates Button

For this kind of scenario, you’ll want to step out of the ApplicationUpdaterUI class, and into its lower-level cousing ApplicationUpdater (sans UI).

The ApplicationUpdater class gives you the low level plumbing to hook into each stage of the update check (is there a new version available? Was the download successful? etc) and override each stage as you see fit. This gives you the ability to display, for example, a custom confirmation dialog to see whether the user want to upgrade to the new version. You can also access the release notes section of your server side updateDescriptor.xml file. For example, I have something like this:

A custom Update Available dialog

Nice. So how do you go about implementing such a beast? Here’s the sample code from the dialog above to give you a leg up on implementing your own custom update logic:

protected function checkForUpdate_clickHandler(event:MouseEvent):void
{
    checkForUpdate.enabled = false;   // disable "check for update" button till we're done
    appUpdater = new ApplicationUpdater();
    appUpdater.configurationFile = new File("app:/updateConfig.xml");
    appUpdater.addEventListener(StatusUpdateEvent.UPDATE_STATUS, afterUpdateCheck);
    // Not sure which update "fail" event might fire, so we catch them all
    appUpdater.addEventListener(StatusUpdateErrorEvent.UPDATE_ERROR, afterUpdateError);
    appUpdater.addEventListener(ErrorEvent.ERROR, afterUpdateError);
    appUpdater.addEventListener(DownloadErrorEvent.DOWNLOAD_ERROR, afterUpdateError);
    appUpdater.initialize();
    appUpdater.checkNow();
}

protected function afterUpdateCheck(event:StatusUpdateEvent) :void {
    if (event.available) {
        event.preventDefault(); // suppress the auto-download functionality
        // prompt user for update, event.details[0][1] holds the release notes from the XML
        Alert.show("An updated version is available: v" + event.version + "." +
            event.details[0][1] + "nWould you like to update?", "Update Available",
            ( Alert.YES | Alert.NO),
            this,
            function(event:CloseEvent):void {
                if (event.detail == Alert.YES) {
                    // The default update mechanism will replace the item
                    appUpdater.downloadUpdate();
                } else {
                    // No update required, exit here and re-enable check button
                    checkForUpdate.enabled = true;
                }
            },
            null, Alert.YES, null);
    } else {
        checkForUpdate.enabled = true;
        Alert.show("No updates are available at this time",
            "No Updates Available", Alert.OK, this, null, null, Alert.OK, null);
    }

}

protected function afterUpdateError(event:ErrorEvent) : void {

    Alert.show("Error updating application. The error is: " + event.text +
     " (error " + event.errorID + ")", "Error During Update", Alert.OK, this,
        null, null, Alert.OK, null);
    checkForUpdate.enabled = true;

}

I’m certainly no ActionScript expert, but this what I was able to piece together about the process from the API refs. Hope it saves you some time!

Happy manual updating!