The back story
(skip ahead to the solution)
So I have been doing quite a bit of work lately with continuous integration and auto-builds using Hudson (which I am really liking). And one of my goals is to have applications abstracted in such a way that the same build that is used for local development can also be used in QA, staging and deployment, but be fed different settings appropriate for each environment. That way when you addressing issues that seem to always crop up when you deploy to live, you don’t have to wonder what’s different between the different builds you would normally have to make to incorporate the varying environment settings.
I primarily develop in Flex these days, and I had been using the Config class of the FlightXD framework to load a localConfig.xml settings file using the XMLConfig sub-class. This class is very nice and simple in that you specify an xml and the values that are pulled from that file are accessible globally through a static reference to the Config class. Although this was very easy and straight-forward, there were some draw-backs to loading a config file at run-time. First of all, if say the URL to your services is loaded up with this file, you have to wait until the xml file has loaded and the values have been populated. And as of right now, the XMLConfig class has no event to listen for to let you know when that has happened. So I had to put in a hack to look for a “loadedDone” property (that was the last property in the xml) to be set every 100ms, and then proceed to initialize the application. Even though this doesn’t have much of a delay, it’s enough to be annoying.
I next turned to FlashVars to load in my settings. These are a little harder to work with since now the html wrapper file has to be different for each environment, but they have the significant advantage in that the values are immediately available at run-time. Also, the Config class of the FlightXD framework also has a FlashVarsConfig sub class that can handle those for you as well.
So these are great for my Flex web-apps, but now I have a project that is an AIR app and I still want environment settings to be abstracted. So after a few hours of Googling I came across several posts about getting arguments when the AIR app is launched from the command line, most notably “Passing parameters to Adobe Air at startup” from Cesare Rocchi’s “Spreading Funkyness” blog. (Which I really think should be titled “Passing arguments to Adobe Air from the command line”.) But no solutions similar to FlashVars. But in looking around at what is packaged with an AIR app when it is installed I noticed the application descriptor file application.xml, and after looking through that for a bit I found my solution. At first I tried to add arguments to the reference to the swf file in <content>, but then the compiler complained about a bad URL, and then I knew what might work.
Each AIR project has a application descriptor file named after the project, like MyProject-app.xml. This file is automatically created when a Flex Builder or Flash Builder Flex Air project is created. One of the nodes in this file is <content>. It is a child of the <initialWindow> node. This is the path to the swf file used in the AIR application. If this file was created by Flash Builder it will look like this:
<content>[This value will be overwritten by Flash Builder in the output app.xml]</content>
When the AIR app gets compiled this line gets changed to look like:
If we set the name of the swf directly in <content> we can then add URL parameters to the swf since <content> is really a URL reference.
We can add multiple parameters by separating them with a “&”, but remember, the application descriptor file is xml, so an ampersand needs to be escaped like “&”.
We can reference these values from within the AIR app using the parameters object which is a property of the base application. So from the MyProject.mxml it would be this.parameters.
this.parameters.myVar == "valueOne"
this.parameters.anotherVar == "valueTwo"
So by setting these values here, I can slip in the values I need at build time in Hudson depending on the target environment, and then the modified application descriptor file is packaged into the AIR installer.