Prepared to head off to Adobe MAX 2008. This will be my 4 or 5th time going, can’t recall all of them. I signed up for lots of advanced Flex and AIR courses, should be pretty good learning experience. I especially enjoy seeing some of the problems others in the field are working on and the unique solutions they demonstrate at MAX. I am also hoping to win a free copy of the new Adobe Creative Suite.
See you all there!
-Mr
My recent employer just released a service announcement that they are closing their doors December 31st 2008. What this means now is that all the applications I helped development for the past 2 years will vanish into the ether, poof! This is very sad indeed as I spent a good amount of time this year working on some software updates that will never see the light of day and all the exiting lines of code will gather dust.
Xdrive Desktop Lite was just presented last year at Adobe MAX 2007 and was selected this year as a semi-finalist in the Adobe MAX 2008 awards. I also released an ActionScript 3 library wrapper for the Open Xdrive JSON API, which will also be defunct after the end of the year. I feel a little loss from this news, but I am also looking for what comes ahead.
Good bye Xdrive my old friend… hello new Flex opportunities!
-Mister
Just received my new T-Mobile G1. I think it arrived a little bit ahead of the estimated arrival date. Just took a couple of photos and now trying to figure out all the goodies of the phone.
Size of G1 compared to my T-Mobile Dash:

Thinks I like about Android:
1. Copy and Paste text, finally (take that iPhone)
2. Crazy amount of cool location aware applications being built
3. Great support for Google gmail, browser, and maps
Things not so keen on:
1. Hard to answer phone when phone locked
2. No on screen keyboard, pain to slide out keyboard all the time
3. Signal strength of 3G network is not as good in my areal
4. No native Google application to handle Google Docs
5. Phone is a bit bulky in the pocket
6. No good case for the phone, unlike iPhone
- Mr
Yesterday was my last day of work at a full-time gig. I now find myself looking for new opportunities for the first time in almost two years. I moved to Los Angeles back in November of 2006 with high hopes to create great Flex applications, expand my knowledge and become more connected to the Flex community. Well, I did create some pretty cool applications and gained a ton of application experience with both Flex and AIR. I event had opportunities to connect to the Flex community by speaking at FITC Hollywood and Adobe MAX. I even had the opportunity to be part of the prerelease programs for Adobe Flex and AIR, and connected with some great people along the way. Is there more to do, yes. Is there more to learn, yes.
Though I didn’t know it at the time, moving to Los Angeles also changed my personal life and many of the goals I had initially laid out. Was it an overall positive move, maybe. I didn’t get as far as I truly wanted with the community connections. I had hoped our corporation would sponsor 360Flex and other community events. Things change at big companies in ways that are not always what you want, and you just sort of have to suck it up. Not unlike the changes in your personal life.
I am looking forward now to new opportunities. I learned that working for the “man” in a large corporations on a permanent basis is definitely not what I want. I want to experience a variety of development opportunities with Flex and AIR. I want to do more consulting and test the contracting waters for a while. I now have direction and new hope for controlling more of my own future. I love to create, Flex and AIR are both my canvas and my paint for creating. I am looking forward to making some great things in the year to come and looking forward to changes to come.
I am fortunate of one thing, working with Flex and AIR have given me choices and opportunities that other development areas may not have. Things might be tight with the economy, but our field is still rolling strong as more companies turn to this technology to deliver compelling applications. I hope our technology area is spared from the economic troubles ahead and development opportunities abound next year.
Here’s to new beginnings and to always discovering more about yourself in everything you do.
-Mister
Adobe AIR has a quick and safe way to store encrypted user data when building applications. Data such as login and password can be persisted in the application using the EncryptedLocalStore available for AIR applications.
To demonstrate this, I wrote a quick demo application that will store username and password after users login. When the application is launched again, the same username and password will be retrieved from the EncryptedLocalStore and propagate the login and password text boxes. User's also have the option to reset the data and store a new username and password, removing the stored data from the EcryptedLocalStore.
This can be handy when you want your application to do auto-login, using the existing stored information from the user's previous session, and of course, the stored data is encrypted.
Example:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="410" height="260" creationComplete="initComponent()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private function initComponent():void
{
var password:ByteArray = EncryptedLocalStore.getItem("password");
var username:ByteArray = EncryptedLocalStore.getItem("username");
try{
if(password.length && username.length){
passwordInput.text = password.readUTFBytes(password.length);
nameInput.text = username.readUTFBytes(username.length);
}
} catch (e:Error){Alert.show(e.message);}
}
private function onLogin(event:Event):void
{
if(nameInput.text == "" || passwordInput.text == ""){
Alert.show("Please enter username and password");
return;
}
try {
EncryptedLocalStore.reset();
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(nameInput.text);
EncryptedLocalStore.setItem("username", bytes);
bytes = new ByteArray();
bytes.writeUTFBytes(passwordInput.text);
EncryptedLocalStore.setItem("password", bytes);
Alert.show("Writing username and password to local store.");
} catch(e:Error){Alert.show("Error writing store: " + e.message)}
}
private function onReset(event:Event):void
{
passwordInput.text = "";
nameInput.text = "";
nameInput.setFocus();
EncryptedLocalStore.reset();
}
private function onKeyDown(event:KeyboardEvent):void
{
if ( event.charCode == Keyboard.ENTER) {
onLogin(null);
}
}
]]>
</mx:Script>
<mx:Canvas width="380" height="240" horizontalCenter="0" verticalCenter="0">
<mx:VBox verticalAlign="middle" horizontalAlign="left" verticalGap="0" horizontalCenter="0" bottom="142">
<mx:Label id="userText" text="username" creationComplete="nameInput.setFocus()"/>
<mx:TextInput id="nameInput" creationComplete="{nameInput.setFocus()}" keyDown="onKeyDown(event)"/>
</mx:VBox>
<mx:VBox verticalAlign="middle" horizontalAlign="left" verticalGap="0" horizontalCenter="0" bottom="95">
<mx:Label text="password" />
<mx:TextInput id="passwordInput" displayAsPassword="true" keyDown="onKeyDown(event)"/>
</mx:VBox>
<mx:ControlBar bottom="16" width="161" height="35" horizontalCenter="0">
<mx:Button id="submitButton" label="submit" click="onLogin(event)" textAlign="center" />
<mx:Button id="resetButton" label="reset" click="onReset(event)" textAlign="center"/>
</mx:ControlBar>
</mx:Canvas>
</mx:WindowedApplication>
To use the example code, just create a new AIR application in Flex Builder and paste the code into your main MXML file.
-Mister
Detecting a listing for local drives using Adobe AIR is fairly straight forward using the Adobe AIR File function getDirectoryListing for Mac or getRootDirectories for PC. The following code will get you a listing of the local drives for Mac or PC:
import flash.filesystem.File;
import flash.system.Capabilities;
private function getDrives():void
{
var os:String = Capabilities.os.substr(0, 3).toLowerCase();
var currentDrives:Array = (os=="mac") ? new File('/Volumes/').getDirectoryListing() : File.getRootDirectories() ;
for each(var file:File in currentDrives){
trace ("Drive: " + file.name + " Size: " + file.size);
}
}
However, what I wanted to do was automatically refresh the the drive listing on a set time interval so I could detect newly added or removed drives. Here is a sample for that:
import flash.
events.
TimerEvent;
import flash.
filesystem.
File;
import flash.
system.
Capabilities;
import flash.
utils.
Timer;
private function setDriveWatcher():void
{
var timer:Timer = new Timer( 2000 );
timer.addEventListener( TimerEvent.TIMER, timerHandler );
timer.start();
}
private function timerHandler(event : TimerEvent):void
{
var os:String = Capabilities.os.substr(0, 3).toLowerCase();
var currentDrives:Array = (os=="mac") ? new File('/Volumes/').getDirectoryListing() : File.getRootDirectories() ;
for each(var file:File in currentDrives){
trace ("Drive: " + file.name + " Size: " + file.size);
}
}
Everything seems to work great on my Mac, but when I tested the application on my PC I heard a strange constant grinding noise coming from the A: drive, you know, that dinosaur floppy drive you probably forgot your PC had. It seems that when AIR gets a listing of all the local drives on the user machine, it pings the A: drive which causes it to make the noise. Remember when you try to access a PC floppy drive when it was empty it makes a lovely grinding noise that sounds like the drive is eating itself.
I suspect this issue arises because I am doing something with the directory detection feature of AIR that was not intended by Adobe, that is to repeatedly get listings of all local drives. However, I am trying to make a hack for a feature that Adobe probably should have included with AIR, automatically detecting drives being added and removed from the users machine. This is the issue that probably needs to be addressed by Adobe. I could not find any way to just skip certain drives, like the A: drive to avoid this issue either.
This issue does not happen on all PC's with floppy drives, just a handful that I have tested. It seems to be less of a problem when users have an actual floppy in the drive, but its not a total solution. It's slightly annoying to auto-detect the adding or removing of drives, so I recommend making a manual drive refresh option for users, something they can click one whenever they add or remove an external drive. Now, if I can only get AIR to recognize the type of drives automatically, like the difference between a hard drive, usb drive, and my camera, that would be nice.
-Mr
Today Google reported that they now have a new algorithm for indexing the textual content of Flash files. This has always been something businesses have been concerned with, how to do SEO (Search Engine Optimization) with Flash. Flash developers (and Flex) would have to place the content of the Flash into a page so that search engines could index it, now it looks like Google has stepped up and created a way to index the content of the Flash file itself, right down to the menu items. Take a look at the article on Google's blog.
Google came out with another post today to answer questions around indexing Flash content. The question answer section of the post was great until you get to the very last question:
Q: What are the current technical limitations of Google's ability to index Flash?
There are three main limitations at present, and we are already working on resolving them:
1. Googlebot does not execute some types of JavaScript. So if your web page loads a Flash file via JavaScript, Google may not be aware of that Flash file, in which case it will not be indexed.
2. We currently do not attach content from external resources that are loaded by your Flash files. If your Flash file loads an HTML file, an XML file, another SWF file, etc., Google will separately index that resource, but it will not yet be considered to be part of the content in your Flash file.
3. While we are able to index Flash in almost all of the languages found on the web, currently there are difficulties with Flash content written in bidirectional languages. Until this is fixed, we will be unable to index Hebrew language or Arabic language content from Flash files.
We're already making progress on these issues, so stay tuned!
Hmm, if Google doesn't index JavaScript and you use something like SWFObject to embed your Flash then you are pretty much back to where you were before Google made the improvements. For issue 1, this might not be a problem for smaller gadgets on 3rd party sites, but you don't want your main application site to have that annoying click through problem caused by the patent law suit by EOLAS against Microsoft. Remember those times, before the issue was solved with JavaScript. For issue 2, your content will get indexed, but it won't be considered part of your Flash content, this might effect some metrics or Omniture reporting (which means money).
Well, I guess its partial good news, at least they say they are working on those isues.
- Mr
I have not posted in a long long while it seems. That would be nice if I were just hanging out on a beach some place. However, I have been busy doing lots of things for work and working on a new AS3 library.
I have been developing for the past few months an AS3 library (as3xdrivelib) wrapper for the Open Xdrive JSON API. Xdrive is an online storage platform and they offer a free JSON API for developers to create storage and other types of applications upon their service. With Xdrive, each user gets a 5GB account for free, with additional costs for more storage.
I finally got around to making an AS3 library that wraps much of the Xdrive API and abstracts the inner workings from those developing Flex, AIR, or Flash applications. The Xdrive API is extremely rich, it offers ways for users to share folders, collaborate on shared collections (look for a later post and application on this feature), and publish assets. However, main part of the platform is file management.
I have placed the library on Google Coders and included a Flex sample application for doing some basic operations with Xdrive. You just need an Xdrive account to start using the library. I am hoping this helps developers starts to build some cool applications using the Xdrive plaform. Along with the library, I included an example application called Xdrive SlimDrive, which demonstrates the basic functionality for doing file management and shows how to work with the library.
===============
as3xdrivelib
===============
The as3xdrivelib project is a wrapper for the Open Xdrive JSON API. It provides much of the client-side functionality for applications; for example, authentication, uploading files, sharing files, and basic file management.
Project Page: http://code.google.com/p/as3xdrivelib
Project Group: http://groups.google.com/group/as3xdrivelib
Authors: Michael Ritchie, Maria Vazquez, Lucas McGregor, Joe Provost
Dependencies: corelib (http://code.google.com/p/as3corelib)
How to use the as3xdrivelib with Cairngorm.
I didn't get a chance to post this to the Google Code, but I wanted to show a quick login example that uses the library with Cairngorm. The following example uses a very simplistic login screen with a Cairngorm Event/Command/Delegate to login to a users Xdrive account. The example is pretty straight forward if you know Cairngorm already. There are some things to notice in the Delegate and Command. In the Delegate, notice how the I setup the delegate to use the as3xdrivelib as a service and how I mapped the events back to the command.
public function login(user:User) : void {
var token : XdriveAPIToken = service.login(user);
token.addEventListener(XdriveAPIEvent.API_RESULT, responder.result);
token.addEventListener(XdriveAPIEvent.API_FAILURE, responder.fault);
}
In the Command notice how I map the payload (user) on the API result to the Model. This is explained in the documentation for the library, but basically the payload contains a return variable(s) name on the payload event that almost always represents the object you send to the library method.
public function result( event : Object ) : void
{
var resultEvent : XdriveAPIEvent = XdriveAPIEvent(event);
model.user = resultEvent.payload.user as User; // store value in model for binding
}
Example File (right-click to view source/download)
- Mister
One of the longest running post on my blog has been about creating XHTML output from the Flex RichTextEditor control. I always thought it would would be nice if someone took all the comments and suggestions for that post and created a customized control that outputs proper XTHML. Well, Axel Jenson has created such a custom control. I want to send many thanks to all those who posted over the past year and to Axel for stepping up and creating this custom control for Flex. Give the component a try and let Axel know what you think.
-Mr
I wanted to write a quick post because I am just exploring the ability to build ASDocs using ANT from within Flex Builder 3. Adobe Labs has a post about using Flex Ant Tasks to manage builds from Flex. With this tool you can compile Flex applications, modules, libraries, and HTML wrapper code, as well as build your documentation with ASDocs. I created a sample Flex Library project that uses the compc feature of the Flex Ant tasks to compile my library into a SWC. I also use exec command in the same build file to create the ASDocs for the project. The path names in the build file have been abstracted into properties file. This properties file can be changed to build the project on both Mac and PC (thanks Joseph and Avani for your help).
The only problems I ran into for this project was pointing to the path of my Mac when compared to the paths on a PC and the name for the asdocs file. The asdoc (asdoc.exe on PC and just asdoc on Mac) doesn't like space in the path names to the output and source directories. So if you place these values direclty in the build XML file you have to use single quotes for the values, something like this:
<target
name=
"asDocs">
<exec executable="${FLEX_HOME}/bin/asdoc" failonerror="true">
<arg line="-doc-sources '/Users/xmritchie/Documents/Flex Builder 3/as3xdrivelib/com'"/>
<arg line="-window-title 'Xdrive AS3 Library'"/>
<arg line="-output='/Users/xmritchie/Documents/Flex Builder 3/as3xdrivelib/docs'"/>
<arg line="-external-library-path='/Users/xmritchie/Documents/Flex Builder 3/as3xdrivelib/libs'"/>
</exec>
<echo>docs created</echo>
</target>
However, if you abstract these value into a properties file you won't have any issues with paths. The build.xml file and the properties file go into the root level of your library project. You need to download and install the flexTasks.jar file from Adobe into your Flex Builder 3 plugins folder. On my machine, I placed the jar file into /Applications/Adobe Flex Builder 3/plugins/org.apache.ant_1.7.0.v200706080842. I also placed the flexTasks.jar file into /Applications/Adobe Flex Builder 3/sdks/3.0.0/ant/lib. Grab the files from http://labs.adobe.com/wiki/index.php/Flex_Ant_Tasks.
Here is the code for the build.xml:
<?
xml version=
"1.0" encoding=
"utf-8"?>
<!-- Flex Library Project ASDocs -->
<project name="ASDocsTest" default="compile" basedir=".">
<!-- import our build properties file -->
<property file="./build.properties" />
<!-- Flex Ant Tasks used to perform compc and mxml compiling more info at http://labs.adobe.com/wiki/index.php/Flex_Ant_Tasks -->
<taskdef resource="flexTasks.tasks" classpath="${basedir}/flexTasks/lib/flexTasks.jar" />
<target name="setup" description="perform an setup operations"/>
<!-- Execute the ASDoc Compile wich runs 3 seperate tasks in a series -->
<target name="compile" description="series of tasks to create docs and swc">
<antcall target="cleanDir" description="clean the docs directory"/>
<antcall target="asDocs" description="full build of asdocs"/>
<antcall target="buildSWC" description="build the SWC file"/>
</target>
<target name="deploy" description="perform an deployment operations"/>
<target name="install" description="perform an installation operations"/>
<!--
DELETE the existing output folder and files and then re-generate the output folder
-->
<target name="cleanDir" description="DELETE the existing output folder and files and then re-generate the output folder">
<delete dir="${basedir}/${docsoutputfolder}" failOnError="true" includeEmptyDirs="true"/>
<mkdir dir="${basedir}/${docsoutputfolder}"/>
<!-- echo dumps output to the console window -->
<echo>doc directory cleaned</echo>
</target>
<!--
Run the ASDoc executable and generate the ASDocs to the new output folder
-->
<target name="asDocs" description="Run the ASDoc executable and generate the ASDocs to the new output folder">
<exec executable="${asdoc.exe}" failonerror="true">
<arg line="-doc-sources ${domainextensions}"/>
<arg value="-window-title" />
<arg value="'${title}'"/>
<arg value="-output" />
<arg value="${basedir}/${docsoutputfolder}"/>
<arg value="-external-library-path" />
<arg value="${basedir}/${libpath}" />
</exec>
<echo>docs created</echo>
</target>
<!--
Compile the SWC file library including libs folder and the path to our classes, we use compc for library, but we
would use mxml for MXML files, check the docs for Flex Ant Tasks, http://labs.adobe.com/wiki/index.php/Flex_Ant_Tasks.
-->
<target name="buildSWC" description="Compile the SWC file for the Librayr Project">
<compc output="${basedir}/${liboutputfolder}/${liboutputfile}">
<!--
Include the path to any external SWC files used in our document, you may have to place name of SWC (corelib.swc) at end of path
I didn't inlcude it because I didn't want to redistribute the corelib.swc. So file path would be file="${basedir}/${libpath}/corelib.swc"
-->
<include-libraries file="${basedir}/${libpath}/" />
<source-path path-element="${basedir}" />
<!-- include our Class packages into the build (com folder) -->
<include-sources dir="${basedir}/${domainextensions}" includes="*" />
</compc>
<echo>SWC created</echo>
</target>
</project>
Here is the code for the build.properties:
# Window and document title for the documentation
title = ASDocs Test Library
# Class-folders you want to search for classes to be included in the docs, seperated by spaces (for example ../com/ ../net/ )
# to include every .as and .mxml file within your project, just state ../
domainextensions = ./com
# The Location of deployment library on your Computer (PC/Mac) for compiled SWC file
liboutputfolder = bin
liboutputfile = ASDocsTest.swc
libpath = libs
# The Location of the output folder for your generated documents
docsoutputfolder = bin/docs
# Home directory for flex sdk 3, change this to build for Mac or PC using # as comment
# FLEX_HOME = C:/Program Files/Adobe/Flex Builder 3/sdks/3.0.0
FLEX_HOME = /Applications/Adobe Flex Builder 3/sdks/3.0.0
# The location of your asdoc.exe, change this to build for Mac or PC using # as comment
#asdoc.exe = C:/Program Files/Adobe/Flex Builder 3/sdks/3.0.0/bin/asdoc.exe
asdoc.exe = /Applications/Adobe Flex Builder 3/sdks/3.0.0/bin/asdoc
Once you have the Ant plugin installed for Flex Builder 3 and you restart, go to Widows --> Other Views and select Ant. Drag the build.xml file to the Ant dialog window, then double-click on compile to run the script. This is how you build the docs and the SWC file. You can also use those same build and properties files in the SDK.
Here is the example file, just download the file directly from link, unzip the file, and import into your Flex builder.
ASDocsTest.zip
- Mister