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
-
function doIt() {
-
avm1TxtFld.text = ("AVM1 function 'doIt' called from AVM2,
-
with the following arguments: " + arguments[0] + " " + arguments[1]);
-
}
-
-
avm2LC.execFunction = function(obj:Object):Void {
-
_root[obj.funcName].apply(null, obj.args);
-
}
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.
-
varBtn.addEventListener(MouseEvent.CLICK, onVarBtn, false, 0, true);
-
-
function onVarBtn(evt:MouseEvent):void {
-
avm2LC.send("avm2", "execFunction",
-
{funcName:"doIt", args:["hello1","hello2"]});
-
}
The result is, when clicking on the Var button, the parameters sent from the AVM2 file are used in the AVM1 file.
Download Data AVM2 to AVM1 (184.8 KB, 1,429 hits)
UPDATE: I've added an expanded example that also shows communication from AVM1 to AVM2. Download the file below.
Download Expanded AVM Bridging Example (1.1 MB, 233 hits)
Print This Post


(7 votes, average: 4 out of 5) 
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..
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!
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..
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?
@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.
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
@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!
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
@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!
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
@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?
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.
One of the movies is in ActionScript 2.0 and not 3.0
The moment you make it 3.0 the thing doesn't work... Nice sample but in my opinion incomplete! Still: CONGRATZ
@Abel, thanks for writing. One of the samples is supposed to be in AS2. This post is about communicating between AS3-based and AS2-based SWFs. Flash Player 9 and later have two separate code bases—one for playing AS3 and one for playing AS2 and/or AS1. You can't program across this divide in the same script, so you need to use one of a few methods to communicate between the SWFs. This post is about this problem, and uses LocalConnection as the method.
Rich, thanks for this clear explanation, I found everything I needed here explained in a brief and concise manner. This saved me alot of experimentation time. Very nice post!
@Josh, I'm happy you had some success with this post. Thanks for writing!
Hi
I not sure if this the correct place to post but... I have been reading through the Learning ActionScript 3.0 book. I just want to know how I would go about communicating between two flash movies (projectors) created in ActionScript 3.0. I have tried a couple of tutorials on the web but then reading this thread it seems the methods i have been trying only work when communicating between AS2 and AS3?
Basically I want to be able to press a button in one movie which is able to increase a number in another movie or just pass data.
Any help would be appreciated.
Thanks
Thanks also for the April 2008 post as well as the book (half way through)
I was thoroughly stuck on the AS3 communications till I put in the various traces you suggested.
Flash is back to being fun for this novice.
Is it possible to control any AVM1 animation by AVM2? While AVM1 Movie have a simple animation without any code. If it's possible then please explain how will it work.
Regards,
FlashDuniya
@Bhupen, if I understand you correctly, you still need a LocalConnection to communicate between two projectors. Can you tell me what you're having trouble with? Are you getting errors?
@Flash Duniya, can you be more specific? The example included in this post does what you're asking, so I'm not sure what you mean. The example above has an AVM1 animation without any code. The AVM2 movie stops, and plays the animation.
hey rich.... thanks for this nice tutorial...
but i just want to know , is there any way to play and stop the AS2 file without having any code in AS2 file..I want all programming in AS3 file .. can this be possible ?
actually the case is .... i m working on a project in which i need to convert PDF file into swf file and then control that swf file. I got pdftoswf converter which generate AVM1 file(AS2 version) from pdf file..But now i dont know how to stop() and play() that file by AS3...
can you suggest me something regarding this ?
@niks. I'm afraid it's not possible to directly control AVM1 from AVM2 without adding code to AVM1. You may have luck injecting an interim AVM1 file. Use AS3 to control an AVM1 loader that can then communicate with the loaded pdf-to-swf conversions all within AVM1. Or, you might replace pdftoswf with something like Print2Flash--an AS3 update of FlashPaper-like functionality. I haven't tried Print2Flash myself but I am considering testing it thoroughly for a future review or inclusion in a book.
@Rich....thanks for this quick reply.....and also thanks for the suggestion...but my bad , i already checked all these options.
My problem is , I want all the pdf pages frame by frame in swf file.
Have you ever been through " swftools " software. What this software does ,it Generates one frame per page , like if there are 10 pages in pdf file then there would be 10 frame in the converted swf file.
so i want something like this.Actually I am planning to integrate PDF file with Video player , something like this video player " http://www.omnisio.com/startupschool08/david-heinemeier-hansson-at-startup-school-08 ".Thats why i need the PDF pages frame by frame.
Any help would be appreciated.
regards,
niks
@Niks, As far as I'm aware, you can't control AVM1 from AVM2 without code in both movies. Your best bet is to have AVM2 control an interim AVM1 movie that you create just for this purpose. The interim AVM1 movie will have control over the loaded PDF conversions, as everything will be in AVM1. The parent shell, which I assume will be in AVM2, can communicate with the interim SWF because you can put code in both.
Hiya
I'm getting a bald patch on my head from frustration with the following problem.
I have a parent AS3 swf which loads in a AS2 swf like so;
contained in the AS2 file is the following script which loads in jpegs when the user clicks the next button, etc.
//stuff that loads in different photos stop(); var i:Number = 1; //load first image straight away. function initialloadup () { i = 1; startLoading("pic"+i+".jpg"); }; initialloadup(); next_btn.onRelease = function () { /*on clicking next image button load next image in sequence*/ i++; if (i > 11 ) {i = 1}; startLoading("pic"+i+".jpg"); trace("pic"+i+".jpg"); }; prev_btn.onRelease = function () { //on clicking previous image button load prev image in sequence i--; if (i < 1 ) {i = 11}; startLoading("pic"+i+".jpg"); }; function startLoading(whichImage) { loadMovie(whichImage, "imageLoader"); }however when you view the AS2 swf via the AS3 swf it does not seem to load in the jpgs when requested.
I need to retain the AS2 file so cannot rewrite in AS3 as the image loading thing is only a small part of the AS2 file.
Any ideas? might it be to do with how the AS2 is read in AS3? I have read the local Connection information, but i'm finding it difficult to migrate the knowledge across. Does the loadMovie command not register in the as2.swf file if it is loaded into the as3 parent swf?
Cheers for your reading this
Melacroso
Hello,
I don't understand a thing. I try to send an order from the as3 swf to the as2 swf like this :
// code in the as3 fla var avm2LC:LocalConnection = new LocalConnection(); avm2LC.addEventListener(StatusEvent.STATUS, onConnStatus); var chargeur:Loader = new Loader(); chargeur.load(new URLRequest("intro1.swf")); addChild(chargeur); function onConnStatus(event:StatusEvent):void{ switch (event.level) { case "status": trace("LocalConnection.send() succeeded"); break; case "error": trace("LocalConnection.send() failed"); break; } } avm2LC.send("avm2", "pauseAnim"); // code in the as2 fla var avm2LC:LocalConnection = new LocalConnection(); avm2LC.connect("avm2"); avm2LC.pauseAnim = function():Void { timeline.pause(); // Where timeline is a TimelineLite instance (greensock) } // end of codeThe result is "LocalConnection.send() failed". I try already to listen the Event.COMPLETE on the Loader and then to send the order to the as2 swf but I have the same error.
Could you help me please ?
Thank you !
Tom
@Malecroso, the only thing I'm sure of is that an AVM1Movie can't load into layers, but you're not doing that. I see the same behavior you're seeing: only the first load works. The only thing that seems to work is removing the movie clip and starting over. That would cause an unpleasant transition, however. Despite your assertion to the contrary, I would recode in AS3. If you don't want to recode everything, just recode the image gallery.
@Thomas, your instruction is happening too fast. The AVM1 file hasn't had time to connect to the LocalConnection. In your code above, your request is sent out before the SWF is even loaded.
In your comment, you said you added it to an Event.COMPLETE listener. That worked for me, but also issued your 'failed' trace. The AVM1 file has just loaded but not yet had time to subscribe to the LocalConnection.
Just by what you've discussed here, what you're trying to do doesn't make sense to me. If you need something to happen right away, why not just let the AS2 file do it right away? If you need the AS2 file to function differently, under different circumstances, just use a Timer to delay the trigger of the LocalConnection call.
The following adds a timer and cleans up the script. This works fine:
// code in the as3 fla var avm2LC:LocalConnection = new LocalConnection(); avm2LC.addEventListener(StatusEvent.STATUS, onConnStatus); var chargeur:Loader = new Loader(); addChild(chargeur); chargeur.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded, false, 0, true); chargeur.load(new URLRequest("intro1.swf")); var tmr:Timer = new Timer(20,1); tmr.addEventListener(TimerEvent.TIMER, callAVM1, false, 0, true); function onLoaded(evt:Event):void { tmr.start(); } function callAVM1(evt:TimerEvent):void { avm2LC.send("avm2", "pauseAnim"); tmr.stop(); tmr.removeEventListener(TimerEvent.TIMER, callAVM1); tmr = null; chargeur.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded); } function onConnStatus(evt:StatusEvent):void { switch (event.level) { case "status" : trace("LocalConnection.send() succeeded"); break; case "error" : trace("LocalConnection.send() failed"); } }Hi Rich
I have to say this is the Best ever simplest example explaining the use of local connection. Good Work!!!
1. in the same example i have tried to invoke a simple function in avm 2 called printNumber(num:Num) using the send method in avm on press of a button. like
on (press) { trace(" avm1 buttton clicked"); avm2LC.send("avm2","printNumber",[331]); }but i dont get the sent number in avm2. how do i do this.
2. when Unloading external as2 swf from as3 files the sound persists so i use a SoundMixer.StopAll() Method before i unload the as2 swf.
But like you pointed out this is more of memory management n garbage collection issue besides sound persistance.
is there any better steps to take from the as3 loader side to ensure proper and clean Unloading of as2 swf.
Thanks in Advance.
@Aditya, thanks for the kind words. To answer 1) I'd have to see your code and, unfortunately, I don't have time to troubleshoot. So, I created an updated example to show you what is required. I can think of two things you might be running into. First, you need a separate LC for send and received, and both have to be common to both avm1 and avm2. Second, in AS3, you need an LC client to process callbacks. All of this is in the commented code.
For 2), the only "sweeping" change (pun intended) is to use the unloadAndStop() method introduced in Flash Player 10. However, this won't work in Flash Player 9, so you'll have to add plugin detection.
Good luck!
@Rich
Great !. thats basically what i was trying for ,just to send a value from avm1 and print it avm2.
The source is in cs4 format
. Can you please re save the files in CS3 format this would make it accessible to a larger audience.
As i understand this connection is mainly for sending calling methods between the two. but is it possible to access stage objects of avm1 from avm2 using something like Movieclip(loader.content) or an equivalent .Ive tried that and got a inaccessible method error.
i guess you should change your original post to something like 2 way communication between avm1 and avm2.
Thanks
@Rich
Can you please save the " Expanded AVM Bridging Example in CS3 format". the present ones cannot be opened in it.
Thanks
@Aditya, the expanded source files have been replaced with CS3 versions. (Since the release of CS4, there is no guarantee that files on this site will be compatible with CS3.) Unfortunately, I won't be able to get to your other questions for some time.
Where are the rest of the examples from chap 13? Maybe you should include a cd next time. I will not recommend your book. :[
@Booky, all the downloadable source files can be found on the Downloads page. You can see all the pages, including Downloads, at the top of the right column/sidebar. You can also use the search box if you're looking for something specific. The Downloads are also mentioned in the Welcome sticky post that is always at the top of the page. I would have emailed you directly to try to help you further, but the email address you provided was unuseable (and unpleasant).
Not including a CD was O'Reilly's choice because it cuts $5 off the cost of the book.