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.

Important: be very careful what convention you use for the version string. The framework compares the version string of the installed application with the one from the server. If the installed version is “greater” than the one from the server the application will not be updated. Here are some examples that you could use:

  • v1.0, v1.1, v1.2
  • 1.0, 1.1,2

However if you use something like 1.0 and later you decide to switch to something like v3.5 it might not work.

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

Later Update 2:

I post here the Error codes from the documentation:

16800 Occurs during validating the downloaded update file. The subErrorID may contain additional information.
16801 Invalid Adobe AIR file (missing application.xml).
16802 Invalid Adobe AIR file (missing mimetype).
16807 Invalid Adobe AIR file (format).
16804 Invalid Adobe AIR file(invalid flags).
16805 Invalid Adobe AIR file(unknown compression).
16806 Invalid Adobe AIR file (invalid filename).
16807 Invalid Adobe AIR file (corrupt).
16808 Configuration file does not exist.
16809 updateURL not set.
16810 Reserved.
16811 Invalid configuration file(unknown configuration version).
16812 Invalid configuration file (URL missing).
16813 Invalid configuration file (delay format).
16814 Invalid configuration file (invalid defaultUI values).
16815 Invalid update descriptor (unknown descriptor version).
16816 Invalid update descriptor (missing update version).
16817 Invalid update descriptor (invalid description).
16818 IO error while saving data to disk. subErrorID may provide more information.
16819 Security error while downloading. subErrorID may provide more information.
16820 Invalid HTTP status code. subErrorID may contain the invalid status code.
16821 Reserved.
16822 IO error while downloading. subErrorID may provide more information.
16823 EOF error while saving data to disk. subErrorID may provide more information.
16824 Invalid update descriptor. subErrorID may provide more information.
16825 The update file contains an application with a different application ID.
16826 The update file does not contain a newer version of the application.
16827 The version contained in the update file does not match the version from the update descriptor.
16828 Cannot update application, usually because the application is running in the AIR Debug Launcher (ADL).
16829 Missing update file at install time.

47 thoughts on “How to easily and seamlessly update an AIR application

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

  2. @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?

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

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

  5. Pingback: polyGeek.com » Blog Archive » Using the AIR 1.1 Updater Framework

  6. Pingback: Update your JavaScript AIR application with ease. at On the Stre@m

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

    Code is OK.

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

    Regards.

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

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

  11. @Rodrigo

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

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

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

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

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

  16. I have the updater working but when i run the “appUpdater.initialize();” function all my scroll bars in my application change color to look like that in the updater messages. How do I stop this? or reset the scroll bars after the check?

  17. That’s interesting! Can you give me some more details? I want to see if I can reproduce it.

  18. here is the code:

    public function startApp():void {
    checkUpdate();
    }
    private function checkUpdate():void {
    appUpdater.updateURL = “127.0.0.1/update.xml”;
    appUpdater.addEventListener(UpdateEvent.INITIALIZED, onUpdate);
    appUpdater.addEventListener(ErrorEvent.ERROR, onError);
    appUpdater.isCheckForUpdateVisible = false;
    appUpdater.initialize();.// if i comment out this line then it doesn’t happen
    }
    private function onUpdate(event:UpdateEvent):void {
    appUpdater.checkNow();
    }
    private function onError(event:ErrorEvent):void {
    Alert.show(event.toString());
    }

  19. I Have this style problem as well. It is changing the styles of my scroll bars, making application buttons larger and making my combo boxes look ugly. Any ideas?

  20. sorry I meant flex builder 3.0.2 and i tried updating again and it actually got worse I saw the ugly button style that you talked about appear on all my AIR apps when the updater started and just as before in flash 9 the data grids wont refresh

  21. Has anyone seen error code 16820?
    When I try to download the update, I get error message “There was an error downloading the update. Error# 16820″

  22. @Dilip Shah

    Here is the description for this error code:

    16820 Invalid HTTP status code. subErrorID may contain the invalid status code.

    Did you look at the comments, and still is not working?

  23. My application already contains an “applicationComplete” tag, can that interfere with “creationComplete”?

  24. hey i’m sorry but i still don’t get this?

    @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;

    That still makes no sense to me? Why do the version numbers within app-xml.xml and update.xml have to be the same? Am I missing a point?

  25. @ryan

    They have to be the same. You as a developer create a new version: 2.99. This is what you set in the AIR application, in the application descriptor file. Then you upload this to your server. Next you want any application already installed when is started to find this new version. To achieve this, you have to write the same 2.99 in the updater file.

    Is it clear now?

  26. yeah i figured it out… i just batteled to understand your process…

    so in case anybody else feels like they in the dark, your compiled application that you wish to distribute must have it’s ..-app.xml version number the same as the version number within ‘update.xml’.

    once you upload both your compiled *.air file and your ‘upadte.xml’ file to the server you are able to run a smooth update that gets rid of error:

    #16824 Invalid update descriptor. subErrorID may provide more information.

    to test this simply upload your files, and from within flash/flex drop your version number within …-app.xml and give it a test, you should now see error:

    #16828 Cannot update application, usually because the application is running in the AIR Debug Launcher (ADL).

    which means that the update process is actually working…

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

    Thanks Sander. This worked!

  28. hi,

    great example which i have working on its own, but when i built into my app it doesn’t call onUpdate() after it has been initialize(d). Any thoughts on why this might happen?

  29. I hope you can add some advice for other developers, it took me three working days to figure this out. The application has some logic that compares the version in the running application with the version specified in the update descriptor file. In my case, the application was running version “1.35p”, and my team decided to change the format of the version because we did not like it. We set the next version in the update descriptor file to “v1.4.5 P”. Every time we checked for updates, the ApplicationUpdaterUI claimed that there were no updates available. After three days of making every guess I could think of, I changed the update descriptor files version number to “1.45p” and woila! The running application finds the new version and recommends updating.

    Please add some instructions about this to your document, I hope that nobody else has to struggle with this like I did.

  30. Hello Mihai…
    Before all, Thanks for the article.
    I have a question related with updating adobe AIR applications.
    There are any way to execute a silent update of an application if i have the newer .air file.

    I mean if it’s posible having “x” application ver 1.0 installed, update this application from command line similar to the “airappinstaller.exe -silent airAppVer2.0.air” i recive “failed due to bad configuration error”.

    thanks…

  31. Hi
    i have fallowed Mihai Corlan tutorial on Using the Adobe AIR update framework and its working
    perfectly, my problem now is that is have 2 servers that holds the update and i want my air app
    to check on both server for update. in case the other server is down my app can still get its update.

    is this possible?

    thanks!!

  32. I can’t get it to work on Flex 3.6 SDK. i already updated the swc in my 3.6 SDK. anything else to do beside this one.

    Thanks

  33. Is it possible to update .apk using server. I tried same for .apk but its not working for me.
    Any possibility to update .APK using server. I am not using Market for distribute APK so need to update through Server.

    Thanks and hope to get reply :-)

  34. Hi I am facing the issue of Error# 16828 and I am not getting how to off the adl can anyone help me
    My application is html base adobe air .

  35. Hi I am facing the issue of Error# 16800 with sub error id: Error# 16802 please help me…

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>