« Tour de Live Cycle, Tour de Flex, What is the Tour de Next? | Main | My Merapi ScreenCapture Example »
LocalConnection – Maintaing connection between AIR applications
| By Rich Tretola | May 27, 2009 | |
| 7,666 views |
In my 360Flex presentation last week in Indianapolis I used LocalConnection to communicate between two AIR applications. Here is a very simple sample of how I set up the two applications to talk to each other.
So, the general concept is this. I have 2 AIR applications, one is the Primary and the other is the Slave. They will communicate with each other over LocalConnection and also utilize a polling methodology as a method of notification when one of the applications is not available.
Primary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"> <mx:Script> <![CDATA[ // primaryLC is this application public var primaryLC:LocalConnection = new LocalConnection(); // slaveLC is the remote app public var slaveLC:LocalConnection = new LocalConnection(); /** * connection string to talk to an AIR application is made up of * app# + application id + . + publisher id + : + application id * example: app#Slave.130A080AFCC69239D6F9896EEBED2327BC93ED43.1:Slave * to use this sample, you must fill in your appropriate connection string below */ private static const slaveLCConection:String = "" // timer to ping LocalConnection private var lcTimer:Timer; [Bindable] private var connected:Boolean = false; [Bindable] [Embed ('thumbsdown.png')] private var thumbsdown:Class; [Bindable] [Embed ('thumbsup.png')] private var thumbsup:Class; private function init():void{ // create LocalConnection primaryLC.allowDomain('*'); primaryLC.client = this; primaryLC.connect("Primary"); slaveLC.addEventListener(StatusEvent.STATUS, lcStatusChanged); // start a timer to ping the Slave lcTimer = new Timer(1000, 0); lcTimer.addEventListener(TimerEvent.TIMER, timerHandler); lcTimer.start(); } // ping the Slave public function timerHandler(event:TimerEvent):void { slaveLC.send(slaveLCConection, "testCon", primaryLC.domain + ':Primary'); } // receive LocalConnection response public function testCon():void{ connected = true; } // handle status changes private function lcStatusChanged(event:StatusEvent):void{ if(event.level == "error")connected = false; } ]]> </mx:Script> <mx:Image source="{(connected)?thumbsup:thumbsdown}" horizontalCenter="0" verticalCenter="0"/> </mx:WindowedApplication> |
Slave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"> <mx:Script> <![CDATA[ import mx.controls.Alert; // primaryLC is the remote app public var primaryLC:LocalConnection = new LocalConnection(); // slaveLC is this app public var slaveLC:LocalConnection = new LocalConnection(); // timer to ping LocalConnection private var lcTimer:Timer; private var responseConnectionName:String; [Bindable] private var connected:Boolean = false; [Bindable] [Embed ('thumbsdown.png')] private var thumbsdown:Class; [Bindable] [Embed ('thumbsup.png')] private var thumbsup:Class; private function init():void{ // create LocalConnection slaveLC.allowDomain('*'); slaveLC.client = this; slaveLC.connect("Slave"); //mx.controls.Alert.show("My pubId is \n" + slaveLC.domain); primaryLC.addEventListener(StatusEvent.STATUS, lcStatusChanged); } // handle status changes private function lcStatusChanged(event:StatusEvent):void { if(event.level == "error")connected = false; } // receive LocalConnection response public function testCon(responseConnectionName:String):void{ connected = true; this.responseConnectionName = responseConnectionName; if(lcTimer == null){ // start a timer to ping the Primary lcTimer = new Timer(1000, 0); lcTimer.addEventListener(TimerEvent.TIMER, timerHandler); lcTimer.start(); } } // ping the Primary public function timerHandler(event:TimerEvent):void { primaryLC.send(responseConnectionName, "testCon"); } ]]> </mx:Script> <mx:Image source="{(connected)?thumbsup:thumbsdown}" horizontalCenter="0" verticalCenter="0"/> </mx:WindowedApplication> |
OK, so what is actually going on in the sample code above?
Lets first take a look at the Primary application source code. Here are the key points:
- Setup the LocalConnection objects for both the Primary and Slave
- Hard code the Slave’s connection string
- Define a Timer object that will be used to poll the Slave
- Define a variable to hold the information telling us the connection status
Upon init() of the Primary application, the primaryLC LocalConnection object is instantiated and an eventListener is setup to listen for status changes to the slaveLC LocalConnection object. A timer lcTimer is also instantiated and scheduled to run every 1 second in which time it will call the testCon method on the Slave. You can see this outbound call in the timerHandler method. Notice that I am passing along the Primary‘s domain so that the Slave can call back to the Primary without having to have the Primary‘s connection string hard coded.
Upon init() of the Slave application, the slaveLC LocalConnection object is instantiated and an eventListener is setup to listen for status changes to the primaryLC LocalConnection object. A timer lcTimer is also instantiated and scheduled to run every 1 second in which time it will call the testCon method on the Primary. You can see this outbound call in the timerHandler method.
So, here is the possible chain of events.
If Primary is launched first, it begins polling for a connection to Slave by calling the Slave‘s tectCon method every 1 second. If and when Slave is found and the call to testCon succeeds, Slave will set its connected property to true and set the responseConnectionString to what was passed in from Primary. Finally, it will begin polling Primary as well. Once Primary‘s testCon method is called from Slave, it sets its connected property to true as well.
If Slave is launched first, it will simply sit and wait as it doesn’t begin polling Primary until Primary makes the first call to Slave‘s testCon method which sets the Primary‘s responseConnectionName and starts the Slave‘s polling timer.
This system works very well to ensure that both applications have awareness about the connection status to each other and also only requires that you hard code one of the connection strings.
If you have other ideas, please feel free to share. I hope this tutorial helps.
If you are having trouble finding the connection string to plug in to line 17 of the Primary, you can uncomment line 33 of Slave and install on your local system. The Alert that pop up on launch will be the string that should be entered on line 17 of Primary.
Note: this can also be used within 2 browser based Flash Player or an AIR application talking to a browser based Flash Player application, although some changes to the connection string would be required if the Slave was in the browser.
Topics: 360Flex, Adobe AIR, Flex | 15 Comments »









May 27th, 2009 at 12:22 pm
Hey Rich,
I can see a good chunk of the use cases for doing something like this is to offload processing to another thread or process.
Have you heard any plans on Adobe’s side to make this easier to do right of the box and packages well?
I mean, like have 2 modules connect through LocalConnection and have them run on separate threads/processes?
I’ve been watching ASC-3222 (http://bugs.adobe.com/jira/browse/ASC-3222) and it doesn’t seem to be going anywhere despite the demand…
Reply to this comment
Rich Tretola Reply:
May 27th, 2009 at 2:12 pm
That was actually the concept of my presentation. Unfortunately, it appears that even though the AIR processes run separately, they ultimately share a single Flash Player and a spike on any process will freeze the entire runtime.
Reply to this comment
Evan Reply:
August 26th, 2009 at 4:58 pm
Hey Rich,
I’m not following what you mean by “they ultimately share a single Flash Player”… do you have a reference you could link to that might explain this in more detail?
Reply to this comment
Rich Tretola Reply:
August 26th, 2009 at 8:43 pm
The AIR runtime utilizes the flash player just as content running in the browser. Even though you may have multiple AIR applications running on your OS, they are sharing a single flash player.
Akhilesh Reply:
November 13th, 2009 at 9:24 am
Hi Rich,
Nice to see the communication between two AIR application.My question is, Can one AIR application communicate with another RIA application? Can u plz explain regarding this.
Thanks
Rich Tretola Reply:
November 13th, 2009 at 11:18 am
Yes, AIR can talk to Flash Player in the browser. See these examples:
http://blog.everythingflex.com/2008/01/11/more-fun-with-air-localconnection-source-included/
http://blog.everythingflex.com/2008/01/02/happy-new-year-localconnection/
Basically, as long as the flash player is involved and you own both applications they can both be AIR, both be Flash in the browser or be one of each.
May 28th, 2009 at 10:14 am
[...] This post was Twitted by jinixx – Real-url.org [...]
September 11th, 2009 at 9:45 am
Hi,
I am working with the same issue – in the project purpose it is required to establish communication between two air application. I tried you example and it doesn’t work on my PC.
-Regards,
Serhiy Vasilyev
Reply to this comment
February 12th, 2010 at 1:07 pm
This example fails to work, do you know this?
Reply to this comment
Rich Tretola Reply:
February 12th, 2010 at 2:01 pm
Did you set the slaveLCConection correctly? What error are you seeing?
Reply to this comment
Rich Tretola Reply:
February 12th, 2010 at 2:02 pm
Also, what version of AIR are you using? This won’t work with AIR 2.
Reply to this comment
February 12th, 2010 at 6:45 pm
Did you see my other questions above?
Reply to this comment
March 12th, 2010 at 12:41 am
Hello,
i have a some problems by using LocalConnections. The Target is a bi-directional communication between Flex and Air (use SDK 4 (AIR 1.5.3)).
The Setup: Flex-Application is located in Domain http://www.xyz.de, the AIR-App. is local installed.
My Setup works very well in Domains like “xyz.de”, but when i change to something like this: “www.some-domain-include.de” i got no communication from AIR to flex (flex to Air is ok).
The “-” in my url-name seems to be a problem, is that right?
The sample-Files (with source-code) are online at:
http://homepages.uni-paderborn.de/spider/LocalConnectionTestAir.air
and
http://homepages.uni-paderborn.de/spider/LocalConnectionTestFlex.swf
You can try it. Press the button “ping” in Flex-App. If ping works fine you get a MSG-Box in AIR. Now press Answer, the Flex-App get a Result or not
(The same unmodified Code, is running on Domains like xyz.de)
Thanks
Sebastian
Reply to this comment
August 23rd, 2010 at 7:27 pm
[...] LocalConnection – Maintaing connection between AIR applications 27 May 2009. evden eve nakliyat on Flash on my TV? all star shoes on.. single Flash Player and a spike on any process will freeze the entire runtime..blog.everythingflex.com/…/localconnection-maintaining-connections/ – LocalConnection – Maintaing connection between AIR applications [...]
September 14th, 2010 at 4:07 am
[...] LocalConnection – Maintaing connection between AIR applications 27 May 2009. evden eve nakliyat on Flash on my TV? all star shoes on.. single Flash Player and a spike on any process will freeze the entire runtime..blog.everythingflex.com/…/localconnection-maintaining-connections/ – LocalConnection – Maintaing connection between AIR applications [...]