My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
LocalConnectionManager  
The LocalConnection Manager supports Flash's LocalConnection system and managing of object types that are passed through the connection.
Phase-Implementation, Phase-Support
Updated Feb 4, 2010 by djha...@gmail.com

Introduction

By default, implementing a local connection requires multiple steps of registering events, proper wrapping of calls in try/catch blocks, and passed sealed Class instances are stripped of their type information when sent over the wire rendering them into generic objects. The LocalConnection Manager is a utility Class that provides a quick way to establish a Flash Player Local Connection and retain type information when passing sealed Class instances over the wire.

The Basics

When establishing and using a Flash Local Connection for communication, two unique identification values need to be defined: the connection name and the target name. Without these values no application can communicate with another. For example, we have two SWFs that want to connect and communicate with each other: SWF A and SWF B. First, both SWFs need to establish a unique connection name for themselves. This connection name is a unique id that acts like a "home address" for the SWF. Any one that wants to send a message to this SWF must know the connection name.

For our example, SWF A is going to assign itself an address (or connection name) as "SWF_A_ADDRESS" and SWF B is going to assign itself an address (connection name) as "SWF_B_ADDRESS". Now, for SWF A to talk to SWF B it needs to know SWF B's address is "SWF_B_ADDRESS", this is the target name for SWF A. SWF B needs to know the address of SWF A, so "SWF_A_ADDRESS" is the target name for SWF B. As you can probably tell, for this to work both SWFs need to know the connection name of the other SWF before it can communicate, so these values need to be established when you create the SWFs.

The other requirement of the Local Connection is to have a public method available on the receiving SWF that the calling SWF must know about. In our example both SWF A and SWF B would have a public method called receiveMessage(). When one of the SWFs wishes to send a message to the other, the SWF passes in the target address, the method to call and any parameters required buy the target method. Let's take a look at a simple example:

SWF A Example Code

public var swfAConnection:LocalConnectionManager;

public function init():void {
	// set up our connection
	swfAConnection = new LocalConnectionManager(this, "SWF_A_ADDRESS");
	
	// register events
	swfAConnection.addEventListener(LocalConnectionEvent.CONNECTION_ERROR, handleLocalConnectionEvent);
	swfAConnection.addEventListener(LocalConnectionEvent.SENT_MESSAGE_ERROR, handleLocalConnectionEvent);
	swfAConnection.addEventListener(LocalConnectionEvent.STATUS_MESSAGE, handleLocalConnectionEvent);
}

public function sendMessage():void {
	// send a message to SWF B
	swfAConnection.sendMessage("SWF_B_ADDRESS", "recieveMessage", "SWF A calling SWF B!");
}

public function receiveMessage(message:String):void {
	// trace out the message if we receive one
	trace(message);
}

SWF B Example Code

public var swfBConnection:LocalConnectionManager;

public function init():void {
	// set up our connection
	swfBConnection = new LocalConnectionManager(this, "SWF_B_ADDRESS");
	
	// register events
	swfBConnection.addEventListener(LocalConnectionEvent.CONNECTION_ERROR, handleLocalConnectionEvent);
	swfBConnection.addEventListener(LocalConnectionEvent.SENT_MESSAGE_ERROR, handleLocalConnectionEvent);
	swfBConnection.addEventListener(LocalConnectionEvent.STATUS_MESSAGE, handleLocalConnectionEvent);
}

public function sendMessage():void {
	// send a message to SWF A
	swfBConnection.sendMessage("SWF_A_ADDRESS", "recieveMessage", "SWF B calling SWF A!");
}

public function receiveMessage(message:String):void {
	// trace out the message if we receive one
	trace(message);
}

Looking at the code you can see that the only real difference between the two SWFs is the connection name they use when they create a new !LocalConnectionManager instance and the target name they use when the SWF calls sendMessage(). By defining a unique address the connection manager can now help broadcast and receive messages via the local connection.

One thing to note about the Local Connection, is that only one SWF can connect using a specific connection name. For example, if we have two instances of SWF B running at the same time, whichever instance was the first to connect will be able receive messages on that channel. The second instance to connect will receive no messages from the broadcaster.

Retaining Class Type

One of the powerful things about the Local Connection is that the data serialization/de-serializaton syntax is based on the AMF protocol. These means that if both SWFs have the same Class type reference, the class object instances can be passed back and forth retaining their type. The process of setting up AMF to do this is tedious so the LocalConnectionManager takes care of this process for you. As long as both applications have the same data type then the Class instance will be serialized and de-serialized correctly.

For example, we have a User object that we want to pass back and forth between SWF A and SWF B:

package com.developmentarc.exmaple {
	public class User {
		public var firstName:String;
		public var lastName:String;
		public var id:uint;
	}
}

Both SWF A and SWF B have references to this class and use it. In this case SWF A will be sending SWF B a user instance:

SWF A Example Code

import com.developmentarc.exmaple.User;

public function sendUser():void {
	// send a user to SWF B
	var userInst:User = new User();
	userInst.firstName = "Homer";
	userInst.lastName = "Simpson";
	userInst.id = 3322;
	swfAConnection.sendMessage("SWF_B_ADDRESS", "recieveUser", userInst);
}

SWF B Example Code

import com.developmentarc.exmaple.User;

public function recieveUser(user:User):void {
	// do something with the user
	trace(user.firstName, user.lastName) //output: Homer Simpson
}

If, for some reason, SWF B did not have the matching User object the LocalConnectionManager is smart enough to first check to see if the type exists, if it does not then SWF B will inform SWF A via a LocalConnectionManager Error Event that it did not have the proper class reference.

Considerations

With any API/Data set there are always considerations that need to be made when using the technology. Its always better to know about these potential issues before hand, rather then implementing the technology and then realizing it does not behave the way that was originally intended.

  • To use Class type management, all applications communicating must use the LocalConnectionManager to handle the Class registration required by the AMF protocol.
  • It is recommended that when you implement the LocalConnectionManager that you define your communication methods and LCM instance in a dedicated Class. By doing this, only the public methods of the dedicated class are exposed, thus limiting what can/cannot be accessed via the local connection.
  • When passing data via the LocalConnectionManager, use dedicated Data Objects that can easily be serialized and de-serialized. If the objects constructor requires properties this can cause creation issues when the new object is created. For more information on using Transient Metadata and passing data across the AMF protocol review Darron Schall's detailed post.
  • AIR and Flash movies can communicate using Local Connection.
Comment by A.Ro...@gmail.com, Mar 5, 2009

Wow! This manager is exactly what I was looking for. Thanks so much for developing it and making it available. I was dreading building a similar system.

Comment by A.Ro...@gmail.com, Mar 9, 2009

I have been using the LCM, and its everything I hope for and more... almost. I'm having problems passing a FileReference? object. Any ideas if this is possible with the LCM? Thanks in advance.

Comment by project member djha...@gmail.com, Mar 31, 2009

Are you passing the FileReference from an AIR app to an AIR app, or is this Flash to Flash, or some kind of mix? In theory this should work but there may be a few issues. The first thing that comes to mind is that the FileReference code may be marked as Transient (its in a package I can't see the code in so I can not verify this). If this is the case this metadata tag would require values to be dropped when serialized. Another issue would be if you are passing AIR to Flash, because I believe the AIR version has more properties, and this may choke on the serialization.

We haven't tested with any of this but my recommendation would be to build a new Object that stores the data that you need, fill this object in from the source FileReference?, pass this new object over the wire, then build another FileReference?. Not elegant, but its the first thing that comes to mind.

Comment by graeme.h...@gmail.com, May 11, 2009

Awesome class. Thank you for sharing. Do you have any suggestions for where I can learn more about the the limitations of passing data via the LocalConnectionManager? Specifically, what kind of objects can be serialized and deserialized?

Comment by project member djha...@gmail.com, May 11, 2009

One place to start would be Darron Schall's post about Transient metadata. This is what inspired me to build the LCM a few years back. Outside of that, I don't know of any resource off the top of my head, but I would recommend getting more familiar with the AMF protocol and the general limitations/ability of Local Connection. Darron has some great links to the the livedocs that cover this topic.

Thinking about your question, my first tip would be: objects that require constructor parameters are not going to deserialize properly. What you are essentially doing with the deserialization is creating a new instance of an object and then populating its values with the values from the serialized data. The problem is that if your constructor expects values and deserialization cannot provide them. So when passing data around, make sure your constructor either has no arguments or has default values that are acceptable when constructed.

Another thing to throw out there is the 40k size limit the the Flash Local Connection system imposes. We just hit this issue on a project that DevelopmentArc? is working on. We were trying to pass references of UI components around, which of course, is a bad idea. The problem is that UI components are massive object with tons of self-references, sub-children and references to other massive objects such as the SystemManager. The way we solved this was the same way I recommended A.Rolelk fix his FileReference issue. We created a custom object that represents the UI Component, but only at the top level (no child objects are passed over the wire).

If we need to get more information, such as accessing one of the child objects, we would then make a call back to the source app for another flat representation of the child object. The actual solution is a lot more complex then this, we wrote a parser that dynamically generated the properties we wanted by using Flash's description API, but the general solution is that we don't pass over the entire object, we just pass limited representations of the object that we can use as a starting point.

So far those have been the biggest application development hurdles we have had with LCM, as you (and we) find more issues please feel let us know so that we can help improve the documentation and the utility.

Comment by miku...@gmail.com, Jun 20, 2009

This sounds like a great utility. How does it handle large objects though? I'd like to store images and sounds in one swf and pass them through the LCM to another. Does it handle the amortization of large objects correctly? Or, perhaps, is there a way of increasing this 40k size limit?

Comment by project member djha...@gmail.com, Jun 20, 2009

The LCM currently does not support file/data management, this is one feature we have been looking at but at the moment it hasn't been as high a priority for the 1.0 release as other features. We are definitely seeing and hearing more use cases for this kind of support and will look at it post 1.0 for sure.

The 40k limit is a Flash Player limit and one that can be adjusted or changed. This means that the only way to support large files is by breaking them down into smaller chunks and then sending them over to be reconstructed.

One of the challenges with this kind of feature is how to properly break up, send over and then reconstruct large data sets. On top of this we need to look at data call order, data integrity validation, preventing recursive self-referencing, and other potential issues. We will need to solve this before we release a new build of the LCM, more then likely this will be an extension of the LCM system.

Thanks for asking about this and if you develop a solution that you would like to share before we take this feature on please let us know!

Comment by leef918@gmail.com, Nov 12, 2009

不错

Comment by patrickl...@gmail.com, Mar 10, 2010

How does this work with https connections?


Sign in to add a comment
Powered by Google Project Hosting