Recipe 18.1. Creating Local Connections


Problem

You want to communicate from one or more Flash movie(s) to another Flash movie playing on the same client computer.

Solution

Use the LocalConnection class in the flash.net package to invoke a function in the receiving movie from the sending movie. Use LocalConnection.connect( ) to listen for messages in the receiving movie and define the function that will be invoked. Use LocalConnection.send( ) from the sending movie(s) to invoke a function in the remote movie. Both the sending and receiving movies must specify the same named channel for communication.

Discussion

When two or more Flash movies are playing on the same client computer, they can communicate with one another via a local connection created with the flash.net.LocalConnection class. As long as the movies are playing on the same computer, a connection can be made regardless of the domains from which the movies are being served.

By default, movies accept communications from movies on the same domain only. However, you can configure them to receive from other domains as well. See Recipe 18.4.


To successfully communicate between multiple movies on the same computer, you must do three things:

  1. Configure the receiving movie to listen for communications.

  2. Tell the receiving movie what to do when messages are received.

  3. Send messages to the receiving movie from the sending movie(s).

A receiving movie must listen for messages over a specific, named local connection. To establish this communication channel, you should create a local connection object in the receiving movie and tell it to listen to a named connection using the connect( ) method:

import flash.net.LocalConnection; // Create the local connection object in the receiving movie. var receiver:LocalConnection = new LocalConnection(  ); // Instruct the local connection instance to listen for messages  // sent over the "_exampleChannel" channel. receiver.connect( "_exampleChannel" );

As shown in the preceding example, the best practice is to name your communication channel (not the local connection object) with an initial underscore (_). Naming your connections in this way also simplifies communicating across domains. By starting the connection name with an underscore, the Flash Player does not augment the connection name with domain-specific information behind the scenes. When an underscore is not the first character in the connection name, the connection name string is converted into domain:connectionName automatically, where domain is either the domain name that served up the .swf file or local host when the .swf file is run locally.

All communications over the local connection are mapped by the receiving local connection instance. By default, the receiving local connection object looks for methods defined on the instance with the same name as the method sent in the request. For example, if the sending movie sends a communication that looks for a method named example( ), the receiving local connection object looks for an example( ) method that it defines. In previous versions of ActionScript, this was simply a matter of creating a function and attaching it to the instance through a name of example.

// Previous to ActionScript 3.0, this would create an example function // that could be invoked through a local connection. receiver.example = function ( ) {   output.text = "communication received"; };

However, in ActionScript 3.0, this will not work. By default, the LocalConnection class does not allow properties and methods to be created on class instances at runtime. That means there are three basic solutions:

  • Create a dynamic LocalConnection subclass, and use instances of that for all receiving local connections.

  • Create a LocalConnection subclass that defines the methods you intend to call from the sending .swf.

  • Redirect requests to a client object.

We'll next look at each of these solutions.

To allow runtime modification of a class to then attach functions to an instance, the class has to be declared dynamic. The easiest way to do this in ActionScript 3.0 is to extend the LocalConnection class with a dynamic class, and use the newly created class as the receiver to attach methods to. That class would look like this:

package {   import flash.net.LocalConnection;   // Create a dynamic Location Connection class that we can   // attach functions to.   dynamic public class DynamicLocalConnection extends LocalConnection {     // Empty  all we need is the dynamic keyword   } }

Now use the DynamicLocalConnection in place of the regular LocalConnection class and create a receiving function as in previous versions of ActionScript:

// Create the local connection object in the receiving movie. var receiver:DynamicLocalConnection = new DynamicLocalConnection(  ); // Instruct the local connection instance to listen for messages  // sent over the "_exampleChannel" channel. receiver.connect( "_exampleChannel" ); // Because the DynamicLocalConnection class is dynamic, we can  // create a new function on the instance to respond to local  // conection messages. receiver.example = function(  ):void {   trace( "communication received" );     };

This first solution has the advantage of being very flexible. You can use the DynamicLocalConnection class for all receiving local connections in all projects. The problem is that it is so flexible that it doesn't lend itself to well-defined interfaces, which is something you typically strive for in object-oriented design.

The second solution requires you use a well-defined API. You can create a LocalConnection subclass that defines the specific method or methods you want to handle. For example, the following class defines an example( ) method.

package {   import flash.net.LocalConnection;   public class ExampleLocalConnection extends LocalConnection {     public function ExampleLocalConnection(  ) {}     public function example(  ):void {       trace("communication received");     }   } }

The next solution uses a LocalConnection property called client to redirect requests to a different object other than the receiving local connection instance. The client object must define the requested methods as public methods. The following example illustrates this:

package {   import flash.net.LocalConnection;   public class Example {     private var _localConnection:LocalConnection;     public function Example(  ) {       _localConnection = new LocalConnection(  );       _localConnection.connect( "_exampleChannel" );       _localConnection.client = this;     }     public function example(  ):void {       trace("communication received");     }   } }

If you want to define the requested methods as private, then you have the option if you use a generic object as a proxy, as shown in the following example:

package {   import flash.net.LocalConnection;   public class Example {     private var _localConnection:LocalConnection;     public function Example(  ) {       _localConnection = new LocalConnection(  );       _localConnection.connect( "_exampleChannel" );       _localConnection.client = {example: example};     }     private function example(  ):void {       trace("communication received");     }   } }

Now that we've configured the receiving .swf, we next need to build the sending .swf. The sending .swf uses the LocalConnection.send( ) method to send a communication. The first parameter of the send( ) method is a string that specifies the name of a connection over which to send the communication, enabling you to create multiple discrete connections. The second parameter of the send( ) method is a string specifying the name of the method to call in the receiving movie. When a movie receives a message, it invokes the method of the same name on the receiving local connection object.

The following example invokes a remote method named example:

// Send a communication across the "_exampleChannel" channel that  // invokes a method named example( ) in the receiving movie. var sender:LocalConnection = new LocalConnection(  ); sender.send( "_exampleChannel", "example" );

When using the LocalConnection class, communication is many-to-one. That is, there can be multiple senders for a specific channel but only a single receiver. If a receiver tries to connect to a channel that another receiver has already opened, the connect( ) method throws an error and won't allow the connection to be made. You can use a try...catch block to test for a receiver being able to successfully create a listening connection on a channel, like this:

var receiver:LocalConnection = new LocalConnection(  ); try {   receiver.connect( "_exampleChannel" ); } catch( e:Error ) {   // Error  could not listen on _exampleChannel because another   // receiver has already claimed it. } 

For LocalConnection to work properly, note that both the sending and receiving movies have to be playing on the same computer at the same time. To communicate between movies that play on the same computer at different times, use an LSO. See Recipe 17.1 and Recipe 17.7 for information on using LSOs.

See Also

Recipes 17.1, 17.7, and 18.2




ActionScript 3. 0 Cookbook
ActionScript 3.0 Cookbook: Solutions for Flash Platform and Flex Application Developers
ISBN: 0596526954
EAN: 2147483647
Year: 2007
Pages: 351

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net