Migrate Flex 4 Beta 2 to Latest Nightly Builds

I have a project based on Flex 4 Beta 2 and now I wanted to migrate to the latest nightly build since there were many important fixes.
Things have changed so here what I did to get my project up and running again:

Halo is now mx

The namespace for halo (Flex 3) components changed from xmlns:mx=”library://ns.adobe.com/flex/halo” to xmlns:mx=”library://ns.adobe.com/flex/mx”. Just do a quick search and replace and this one is solved. Also do not forget to update you CSS file namespace to @namespace mx “library://ns.adobe.com/flex/mx”;

Flex 3 compatibility mode is gone

My project originally was based on Flex 3 so I used the Flex 3 compatibility option in Flex 4 Beta 2. This does not seem supported anymore and you get lots of dependency errors for halo/mx components that they require at least 4.0.0. So disable the Flex 3 mode and select the halo theme to be still compatible with Flex 3 aka halo components.

Ant

I build my AIR project with Ant so I had to define to use the halo theme:

<compiler.theme dir="${flex.sdk.dir}/frameworks/themes/Halo/">
	<include name="halo.swc" />
</compiler.theme>

In my case I switched to build 4.0.0.13323 and it looks pretty cool. The compiler seems faster and my app in general performed well. There is now also a Spark ToggleButton but a few things are still missing like IconButton, SparkAlert and so on. Anyway, I use Flex 4 for production already and feel pretty solid about it. The workflow is way better than with Flex 3 because of the new state syntax, better skinning, FXG, light weight groups etc.

Chunk File Upload

A while back I worked on an AIR client which had to be capable uploading very large files. In this scenario you have to upload files in little chunks. The research on how to solve this took me quite a while so I thought it would make sense to post my findings.

More or less I have taken the NirvanixBinaryUploader as a base and then extended (I should say forked) it to fit my needs.

The class UploadFile takes a file and upload URL as constructor arguments. You can also define a separate resumeUrl if it differs from the upload URL. Further you can set the flag doCalcMD5 to true which is kind of experimental. It works using the as3corelib MD5Stream class but calculating the MD5 hash for large chunks like 1MB took about 20-30 secs on my machine.

I have also implement getters for bytesLoaded and bytesTotal so I can use an instance as a data source for the Flex ProgressBar in polled mode which comes in very handy.

<mx:ProgressBar source="{uploadFile}" mode="polled" label="Uploading" />

If you want to use my code I guess you want to subclass my class because it contains example code and you probably want to override at least the createBody method. However, if you have a similar scenario like me, the code might be a good start.

Another interesting read on this topic was A long journey through chunked transfer and file uploading.

Here now the code:

Twitter AS3 OAuth Lib with Flex 4 example

I have build a little Twitter AS3 library which handles Twitter OAuth authentication and let’s you update your Twitter status. The lib basically uses the OAuth AS3 lib and should be a good example how to use the actual OAuth lib.

This is still basic functionality but since it’s open source someone may fork and extend it. To get a simple idea of the current feature-set have a look at the ITwitter interface.

Further I have build a simple Flex 4 example AIR app which shows things in action. The only thing you need to do upfront is registering a Twitter app to obtain an OAuth consumer key and secret which you have to add to the example:

BTW: You maybe have already granted access to your Twitter account for some apps which you can check here.

Swiz Desktop for AIR support

When you develop AIR applications you see repeating tasks which you have in all projects. You need to take care about the update process and online status. I am developing all my applications with the Swiz framework so I tried to come up with some re-usable code which fits nicely into Swiz.

Source and Download

Define the SwizUpdateBean in your Swiz BeanLoader:

<desktop:SwizUpdateBean xmlns:desktop="com.soenkerohde.desktop.*"
	id="swizUpdateBean"
	updateUrl="http://yourdomain.com/YourApp.air"
	autoCheckUpdate="true" autoStartUpdate="true" />

We have set the update URL and the flag to automatically check for an update and automatically download and invoke the update when a newer version is online.
However you may only want to use this in a very early stage of your development to simply ensure that the user always get’s the latest version. The user experience is a bit odd though since the user get’s no visual feedback at all and might be upset when the app closes, updates and restarts itself.

Control Update
A controller can add event listeners to the SwizUpdateBean to get notified when the update phase change so you get a point to interact. You can autowire the bean also against a setter which gives you the possibility to add event listeners:

package com.soenkerohde.example {
 
	import com.soenkerohde.example.UpdateWindow;
	import com.soenkerohde.desktop.ISwizUpdateBean;
	import com.soenkerohde.desktop.event.OnlineEvent;
	import com.soenkerohde.desktop.event.UpdateEvent;
 
	import org.swizframework.Swiz;
 
	import spark.components.Window;
 
	public class UpdateController {
 
		[Autowire]
		public function set updateBean( bean : ISwizUpdateBean ) : void {
			bean.addEventListener( UpdateEvent.VERSION_INFO, versionInfoHandler, false, 0, true );
			bean.addEventListener( UpdateEvent.UPDATE, updateHandler, false, 0, true );
			bean.addEventListener( OnlineEvent.CHANGE, onlineHandler, false, 0, true );
		}
 
		protected function versionInfoHandler( event : UpdateEvent ) : void {
			// when locale and remote version are different show update window
			if ( event.updateInfo.localVersion != event.updateInfo.remoteVersion ) {
				var updateWindow:Window = new UpdateWindow();
				Swiz.registerWindow( updateWindow );
				updateWindow.open();
				updateWindow.move( 50, 50 );
			}
		}
 
		protected function updateHandler( event : UpdateEvent ) : void {
			// prevent automatic update and wait for user to invoke
			event.preventDefault();
		}
 
		protected function onlineHandler( event : OnlineEvent ) : void {
			var online:Boolean = event.online;
			// TODO handle online status
		}
 
	}
}

Visual Feedback
Since the SwizUpdateBean is loaded in the BeanLoader we can autowire it into any view. The SwizUpdateBean implements the ISwizUpdateBean so we can autowire the interface by type without caring about the id. The ISwizUpdateBean has a getter for updateInfo which is a bindable getter for detailed update status information. In the example below we autowire it by property. We could also access it from the swizUpdateBean.updateInfo but I like it more as an extra member variable.

UpdateInfo gives you access to:

  • localVersion
  • remoteVersion
  • percent
  • bytesLoaded
  • bytesTotal
  • kiloBytePerSecond (we calculate the connection speed of the user)
  • timeRemaing (the time in seconds we have calculated remains to download the update)
  • updateFilePath (the path to the downloaded update file)
<s:Window width="240" height="210"
		  xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
		  xmlns:mx="library://ns.adobe.com/flex/halo" title="Update" alwaysInFront="true" resizable="false" showStatusBar="false">
 
	<s:layout>
		<s:BasicLayout />
	</s:layout>
 
	<fx:Script>
		<![CDATA[
			import flash.events.MouseEvent;
			import com.soenkerohde.desktop.ISwizUpdateBean;
			import com.soenkerohde.desktop.info.IUpdateInfo;
 
			[Bindable]
			[Autowire(bean="swizUpdateBean", property="updateInfo")]
			public var updateInfo:IUpdateInfo;
 
			[Bindable]
			[Autowire]
			public var swizUpdateBean:ISwizUpdateBean;
 
			protected function clickHandler( event : MouseEvent ) : void {
				swizUpdateBean.executeUpdate( false )
			}
		]]>
	</fx:Script>
 
	<s:VGroup horizontalCenter="0">
		<mx:Form verticalGap="0">
			<mx:FormItem label="Your Version:">
				<s:Label text="{updateInfo.localVersion}" />
			</mx:FormItem>
			<mx:FormItem label="New Version:">
				<s:Label text="{updateInfo.remoteVersion}" />
			</mx:FormItem>
		</mx:Form>
 
		<s:Label text="Progress: {updateInfo.bytesLoaded}/{updateInfo.bytesTotal} Bytes" />
		<mx:ProgressBar indeterminate="false" label="Remaining: {updateInfo.timeRemaining} sec with {updateInfo.kiloBytePerSecond} KB/s" mode="polled"
						source="{updateInfo}" />
 
	</s:VGroup>
 
	<s:Button bottom="10"
			  horizontalCenter="0" label="Update and Restart" enabled="{updateInfo.complete}" click="clickHandler(event)" />
 
</s:Window>

You see how easy it is to implement the ProgressBar. Because the updateInfo object has a getter for bytesLoaded and bytesTotal we only have to set the mode to “polled” and can set the object itself as the source of the ProgressBar.

Feedback appreciated or just fork the project on GitHub if you want to extend it.

FGATracker for Google Analytics tracking

FGATracker is an AS3 library which wraps gaforflash for Google Analytics and can be easily used in combination with the Swiz framework.

Source and Download

Usage

Add FGATracker to your BeanLoader:

<ga:FGATracker id="fgaTracker"
	   account="GOOGLE ANALYTICS ID" xmlns:ga="com.soenkerohde.ga.*" />

Dispatch TrackPageEvent or TrackActionEvent:

From a view class (set bubbles=true):

dispatchEvent( new TrackPageEvent( TrackPageEvent.PAGE, "/pagename", true ) );
dispatchEvent( new TrackActionEvent( TrackActionEvent.ACTION "category", "action", "label", NaN, true ) );

From a non-view class:

_dispatcher.dispatchEvent( new TrackPageEvent( TrackPageEvent.PAGE, "/pagename" ) );

You can get a reference if your class implements the IDispatcherBean interface:

private var _dispatcher:IEventDispatcher;
public function set dispatcher(dispatcher:IEventDispatcher):void
{
	_dispatcher  = dispatcher;
}

FlairLoc Public Beta

FlairLoc is an Adobe® AIR™ application to localize Adobe® Flex® applications.

Today I am happy to announce that the public beta of FlairLoc is available.

Features

  • Change resources in a user interface with search capability
  • Extract resource keys from source code and synchronizes it with all locale sets
  • Automatic translation into 42 languages with the Google Translate API
  • Add new automatic translated languages in only 4 CLICKS
  • Generation of locale compile statement and Ant parameters

For more information, screenvideo and screenshots and to install the application please visit the product page.