Tag Archives: air

AIR 3.2 & Flash Player 11.2 Release Candidates Available on Adobe Labs

AIR 3.2 and Flash Player 11.2 release candidates are now available for download on Adobe Labs. These latest versions have some exciting new features, including Stage3D for mobile devices, broader Stage3D support on desktop machines, multi-threaded video decoding, and better mouse support for gaming scenarios.   Get ready for some incredible mobile and desktop experiences powered by Adobe Flash & AIR.

You can read more about what’s new in Flash Player 11.2 and AIR 3.2 on the Adobe Digital Media blog, or check out the videos below to see some of the new features in action.

AIR 3.2

Flash Player 11.2

Download AIR 3.2 and Flash Player 11.2 release candidates today!

You can also check out additional examples of AIR 3.2 features from fellow Adobe Evangelists:

Adobe Roadmap for Flash Runtimes

To complement the white paper released last week covering the future of Flex and the transition to Apache, Adobe has released a white paper covering the the roadmap for the Flash and AIR runtimes. Flash is very much alive and well, and is continuing to evolve to be able to bring uncompromising rich experiences to the web, desktop, and mobile devices. You can read the white paper online at:

Or download a PDF version to read later.

Here is an excerpt; be sure to read the entire white paper for a clear outline of the future of Flash runtimes.   The future is going to be awesome.

Summary

For the past decade, Flash Player and, more recently, Adobe AIR have played a vital role on the web by providing consistent platforms for deploying rich, expressive content across browsers, desktops, and devices. Beginning as a platform for enabling animation, the Flash runtimes have evolved into a complete multimedia platform, enabling experiences that were otherwise not possible or feasible on the web.

Looking forward, Adobe believes that Flash is particularly suited for addressing the gaming and premium video markets, and will focus its development efforts in those areas. At the same time, Adobe will make architectural and language changes to the runtimes in order to ensure that the Flash runtimes are well placed to enable the richest experiences on the web and across mobile devices for another decade.

Stage3D & Flex Demo w/ Source

Back in the summer, I was lucky enough to get my hands on some early builds of Stage3D for mobile. I built some simple examples, including basic geometric shapes and simple 3D bubble charts inside of mobile Flex/AIR applications. I have been asked numerous times for the source code, and I’ve finally given in, and am sharing some source code.

I am not posting the full mobile application source code, since Stage3D for mobile is not yet available. However, I have ported the 3D bubble chart example to run in a Flex application targeting the desktop (Flash Player 11). The bubble chart example extends the concepts explored in the basic geometric shapes example.

Before you say “shoot, he didn’t give us the mobile code”, let me explain… When I ported the code from the mobile project to the desktop Flex project, all I changed was code specific to the mobile Flex framework. I changed <s:ViewNavigatorapplication> to <s:Application> and the corresponding architecture changes that were required, and I changed the list item renderers to Spark item renderers based on <s:Group> instead of mobile item renderers.   In the mobile item renderers, all my drawing logic was done using the ActionScript drawing API.  For simplicity in the port, I just used <s:Rect> to add the colored regions in the desktop variant.

That is all I changed!  

The stage3D code between the desktop and mobile implementations is identical.    You can see the desktop port in action in the video below:

Or, you can test it for yourself here:

The source code was intended to be exploratory at best… I was simply experimenting with hardware accelerated content, and how it can be used within your applications.   There is one big “gotcha” that you will have to watch out for if you want Stage3D content within a Flex application… Stage3D content shows up behind Flex content on the display list.   By default, Flex apps have a background color, and they will hide the Stage3D content.   If you want to display any Stage3D content within a Flex application (regardless of web, desktop AIR, or mobile), you must set the background alpha of the Flex application to zero (0).  Otherwise you will pull out some hair trying to figure out why it doesn’t show up.

The source code for the web/Flex port of this example is available at:

This also requires inclusion of the Away3D library, available at:

You can check out my original posts, showing Stage3D on mobile here:

You can also check out a video of this code running on a mobile device (Samsung Galaxy Tab 10.1) below:

Enjoy!

2012 Flex User Group Tour: North America Dates Announced

If you hadn’t heard already, Flex has been accepted by the Apache Software Foundation. If you are wondering what exactly this means, or you have asked yourself any of the following questions, then you might want to check out the Adobe Flex User Group Tour:

  • Do you want to learn more about the future of Flex?
  • Do you want to learn more about the Flex transition to the Apache Software Foundation?
  • How can you contribute and help make Flex thrive?
  • Do you have questions that you would like to voice to Adobe?

As promised, Adobe is kicking off The Flex User Group Tour to discuss recent events surrounding Flex and the Flash Platform.   These meetings are intended to help you understand the changes happening with Flex and Flash, the impact to related tools, as well as to educate about the process & transition to Apache.   You can learn more about the user group tour and get an up-to-date listing of dates & cities from the Flex Team blog – be sure to check back periodically for updates. Initial cities include New York, Boston, Denver, Seattle, Los Angeles, Sand Diego, and Dallas.   Expect more cities & countries to be announced at a later date.

We hope to see you at one of the upcoming events. I’m scheduled to speak at the Dallas event in April, and I hop to see you there!

Capturing User Signatures in Mobile Applications

One growing trend that I have seen in mobile & tablet applications is the creation of tools that enable your workforce to perform their job better. This can be in the case of mobile data retrieval, streamlined sales process with apps for door-to-door sales, mobile business process efficiency, etc…

One of the topics that comes up is how do you capture a signature and store it within your application? This might be for validation that the signer is who they say they are, or for legal/contractual reasons. Imagine a few scenarios:

  • Your cable TV can’t be installed until you sign the digital form on the installation tech’s tablet device
  • You agree to purchase a service from a sales person (door to door, or in-store kiosk) – your signature is required to make this legally binding.
  • Your signature is required to accept an agreement before confidential data is presented to you.

These are just a few random scenarios, I’m sure there are many more.   In this post, I will focus on 2 (yes, I said two) cross-platform solutions to handle this task – one built with Adobe Flex & AIR, and one built with HTML5 Canvas & PhoneGap.  

Source for both solutions is available at: https://github.com/triceam/Mobile-Signature-Capture

Watch the video below to see this in action, then we’ll dig into the code that makes it work.

The basic flow of the application is that you enter an email address, sign the interface, then click the green “check” button to submit to the signature to a ColdFusion server.  The server then sends a multi-part email to the email address that you provided, containing text elements as well as the signature that was just captured.

If you’d like to jump straight to specific code portions, use the links below:



The Server Solution

Let’s first examine the server component of the sample application.   The server side is powered by ColdFusion. There’s just a single CFC that is utilized by both the Flex/AIR and HTML/PhoneGap front-end applications.   The CFC exposes a single service that accepts two parameters: the email address, and a base-64 encoded string of the captured image data.

<cffunction name="submitSignature" access="remote" returntype="boolean">
    <cfargument name="email" type="string" required="yes">
    <cfargument name="signature" type="string" required="yes">
    
    <cfmail SUBJECT ="Signature"
        FROM="#noReplyAddress#"
        TO="#email#"
        username="#emailLoginUsername#"
        password="#emailLoginPassword#"
        server="#mailServer#" 
        type="HTML" >
        
        <p>This completes the form transaction for <strong>#email#</strong>.</p>
        
        <p>You may view your signature below:</p>
        <p><img src="cid:signature" /></p>
        
        <p>Thank you for your participation.</p>
        
        <cfmailparam
            file="signature"
            content="#toBinary( signature )#"
            contentid="signature"
            disposition="inline" />
    
    </cfmail>

    <cfreturn true />
</cffunction>

Note: I used base-64 encoded image data so that it can be a single server component for both user interfaces. In Flex/AIR you can also serialize the data as a binary byte array, however binary serialization isn’t quite as easy with HTML/JS… read on to learn more.


The Flex/AIR Solution

The main user interface for the Flex/AIR solution is a simple UI with some form elements. In that UI there is an instance of my SignatureCapture user interface component. This is a basic component that is built on top of UIComponent (the base class for all Flex visual components), which encapsulates all logic for capturing the user signature. The component captures input based on mouse events (single touch events are handled as mouse events in air). The mouse input is then used to manipulate the graphics content of the component using the drawing API. I like to think of the drawing API as a language around the childhood game “connect the dots”. In this case, you are just drawing lines from one point to another.

When the form is submitted, the graphical content is converted to a base-64 encoded string using the Flex ImageSnapshot class/API, before passing it to the server.

You can check out a browser-based Flex version of this in action at http://tricedesigns.com/portfolio/sigCaptureFlex/ – Just enter a valid email address and use your mouse to sign within the signature area. When this is submitted, it will send an email to you containing the signature.

You can check out the SignatureCapture component code below, or check out the full project at https://github.com/triceam/Mobile-Signature-Capture/tree/master/flex%20client. This class will also work in desktop AIR or browser/based Flex applications. The main application workflow and UI is contained with Main.mxml.

package
{
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.core.UIComponent;
	import mx.graphics.ImageSnapshot;
	import mx.managers.IFocusManagerComponent;
	
	import spark.primitives.Graphic;
	
	public class SignatureCapture extends UIComponent
	{
		private var captureMask : Sprite;
		private var drawSurface : UIComponent;
		private var lastMousePosition : Point;
		
		private var backgroundColor : int = 0xEEEEEE;
		private var borderColor : int = 0x888888;
		private var borderSize : int = 2;
		private var cornerRadius :int = 25;
		private var strokeColor : int = 0;
		private var strokeSize : int = 2;
		
		public function SignatureCapture()
		{
			lastMousePosition = new Point();
			super();
		}
		
		override protected function createChildren():void 
		{
			super.createChildren();
			
			captureMask = new Sprite();
			drawSurface = new UIComponent();
			this.mask = captureMask;
			addChild( drawSurface );
			addChild( captureMask );
			
			this.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown );
		}
		
		protected function onMouseDown( event : MouseEvent ) : void
		{
			lastMousePosition = globalToLocal( new Point( stage.mouseX, stage.mouseY ) );
			stage.addEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
			stage.addEventListener( MouseEvent.MOUSE_UP, onMouseUp );
		}
		
		protected function onMouseMove( event : MouseEvent ) : void
		{
			updateSegment();
		}
		
		protected function onMouseUp( event : MouseEvent ) : void
		{
			updateSegment();
			stage.removeEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
			stage.removeEventListener( MouseEvent.MOUSE_UP, onMouseUp );
		}
		
		protected function updateSegment() : void
		{
			var nextMousePosition : Point = globalToLocal( new Point( stage.mouseX, stage.mouseY ) );
			renderSegment( lastMousePosition, nextMousePosition );
			lastMousePosition = nextMousePosition;
		}
		
		
		public function clear() : void
		{
			drawSurface.graphics.clear();
		}
		
		override public function toString() : String
		{
			var snapshot : ImageSnapshot = ImageSnapshot.captureImage( drawSurface );
			return ImageSnapshot.encodeImageAsBase64( snapshot );
		}
		
		override protected function updateDisplayList(w:Number, h:Number):void
		{
			super.updateDisplayList(w,h);
			
			drawSurface.width = w;
			drawSurface.height = h;
			
			var g : Graphics = this.graphics;
			
			//draw rectangle for mouse hit area
			g.clear();
			g.lineStyle( borderSize, borderColor, 1, true );
			g.beginFill( backgroundColor, 1 );
			g.drawRoundRect( 0,0,w,h, cornerRadius, cornerRadius );
		
			
			//fill mask
			g.clear();
			g = captureMask.graphics;
			g.beginFill( 0, 1 );
			g.drawRoundRect( 0,0,w,h, cornerRadius, cornerRadius );
		}
		
		protected function renderSegment( from : Point, to : Point ) : void
		{
			var g : Graphics = drawSurface.graphics;
			g.lineStyle( strokeSize, strokeColor, 1 );
			g.moveTo( from.x, from.y );
			g.lineTo( to.x, to.y );
		}
	}
}



The HTML5/PhoneGap Solution

The main user interface for the HTML5/PhoneGap solution is also a simple UI with some form elements. In that UI there is a Canvas element that is used to render the signature. I created a SignatureCapture JavaScript class that encapsulates all logic for capturing the user signature. In browsers that support touch events (mobile browsers), this is based on the touchstart, touchmove and touchend events. In browsers that don’t support touch (aka desktop browsers), the signature input is based on mousedown, mousemove and mouseup events. The component captures input based on touch or mouse events, and that input is used to manipulate the graphics content of the Canvas tag instance. The canvas tag also supports a drawing API that is similar to the ActionScript drawing API. To read up on Canvas programmatic drawing basics, check out the tutorials at http://www.adobe.com/devnet/html5/html5-canvas.html

When the form is submitted, the graphical content is converted to a base-64 encoded string using the Canvas’s toDataURL() method. The toDataURL() method returns a base-64 encoded string value of the image content, prefixed with “data:image/png,”. Since I’ll be passing this back to the server, I don’t need this prefix, so it is stripped, then sent to the server for content within the email.

You can check out a browser-based version of this using the HTML5 Canvas in action at http://tricedesigns.com/portfolio/sigCapture/ – Again, just enter a valid email address and use your mouse to sign within the signature area. When this is submitted, it will send an email to you containing the signature. However, this example requires that your browser supports the HTML5 Canvas tag.

You can check out the SignatureCapture code below, or check out the full project at https://github.com/triceam/Mobile-Signature-Capture/tree/master/html%20client. This class will also work in desktop browser applications that support the HTML5 canvas. I used Modernizr to determine whether touch events are supported within the client container (PhoneGap or desktop browser). The main application workflow is within application.js.

Also a note for Android users, the Canvas toDataURL() method does not work in Android versions earlier than 3.0. However, you can implement your own toDataURL() method for use in older OS versions using the technique in this link: http://jimdoescode.blogspot.com/2011/11/trials-and-tribulations-with-html5.html (I did not update this example to support older Android OS versions.)

function SignatureCapture( canvasID ) {
	this.touchSupported = Modernizr.touch;
	this.canvasID = canvasID;
	this.canvas = $("#"+canvasID);
	this.context = this.canvas.get(0).getContext("2d");	
	this.context.strokeStyle = "#000000";
	this.context.lineWidth = 1;
	this.lastMousePoint = {x:0, y:0};
	
	this.canvas[0].width = this.canvas.parent().innerWidth();
    
	if (this.touchSupported) {
		this.mouseDownEvent = "touchstart";
		this.mouseMoveEvent = "touchmove";
		this.mouseUpEvent = "touchend";
	}
	else {
		this.mouseDownEvent = "mousedown";
		this.mouseMoveEvent = "mousemove";
		this.mouseUpEvent = "mouseup";
	}
	
	this.canvas.bind( this.mouseDownEvent, this.onCanvasMouseDown() );
}

SignatureCapture.prototype.onCanvasMouseDown = function () {
	var self = this;
	return function(event) {
		self.mouseMoveHandler = self.onCanvasMouseMove()
		self.mouseUpHandler = self.onCanvasMouseUp()

		$(document).bind( self.mouseMoveEvent, self.mouseMoveHandler );
		$(document).bind( self.mouseUpEvent, self.mouseUpHandler );
		
		self.updateMousePosition( event );
		self.updateCanvas( event );
	}
}

SignatureCapture.prototype.onCanvasMouseMove = function () {
	var self = this;
	return function(event) {

		self.updateCanvas( event );
     	event.preventDefault();
    	return false;
	}
}

SignatureCapture.prototype.onCanvasMouseUp = function (event) {
	var self = this;
	return function(event) {

		$(document).unbind( self.mouseMoveEvent, self.mouseMoveHandler );
		$(document).unbind( self.mouseUpEvent, self.mouseUpHandler );
		
		self.mouseMoveHandler = null;
		self.mouseUpHandler = null;
	}
}

SignatureCapture.prototype.updateMousePosition = function (event) {
 	var target;
	if (this.touchSupported) {
		target = event.originalEvent.touches[0]
	}
	else {
		target = event;
	}

	var offset = this.canvas.offset();
	this.lastMousePoint.x = target.pageX - offset.left;
	this.lastMousePoint.y = target.pageY - offset.top;

}

SignatureCapture.prototype.updateCanvas = function (event) {

	this.context.beginPath();
	this.context.moveTo( this.lastMousePoint.x, this.lastMousePoint.y );
	this.updateMousePosition( event );
	this.context.lineTo( this.lastMousePoint.x, this.lastMousePoint.y );
	this.context.stroke();
}

SignatureCapture.prototype.toString = function () {

	var dataString = this.canvas.get(0).toDataURL("image/png");
	var index = dataString.indexOf( "," )+1;
	dataString = dataString.substring( index );
	
	return dataString;
}

SignatureCapture.prototype.clear = function () {

	var c = this.canvas[0];
	this.context.clearRect( 0, 0, c.width, c.height );
}

Source for the ColdFusion server, as well as Flex/AIR and HTML5/PhoneGap clients is available at: https://github.com/triceam/Mobile-Signature-Capture