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 innovate to be able to bring uncompromising rich experiences to the web, desktop, and mobile devices. You can read the white paper online at:
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.
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:
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:
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!
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.
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:
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.
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.)
While working with Kevin’s code, I started tinkering… “what if I change this, what if I tweak that?” Next thing you know, I put together a sample scenario showing subscription-based realtime data streaming to multiple web clients using web sockets. Check out the video below to see it in action.
You are seeing 9 separate browser instances getting realtime push-based updates from a local server using web sockets. When the browser loads, the html-based client makes a web socket connection, then requests all symbols from the server. The server then sends the stock symbol definitions back to the client and displays them within the HTML user interface. From there, the user can click on a stock symbol to subscribe to updates for that particular symbol. DISCLAIMER: All that data is randomly generated!
I put together this example for experimentation, but also to highlight a few technical scenarios for HTML-based applications. Specifically:
Realtime/push data in HTML-based apps
Per-client subscriptions for realtime data
Multi-series realtime data visualization in HTML-based apps
The server is an AIR app started by Kevin, based on the web sockets draft protocol. It is written in JavaScript, and the client is a HTML page to be viewed in the browser.
If you don’t feel like reading the full web sockets protocol reference, you can get a great overview from websocket.org or Wikipedia.
One thing to keep in mind is that web sockets are not widely supported in all browsers yet. There is a great reference matrix for web socket support from caniuse.com:
If you still aren’t sure if your browser supports web sockets, you can also check simply by visiting websocketstest.com/. If you want to test for web socket support within your own applications, you can easily check for support using Modernizr. Note: I didn’t add the Modernizr test in this example… I only tested in Chrome on OSX.
OK, now back to the sample application. All of the source code for this example is available on github at: https://github.com/triceam/Websocket-Streaming-Example. To run it yourself, you first have to launch the server. You can do this on the command line by invoking ADL (part of the AIR SDK):
cd "/Applications/Adobe Flash Builder 4.6/sdks/4.6.0/bin"
./adl ~/Documents/dev/Websocket-Streaming-Example/server/application.xml
You’ll know the server is started b/c an air window will popup (you can ignore this, just don’t close it), and you will start seeing feed updates in the console output.
Once the server is running, open “client/client.html” in your browser. It will connect to the local server, and then request the list of symbols. If you click on a symbol, it will subscribe to that feed. Just click on the symbol name again to unsubscribe. You’ll know the feed is subscribed b/c the symbol will show up in a color (matching the corresponding feed on the chart). Again, let me reiterate that I only tested this in Chrome.
You can open up numerous client instances, and all will receive the same updates in real time for each subscribed stock symbol.
The “meat” of code for the server starts in server/scripts/server/server.js. Basically, the server loads a configuration file for the socket server, then creates a ConnectionManager and DataFeed (both of these are custom JS classes). The ConnectionManager class encapsulates all logic around socket connections. This includes managing the ServerSocket as well as all client socket instances and events. The DataFeed class handles data within the app. First, it generates random data, then sets up an interval to generate random data updates. For every data update, the ConnectionManager instance’s dispatch() method is invoked to send updates to all subscribed clients. Rather than trying to put lots of code snippets inline in this post (which would just be more confusing), check out the full source at: https://github.com/triceam/Websocket-Streaming-Example/tree/master/server
The client code all starts in client.html, with the application logic inside of client/scripts/client.js. Once the client interface loads, it connects to the web socket and adds the appropriate event handlers. Once subscribed to a data feed, realtime data will be returned via the web socket instance, transformed slightly to fit the data visualization structure, then rendered in an HTML canvas using the RGraph data visualization library. RGraph is free to get started with, however if you want to deploy a production app with it, you’ll need a license. You’ll notice that each feed updates independently, based upon the client subscriptions. Note: The data visualization is not temporally aligned… if you want the updates in time-sequence, there is a litte bit more work involved in the client-side data transformation.
This example is intended to get your minds rolling with the concepts; it is not *yet* an all-encompassing enterprise solution. You can expect to see a few more data push scenarios here in the near future, based on different enterprise server technologies.
In case you had not seen on the Flex team blog, twitter or through some other medium, Flex SDK 4.6 and Flash Builder 4.6 were released today! Go get them, if you have not done so already. Flex 4.6 marks a huge advancement for the Flex SDK, especially regarding mobile applications.
Flash Builder 4.6 is a FREE update for Flash Builder 4.5 users. From the Flex team blog:
A lot is included in this update, so much so that we couldn’t deliver it in the Adobe Application Manager. This means Flash Builder 4.5 users won’t automatically be notified about the update and will have to download the full Flash Builder 4.6 installer and enter their Flash Builder 4.5 serial number.
Coinciding with the Flex & Flash Builder releases, new content around Flex and Flash Builder 4.6 have been posted on Adobe TV. There is a bunch of great new content worth checking out, including fellow evangelist Michael Chaize’s adaptive UI for different platforms and device form factors. In addition, here I am speaking out the new Captive Runtime feature introduced in AIR 3…
Perhaps you have heard of the topic “cross platform development”, but aren’t really sure what it is, or you aren’t sure why you would want to use cross-platform technologies. If this is the case, then this post is especially for you. I’ll try to shed some light onto what it is, and why you would want to use cross-platform development strategies.
What is cross-platform development?
Cross platform development is a concept in computer software development where you write application code once, and it runs on multiple platforms. This is very much inline with the “write once, run everywhere” concept pioneered in the 90s, and brought to a mainstream reality with Flash in the browser, and AIR on the desktop. The standard evolution of technology has been to make everything faster, smaller, and more portable, and it is only natural that that this concept has now come into the mobile development world. In mobile scenarios, it is applied by writing an application using a codebase & technology that allows the application to be deployed and distributed across multiple disparate platforms/operating systems/devices.
Using Adobe AIR, this includes Apple’s iOS devices (iPhone and iPad), Android (a plethora of devices), BlackBerry Playbook & upcoming BBX platform, and soon Windows Metro (the tablet offering of Windows 8). Using PhoneGap, this includes Apple iOS, Android, BlackBerry 4.6 and higher, HP WebOS, Symbian, Samsung Bada, and Windows Phone 7 – Mango platforms.
In case you’re wondering why I offered 2 cross platform technologies, that is because Adobe will soon have 2 cross-platform product offerings. Adobe has entered an agreement to purchase Nitobi, the creators of PhoneGap.
Adobe AIR
Adobe AIR is a cross-platform technology with roots in the Flash Player and the AIR desktop runtime. AIR allows you to build cross-platform mobile applications using ActionScript and the open source Flex framework. AIR apps can be built from the Flash Professional timeline-based design/animation tool, Flash Builder (an Eclipse-based development environment), or other open source solutions using the freely available AIR SDK. Applications developed with Adobe AIR can target desktop platforms (Mac, & Windows), smart phone and tablet platforms (iOS, Android, BlackBerry, soon Windows), and even smart televisions.
PhoneGap (Apache Callback)
PhoneGap is an open source cross platform technology with roots in the HTML world. Essentially, a PhoneGap application consists of a web view that consumes 100% of the available width & 100% of the available height, taking advantage of web browsers on each platform. PhoneGap offers a JavaScript to native bridge that enables you to build natively-installed applications using HTML and JavaScript, using the native bridge to interact with the device hardware/APIs. Note: PhoneGap is also being submitted to the Apache Foundation as the Apache Callback project.
More Devices, Less Code
The driving factor behind cross-platform technologies is that you will be able to use those technologies to target more devices & platforms, with writing a minimal amount of source code. There are many advantages with this approach. Here are a few of the major reasons…
Lower Barrier of Entry
Generally speaking, development with HTML & JavaScript or Flex & ActionScript is easier than developing with Objective-C or Java. Due to the ease of use of the development tooling and familiarity of the languages, cross platform technologies lower the technical barriers which may have prevented adoption of native development. This allows your development team to build applications that they may not previously have been able to, and also enables your team to focus on what matters – the application; not the skills required to develop on multiple disparate platforms.
Reduce the Number of Required Skills for the Development Team
Native development on multiple platforms requires your development team to learn Objective C for iOS applications, Java for Android applications, Silverlight for Windows Phone applications, etc… Finding all of these skills in a single developer is nearly impossible. Using cross-platform development technologies, your team only needs to be proficient with one language/skillset. Knowledge of the native development paradigms and languages are always a plus, but are no longer a requirement. Many developers transitioning from web development already know either Flex/ActionScript and/or HTML/JavaScript, and making the transition from web to mobile development will not be a major undertaking.
Reduced Development & Long Term Maintenance Costs
Cross-platform mobile applications can originate from a single codebase, which requires a single development skillset. You don’t need to have staff for each individual platform. Instead, resources working on the shared codebase can cover all target platforms. Having a single codebase also reduces long term maintenance costs. You no longer need to have bug tracking for X number of codebases, and do not need to maintain a larger staff to support each platform. Did I also mention that you have one codebase to maintain?
Having a single codebase doesn’t reduce the need for QA/testing on each target platform – nothing can get rid of this. It is absolutely imperative that you test your codebase on physical devices for all platforms that you intend to support. Emulators and Simulators can go a long way during development, but they will undoubtedly not cover all scenarios possible on a physical device, and they will not have the same runtime performance as a physical device.
Play the Strengths of a Technology
Some technologies make tasks easier than others. For example, programmatic drawing and data visualization are very easy using Flex & ActionScript. Developing equivalent experiences in native code can be significantly more complex and time consuming. Use the the features of the language to their fullest potential, to your advantage- that’s why they exist.
I was recently asked by a friend and former colleague about the best way to get text within a s:Label to behave and scroll properly, especially in the Flex mobile SDK. In particular, having a large block of text wrap correctly and scroll only in the vertical direction. By default if you don’t set a size on the label, the behavior of the Flex framework is that the views containing the label will resize, and the text will be displayed as entered (without word wrap or truncation). This may cause some layout issues and confusion as to “what the heck is going on with my text”.
I’ve found that the best way to achieve the desired behavior is to set a maxWidth on the label to force proper word wrapping, and then wrap the label in a s:Scroller to have it scroll properly. I chose to set a maxWidth to allow the label to determine it’s own size, and only to wrap if it needs to. An easy shortcut for proper wrapping is to bind the maxWidth of the label to the width of the scroller component. Also, DO NOT set a static height or a max height. This will cause the text within the label to be truncated, and it will not scroll at all if the static height is less than the height of the scroller. I’ve also noticed that setting cacheAsBitmap=true on the label also helps scroll performance in some circumstances, but this is not required.
Check out a video showing the scroll behavior of a large text block using this approach:
Below is the code that makes it work, which follows the method described above:
<s:Scroller height="100%" width="100%" id="scroller1">
<s:Group>
<s:Label id="labelInstance"
cacheAsBitmap="true"
maxWidth="{ scroller1.width }"
color="#FF0000" fontSize="32">
<s:text>Bacon ipsum dolor sit amet sint cow irure et magna, meatball aliquip qui. Tempor turkey capicola, eiusmod sed nisi dolore. Pig nisi rump boudin in culpa chuck. In ex sausage filet mignon shankle ut. Flank ball tip cillum aute. Nulla frankfurter culpa, elit et esse aute pork salami. Laborum mollit short ribs, in meatloaf eu irure dolor consectetur elit strip steak.
{note: text has been truncated to emphasize actual code, not the random text}
</s:text>
</s:Label>
</s:Group>
</s:Scroller>
The recordings of my presentations don’t seem to be available yet on Adobe TV, but here is the content, as promised. I spoke at MAX this year on “Multi Device Best Practices using Flex & AIR for Mobile”, and “Create beautiful, immersive content and applications with HTML5 and CSS3″, and the content from these presentations is below.
Multi Device Best Practices using Flex & AIR for Mobile
In the multi-device best practices session I covered the basics for building a multi-device/multi-form-factor application that conforms to device constraints (phone and tablet), using a single codebase that is able to detect device dimensions and orientation. This was followed by online/offline detection for occasionally-connected applications, and then followed by device-specific layout using CSS media queries and MultiDPIBitmapSource images. The presentation slides are below.
Create beautiful, immersive content and applications with HTML5 and CSS3
In this session, I gave a “crash course” in developing rich content experiences with HTML5 and CSS3. I started with a general overview presentation, followed by diving directly into code. I covered <video>, <audio>, dynamic graphics with <canvas>, <svg>, HTML5 Form elements, CSS3 Web Fonts, Visual Styles (shadows, corners), CSS3 Color spaces (RGBA, HSLA), graidents, transforms, animations, and media queries. In the presentation, I also discussed the necessity of client-side solution accelerator frameowrks (jQuery or other JS framework), in addition to graceful degradation and HTML5 feature detection using Modernizr. The presentation slides are below:
Tomorrow (Thurs) I'm presenting an "Introduction to Mobile Development with PhoneGap" at Towson University http://t.co/Qch6pD93 Come on out! 3 hours ago
Recent Comments