Gyandas's Blog

flavour's of RIA

Tutorial: Talking between Flex 3 and Flash CS3 SWFs

For a project I’m working on I needed a way to be able to write a Flash CS3 SWF, put some controls into it as well as some methods and be able to call those methods and subscribe to the control’s events in the Flash CS3 SWF from Flex 3. When your working with Flash CS3 and Flex 3 things get much easier than using things like the LocalConnection class (not needed for Flash CS3 AS3 to Flex 3 communications). Here is a quick tutorial on how to do this.

This won’t be anything pretty to look at, keep in mind this is just a tutorial to show you how to hook this stuff up. Obviously you would want to clean things up and make the UIs look pretty, etc.

First, fire up Flash CS3 and create a new “Flash File (ActionScript 3)”. Save the Project as “Test.swf”. I then created a new MovieClip and added two controls to it: A TextInput control called “test_txt” and a Button control called “test_btn”. I also added some code on the first frame of the new MovieClip as seen in the image:

jan172008-s1.jpg

Publish this SWF from the Flash file menu.

Now open up Flex Builder 3 and create a new Flex project and call it “TalkToFlash”. Drag a SWFLoader control onto the design surface and set the following properties
id: mySWF
source: Test.swf
autoload: true
creationComplete: creationComplete();

Take the Test.swf that you just compiled in Flash CS3 and drag that into Flex’s bin-debug folder. Now, in Flex Builder you will need to add some code. Here are the MXML contents:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
        <![CDATA[
            import flash.display.MovieClip;
            private function creationComplete():void
            {
                var mc:MovieClip = MovieClip(mySWF.content);
                mc.myMovie_mc.TestMovieCall();
                mc.myMovie_mc.test_btn.addEventListener(MouseEvent.CLICK, onClicked, false);
            }
            private function onClicked(evt:MouseEvent):void
            {
                trace("The Flash CS3 Test button was clicked");
            }
        ]]>
    </mx:Script>
    <mx:SWFLoader x="469" y="136" source="Test.swf" creationComplete="creationComplete();" autoLoad="true" id="mySWF"/>
</mx:Application>

The code should be pretty straight forward. We essentially cast the mySWF.content into a MovieClip (if we didn’t it would have come back as a DisplayObject). At that point we have access to pretty much anything in that Flash CS3 SWF. Run the Flex project in debug mode (so you can see the trace results). Immediately you should see the textbox give you a greeting. Now click the button in the loaded SWF. You should see a trace message down in the Flex Builder console.

jan172008-s2.jpg

So with that small amount of code we could call methods in the SWF and subscribe to events as well. Also, nothing would stop you from defining your own custom events and using those – which is what I have to do now for my project.

May 17, 2011 Posted by | Adobe Flash, Adobe Flex, Flash Support, making flash development easy | Leave a Comment

Accessing document class of an externally loaded swf with AS3

I have seen a lot of posts lately with people asking how they can access variables and methods in an external swf that is loaded at runtime using AS3. This isn’t a difficult task, but it is much different than AS2/AS1 where you could just call directly into the loaded swf using the instance chain if you were in the same security sandbox.

First off, lets create our swf that wil be loaded in at runtime. Open up your favourite actionscript editor and create a new class with the following code.

package com.scottgmorgan {
     import flash.external.ExternalInterface;
     import flash.display.Sprite;
     public class ExternalMovie extends Sprite {
          public function ExternalMovie():void {
               //nothing in our constructor right now.
          }
          public function alert(msg:String):void {
               trace(msg);
               ExternalInterface.call('alert', msg);
          }
     }
}

Now create a new FLA and set the above class as the document class. If you are not sure how to do this simply enter the class path (com.scottgmorgan.ExternalMovie) into the document class textfield found in the property panel. Lather, rinse, repeat, compile.

Next we will create the swf that will load our ExternalMovie swf we just created. Let’s jump back to our favourite actionscript editor and create a new class with the following code.

package com.scottgmorgan {
     import flash.display.Loader;
     import flash.net.URLRequest;
     import flash.events.Event;
     import flash.display.LoaderInfo;
     import flash.display.Sprite;
     public class SourceMovie extends Sprite {
          public function SourceMovie():void {
               var loader:Loader = new Loader();
               loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
               loader.load(new URLRequest('ExternalMovie.swf'));
          }
          private function onLoadComplete(e:Event):void {
               var loaderInfo:LoaderInfo = e.target as LoaderInfo;
               addChild(e.target.content);
               var swf:Object = loaderInfo.content;
               swf.alert('Hello World');
          }
     }
}

That’s it, LoaderInfo saves the day. LoaderInfo.content connects you with the document class of the externally loaded swf. Lets create a new FLA, assign the SourceMovie class as the document class and compile. Make sure the SourceMovie.swf and ExternalMovie.swf are in the same directory. The as files should be in /com/scottgmorgan/. Let’s compile the SourceMovie and you should see “Hello World” in the output window if you run the swf inside the IDE, if you run it from a browser you should see an alert dialog with “Hello World”.

Another option you have is to use the ApplicationDomain class. Using the ApplicationDomain class you can add the classes from the ExternalMovie to the SourceMovie’s ApplicationDomain. This is a great way to load in code libraries at runtime.

Lets pretend we have a large application with multiple levels of security, maybe we are creating a content management system and we need multiple permission levels. User A can only update content, User B can update content and update the site map, User C is an administrator and can do everything User A and B can do but can also access tracking information, edit user profiles, update permissions, etc. When User B logs in the application loads the site map code library (sitemapadmin.swf) and adds its classes to the main ApplicationDomain. When User C logs in the sitemapadmin.swf classes would be added to the main ApplicationDomain, for this user the application would also load the trackingadmin.swf, and useradmin.swf code libraries and add all the included classes to the main ApplicationDomain.

Let’s update our SourceMovie.as file and add the ExternalMovie class to SourceMovie’s ApplicationDomain.

package com.scottgmorgan {
     import flash.display.Loader;
     import flash.net.URLRequest;
     import flash.events.Event;
     import flash.display.LoaderInfo;
     import flash.display.Sprite;
     import flash.system.ApplicationDomain;
     public class SourceMovie extends Sprite {
          public function SourceMovie():void {
               var loader:Loader = new Loader();
               loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
               loader.load(new URLRequest('ExternalMovie.swf'));
          }
          private function onLoadComplete(e:Event):void {
               ApplicationDomain.currentDomain.getDefinition("com.scottgmorgan.ExternalMovie");
               var myExternalMovie:ExternalMovie = ExternalMovie(e.target.content);
               myExternalMovie.alert('Hello World');
          }
     }
}

There you have it. One thing you will notice is you don’t have to add the loaded swf to the display list to access its classes. Hopefully you will be able to use these techniques in future projects.

May 17, 2011 Posted by | Adobe Flash, Adobe Flex, Flash Support, making flash development easy | Leave a Comment

Embedding assets from SWF files

Another cool way to embed assets into a Flex application is to load a SWF file and embed specific library assets using the [Embed] metadata and specifying the library symbol to embed.

Full code after the jump.

The following example embeds three different symbols from the “assets/icons.swf” file. Each asset is given its own unique variable so even though there is only one SWF file, you can easily reference each individual library asset:

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/07/25/embedding-assets-from-swf-files/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white">

    <mx:Script>
        <![CDATA[
            [Bindable]
            [Embed('assets/icons.swf', symbol='bulletCheck')]
            private static var BULLET_CHECK:Class;

            [Bindable]
            [Embed('assets/icons.swf', symbol='bulletCritical')]
            private static var BULLET_CRITICAL:Class;

            [Bindable]
            [Embed('assets/icons.swf', symbol='bulletWarning')]
            private static var BULLET_WARNING:Class;
        ]]>
    </mx:Script>

    <mx:Button id="checkBtn" label="Check" icon="{BULLET_CHECK}" />
    <mx:Button id="warningBtn" label="Warning" icon="{BULLET_WARNING}" />
    <mx:Button id="critcalBtn" label="Critical" icon="{BULLET_CRITICAL}" />

</mx:Application>

You could also make the code a bit nicer (in my opinion) by moving those Embed tags and variable names into an external ActionScript file, as seen in the following example:

Images.as

/**
 * http://blog.flexexamples.com/2007/07/25/embedding-assets-from-swf-files/
 */
package
{
    public class Images
    {
        [Embed('assets/icons.swf', symbol='bulletCheck')]
        public static const BULLET_CHECK:Class;

        [Embed('assets/icons.swf', symbol='bulletCritical')]
        public static const BULLET_CRITICAL:Class;

        [Embed('assets/icons.swf', symbol='bulletWarning')]
        public static const BULLET_WARNING:Class;
    }
}

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/07/25/embedding-assets-from-swf-files/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white">

    <mx:Button id="checkBtn" label="Check" icon="{Images.BULLET_CHECK}" />
    <mx:Button id="warningBtn" label="Warning" icon="{Images.BULLET_WARNING}" />
    <mx:Button id="critcalBtn" label="Critical" icon="{Images.BULLET_CRITICAL}" />

</mx:Application>

Pretty neat.

Updated 7/29/2007

Another trick when embedding assets from SWF files is you can use the following shorthand notation:

[Bindable]
[Embed('assets/icons.swf#bulletCheck')]
private var BULLET_CHECK:Class;

[Bindable]
[Embed('assets/icons.swf#bulletCritical')]
private var BULLET_CRITICAL:Class;

[Bindable]
[Embed('assets/icons.swf#bulletWarning')]
private var BULLET_WARNING:Class;

Note that the Flash library symbol name is appended after the SWF with a “#” sign.

May 17, 2011 Posted by | Adobe Flex, Flash Support | Leave a Comment

   

Follow

Get every new post delivered to your Inbox.