01
Feb

10 recipes on ADC Cookbooks covering AIR 2.0 new APIs

AIR 2.0 beta is available publicly and when I was asked by Adobe’s marketing team, as well as Apress editor to post some recipes for Flex and AIR in the Adobe Developer connection Cookbooks I decided to combine the two. Adobe are looking to have the Cookbooks gain momentum & I decided to lend a hand and released 10 recipes with applications I built with the new AIR 2.0 APIs while I was part of the Beta program. I revised the applications and they are running correctly on the latest built of AIR available for the pre-release users.

Adobe Developer connection Cookboks

These recipes are listed below:

1: SQLite Manager

SQLiteManager does just that and allows you to set the database settings and then access the manager from anywhere in your application. It makes the process simpler and integrates very well with micro architecture frameworks. View recipe.

2: Retrieve user’s Network Information

Create an example of displaying the user’s available networks… View recipe.

3: Retrieving DNS records

Take a look at the app example, which performs DNS and reverse DNS lookup. View recipe.

4: Launching and Interacting with Native Processes

The application below opens up a text file: foobar.txt using the MacOS TextEdit text editor. View recipe.

5: Recipe for using the File promises API

Application below allows dragging of items from a list into the user’s local machine and then the copying of the files. View recipe.

6: Open file with Default Application

An AIR application that you can browse for a supported file, and watch how the registered application opens the file. View recipe.

7: SimpleAudioRecorder - Microphone Access API

The following application lets you record from any microphone connected. While you record the audio you can see a bar that shows the volume of your voice as a graphic. Once you complete recording, you can playback see the a visualization of your recording and save it as a Wave file. View recipe.

8: Mass Storage Device Detection

The following application will display the existing storage devices available as well as add and remove mass storage devices in case you add a new device or remove a device such as a USB key. View recipe.

9: Multi-touch functionality

We first switch between the different options and than we listen to the gesture events which will fire and display the gesture information in the console. View recipe.

10: WebKit with the SquirrelFish Extreme

Using the same HTML component, take a look at the following example which allows you to test some of the new WebKit functionality. View recipe.

Cheers :)

29
Jan

Creating a WebBrowser app using Robotlegs MVCS implementation in less than 2 min!

MVC Frameworks are notorious for requiring developers to spend most of their time working on the framework’s classes instead of the actual code. Since I posted the article about the Ant tasks for RobotLegs I was asked couple of times to show how to use the Ant tasks.

Why Ant tasks? The whole idea of the Ant tasks is to speed up your development and allow people that are not that familiar with RobotLegs to get started quickly on PC or Mac. I decided to create a video showing how I can create an AIR web browser application using RobotLegs with the MVCS implementation and try to do that in less than 2 mins, pretty bold ha?!

The application is going to be a simple web browser, see final screen shot below:

screen-shot-2010-01-29-at-11102-am

See the video tutorial here:

This movie requires Flash Player 9

In case you are having hard time viewing the video use the following URL:
http://www.screencast.com/users/eladnyc/folders/Jing/media/239bd195-4888-4570-bfea-2ddb1362ea6c

Feel free to download the Ant tasks:
http://github.com/EladElrom/robotlegs-utilities-AntGenerator

Download the WebBrowser AIR project from here.

BTW I did end up cheating and do little copy&paste and it took 2:20 seconds… but you get the point :)

27
Jan

Dear Apple, I will be using #FuckTheIpad hashtag till you install #Flash and #AIR

Today Apple announced the release of the iPad. As someone that owns: iMac 29″, Mac AIR, MacBook Pro and the iPhone I couldn’t be more excited to get a hold of the new device. I had some doubts if Apple will install the Flash Player, but honestly I didn’t think that they will dare to release a device that is capable to use the Flash Player with specs that includes 16GB-64GB flash drive ,1GHz processor and 1024-by-768-pixel resolution. It’s one thing not to install Flash Player on the iPhone with claims that it isn’t ready for the device, but another to release a tablet with the Apple A4 without the Flash Player.

apple-ipad-a4-chip-2_270x119

I was extremely disappointed to find out today that the iPad wont support the Flash Plugin nor Adobe AIR. It probably wont support Flash Lite either. I started the #FUCKTheIpad hashtag on twitter as protest with the following entry:

Dear Apple, I will be using #FuckTheIpad hashtag till you install #Flash and #AIR!

screen-shot-2010-01-27-at-64502-pm

The idea is not to be vulgar or rude, that’s not who I am, but to ensure Apple gets the message and understands that the Flash community has had enough with Apple’s refusal to include Flash in their devices. I don’t believe you can get a true web experience without having the Flash Player installed on a device. Additionally, I believe that the iPad is a great device for developers to develop AIR applications, not to mention it would be great to be able to port existing application such as the New York Times Reader.

In an hour the hashtag was used about 50 times. I encourage the Flash community to use the #FuckTheIpad hashtag when talking about the device on twitter, as well as post letters on the FuckTheIpad.com blog so maybe Apple will understand that we (the Flash community) demand they install the Flash Player, otherwise we wont bless or buy their device.

appletabletb120

Microsoft have tried a similar approach of locking other technologies and end up in court with the EU antitrust action as well as losing the support of many in the development community, since then they have learned. Apple please don’t take the same approach!

To show your support please use the #FUCKTheIpad on twitter and visit http://FuckTheIpad.com, we will post some letters soon and skin the blog.

23
Jan

RobotLegs Presentation Model implementation that access entire component events lifecycle

Last night, I was part of the RIARadio recording about RobotLegs. I have been supportive of the framework ever since I was introduced to it by Joel. We had an awesome time talking about Frameworks, OOP and RobotLegs. I raised a question to Shaun Smith and Joel Hooks about the presentation model vs Mediator and I pointed out that I haven’t seen a solution to the problem I presented on RobotLegs forums. See here. Joel challenged me to create my own implementation. I decided to accept the challenge and take a stab at it and see what I can come up with.

Problem

You cannot capture all the lifecycle events of a components ( such as PREINITIALIZE, INIT_PROGRESS, INITIALIZE & CREATION_COMPLETE) when using the mediator in Robotlegs. In addition I haven’t seen any implementation that uses the Presentation Model (PM) so you can do stuff before the component gets created or just drop an Presentation Model implementation you have done outside of the RobotLegs framework.

Under the hood

So why can’t we capture the component life cycle events in the Mediator?

The reason is that RobotLegs uses the contextView which is using the DisplayObjectContainer. The DisplayObjectContainer capture the event once the view is already added to the stage (see in 231 in MediatorMap.as)

The view gets added to the stage and than “onViewAdded” method being called and the mediator gets created. At this point it’s already too late, since most of the events to init the component have already been fired.

Meaning, even if you’ll change the mediatorBase code to the following:


		public function preRegister():void
		{
			if (flexAvailable && (viewComponent is UIComponentClass) && !viewComponent['initialized'])
			{
				IEventDispatcher(viewComponent).addEventListener('preinitialize', onCreationComplete, false, 0, true);
			}
			else
			{
				onRegister();
			}
		}

You cannot guarantee it will fire the pre-initialize event, and in fact when I have done some testing I found out that many times the if statement doesn’t get executed and it uses the onRegister directly.

Solution

So the options were either to modify RobotLegs entirely or try to create a more elegant solution that will use RobotLegs architecture while providing the ability to create presentation model in RobotLegs. Since I couldn’t think of a solution other than creating my own mapping system for the presentation model I started modifying RobotLegs framework, however as I was modifying the framework it hit me that there is a more elegant solution using the existing architecture.

Feel free to view and download (right click to ‘view source’) the full example from here:

screen-shot-2010-01-23-at-110559-am

Implementation

Let’s take a look at the example in detail. My entry point, main MXML application, calls the context:ApplicationContext just like any Robotlegs (MVCS) implementation. I have added component that gets attached to the view called mainView


<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/halo"
			   xmlns:context="com.elad.application.*"
			   minWidth="1024" minHeight="768"
			   xmlns:view="com.elad.application.view.*">

	<fx:Declarations>
		<context:ApplicationContext contextView="{this}" />
	</fx:Declarations>

	<view:MainView id="mainView" width="100%" height="100%" />

</s:Application>

Using a presentation model will allows me to easy unit test my application better, since I can create test cases just for the logic and if needed test cases for the view. Additionally, I can replace my view easily and create different views for the same logic, which will help big time with Flex 4 new architecture and Flash Catalyst.

So using presentation model such as passive view I can than split my laundry to two piles, view and presenter:

View:
1. State is in the view
2. Transitions
3. View is passive and is not aware of the Presenter

Presenter:
1. Logic is in the Presenter.
2. Presenter observes view events
3. Presenter updates the view data.
4. Presenter ‘knows’ about the components in the view.
5. Presenter holds the data or point to a data class.

In fact, I have used the exact same example I created for Flash&Flex Magazine with very small modifications. Take a look at TweetListPresenter, which holds the responsibilities that I described:


package com.elad.application.view.presenter
{
	import com.elad.application.view.TweetListView;

	import flash.events.TimerEvent;
	import flash.utils.Timer;

	import mx.events.FlexEvent;

	import org.robotlegs.mvcs.Actor;

	import utils.twitter.TwitterHelper;
	import utils.twitter.events.TwitterHelperFailureEvent;
	import utils.twitter.events.TwitterHelperSuccessEvent;
	import utils.twitter.vo.TweetVO;

	public class TweetListPresenter extends Actor
	{
		/**
		 * Corresponding view
		 */
		private var _tweetListView:TweetListView;

		/**
		 * Method to go and retireve tweets every defined number of seconds
		 *
		 * @param seconds
		 *
		 */		

		public function get tweetListView():TweetListView
		{
			return _tweetListView;
		}

		public function set tweetListView(value:TweetListView):void
		{
			_tweetListView = value;
		}		

		/**
		 *  Twitter helper utility class instance
		 */
		public var twitterHelper:TwitterHelper;

		/**
		 *   Holds a timer so we will be able to update list
		 */
		public var timer:Timer;

		//--------------------------------------------------------------------------
		//
		//  Default Constructor
		//
		//--------------------------------------------------------------------------

		// called right after pre-init
		public function TweetListPresenter()
		{
			_tweetListView = new TweetListView();
			_tweetListView.width = 800;
			_tweetListView.height = 400;

			_tweetListView.addEventListener( FlexEvent.PREINITIALIZE, onPreinitialize );
			_tweetListView.addEventListener( FlexEvent.INITIALIZE, onInitialize );
			_tweetListView.addEventListener( FlexEvent.CREATION_COMPLETE, onComplete );

			twitterHelper = new TwitterHelper();
			twitterHelper.addEventListener( TwitterHelperSuccessEvent.RETRIEVE_TWEETS, onRetrieveTweets );
			twitterHelper.addEventListener( TwitterHelperFailureEvent.SERVICE_FAILURE, onFaultRequest );
		}

		public function retrieveTweetsEveryFewSeconds( seconds:int ):void
		{
			timer = new Timer( seconds*1000, 100000 );
			timer.addEventListener( TimerEvent.TIMER, onTimerHandler, false, 0, true );

			timer.start();
		}

		//--------------------------------------------------------------------------
		//
		//  Handlers
		//
		//--------------------------------------------------------------------------		

		private function onPreinitialize(event:FlexEvent):void
		{
			// implememt
			trace("onPreinitialize");
		}

		private function onInitialize(event:FlexEvent):void
		{
			// implememt
			trace("onInitialize");
		}

		private function onComplete(event:FlexEvent):void
		{
			trace("onComplete");
			retrieveTweetsEveryFewSeconds( 2 );
		}

		/**
		 * Method to handle a timer event
		 *
		 * @param event
		 *
		 */
		private function onTimerHandler( event:TimerEvent ):void
		{
			twitterHelper.retrieveTweetsBasedOnHashTag( "FlashAndTheCity" );
		}

		/**
		 * Handler for results
		 *
		 * @param event
		 *
		 */
		private function onRetrieveTweets( event:TwitterHelperSuccessEvent ):void
		{
			var dataProvider:Array = new Array();

			event.collection.forEach( function callback(item:TweetVO, index:int, vector:Vector.<TweetVO>):void {
				dataProvider.push( item );
			} );

			this._tweetListView.dataGrid.dataProvider = dataProvider;
		}

		/**
		 * Handler for fault
		 *
		 * @param event
		 *
		 */
		private function onFaultRequest( event:TwitterHelperFailureEvent ):void
		{
		}
	}
}

Couple of things to notice.

  • Actor - The presenter extends Actor just like any other RobotLegs actor
  • Component’s life cycle events - The default constructor creates the passive view and set the size as well as the component’s life cycle events

The view is passive and just holds the component (in our case a DataGrid):


<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/halo"
		 width="400" height="300">

	<mx:DataGrid id="dataGrid" width="500" height="400" />

</s:Group> 

The next step is to create the mediator for the main view:


	public class MainViewMediator extends Mediator
	{
		[Inject]
		public var mainView:MainView;

		[Inject]
		public var tweetListPresenter:TweetListPresenter;			

		override public function onRegister():void
		{
			mainView.addElement( tweetListPresenter.tweetListView );
		}
	}

Notice that I am using the DI to inject the presenter just as we do to any Actor in RobotLegs:
[Inject] public var tweetListPresenter:TweetListPresenter;

And once the main view is registered I can than add the component to the display:
mainView.addElement( tweetListPresenter.tweetListView );

Lastly, I need to map everything up in the ApplicationContext class:


		override public function startup():void
		{
			//todo: add commands
            commandMap.mapEvent(ContextEvent.STARTUP, StartupCommand, ContextEvent, true);

			// todo: Add Model
            injector.mapSingleton( TweetListPresenter );

			// todo: Add Services

			// todo: Add View
            mediatorMap.mapView(MainView, MainViewMediator);

			// Startup complete
			dispatchEvent( new ContextEvent( ContextEvent.STARTUP ) );
		}

Take a look at the folder structure:

screen-shot-2010-01-23-at-113505-am

Feel free to download the full example from here, and let me know your thoughts.

Cheers :)

19
Jan

Flexunit 4 with Test Driven Development article on FFDMag

I recently published an article on Flash&Flex Magazine about Flexunit 4 with Test Driven Development. You can download it from here:
http://ffdmag.com/magazine/991-flash-and-mobile-apps-iphone-and-ipod-touch

I decided to use a real life example to help reader better understand FlexUnit 4 and TDD. While trying to come up with an example, I realized that one of my tasks these days is to create and AIR application similar to Adobe MAX Companion AIR Application for a conference I am organizing called FlashAndTheCity. Creating a real application can show you how the process goes in real development and not in a fake example that tries to make everything simple and easy. Creating applications is complex and changes often even as you build your application.

Feel free to download from here and feel free to ping me with any feedback:
http://ffdmag.com/magazine/991-flash-and-mobile-apps-iphone-and-ipod-touch

19
Jan

I am very pleased and honored to join the Adobe Community Experts, now called Adobe Community Professional

I am very pleased and honored to join the amazing list of Adobe Community Experts, now called Adobe Community Professional, this year. It is very gratifying to be acknowledged for the work one put into the Flash community and I will be continue my commitment to share my knowledge as well as help the Flash community with my own event (FlashAndTheCity) as well as speaking and helping other Flash events.

So what is the Adobe Community Professional (ACP) program anyway? “The Adobe Community Experts Program is a community based program made up of Adobe customers who share their product expertise with the world-wide Adobe community. The Adobe Community Experts’ mission is to provide high caliber peer-to-peer communication educating and improving the product skills of Adobe customers worldwide.” - http://www.adobe.com/communities/experts/

Thanks Adobe!

19
Dec

Adobe closed major security concerns with Flash Player 10.0.42.34 however these changes may effect the ability to access swfs when setting Security.allowDomain

It appears that Adobe closed some major security concerns with Flash Player 10.0.42.34 see here, however I believe these security concerns have changed the ability to access swf when setting Security.allowDomain.

ASDOC says:

“If two SWF files are served from different domains — for example, http://siteA.com/swfA.swf and http://siteB.com/siteB.swf — then, by default, Flash Player does not allow swfA.swf to script swfB.swf, nor swfB.swf to script swfA.swf. A SWF file gives SWF files from other domains by calling Security.allowDomain(). This is called cross-domain scripting. By calling Security.allowDomain(”siteA.com”), siteB.swf gives siteA.swf permission to script it.” > see here.

In the example below I am creating the example ASDOC is describing. I will create two application which will be hosted on two separate domain names, however I am unable to change properties in the accessed application, see detail below:

Accessed application will holds a label and set the Security.allowDomain to wild card (*) so any application should be able to load this swf and change properties. See below:


<Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/halo"
			   minWidth="1024" minHeight="768" preinitialize="application1_initializeHandler(event)">
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;

			protected function application1_initializeHandler(event:FlexEvent):void
			{
				Security.allowDomain("*");
			}

		]]>
	</fx:Script>

	<Label id="label" text="Hello from accessed application!"  x="8" y="9"/>

</s:Application>

The second application (accessing application) will be hosted on a separate domain and load the accessed swf and change the label property:


<Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/halo"
			   minWidth="1024" minHeight="768"
			   initialize="initializeHandler()">
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.events.FlexEvent;

			// define variables
			private var loader:Loader;
			private var content:*;

			// load swf
			private function initializeHandler():void
			{
				loader = new Loader();
				loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadContent_onComplete);
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.load(new URLRequest("http://zeen.com/temp/bin-debug/AccessedApplication.swf"));

				component.addChild(loader);
			}

			// Event Handler

			private function loadContent_onComplete(event:Event):void
			{
				content = event.target.content;

				var onContentApplicationComplete:Function = function(event:Event):void
				{
					// content loaded successfully
				}

				content.addEventListener(FlexEvent.APPLICATION_COMPLETE, onContentApplicationComplete);
			}

			private function ioErrorHandler(event:IOErrorEvent):void
			{
				loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				Alert.show(event.text);
			}

			private function securityErrorHandler(event:SecurityErrorEvent):void
			{
				loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				Alert.show(event.text);
			}          

			// methods to access loaded swf

			private function callAccessedApplication():void
			{
				this.content.document.label.text = "label change!";
			}

		]]>
	</fx:Script>

	<mx:UIComponent id="component" width="400" height="82" x="11" y="43" />

	<Button label="Call accessed application"
			  click="callAccessedApplication()" x="84" y="0"/>   

</s:Application>

I also have set the cross-domain policy on the accessed applciation server to allow access:


<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
   <allow-access-from domain="*"/>
</cross-domain-policy> 

The swf is loaded successfully, but with a warning alert. Additionally, I am unable to change the label properties on the accessed application, see screen shot below:

screen-shot-2009-12-19-at-71327-pm

The application is hosted here:
http://eladelrom.com/bin-debug/AccessingApplication.html

I am hoping to get a clarification: https://bugs.adobe.com/jira/browse/FP-3513

10
Dec

Lightweight Ant script extensions generator for Robotlegs following best practices.

RobotLegs is one of the newest AS3 Micro-Architecture framework out there and to help folks that are starting with Robotlegs, as well as make life easier for current Robotlegs users, I have created Ant script extensions that generate most of the code you need in order to work with RobotLegs following best practices.

robotlegssketchsmall

The Ant tasks will generate the following:

  • Robotlegs Folder structure.
  • Robotlegs libraries and source code
  • Automatic ThunderBolt integration to each user-gesture.
  • Creating VO.
  • Add event command user gesture
  • Add startup command
  • Add main class and Context class
  • Create model class
  • Create service class
  • Create view and mediator combo
  • Move libraries and source code to project lib

You can download the Ant tasks from GitHub:
http://github.com/EladElrom/robotlegs-utilities-AntGenerator

Feel free to add these tasks to your arsenal.. Cheers :)

09
Dec

Top security threats to Flash/Flex applications and how to avoid them - series on InsideRIA

Just published the 1st article In the series of articles I will be posting on InsideRIA in regards to Flash/Flex security. The intention of these articles is for you to gain knowledge about security in regards to Flash and Flex applications. In each article I will be covering specific security vulnerabilities, showing examples of how an attacker can abuse Flash/Flex applications, and pointing out ways to help prevent these attacks. The purpose of these articles is to increase awareness so you will take security into consideration when building your applications.

flashsecurity

See the first article that talks about Cross-domain Scripting threat here:
http://www.insideria.com/2009/12/top-security-threats-to-flashf.html

01
Dec

RIABeardOff - charity event for members of the RIA community

In case you didn’t hear, Chuck Freedman started an amazing and generous event called RIA Beard Off. The event is a charity event for members of the RIA community to grow beards and raise money for Marine Toys for Tots Foundation.

I decided to help out and I stopped shaving last Monday. We are looking to reach at least $2,000, but hopefully more, so to entice you to donate I decided to give away prizes.

This is what you need to do: make a donation to #RIABeardoff and mention my name when you make the donation and two lucky people will win the book I co-authored click here to view. The book will be shipped to your preferred address.

In addition to the two books, I am also going to give away a 3rd prize, which is going to be a surprise. Make a donation now! http://firstgiving.com/riabeardoff

    TIMELINE:

  • 11/23 - Monday - Bearder registration starts
  • 11/27 - Friday - Bearder registration ends, Open donations start!
  • 11/30 - Monday - First of many, frequent beader snapshots posted!
  • 12/14 - Monday - Last Bearder update posted!
  • 12/15 - Tuesday - Bearding ends. Bearders can shave & move on with their lives.

Here is the list of the generous Flash developers that agreed to stop shaving:

LordAlex Leon
Stacey Mulcahy ( BitchWhoCodes)
Bernie & Erikka Perkins
Mims H. Wright
Scott Janousek
Chris Allen
Curt Staubach (@curtStaubach)
Paul Gregoire (@mondain)
@BenStucki
Todd Anderson (@bustardcelly)
Robert Hall (@rhall)
Joseph Labrecque (@JosephLabrecque)
Jesse Freeman (@theflashbum)
Kevin Suttle (@kevinSuttle)
Brian Connatser (@connatser)
Elad Elrom (@EladElrom)
Chuck Freedman (@chuckstar)

I want to point out that some have actually shaved beards that were years old, like Robert Hall and Scott Janousek.

This is a great cause and every donation counts, so please donate!