• Home
  • About Me
  • AIR Central
  • AS3 Libs
  • Books
  • Flex Central
  • Resources
  • The Guru's
  •  

    Do a Screen Capture with Adobe AIR

    I have created a sample AIR application that takes screen shots and saves them to disc. Impossible? Well yes it would be impossible if I were only using AIR. However, thanks to the Merapi Java bridge, we have new functionality exposed to AIR. Yes, it is true that currently there is no shell execute functionality from AIR to start up the Java service. Hopefully, this will change with future versions of AIR.

    For now in my test environment, I just manually start the Java service which will then listen for messages from AIR.

    The first image shows the Merapi Screen Capture application right after it has been launched.

    Merapi Screen Capture AIR application in initial state

    The next image shows the AIR application after it has taken a screen shot. You can see that the new screen shot is now included within the application as a thumbnail.

    Merapi Screen Capture after screen shot

    Clicking on the thumbnail launches a preview of the new screen shot.

    Merapi Screen Capture preview window

    The screen shots are being stored in a directory under the user directory /Pictures/merapi/screenshots.

    Mac Finder shows new image file

    So how does this all work? In addition to the required jar files, there are 2 custom Java classes. The first class is the Main class which is runnable. This class has just one method which is the main method. It gets an instance of the merapi.Bridge class and then registers a message handler to react to incoming messages from AIR.

    Main.class - main method

    1. public static void main( String[] args ) throws Exception {
    2.     /*
    3.      * get an instance of the Bridge
    4.      * Create a handler for incoming Flex message
    5.      * register the handler and listen for the takeScreenShot message
    6.      */
    7.     Bridge bridge = Bridge.getInstance();
    8.     ScreenCaptureMessageHandler handler = new ScreenCaptureMessageHandler();
    9.     bridge.registerMessageHandler("takeScreenShot", handler);
    10. }

    The handler is a class named ScreenCaptureMessageHandler. This class implements the merapi.messages.IMessageHandler which must implement the abstract method handleMessage. This method accepts a merapi.messages.IMessage. If you take a look at the handleMessage method below, you can see that it simply calls another method named takeShot() and passes along a piece of data which contains the storage directory path from the incoming message.

    ScreenCaptureMessageHandler.class - handleMessage method

    1. public void handleMessage( IMessage message ){
    2.     try{
    3.         /*
    4.          * read the storage directory from the message data object
    5.          */
    6.         takeShot(message.getData().toString());
    7.     } catch (Exception e){
    8.         System.out.print(e);
    9.     }
    10. }

    The takeShot() method does the work of taking the screen shot, it then creates a unique file name and saves the png file to the storage directory that was passed in from AIR. Finally, it creates a new merapi.messages.Message object, sets the new absolute path of the saved png as data on the message, gets an instance of the merapi.Bridge and finally sends the message back to AIR.

    ScreenCaptureMessageHandler.class - takeShot method

    1. public void takeShot(String storageDirectory) throws
    2.     AWTException, IOException, Exception {
    3.     /*
    4.      * capture the whole screen
    5.      */
    6.     BufferedImage screencapture = new Robot().createScreenCapture(
    7.             new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
    8.     /*
    9.      * Create a new file using the incoming storage directory
    10.      * and a unique time stamp
    11.      * Save as a png
    12.      */
    13.     Date d = new Date();
    14.     File file = new File(storageDirectory + "sc_" + d.getTime() + ".png");
    15.     ImageIO.write(screencapture, "png", file);
    16.     /*
    17.      * Create a message
    18.      * pass the file path to the merapi bridge
    19.      * send the message to Flex
    20.      */
    21.     Message message = new Message();
    22.         message.setData( file.getAbsolutePath() );
    23.         Bridge bridge = Bridge.getInstance();
    24.         bridge.sendMessage( message );
    25. }

    On the AIR side which in this case is a Flex application, the first thing that occurs is that the Merapi Bridge is instantiated through an MXML tag as shown below.

    1. <!-- Initialize the connection to the merapi bridge -->
    2. <merapi:BridgeInstance id="bridge" />

    Next, upon applicationComplete an event listener is added to the bridge to listed for the completed message coming back from Java after the takeShot() method has completed.

    1. bridge.addEventListener(ResultEvent.RESULT,completed);

    The “Take Screen Shot” button within the AIR application calls the takeShot() ActionScript function shown below. This function first sets the application to not be visible (avoid appearing in the screen capture) and then creates a new Message sets the type to “takeScreenShot”, sets the data to the storage directory, and then sends the message to Java which if you remember from above already has a handler setup listening for the “takeScreenShot” message.

    1. private function takeShot():void{
    2.     /*
    3.      * Hide application so it doesn't appear in screen shot
    4.      */
    5.     this.visible = false;
    6.     /*
    7.      * Create new message, set type to takeScreenShot
    8.      * which matches the listener created on the java side of the merapi bridge,
    9.      * pass the storage directory to the merapi bridge,
    10.      * send the message on to java
    11.      */
    12.     var message:Message = new Message();
    13.          message.type = "takeScreenShot";
    14.          message.data = storageDirectory.nativePath + File.separator;
    15.          bridge.sendMessage(message);
    16.   }

    Finally, Java completes its work it sends back the “completed” message which the AIR application is already setup to listen for. The listener calls the completed() ActionScript function shown below. This function simply returns the application to a visible state and adds the image thumbnail.

    1. private function completed( event : ResultEvent ) : void {
    2.     this.currentState = "withshots";
    3.     this.visible = true;
    4.     if(tile.numChildren > 9) {
    5.             tile.removeAllChildren();
    6.         }
    7.     var message : IMessage = event.result as IMessage;
    8.          
    9.     var image:Image = new Image();
    10.          image.addEventListener(MouseEvent.CLICK,openPreview);
    11.          image.toolTip = "Click for preview";
    12.              image.width45;
    13.              image.height = 35;
    14.                    
    15.     if(Capabilities.os.search("Mac") >= 0){
    16.         image.source = "file://" + message.data as String;
    17.     } else {
    18.         image.source = message.data as String;
    19.     }     
    20.         tile.addChild(image);   
    21. }

    For more information on Merapi, please visit http://merapiproject.com

    7 Responses to “Do a Screen Capture with Adobe AIR”

    1. jeanphilippe Says:

      Hi,
      It’s really an interesting project ! and a good job !
      Where can we download the framework Merapi ? i don’t find it on merapiproject ?
      Thanks
      JP

    2. everythingflex Says:

      The public beta is not available yet.

    3. jeanphilippe Says:

      ok…
      so, wait and see :)

    4. Merapi Project Alpha Register Now! | EverythingFlex Says:

      […] up for the alpha and you will be able to run my screen capture sample as soon as the jars are […]

    5. Kinetic13 Says:

      Hi, is there another way to do this purely from Flex/Flash? Adobe Connect (which I believe is a Flash or Flex app) can share your screen? Is there a way to replicate this functionality for my own use?

      Thanks!

    6. everythingflex Says:

      No, you can not interact with the operating system from a web based flex or flash application and Adobe AIR does not have the ability to screen cap naively in AIR 1 either.

    7. Denis Says:

      Then how is Adobe doing it with Connect Now?? Does anybody know…

    Leave a Reply