How to update Adobe AIR applications automatically with JavaScript – AIRUpdater.js
Tweet Follow @robertnymanWhen developing applications with Adobe AIR, a vital feature is being able to push application updates to the end users. As it’s quite hard to find complete examples from Adobe, I thought I’d offer you a script how to do it.
Background
Going through the Adobe documentation for HTML and AJAX development, which overall is quite sparse, the information for updating applications isn’t complete for most peoples’ needs, and it doesn’t offer any example of version comparison to see if an update is needed or not.
I was attending the on AIR Tour event in Stockholm last Monday, which by the way was a great event with good presentations and lots of gifts, candy, assorted food for us spoiled web developers. It was good to meet Mike Chambers in person and ask about “cache object is too large to persist to store” errors when developing with Adobe AIR on Macs (this was then solved with the latest Apple OS X upgrade), and to have the possibility to ask Mike and Kevin Hoyt about some of my Adobe AIR ideas and if they were actually possible to realize.
One presentation went through updating applications which was exactly what basically everyone needs. It was written in ActionScript, but unfortunately I couldn’t find any occurrence of it online. After a long time searching, I found another gem: David Tucker’s AIR API – Performing Updates in JavaScript. He has some sample code and an AIR project you can download and play around with.
I wanted to package it even more, and basically make it as easy as possible to adapt to any application. Therefore I created AIRUpdater. What you need to do to use it is:
- Include it on your AIR application page:
<script type="text/javascript" src="js/AIRUpdater.js"></script> - Customize URLs in the
AIRUpdater.jsfile for which URL to use to compare versions, and which to get a new release from. - Adapt the presentation of an update dialog to your end users for the best possible experience.
That’s it!
The code
The code is heavily commented in respect to the parts you can, and should, customize. The general idea is to use your URLs and have one that offers an XML file you can use to do version checking against, and another where you can download the actual update (i.e. the .air file).
This script, in its original form, takes for granted that you use numbers for versioning, since it’s the simplest and most fool-proof approach. Naturally, you can change thus if you want to.
From here, you can download the AIRUpdater code right away, or start by going through the complete code below.
/*
Written by Robert Nyman, http://www.robertnyman.com
Inspired by http://www.insideria.com/2008/03/air-api-performing-updates-in-1.html, and then modified
*/
var AIRUpdater = function () {
// This is only used for the filename of the installer
var applicationName = "MyApp.air";
var applicationVersion = 0;
var latestVersion = 0;
/*
URL to go to to check the value of the <version> and <releasenotes>
The value in version is compared to the one in the applications XML setup file,
and an update dialog is triggered if the <version> in the below XML file is higher
From there on, suggested alternatives for the end user is to
start an update or cancel it for the moment
Suggested XML structure:
<?xml version="1.0" encoding="UTF-8"?>
<application>
<latestversion>0.7</latestversion>
<releasenotes>Added automatic update downloading feature.</releasenotes>
</application>
*/
var latestVersionCheckUrl = "http://www.myapp.com/versioning.xml";
var updateAvailable = null;
var updateAvailableDialog = null;
var releaseNotes = null;
var releaseNotesText = "";
/*
Change this URL to the download URL of your AIR app. Version number
and ".air" extension will automatically be added; version taken
from the XML value found in the latestVersionCheckUrl page
*/
var updaterUrl = "http://myapp.googlecode.com/files/myapp-";
var stream = null;
var updateFile = null;
var getApplicationVersion = function () {
// This will get the version of the currently installed application
var appXML = air.NativeApplication.nativeApplication.applicationDescriptor;
var xmlObject = new DOMParser().parseFromString(appXML, "text/xml");
applicationVersion = parseFloat(xmlObject.getElementsByTagName('version')[0].firstChild.nodeValue);
};
var getLatestVersion = function () {
/*
Checks for what the latest available version is
from the URL specified in latestVersionCheckUrl
*/
var XMLHttp = new XMLHttpRequest();
XMLHttp.onreadystatechange = function () {
if (XMLHttp.readyState === 4) {
var response = XMLHttp.responseXML;
var releaseNotesNode = response.getElementsByTagName("releasenotes")[0];
/*
Adds a reference to a releaseNote for the latest version,
IF a <releasenotes> node exists
*/
if (typeof releaseNotesNode === "object" && releaseNotesNode.firstChild) {
releaseNotesText = releaseNotesNode.firstChild.nodeValue;
}
var latestVersionNode = response.getElementsByTagName("latestversion")[0];
/*
Triggers a version comparison with the existing installed application,
IF a <latestversion> node exists
*/
if (typeof latestVersionNode === "object" && latestVersionNode.firstChild) {
latestVersion = parseFloat(latestVersionNode.firstChild.nodeValue, 10);
compareVersions();
}
}
};
XMLHttp.open("GET", latestVersionCheckUrl, true);
XMLHttp.send(null);
};
var compareVersions = function () {
if (applicationVersion > 0 && latestVersion > 0 && latestVersion > applicationVersion) {
/*
Here you should, for example, present an "Update available" to your
end user, and give them the option to start the update
The code below is just sample code:
*/
// Present release notes for the new version available
document.getElementById("release-notes").innerHTML = releaseNotesText;
// Add onclick event to start update button
document.getElementById("update-application").onclick = initUpdateApplication;
// Add onclick event to cancel update button
document.getElementById("cancel-update").onclick = function () {
document.getElementById("update-available-dialog").style.display = "none";
};
// Show the update dialog to the end user
document.getElementById("update-available-dialog").style.display = "block";
}
};
var initUpdateApplication = function () {
/*
The updating has started. Prefereably, you'd like to hide
or disable the start and cancel update buttons now
*/
stream = new air.URLStream();
/*
This event is recommend to give the end user continuous
feedback about how the update goes
*/
stream.addEventListener(air.ProgressEvent.PROGRESS, updatingStatus);
stream.addEventListener(air.Event.COMPLETE, updateApplication);
// Note that the latest version number and ".air" extension is automatically added
stream.load( new air.URLRequest(updaterUrl + latestVersion + ".air"));
};
var updatingStatus = function (e) {
// This is example code to show updating status
var percentage = Math.round((e.bytesLoaded / e.bytesTotal) * 100);
document.getElementById("current-updating-status").innerHTML = percentage + "%";
};
updateApplication = function () {
var ba = new air.ByteArray();
stream.readBytes(ba, 0, stream.bytesAvailable);
updateFile = air.File.applicationStorageDirectory.resolvePath(applicationName);
fileStream = new air.FileStream();
fileStream.addEventListener( air.Event.CLOSE, installUpdate );
fileStream.openAsync(updateFile, air.FileMode.WRITE);
fileStream.writeBytes(ba, 0, ba.length);
fileStream.close();
};
var installUpdate = function () {
var updater = new air.Updater();
// Notice that the version name has to be present as a second parameter
updater.update(updateFile, latestVersion.toString());
};
return {
init : function () {
getApplicationVersion();
getLatestVersion();
}
};
}();
window.onload = AIRUpdater.init;
Happy updating!
I hope this script helps you as much as it has helped me, since it’s now seamless to start developing new applications and already have this important functionality on place.
Happy Adobe AIR developing!

45 Comments
June 10th, 2008 at 1:39
Good man! Thanks for making it public. Now to crack on with my little AIR app.
June 10th, 2008 at 5:28
Very cool, have you given thought to using JQuery?
June 10th, 2008 at 14:48
Remy,
Well, I got a bit worried that you'd put something out first, so I had to beat you to it.
Douglas,
Thanks! This code was meant to be completely JavaScript-library independent. In my AIR applications I use the faster and more light-weight DOMAssistant; an example can be seen in the updater for facedesk.
June 10th, 2008 at 19:52
[...] updates to the end users isn’t as easy as it seems nor as it should be. I’ve created a script to automatically update AIR applications, inspired by others, but it was far too much [...]
June 13th, 2008 at 15:16
Hi Robert,
This is a handy looking piece of code! I don't see a license applied to it. Is this usable under some open source license?
Thanks!
Kevin
June 13th, 2008 at 21:42
Kevin,
Thank you! It's my bad, I didn't put in the source file…
It is released as open source, under a MIT license (this is mentioned and there's a link to the terms for that license at the AIRUpdater project start page).
July 20th, 2008 at 4:15
If your application has problems downloading the .air installer file from your server, you may need to explicitly set the mime type on your server so it handles the file correctly.
Check out <a href="http://www.rogue-development.com/blog2/2007/10/air-mime-type/” target=”_blank”>www.rogue-development.com/blog2/2007/10/air-mime-… for details.
I had to do this as my server was trying to preprocess the .air file before sending it, instead of just sending it as an application file.
July 31st, 2008 at 23:32
Thank you so much for this!
I'm going to be integrating it into my AIR application that's still in development.
August 19th, 2008 at 0:51
johnbillion,
Thanks for the tip!
Mark,
You're welcome!
September 8th, 2008 at 14:24
What about updating the database ? If changes were made to the SQLite database in the new version, is there a smooth and easy way to detect the changes (fields/tables added/removed) and apply it to the old database ?
September 9th, 2008 at 2:41
Is there a way to have a series of commands executed right after the update is completed only once ?
The idea here is to update the old database with new fields based on the old version number.
September 9th, 2008 at 14:34
seme,
Interesting questions. But no, this only checks version number of the application. If you want to make extra calls when it is done, you need to tweak the script.
October 11th, 2008 at 13:49
We need to develop one sales presentation in flash with Adobe AIR capabilities. The idea is once developed and deployed, sales guys will get updated content using Adobe AIR Update Frame work. As the intial application will be around 10 mb and it will have many seperate SWFs. We intend to update only few swf or few XML files in further release of applicaiton. Otherwise updating entire APP will be of Huge size. Does AIR have this kind of support / capabilities.
October 11th, 2008 at 22:14
Hemagiri,
As far as I know, it's not possible.
October 24th, 2008 at 10:35
Even though you can't update only parts of an AIR app using the AIR Updater framework, you could certainly incorporate your own code to download and overwrite specific xml/swf files. So your sales guys wouldn't know the difference, and (perhaps even better, depending on your viewpoint) the app wouldn't have to restart after downloading the new content.
The code to download would be very similar to initUpdateApplication above, and when it's done the app could display its own message if you want, or it could just start using the updated files seamlessly.
At work we have a digital sign app which gets new XML playlists and data feeds, FLV / SWF video ads and static image ads, and they automatically update those assets without AIR's update framework, and when the app itself needs a fix, it uses the update framework.
October 27th, 2008 at 0:31
HB,
Absolutely, that could be an interesting option!
October 30th, 2008 at 12:28
[...] Learn more on how to push application updates to the end users @Â AIRUpdater [...]
November 2nd, 2008 at 6:05
I feel like a complete idiot asking this because it should be such a simple question….
but I've been trying to figure it out all day.
How do I provide an ok/cancel (or yes/no) confirmation window within the application when it loads to state there's an update available and give the user the option to upgrade now?
I see the "release-notes" and "update-application" in the js above, but everything I've tried on my application didn't seem to do anything.
I have the above code in a js file and imported in the header.
Many thanks,
Shannon
November 2nd, 2008 at 11:23
Shannon,
There's also an element named cancel-update expected, if you look closer in the <code>compareVersions</code> method. Just make sure to have an element named that, and a click on it will hide the update dialog.
December 9th, 2008 at 4:32
Great script. I knew nothing, now I know a bit more
Anyone seen a packaged script like this that handles docking and undocking an air application to the system tray. I can’t seem to find anything that doesn’t rely on Flash, Flex or AS3.
December 30th, 2008 at 10:43
Sorry because I try to fix my comment format but it’s not ok. You can read my full question in http://www.actionscript.org/forums/showthread.php3?t=192460
December 30th, 2008 at 12:29
Hi Robert Nyman! I have problem with javascript. Can you help me? I try to use Javascript inside Actionscript which call MS word to read document. But it error when I initial ActiveXObject.
Here is my code
test.mxml
<code>
</code>
htmlwithJS.html
<code>
function loadworddoc(){
var doc = new ActiveXObject("Word.Application");
doc.Visible=false;
doc.Documents.Open("C:SamSam.doc");
var txt;
txt = doc.Documents("C:SamSam.doc").Content;
document.all.myarea.value = txt;
doc.quit(0);
}
test now
</code>
If I run AIR app the error message is : ReferenceError: Can't find variable: ActiveXObject but if I run each htmlwithJS.html I can see it load MS Word document. Why it is wrong?
Thank any suggest!!!
Hai Anh
December 30th, 2008 at 12:38
Hi Robert Nyman! I have problem with javascript. Can you help me? I try to use Javascript inside Actionscript which call MS word to read document. But it error when I initial ActiveXObject.
Here is my code
test.mxml
<code>
</code>
htmlwithJS.html
<code>
function loadworddoc(){
var doc = new ActiveXObject("Word.Application");
doc.Visible=false;
doc.Documents.Open("C:SamSam.doc");
var txt;
txt = doc.Documents("C:SamSam.doc").Content;
document.all.myarea.value = txt;
doc.quit(0);
}
test now
</code>
If I run AIR app the error message is : ReferenceError: Can't find variable: ActiveXObject but if I run each htmlwithJS.html I can see it load MS Word document. Why it is wrong?
Thank any suggest!!!
Hai Anh
December 30th, 2008 at 15:40
enlightened,
Sorry, no ideas there.
hai anh,
Sorry, I have no idea how to solve that.
December 30th, 2008 at 22:41
[...] AIRUpdater [...]
January 12th, 2009 at 20:58
[...] How to update Adobe AIR applications automatically with JavaScript – AIRUpdater.js – robertnyman.com [...]
March 2nd, 2009 at 23:55
Have you given thought to reworking this code to take advatage of the new built in updater class?
March 3rd, 2009 at 0:03
Andy,
No, not at the moment, but if you want to give it a go, feel free!
March 29th, 2009 at 12:42
Awesome, thanks for sharing! Has anyone seen anything for auto-PACKAGING AJAX AIR apps on a server? I'm thinking about being able to dynamically build an AIR installer on a Linux server based on simple choices in a PHP-based UI… searching for possible deployment solutions.
June 19th, 2009 at 5:42
hi to all
well ive recently finished an app which i made in flash cs4 and converted to an air app….the issue iam having is the update code….iam wanting to create a seamless install and have the air app update the users app when i update mine on my server..ive tried so many options and tried to find info,i think i nearly nailed it,but the update method doesnt seem to work i get an error Error #2044: Unhandled IOErrorEvent:. text=Error #2032: Stream Error.
at VisNova_fla::MainTimeline/frame1()[VisNova_fla.MainTimeline::frame1:66]
also this error Error: This method is not supported if application is launched from ADL.
at flash.desktop::Updater/update()
this is my code
import flash.desktop.*;
import flash.filesystem.*;
import flash.net.*;
var updater:Updater = new Updater();
var airFile:File = File.desktopDirectory.resolvePath("VisNova.air");
var version:String = "2.01";
updater.update(airFile, version);
var urlString:String = "http://visnova.biz/AIR/vis/VisNova.air";
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
function loaded(event:Event):void {
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
writeAirFile();
}
function writeAirFile():void {
var file:File = File.applicationStorageDirectory.resolvePath("My App VisNova.air");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(fileData, 0, fileData.length);
fileStream.close();
}
iam not very experienced with as3 and this is my first air app,but its for my users that buy my products,so its very important to me….if someone is willing to help,i will pay for there services…you can contact me at [email protected]
thanks….Shayne Shiells
June 19th, 2009 at 13:15
Greg,
Thank you!
shayne shiells,
I'm sorry, I don't have any experience with how to do that with Flash in Adobe AIR. Good luck!
July 23rd, 2009 at 19:12
Thanks for this mate – just what I needed
August 17th, 2009 at 1:35
brothercake,
Sweet! It's an honor to help someone like you!
November 12th, 2009 at 3:43
Just what I needed to polish off an app that I'm creating. Well commented so I could easily modify it to suit my requirements. Thanks for sharing.
April 10th, 2010 at 2:02
Brilliant script! I can't tell you how grateful I am, this has just saved me countless hours. Thank you!!
August 9th, 2010 at 6:23
Hi Mate,
I dont know if this is just me being stupid, but I cannot get this to work
I have a microsite which im distributing via USB sticks as an air app. I have set the version in the application.xml file to 1.0 and packaged the app and installed it
I have then created a version called with 1.1 in the application.xml file, saved it as abstracts-1.1.air and uploaded it to the location that i pointed to in the AIRUpdater JS file. I haev also included a versioning.xml file with the correct information in it also.
However, no matter what i do I dont get a dialogue saying update available.
Anything ive missed?
Thanks
Dan
August 16th, 2010 at 0:37
Dan,
Sounds ok at least. Sorry I can't help more, was quite some time since I worked with it.
June 22nd, 2011 at 16:28
[...] across very interesting article by @robertnyman and one by David Tucker Bookmark on DeliciousDigg this postRecommend on [...]
September 8th, 2011 at 12:50
Found this at cookbooks.adobe.com:
Updating an AIR application with the Update Framework – AIR 1.1
… and this one at help.adobe.com:
Updating AIR applications
October 5th, 2011 at 21:45
Hello, Awesome script, thanks for posting it, I realize its pretty old but it helped out a ton. Question… After making the air file, note I don’t have a certificate but am just developing it and testing my app right now. I get an error after the update saying installer is misconfigured.
Any thoughts on this?
October 7th, 2011 at 1:39
josh,
Sorry, no idea. Haven’t worked with it in years.
November 7th, 2011 at 0:21
Thanks Robert, it’s very2 simple.
January 28th, 2013 at 21:24
First of all thanks for the code. But i’m keep on trying to update my application it says “This application cannot be installed because this installer has been mis-configured. Please contact the application author for assistance.”
How to fix this?
I have tried with change the certificate (created 2 certificates for each air package).
Version is 0.9 to 1.0
I’m using air 2.0
Application working fine. Only updater is the issue.
What is the solution here plz?
January 28th, 2013 at 21:30
Even if i try to install the package manually it asks for replace the version. But while auto update it says misconfigured. What shall i do
January 29th, 2013 at 10:30
Manoj,
Sorry, the code here is 4 and a half years old, and it’s very likely that Adobe have changed things since.
I’d recommend talking to them. Good luck!
Write a comment