How to easily and seamlessly update an AIR application

Introduction

Last year I built an internal application for our local office that manages employee’s days off. I chose to use AIR/Flex for the client and PHP/MySQL on the server. Soon after the first release I ran into a big problem: as bugs were fixed and new features were implemented I would send email notifications to all users to update the application (many of these changes broke compatibility and thus without the update the user wasn’t able to use the application anymore). So you can imagine that after several notifications both my client (the HR manager) and some of the users were quite loud in their complaints. The client even suggested that it might be a better idea to redeploy the application as a web-based one.

This was indeed a problem. How can you push your updates for an AIR application as simply and non intrusively as you do with web-based applications?

Solution

Fortunately, at the same time the local AIR team had a project that addressed exactly this problem. Raul Hudea (the lead engineer of this project) had been working for some time on a Flex library that lets you update any AIR application (Flex or HTML/JavaScript) very easily. I became his first client and in no time we were able to roll out updates without any email notifications.

Yesterday, as part of the Adobe AIR 1.1 release, the Update Framework was launched. It is still in beta but I think it is OK to use it in production (I have been using it for some time and I didn’t have problems).

How to use the Adobe AIR Update Framework

It is not hard at all to use the Update Framework. The simplest approach has three main steps:

  1. Add the update library SWC file to your application
  2. Create and add the updater descriptor file - this is small XML file that keeps information needed by the updater (for example, what version is available, from where to take it and what info to display)
  3. Write about 10-15 lines of code in your AIR application … and you are done!

How does it work? Once you have integrated the Update Framework library into your application, whenever the application is started it checks if a new version is available. If a new version is available it can start to download the update (either automatically or after you show the user a window that displays some info about what improvements were made etc and ask the user to approve the update). After the update is downloaded, it is installed and the application is restarted.

Let’s create a simple Flex/AIR application to see how you can use it. (You can download the exported project here; in the archive you will find a readme.txt that explains how to import and set up the project).

For my example, I used Flex Builder 3. We need an AIR Flex project (I’ve called it air_updater). Then we need to add to the “libs” folder of the project the Update Framework library file: applicationupdater_ui.swc (you should find this file inside of the downloaded framework).

The next step is to create the updater descriptor file. This file lets you define the URL from where to download the new version of the application, and to set the version number, to set the description text you want to display to the user. Mine looks like this:

<?xml version=“1.0″ encoding=“utf-8″?>
<update xmlns=“http://ns.adobe.com/air/framework/update/description/1.0″>
    <version>1.9</version>
    <url>http://localhost/updater/air_updater.air</url>
    <description><![CDATA[
This version has fixes for the following know issues:
*First issue
*Second issue
  ]]></description>
</update>

You need to place this file on your web server. On my machine this file is reachable using this URL: http://localhost/updater/update.xml. In the same folder you place the release build of the application (or you can change the URL to the AIR app in the XML file if you want to have the file in another place ).

Now it is time to move to the aplication file and write some ActionScript code. So open the application file air_updater.mxml and add a handler called checkUpdate for the event creationComplete of the WindowedApplication:

<?xml version=“1.0″ encoding=“utf-8″?>
<mx:WindowedApplication xmlns:mx=“http://www.adobe.com/2006/mxml” layout=“absolute” creationComplete=“checkUpdate()”>

checkUpdate will be called every time the application is loaded. Next we need to write a little bit of ActionScript code to wire things together.

First thing, add a mx:script tag and create a variable appUpdater which will keep a reference to the updater object (this object will be our interface to the framework update). Next create the function checkUpdate(). This function will be in charge of initializing and setting some values needed by the updater object; the updateURL property tells the updater how to find the updater descriptor file (the file we have created earlier); then we register two functions for the error event and initialized event; the isCheckForUpdateVisible property lets you decide if you want to give the user the option to choose if he wants to allow the updater to check for a new version. In our case, set it to false, skipping this dialog in order to check for a new version every time. The last line appUpdater.initialize() does exactly what the name implies. When the updater is initialized it calls the listeners you have registered for the initialize event and inside of these listeners you start the process of checking for a new version.

The next two functions are the implementations for the event listeners for error and initialize events. Inside of the onUpdate() function we call the method checkNow() on the updater, starting the update process.

The last function setApplicationVersion() just read the current version of the app and displays it using a label.

<mx:Script>
    <![CDATA[
        import air.update.events.UpdateEvent;
        import mx.controls.Alert;
        import flash.events.ErrorEvent;
        import air.update.ApplicationUpdaterUI;

        /**
         * @var the object that that handles the update related actions
         */
        private var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI();

        /**
         * This function is triggered when the application finished to load;
         * Here we initialize <code>appUpdater</code> and set some properties
         */
        private function checkUpdate():void {
            setApplicationVersion();
            // we set the URL for the update.xml file
            appUpdater.updateURL = "http://localhost/updater/update.xml";
            //we set the event handlers for INITIALIZED nad ERROR
            appUpdater.addEventListener(UpdateEvent.INITIALIZED, onUpdate);
            appUpdater.addEventListener(ErrorEvent.ERROR, onError);
            //we can hide the dialog asking for permission for checking for a new update;
            //if you want to see it just leave the default value (or set true).
            appUpdater.isCheckForUpdateVisible = false;
            //we initialize the updater
            appUpdater.initialize();
        }

        /**
         * Handler function triggered by the ApplicationUpdater.initialize;
         * The updater was initialized and it is ready to take commands 
         * (such as <code>checkNow()</code>
         * @param UpdateEvent 
         */
        private 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
         * @param ErrorEvent 
         */
        private function onError(event:ErrorEvent):void {
            Alert.show(event.toString());
        }

        /**
         * A simple code just to read the current version of the application 
         * and display it in a label. 
         */
        private function setApplicationVersion():void {
            var appXML:XML = NativeApplication.nativeApplication.applicationDescriptor;
            var ns:Namespace = appXML.namespace();
            lblAppVersion.text = "App version: " + appXML.ns::version;
        }
    ]]>
</mx:Script>

And last let’s add a label component to display the current version of the application:

<mx:VBox>
    <mx:Label id=“lblAppVersion” width=“300″/>
</mx:VBox>

We have now all the code in place but we haven’t finished, yet. It is very important not to forget this: in order for the update to work you need to carefully set the same version number in these files: updater descriptor file and application descriptor (in our case air_updater-app.xml). In both these files you will find a tag version and what you put here needs to be exactly the same.

Now it is time to test what we have done. Choose Export > Flex Project > Release Build. Install the AIR application and then go back to Flex Builder and change the version number from each file (as I explained above) and also you can add a button to see that it is working. Then export the app again using the Release Build and place it on your server in the same folder as the updater.xml file. The next time you open the installed AIR app you should see a screen like this:

Application Window Update available screen

If you click on the “Download now” option you will see the following screen:

Install update screen

Want more?

As I said, this framework can handle many things: Flex and HTML/JavaScript AIR clients, you can have it with UI or without (transparent to the user), you can use any one of the languages supported by AIR 1.1 (English, Brazilian Portuguese, Chinese, French, German, Italian, Japanese, Korean, Russian, and Spanish), you can decide what UI you need, and you can handle the various errors that might happen (no connectivity, wrong URL, and many more). So, if you want to learn more about it, go here and download both the framework and samples and start to dig in.

Later Update:
My friend Remus posted an article about Update Framework, but use it with an HTML AIR application:
http://www.stratulat.com/blog/update-your-javascript-air-application-with-ease

Comments

18 Responses to “How to easily and seamlessly update an AIR application”

  1. William from Lagos on June 21st, 2008 11:16 pm

    Thanks for the info.

  2. Mihai Corlan on June 22nd, 2008 11:23 am

    I hope it helped!

  3. Sander Adamson on June 26th, 2008 3:48 pm

    I tried this out, and when I tested the update I got “There was an error downloading the update. Error# 16824″. Does anybody know what this means, or at least where to look up AIR error codes?

  4. Mihai Corlan on June 26th, 2008 9:20 pm

    @Sander Adamson

    If you download the framework: http://download.macromedia.com/pub/labs/air/appupdater/air_appupdater_062408.zip
    you will find an AIR_Update_Framework.pdf and at page 7 you can find the list of error codes.

    16824 means: “Invalid update descriptor. subErrorID may provide more information.”

    My guess is the update.xml is not valid or something. If I were you I would try to access directly in the browser using the URL you have set in the ApplicationUpdater?

  5. polyGeek on June 26th, 2008 11:31 pm

    Great, GREAT work.

    One problem that I ran into was copying the code and getting strange characters replaced here and there. Watch out for that. Maybe I should have downloaded the example files instead.

    I’m starting my first serious AIR app for a client and I knew that this was the first thing I wanted to enable. I don’t want to have to send out updates manually. You covered everything clearly and concisely. What a time saver this was.

  6. Mihai Corlan on June 26th, 2008 11:41 pm

    @polyGeek
    Thank you for your hint :) Maybe if you first copy the code into a Notepad or something and from there into your editor you get rid of the unwanted chars.

  7. polyGeek.com » Blog Archive » Using the AIR 1.1 Updater Framework on June 26th, 2008 11:48 pm

    [...] Mihai Corlan wrote a very concise and helpful tutorial on adding this functionality to a new or exis…. I went from start to finish on his tutorial in about 15 minutes - and it was 15 minutes well spent. [...]

  8. Update your JavaScript AIR application with ease. at On the Stre@m on June 27th, 2008 11:15 am

    [...] was inspired in this article by the one written by Mihai Corlan on his blog: How to easily and seamlessly update an AIR application. The article is discussing exactly the same topic but from the Flex [...]

  9. Pierre on June 29th, 2008 5:32 pm

    Thanks for your article. Yours explcations are clear. It’s a real pleasure to read a good writen post .

    Code is OK.

  10. Pierre on June 29th, 2008 5:34 pm

    In order to complite this post, It’s possible to have an article on install badge?

    Regards.

  11. Mihai Corlan on June 29th, 2008 7:00 pm

    @Pierre
    Thank you for your suggestion! Keep on eye on my blog :)

  12. Rodrigo Gomez-Tagle on July 3rd, 2008 2:03 am

    Hello,
    Great article Mihai, unfortunately, I ran into the same issue that Sander Adamson had. The message “There was an error downloading the update. Error# 16824″ Appeared when I tried to download my app’s update. These are the things that I have tried so far.
    1. Checked URLs, I am positive all URLs are correct and link properly to the update.xml and new .air file.
    2. Checked I had a valid update.xml
    3. Added .air MIME type to my apache server.

    Any other suggestions would be really appreciated.

    Cheers.

  13. Sander Adamson on July 3rd, 2008 12:13 pm

    My problem was that the version numbers inside update.xml and whatever-app.xml were not the same.

    You can also check the subErrorId (or whatever) if you create an error handler for the DownloadError and use ApplicationUpdater instead of ApplicationUpdaterUI.

  14. Mihai Corlan on July 4th, 2008 10:10 am

    @Rodrigo

    Indeed, Sander has been right. Probably you have different versions inside of the two files: -app.xml and update.xml.

  15. Rodrigo Gomez-Tagle on July 4th, 2008 7:58 pm

    Maybe I misunderstood, I thought that was the whole point, to have different version numbers in both of those documents so that you application knows that there is an update available.
    Right now I have them like this:
    -app.xml: Current version installed on my computer
    update.xml: New version on the server.
    If I change both of the numbers to be the same, then I get a message saying “No Updates Available”.
    Thank you in advance for your help.

  16. Mihai Corlan on July 4th, 2008 10:42 pm

    @Rodrigo

    Indeed, the whole point is to be able to push updates to clients. But this is how it is working:
    - you install application with let say the version 1.0 on your machine;
    - then you change in update.xml and …-app.xml the version to 1.1
    - then you export the application and place it under your web server where update.xml is;
    - then you open your installed application that will check for a new version and will do the update;

    I hope I managed to explain better this time.

  17. Rodrigo Gomez-Tagle on July 5th, 2008 1:25 am

    Problem solved!
    Thanks for your help, I just had the whole version number thing misunderstood. You were right the version numbers have to be the same in both documents.

  18. Rostislav Siryk on July 8th, 2008 12:07 am

    Mihai, your post is probably the only one which explains the error #16824. I just run into the same problem and comments here helped me to figure out what I’m doing wrong.

    Thank you a lot for this post

Leave a Reply