I wanted to make some kind of loader, which loads swf file, and accompanying asset files ( like for example dynamically loaded images or xml configuration files ) from one zip archive. Then we could have only 2 files – loader file and an archive with an application to load, instead of bunch of folders and files.
I wanted to make it cross-platform, so I’ve tried to do it in Adobe AIR ( standard flash player won’t allow us to create any files or folders ).
It would also serve as a Flex to AIR converter, becasue you add your Flex application’s files to data.zip archive, launch our AIR loader, and you have your Flex application running in AIR, without need to change xml files and so on.
We have AIR’s File class, which allows us to create folder and files.
So the basic idea is:
- unpack data.zip into some temporary directory ( File.applicationStorageDirectory is recommended by Adobe lang reference… )
- run some .swf file found in unpacked files.
Yes… No. That’s not possible. You cannot run files from appStorageDir. Stupid sandbox violation errors will appear. SandBox in standalone applications… gr8 idea.
You will think of a hack: Let’s load this swf into ByteArray, and then execute this ByteArray using Loader class!!!
for example:
var ldr:Loader = new Loader();
var fstream:FileStream = new FileStream();
fstream.open( YOUR_SWF_TO_LOAD , FileMode.READ );
ldr.load( fstream.readBytes() );
… Ok, it will run, but it won’t see any other files you’ve unpacked. Suppose we have config.xml in applicationStorageDirectory. It won’t see this config.xml, it will only see files in applicationDirectory – directory where our loader resides.
Ok: so let’s abandon this useless applicationStorageDirectory, and unpack everything to applicationDirectory. You think they will let you? Ha! You ingenuous little developer. They of course knows better what’s good for you. You can’t write to applicationDirectory. They say “it’s a bad practice”, and they also say “better use applicationStorageDirectory” They also say “make sandbox bridges to run active content from applicationStorageDirectory”. Sandbox bridges? This just some trivial feature in HTMLLoader class. SWF which runs in HTMLLoader is rendered by built-in flash AIR browser, and it runs 10x slower than it could in pure standalone flash player.
Ok, so we are still stuck with the problem – how to run this swf in AIR – and another problem – we can’t write to applicationDirectory. But wait… we can write to any other directory… So we can write to applicationDirectory too.
This is so stupid … Look, this causes security exception:
var new_directory:File = File.applicationDirectory.resolvePath( "some_new_directory" ); // create path to "some_new_directory" in our loader's directory
new_directory.createDirectory(); // <---- ERROR
And this doesn’t:
var new_directory:File = new File( File.applicationDirectory.resolvePath( "some_new_directory" ).nativePath );
new_directory.createDirectory();
We basically create new File object, with path equal to File.applicationDirectory/some_new_directory, but flash doesn’t know it’s our apps dir, so it doesn’t throw an exception. The rest is obvious – we execute .swf using File.applicationDirectory, because all files we need are actually in our application’s directory. And this is the simplest possible detour for these unnecessary sandbox “feature”.
And finally I’ve made this AIR swf loader, but… It appears, that files you load into AIR application has fewer fps, than they could have, when run stand-alone.
These are the mxml sources, along with some additional dependencies, in case you’d ever want to load some swf’s dynamically from AIR.
It depends on “newzip”, nochump’s zip loading library, which I’ve modified slightly, to support asynchrounous loading ( then if you’ll have 30MB zip, your flash won’t hang due to timeout exception ). Just build .air package along with your data.zip archive ( the .swf files to launch ) and you’re ready to go. Sample data.zip included.