How to compile both Flex and AIR Application from the same codebase.

Today, I decided it would be easier for me to demonstrate my AIR application to end users if they could just go to a link on a website.  However, getting AIR code to compile into a Flex SWF file, isn't as simple as I initially thought.  Naturally, there's the additional APIs that AIR allows the developer to use, like all the local file system interaction.  But, I figured I'd just use some form of pre-processor compilation tags, place them around the code I didn't want, compile,  call it a day, and drink a beer.  Wrong.

I searched around a bit and found a few conversations discussing how one should go about doing this.  David Coletta had some ideas posted over at his blog.  But I couldn't find any working code.  Since this took me several hours how to get it working, I thought I'd share my sample project files with you.  Mind you, I'm not totally happy with my solution and think it can be improved upon, but it's a start.

Download the code here.  (It's only for Flex Build 3, Moxie.)

The solution:  create thee projects.  One for your AIR application, one for your Flex application, and one to place most all the code, we'll call it CommonCode.  For these three projects, you create source path references to each other to include common code into their build paths.

The AirCode project includes a source path to the CommonCode project.

The WebCode project includes a source path to the CommonCode project.

Media_httpwwwsimplifi_fgpph

The crux of the solution involves coding common code to Interfaces defined in the CommonCode project.  Both the Air and Flex Projects then Implement these interfaces into concrete classes specific to their projects.  For Air, the implementation might include functionality to save to local file system (File.browseForSave).  In Flex, you may prompt the user for an email address to send the file to. 

The other part of this solution is the shared UI.  The UI for both applications is defined in CommonCode::TestCanvas.mxml.  The AirCode and WebCode projects load this in their respective MXML files -- AirCode.mxml and WebCode.mxml -- upon starting.

At runtime when you need to save a file, you selective create the appropriate class depending on the runtime environment (Flex vs AIR), and then call the method on the Interface.   The following shows the basic implementation of the GeneralFactory class.

Media_httpwwwsimplifi_vjkjz

Misc thoughts :

    1. Security.APPLICATION static string declarations exists only in the AIR framework.  Trying to reference that from a Flex project will result in a compilation error.  Use the string "application," instead.   Same goes for Capabilities.playerType DESKTOP, use the string "desktop" instead -- if using that method of determining whether you're running in the browser or in AIR.
    2. The Flex compiler will not include any classes that aren't explicitly referenced in the code.  This must be an optimization.  Because of this, you need to include a declaration to all your classes that you want to have dynamically generated at runtime.  (Look at the static const called neededForCompilation in both the AirCode.mxml and WebCode.mxml -- this is essential for compilation.)
    3. I don't like having the class names hard-coded as strings in the Common Code.   I could get around this by making some a Factory available on each the FlexProject and AirProject, but this seems to be a little too complicated.  For now, this is a livable solution
    4. This is for compilation purposes only.   There's no dynamically loading modules at runtime. 
    5. There is one negative side effect:  this slows compilation time considerably.  I now feel like I'm working in C++ back in the mid-90s.

I'm welcome to ideas on improving this implementation.  Also, does anyone have any code or CSS stylesheet for including ActionScript code in a blog without creating an image of it?  Thanks.