Runtime Flash CS3/Flex Integration via SWF9 files
DIGG IT!
14
Comments
Published
Monday, November 12, 2007
at
1:52 PM
.
Using the flash.net.Loader or mx.controls.SWFLoader classes it is easy to load any SWF file into a Flex application for display. The problems begin when you want to use these assets at runtime and dynamically load SWF files containing custom MovieClips/Variables/Methods/Etc. This is possible but you must do some prep work to avoid 2 problems:
1. Dynamic access to the loaded SWF file!
2. A loaded SWF can only create class instances within itself!
Once you address these two issues, you can really take the gloves off with dynamically loaded libraries and SWF content.
1. Dynamic access to the loaded SWF file
The first problem is easy, to access methods/properties within a loaded SWF you simply need to make the calls dynamic from Flex so that they compile properly. The Flex compiler wants to know in advance that methods in the loaded SWF file are present and will not let you compile otherwise given that the SWFLoader.content returns a DisplayObject by default. The key is forcing the compiler to evaluate member access into the loaded SWF as dynamic vs the strongly typed value of DisplayObject.
Here is an example:
//Create a loader to load a SWF into.
var myLoader:Loader = new Loader();
//Load a SWF into the loader
myLoader.load( new URLRequest( 'custom.swf' ) );
//after the SWF has loaded
//Cast the 'content' property as a MovieClip
//call the getInstance method defined in Frame 1 of my CS3 AS3 SWF file
//note the use of casting via MovieClip at the SWF boundary
MovieClip(myLoader.content).getInstance("DA");
Here is the same code without type casting, since .content returns a DisplayObject the compiler complains because there is no 'getInstance' method on a DisplayObject:
myLoader.content.getInstance("DA");
In this case the Flex compiler will throw the following error:
"1061: Call to a possibly undefined method getInstance through a reference with static type flash.display:DisplayObject"
Once access to the loaded SWF file is dynamic you are free to call any method or property.
2. A loaded SWF can only create class instances within itself!
The second problem is that Flash Player will only allow a SWF to create instances within itself. The instances can be passed anywhere in the player but the constructor must be called within the scope of the loaded SWF file. Using a Factory-like method we can create a method within the loaded SWF to provide instances to the parent Flex/AS3 application. This is very handy because it allows us to make the interface to generating instances simple. I use a method called 'getInstance" and pass a string that correlates to the class name. In the example below, I simply return a new MovieClip instance when this method is called and create different MovieClips depending on what is requested. The parent Flex app can save these as variables and use them as it wants.
The example below loads a SWF file (cards.swf) containing all the card designs in a deck of cards and instances are created and passed to the parent Flex application. Since the SWF was made in CS3, I was able to design the cards look and feel easily and can provide an FLA to any designer to enhance these.
Runtime Playing Cards
Runtime Playing Cards Source
Once you pass these two hurdles you can seamlessly integrate dynamically loaded SWF graphics and AS3 libraries into any part of your Flex application at runtime. Let the mayhem begin!
Cheers,
Ted :)

I'd be more impressed if there was a legacy way of communicating with dynamically loaded as2 code from newer as3 base swf files.
It's not uncommon for there to be a lot of as2 work already done on a large project, even if all it is is simple animation control. It's still better to use existing code that works than waste money developing newer "better" code that just does the same thing.
You can use local sockets to communicate between as2/as3 but this is flakey at best. A simple solid well designed messaging system between the two machines would be fairly simple to create and ease the uptake of as3 on any as2 project. Yes its a bit icky, but in the real world engineering is always a bit icky.
I thought backwards compatibility was something that the flash team cared about?
Have you ever tried integrating Flex SWFs in a Flex application? As far as I know this doesn't work at all... Not only from a PopupManager point of view but just in general. It just doesn't seem to work... Can someone confirm this?
The jump from AVM1(AS1/2) to AVM2 (AS3) is a new virtual machine. There are two vm's in Flash Player both supporting different bytecode formats and AVM2 provides substantially improved performance.
When you load an AVM1 SWF into an AVM2 SWF (Flex/Flash) via loader it instanciates the legacy VM. This is two virtual machines working in parallel processing code. The problem is that tieing thise to VMs together is difficult, very difficult. If the two are tied together it will run with the performance of the slower VM which sort of defeats the purpose.
During development of AVM2 a decision was made to keep the VM's separate as tieing them together would hinder performance in the new areas. AVM1 to AVM2 is a hard line.
In many cases porting working code to AS3 is very productive as many barriers were removed in the new AVM2 and the api's within. It is a much more professional development model, better compiler, better degugger, better error messages, and strong typing. I personally thing the trade-off here was well worth it.
Hope that helps.
Ted
For loading Flex SWF files into Pop-Up Manager the problem is the base class of Application. Use Modules. Create a ModuleLoader and denote a URL to the same application packages as a Module. It will work seamlessly.
Ted :)
Personally I am very happy with the incompatibility of AS2 to AS3 due to the two VMs. I don't believe backwards compatibility would be worth the sacrifices that would have to be made to achieve it, for the brief period of time that it would be useful. It would also slow down the acceptance of AS3 and hurt the viability of the platform in general. But this post is not at all about AS2/AS3 compatibility. It is about Flex/Flash compatibility, which is of concern if Flex is to be embraced by those who like the experiential nature of Flash. Thanks for the tips Ted.
Ted,
The fact that you can't integrate Flex applications using the Application object (like all Flex applications do...) means that you can't build an online desktop solution that integrates different Flex applications from different vendors (I can't ask them to change their 'application' based solutions to 'modules' based solutions). Wouldn't it be possible to have some kind of iframe-mechanism for integrating any Flex application in another Flex application? Next question is of course: when will I be able to integrate non-Flex applications (like AJAX based websites or even, God forbid, Silverlight applications) in my Flex based desktop?
Best regards,
Tom
ria flex:
I've integrated Flex SWFs into a Flex app...
I assume you're talking about a compiled Flex SWF? If so, you can definitely do this (I am currently using it in an app):
Assume I have 2 Flex apps (and have the source AppToLoad when compiling HostApp):
HostApp.swf
AppToLoad.swf
and you want to load AppToLoad.swf into HostApp:
1. Load the AppToLoad.swf into a SWFLoader.
2. Cast the content of the SWFLoader to AppToLoad.
3. Call directly into AppToLoad using it's public functions
The casting part was a little tricky, but you can do it like this:
import mx.managers.SystemManager;
function timeToCastAppToLoad():void {
var atl:AppToLoad = (swf.content as SystemManager).application as AppToLoad;
atl.functionDefinedInAppToLoad(); // just called into AppToLoad from HostApp
}
...
<mx:SWFLoader id="swf" source="AppToLoad.swf" />
I have a nice bells and whistles "container" app made with Flash CS3, and want to load the boring but functional Flex-made swf files into it. At first this didn't work at all... AH! ActionScript 3! Spend DAYS converting all the code in the container movie to AS3. Now it loads the Flex swf... but it looks completely wrong. It's asif the skin of the Flex SWF is missing. I can only see the text... so a datagrid consists of these disjointed little column headers and stuff floating around. Other than that the buttons actually work and everything seems fine. What's missing here? I don't need to communicate between flash and flex... I just want it to display correctly.
Casting to AppToLoad doesn't seem to work for me. I get an "Access of undefined property AppToLoad" error. How would the compiler know what AppToLoad is? Right now to get it to work I cast it as Object after I cast the loader.content to SystemManager.
Any idea what I'm doing wrong?
ok, i get it now. In order for you to type cast to AppToLoad you need to have AppToLoad in the class path of the loaded swf. there are basically 2 methods for accessing members in a loaded swf (from Colin Moock's Essential AS 3.0 book around page 783):
1. Opt out of compile type checking. This is what I did by casting to Object although the implementation depends on weather or not the object was created in Flash CS3 or Flex (which i think is unfortunate).
2. Give the Compiler Access to the loaded class by one of the following:
a. Adding the module class (loaded swf dir) to the class path
b. adding the module class to the library path
c. Adding the module class to the external library path
I'm going crazy with an AVM1 swf issue. It loads and runs fine. But it propagates no mouse events. Even attaching a listener to loader.content gives me nothing. Any ideas on this?
This was a great tutorial! I'm hoping you can provide an answer to a similar question scenario.
I'm loading an SWF9 file into my Flex app. and want to call a Flex function from the imported SWF. I need to be able to tell Flex when the SWF has finished playing.
SRSLY, THX... for the article. I am trying to load a flex app into a flash swf. The app loads and I can listen for events across the apps, however when I try to access functions defined in the flex application's mx:Script tag. The (public) functions cannot be found(i've done a dom search yielding nada)
How can I call a Flex method from my imported swf?
If my swf contains a form and the user clicks on the submit button, I want to call a flex function that retreives the fields and sends them, for example, to a webservice function.