14
Dec
07

Sending Data from AVM2 to AVM1

In Chapter 13, we showed how to use a LocalConnection to communicate between an AS3-based movie in Flash Player's AVM2, and an AS2-based movie in Flash Player's AVM1. The example was basic, using functions to stop and start an animated movie clip. In this first of future additional examples, we'll pass data into a function in the AVM! movie.


The following code is the additional ActionScript 2.0 added to the avm1.fla file from the Chapter 13 example. Lines 1 through 3 define a function that places a string into a text field on the stage. There is nothing specific to LocalConnection communication. Although you will most likely write specific functions for AVM communication, this example is designed to be relatively flexible. It parses incoming data using the arguments array.

AVM1 FLA

ActionScript 1.0/2.0:
  1. function doIt() {
  2.     avm1TxtFld.text = ("AVM1 function 'doIt' called from AVM2,
  3.                        with the following arguments: " + arguments[0] + " " + arguments[1]);
  4. }
  5.  
  6. avm2LC.execFunction = function(obj:Object):Void {
  7.     _root[obj.funcName].apply(null, obj.args);
  8. }

Lines 5 through 7 comprise the important part of the AVM1 file. They create a function that the LocalConnection instance can access, called execFunction. It uses an object as an argument to allow you to pass a variable amount of data into this conduit. This makes it possible to call different functions with different arguments.

The latter process is achieved by first identifying which function to call by parsing funcName from the incoming argument data (_root[obj.funcName], and then using the apply() method to send the incoming arguments to that function.

 
AVM2 FLA

Now that the infrastructure has been added to the AVM1 file, we need to add another button to the avm2.fla file. This uses the same process as the book example, using the send() method to send parameters to the AVM1 file via the established local connection. However, in this case, a third parameter is sent containing the name of the function to ultimately be triggered, as well as data to send to that function.

ActionScript 3.0:
  1. varBtn.addEventListener(MouseEvent.CLICK, onVarBtn, false, 0, true);
  2.  
  3. function onVarBtn(evt:MouseEvent):void {
  4.     avm2LC.send("avm2", "execFunction",
  5.                 {funcName:"doIt", args:["hello1","hello2"]});
  6. }

The result is, when clicking on the Var button, the parameters sent from the AVM2 file are used in the AVM1 file.

This movie requires Flash Player 9. Please update your player.

Download: Data AVM2 to AVM1  Download Data AVM2 to AVM1 (184.8 KB, 215 hits)

Share This:
  • Digg
  • del.icio.us
  • Netvouz
  • DZone
  • ThisNext
  • MisterWong
  • Wists
  • blogmarks
  • BlogMemes
  • Fark
  • feedmelinks
  • Furl
  • Ma.gnolia
  • Netscape
  • Reddit
  • Slashdot
  • SphereIt
  • Spurl
  • StumbleUpon
  • Technorati
  • YahooMyWeb
  • BlinkList
  • DotNetKicks
  • LinkaGoGo
  • NewsVine
  • blinkbits
  • co.mments
  • MyShare
Print This Post Print This Post


12 Responses to “Sending Data from AVM2 to AVM1”


  1. 1 Fajar Sylvana Mar 1st, 2008 at 9:49 am

    wow Interesting Tutorial Rich, i wondering what if you made this to sending Data from AVM2 to AVM2 but still based on Movie. Maybe in different example or more complicated. like a sending data to a client computer trough LAN perhaps ?! you know, most of the Flasher right now is moving to ActionScript 3.0 maybe in the future the AVM1 is already not using anymore. i ask to several Flash master, and all of them is expert on web based things. they not that good at Flash stuff out of web. maybe you can help us who want to explore more Flash Stuff on the Application based..

  2. 2 Rich Mar 1st, 2008 at 9:25 pm

    Welcome, Fajar. I'll add your thoughts to the list of planned future posts. Unfortunately, I'm quite backlogged with posts at the moment, but I'll keep your idea alive. LocalConnections only work between Flash Player instances on the same computer, so communicating over a LAN would not work with LC. However, I'll try to look into other options, as well as application based alternatives, in the coming months. Thanks for your comment!

  3. 3 Fajar Sylvana Mar 3rd, 2008 at 12:09 am

    Thanks Rich for the answer,
    by the way do you know i'm dying to have your book. wow.. it's so hard to get your book in Asean Country if you know that. and i have to go to the Singapore again next month, just to buy your book.. phew, but for now i'm just learning with the AS3 Documentation(not much helping, but thats not Bad). hey maybe you can help me with a code. i'm already hopeless doing an LC. what i'm gonna do is, i wanna made a first swf just for a button control and the other swf is for a Movie(i'm just loading an swf Movie inside second swf) what that apps gonna do is, when you click the Button on first swf and the Movie on second swf is appear.. Thats it.. simple concept right.. but it's hard to do(for me).. can you give me a code Example Rich, please Help me with this one? Thanks for Everything !

    PS: i'm gonna have your Book someday.. i will..

  4. 4 Michael Johnson Apr 16th, 2008 at 10:42 am

    Can you use LocalConnection to communicate between two swfs that are Actionscript 3.0? I'm trying to get an externally loaded swf to communicate with the main timeline so that I can close the loaded swf. Is that possible using LocalConnection?

  5. 5 Rich Apr 16th, 2008 at 8:45 pm

    @Michael, yes you can, but it's not required. AS3/AS3 asset sets can communicate with each other without LocalConnection. There are lots of issues with loading and unloading AS3 assets, and we've been massaging a few posts about the topic for quite a while now. (We we're trying to get the definitive word on what we think is a bug in the Flash IDE, but we're going to post in the meantime, too.)

    For everyone's benefit, on Friday, we'll start the series and you'll be able to follow this thread through a few posts over the ensuing days. However, here's a quick discussion about AS3 loader/loadee arrangements. I caution you that this is just a discussion, a quick answer to your question, and won't have the clarity of a proper post. If you have any trouble with my context here, don't worry, the post will clear it all up and provide sample files. If you can muddle through this, however, it'll give you a jump start.

    For this quick discussion, I'll assume you are using timeline code (it's a bit different with classes) and can successfully load a SWF, using the simple example at the top of page 285. Then, in the loaded SWF (called "toLoad" in the example), you can learn about the relationship between the parent and child this way. First, add "trace(parent);" to the "toLoad" file. When you test the loadee, the result will be the stage. When you test the loader you created earlier, the result will the be instance of the Loader class used to load the external SWF.

    Next, add "trace(parent.parent);" to the loadee. This will show null when testing the loadee, because there is no parent higher than it's stage. But in the loader, this will reference the Loader instance's parent--in this case, the main timeline. You now have a path to talk to the loader from the loadee.

    So, as an example, if you have a variable in the loader main timeline, called "loaderVar", for instance, you can get it's value this way (theoretically): "trace(parent.parent.loaderVar);" The only issue is that, in Strict Mode (which you should always use), the compiler doesn't know that loaderVar is a property (variable) of the movie clip (loader main timeline). So, you can explicitly cast the parent as a movie clip (again, assuming, as is true in this example, that the parent is the main timeline of the loader, not another display list child). To do this, all you need to do is add the MovieClip() casting method: "trace(MovieClip(parent.parent).loaderVar);" This way, the compiler knows that loaderVar is a property (variable) of the parent's parent you are trying to target.

    The result is that you can get the variable value in the loader, from within the loadee. You can communicate both ways, trigger functions, etc. Remember that there is a lot to consider here--from how things change in classes, to identifying the parent of the loaded content (if, for example, it's not the main timeline), to properly unloading the content, to security issues if the loaded content isn't in the same domain, etc. For the most part, these are not inconsistent with AS2 issues, and are just added layers of concern that come with added complexity.

    Stay tuned for the loading/unloading series (see the comment date for time-context) for a more clearly explained post and sample files.

  6. 6 Alex Drelles May 13th, 2008 at 2:00 am

    Any word on the loading/unloading series of posts? I've been back and forth in the book trying to understand loading/unloading AS2 and AS3 swfs into an AS3 shell. They load fine, I just can't get them out of memory. They are off the display list, but the audio track continues to play after I call the removeChild method.

    Great book by the way, I started with Essential ActionScript 3.0 and was overwhelmed.

    thanks

  7. 7 Rich May 13th, 2008 at 2:22 am

    @Alex: Yes, they will be going up this week. I'm to blame for their delay, and not for very professional reasons, I'm afraid. My wife and I just had a baby daughter and she arrived a week early. So, both the build up and the aftermath have thrown my schedule for a loop. Sorry about that!

    In short, you need to stop everything you started before you unload. This is good practice anyway, but does require more diligence. For example, stop all sounds and videos, close any sound and video streams, stop all timers (a running timer can never be garbage collected), remove listeners (especially enter frame listeners), and then unload.

    That should enable your assets to be collected but, even then, you don't know when and have no control over the process. This is not a question for lingering sound playback of course, but rather for memory management. This, too, may not be an issue for you if your project is a get-in and get-out type of thing, but it's important for things like kiosks that run continuously.

    If all goes well, we'll have the loading/unloading material live this week. Thanks!

  8. 8 Alex Drelles May 13th, 2008 at 3:05 am

    Congratulations and absolutely no need to apology. I have 2 young ones myself. I've been working in Flash for years and never posted a question to a forum, so getting a response is like internet magic.

    Quick question, on p 63 of the book you have a section titled Removing Objects from Memory, you essentially set ball=null to clear it from memory after removing it from the display list. I tried setting my loader to null after I remove it from the display list and it still plays the audio from the loaded swf. So when you say "In short, you need to stop everything you started before you unload...." the loaded swf must be responsible for it's own cleanup.

    thanks again

  9. 9 Rich May 13th, 2008 at 3:18 am

    @Alex: Not exactly. If you know which steps must be taken, you can do so from the loader. I tend to prefer doing this from the loadee, but you can do either, given the right information. The important thing is, there's a big difference between stopping each process and unloading the loader. You have to stop the sound from playing, stop all other processes I mentioned, then unload, then nullify. Just unloading doesn't do the job the way it did with AS2.

    I'll try to get these posts up asap!

  10. 10 Manuel May 14th, 2008 at 9:06 am

    Hey Rich thanx for the post. The file you posted doesn't work with as2. I bet maybe it just needs a couple of tweaks. It's just to let you know

  11. 11 Rich May 14th, 2008 at 9:15 am

    @Manuel, can you describe what doesn't work? Which file? There is an AS2 file (avm1.fla) and AS3 file (avm2.fla). The AS2 portion of the demo is an animation that autoplays. Is it not playing on your machine?

  12. 12 Steve Jun 9th, 2008 at 11:11 am

    I'm interested in extending this example to control a number of dynamically loaded swfs. When dealing with two AVM1Movie instances, It seems that the first loaded AVM1Movie eats the LocalConnection event and blocks it from propagating to other listeners. Hey, no fair!

    You can see this in action if you open up two browser windows of this page. The play/stop controls in each embedded movie will only affect the first loaded AVM1Movie instance loaded.

    Pperhaps the way to do this is for the AVM1Movie to broadcast on a predetermined statically named LocalConnection to the AVM2 container, informing it of a dynamically (run-time) determined LocalConnection receiving channel name. The AVM2 container movie would have to keep track of each AVM1 instance and it's dynamic LocalConnection name for when it wants to send commands. It seems like an ugly solution.

Leave a Reply