P2P – Share real-time data across Android and desktop AS3

sing native IP-only multicast feature available with Adobe AIR 2.0 and Flash Player 10.1 you can easly establish a connection and share real-time data between two or more clients over the same network (LAN).
The immediate advantage you can get from this tecnique is that you won’t need to use a dedicated server (like Flash Media Server, AFCS, and so on) to share real-time data across multiple clients.
Another cool stuff is that you can use P2P to share data between mobile Air for Android apps and desktop AIR applications, and in this post I’ll provide you a video demo and the source code to put in place this, getting you the fundamentals to build your own multiuser game or collaborative application.
androidp2p_screenshotvideo
What you can also do using this technology:
- Building real-time chats
- Collaborative whiteboards
- real-time multiusers games
- manage a desktop AIR application from your Android device: let’s think about an AIR Media Center on your TV managed from your mobile device; or moving a slide presentation on your laptop from your Android smartphone, and so on
- everything else needs to share real-time data across multiple clients and different platforms.
Below, the video demo (no-sound) where I show you the final result.
Moving the movieclip on my Android device, I will move the clip on my desktop application too, and viceversa.
Get the latest Flash Player to see this player.
Following the ActionScript source code (full-commented) to build the Air for Android application in Adobe Flash Professional CS5.
Document class:
package  {
 
 import flash.display.MovieClip;
 import flash.events.NetStatusEvent;
 import flash.events.MouseEvent;
 import flash.net.NetConnection;
 import flash.net.NetGroup;
 import flash.net.GroupSpecifier;
 import fl.transitions.Tween;
 import fl.transitions.easing.Strong;
 
 
 public class Main extends MovieClip {
 
  private var nc:NetConnection;
  private var group:NetGroup;
 
 
  /**
   * Constructor
   */
  public function Main()
  {
 
   mc.addEventListener(MouseEvent.MOUSE_DOWN, drag);
   this.stage.addEventListener(MouseEvent.MOUSE_UP, drop);
 
   connect();
  }
 
 
  /**
   * Connect
   */
  private function connect():void
  {
   nc = new NetConnection();
   nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
   nc.connect("rtmfp:");
  }
 
 
  /**
   * Net Status event handler
   */
  private function netStatus(event:NetStatusEvent):void{
 
   switch(event.info.code){
 
    // The connection attempt succeeded
    case "NetConnection.Connect.Success":
     setupGroup();
     break;
 
    // The NetGroup is successfully constructed and authorized to function.
    case "NetGroup.Connect.Success":
     // Do nothing
     break;
 
    // A new group posting is received
    case "NetGroup.Posting.Notify":
     moveObject(event.info.message);
     break;
   }
  }
 
 
  /**
   * Create a group
   */
  private function setupGroup():void
  {
   // Create a new Group Specifier object
   var groupspec:GroupSpecifier = new GroupSpecifier("myGroup/groupA");
 
   // Enable posting
   groupspec.postingEnabled = true;
 
   // Specifies whether information about group membership can be exchanged on IP multicast sockets
   groupspec.ipMulticastMemberUpdatesEnabled = true;
 
   // Causes the associated NetStream or NetGroup to join the specified IP multicast group and listen to the specified UDP port.
   groupspec.addIPMulticastAddress("225.225.0.1:30000");
 
   // Constructs a NetGroup on the specified NetConnection object and joins it to the group specified by groupspec.
   group = new NetGroup(nc,groupspec.groupspecWithAuthorizations());
 
   // Set the NET_STATUS event listener
   group.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
  }
 
 
 
  /**
   * Drag the object
   */
  protected function drag(e:MouseEvent):void
  {
   this.stage.addEventListener(MouseEvent.MOUSE_MOVE, move);
  }
 
 
  /**
   * Move the object in accordind of the mouse position
   */
  protected function move(e:MouseEvent):void
  {
   mc.x = this.mouseX - mc.width/2;
   mc.y = this.mouseY - mc.height/2;
   e.updateAfterEvent();
  }
 
 
  /**
   * Drop the object and send a message to all members of a group.
   */
  protected function drop(e:MouseEvent):void
  {
 
   // Create the object to send to all members
   var obj:Object = new Object();
 
   // Save the current movieclip position
   obj.x = mc.x ;
   obj.y = mc.y ;
 
   // Set the peerID to a group address suitable for use with the sendToNearest() method.
   obj.sender = group.convertPeerIDToGroupAddress(nc.nearID);
 
   // Sends a message to all members of a group.
   group.post(obj);
 
   // REmove the move event listener
   this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, move);
  }
 
 
 
  /**
   * Move the object after posting has been received
   */
  public function moveObject(message:Object):void
  {
   var myTweenX:Tween = new Tween(mc, "x", Strong.easeInOut, mc.x, message.x, 1, true);
   var myTweenY:Tween = new Tween(mc, "y", Strong.easeInOut, mc.y, message.y, 1, true);
  }
 
 
 }
}
To test this sample you should use the previous class as document class of a new Air for Android Flash file (using Flash Professional CS5) and create a movieclip on your stage setting its instance name to ‘mc’ (see image below):
androidp2p_fla
To verify if P2P is working, let’s run two instances of the application on your desktop and drag the movieclips.
If it works, install the application on your Android device, open an instance on your desktop and move the movieclip on both platforms to see if clients are connected.
Remember to set the android manifest permission to allow internet connections on your android xml-descriptor file:
  <android>
    <manifestAdditions>
       <![CDATA[
<manifest>
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>]]>
    </manifestAdditions>
  </android>

Comments

Popular posts from this blog

Basic motion detection and tracking with Python and OpenCV

Complete Raspberry Pi Magic Mirror Tutorial

Voice Activated Home Automation