Erik’s Brain

The reward of a thing well done...

Loading in Local External Assets Into an Air App

I’ve recently been tasked with turning an existing Flash app (that is to say, a self contained Windows EXE/Mac App) into an Air app. The original was only meant to run locally. It was never meant to be hosted on a web server. This module depends on loading in lots of external XML docs and images when you navigate to different sections. When loading in an XML doc, the code looks something like this:

1
2
3
4
5
6
7
8
9
10
// make the URLLoader that'll load in XML doc
var _l:URLLoader = new URLLoader(new URLRequest(_url));

// add a listener to use when the XML doc has loaded
// The xmlLoaded() method actually creates the XML object
_l.addEventListener(Event.COMPLETE, xmlLoaded)

// load in an XML doc named "myxml.xml" located in the
// "swf_assets" folder that's next to the SWF
_l.load(new URLRequest("swf_assets/myxml.xml"))

That should look familiar to you if you’ve loaded in an external XML doc before. But this doesn’t work with an Air app. Why? You don’t package external files with an Air app like you do with a SWF. So you need to handle finding external files differently with Air. It goes a little something like this:

1
2
3
4
5
6
7
// the File object is used to find the location of the
// XML doc we want to load in
var file:File = File.documentsDirectory.resolvePath("air_app_assets/myxml.xml");

// Pass the file.url property to the URLRequest constructor
var _l:URLLoader = new URLLoader(new URLRequest(file.url));
_l.addEventListener(Event.COMPLETE, xmlLoaded)

What that File.documentsDirectory.resolvePath business is doing is telling the Air app to go to the computer’s Documents directory, then dig into the “air_app_assets” folder to find the “myxml.xml” doc. The key here is that Air will know where the Documents folder is. It’s different on OS X vs. Windows vs. Linux. We just need to make sure that the “air_app_assets” folder lives in the Documents folder.

This isn’t an ideal solution. Had I known that this SWF was going to turn into an Air app, I would have set things up a lot differently. But at this point it’s not worth the trouble to deal with turning a TON of XML docs into a database.

The same principles used above will work for loading external images into your Air app. The key remains using the File class to tell Air where to find the files you want to load in. We can’t just pass in folder and file names when creating new URLRequest instances.

It took way too long to figure this out. I originally found a more complicated way to do this. It went like this:

1
2
3
4
5
6
7
8
9
10
11
// Same as before...
var file:File = File.documentsDirectory.resolvePath("air_app_assets/myxml.xml");

// We're going to use a FileStream object to load in the XML doc
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);

// Use the FileStream.readUTFBytes() method to write the myxml.xml data
// directly to a new XML object
var _xml:XML = new XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();

That worked and I thought it was the only way to handle loading in external assets that lived on the user’s hard drive. But that’s messier and I like the first method better.

I’m new to this Air thing. Maybe method two is better. I really don’t know. If someone has a real answer and can explain it, I’d love to hear!

Comments