Garbage Collection in the UcompOS RXF
In large and sophisticated Flash-based applications, such as the Rich Portal Applications you develop with the UcompOS Rich Experience Framework, Garbage Collection becomes an increasingly important consideration.
Garbage Collection is a computer science concept that deals with memory management and re-allocating memory occupied by objects that are no longer needed or in use by the computer program.
Garbage Collection in a large-scale event-driven Flash architecture is a crucial consideration and unfortunately, can also be a tedious proposition to properly implement.
One of the more important considerations in aiding with Garbage Collection in Flash-based application is proper management of event listeners.
In a best-practice implementation, any call to addEventListener() would be followed up with a call to removeEventListener() once the event listener was no longer needed. Event listeners perpetuate the objects they are associated with so even once a particular object is destroyed, that doesn’t necessarily mean any event listeners associated with it will be destroyed too.
Failure to remove event listeners once they are no longer needed in a large-scale implementation can cause memory leaks and performance can break down over time.
In all your Flash applications, you should employ this strategy when and where possible.
In a typical large-scale UcompOS RXF implementation, Flash-based applications and sub-applications are continuously being loaded and unloaded into the UcompOS Portal.
The concept of Proxy Components in the UcompOS RXF involves event listeners being attached to a Proxy Component in one entity that represents an object in another UcompOS entity and then listening for dispatched events.
Therefore, the concept of garbage collection takes on especially critical importance in the UcompOS RXF because if UcompOS applications are being loaded and unloaded constantly and the event listeners that are attached to them are not being properly removed, performance would become an issue in a large-scale implementation.
The UcompOS Portal has been designed such that when SWF content that has been loaded into the UcompOS Portal is unloaded, a garbage collection routine is implemented to try to optimize system performance. (The three ways SWF content is loaded into the UcompOS Portal is in UcompOS Window instances, UcompOS Artifact instances, or into the UcompOS run-time.)
As of the UcompOS RXF Public Alpha release 0.4.6, some additional enhancements to the garbage collection process have been implemented that I will discuss here.
Understanding the UcompOS RXF garbage collection architecture can help you build more scalable Rich Portal Applications.
The recent enhancements come in the realm of Proxy Components.
By strict convention, all Proxy Components must extend the SDK class AbstractProxyComponent. As of UcompOS RXF 0.4.6, AbstractProxyComponent now extends a new SDK class called SDKEventDispatcher which extends EventDispatcher.
(Also, as a side-note, the AbstractProxyComponent class now implements IEventDispatcher in addition to IProxyComponent so you can refer to your Proxy Components as IEventDispatcher or IProxyComponent instances interchangably.)
SDKEventDispatcher simply overrides addEventListener() and offers a protected property _listeners of type Array.
I chose to create this separate class versus simply overriding addEventListener() in AbstractProxyComponent so that in the event the new clean-up process employed can be useful outside the scope of a Proxy Component, one could simply extend SDKEventDispatcher versus EventDispatcher.
Here is the over-ridden addEventListener():
override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { _listeners.push({type:type,listener:listener}); super.addEventListener(type,listener,useCapture,priority,true); }
Notice that I am always assigning a true value to the useWeakReference parameter in the super call to addEventListener(). This is because in the context of attaching event listeners to Proxy Components, you always would want them to be weak references to aid in garbage collection.
In AbstractProxyComponent, there is a new protected method, cleanup() which is as follows:
protected function cleanup(event:SDKEvent=null):void { while(_listeners.length) { var object:Object = _listeners.pop(); removeEventListener(object.type,object.listener); } _sdkModel.removeProxyComponent(this.uuid); var commandObject:CommandObject = new CommandObject("SDK.cleanup",{uuid:this.uuid}); var dataPackage:DataPackage = new DataPackage(Utilities.createUID(),_sdkModel.connectionId,this.destination,commandObject); _sdkClient.send(dataPackage); }
What the cleanup() method does is it automatically removes any event listeners that have been attached to the Proxy Component.
It also sends a message to the end-point of the Proxy Component targeting its SDK.cleanup public API method that is built into the UcompOS SDK and therefore exposed by any UcompOS entity. This aids in UcompOS RXF garbage collection-related activities.
Calls to cleanup() do not occur automatically.
When you would call cleanup() in a Proxy Component would be an implementation specific consideration.
For instance, with these new capabilities, I have updated some of the UcompOS Portal Proxy Components that are built into the UcompOS SDK.
Consider the updated constructor of the UcompOSWindowProxy class:
public function UcompOSWindowProxy() { super(); // set the destination property to the UcompOS Portal super._destination = _sdkModel.root; <strong>addEventListener(CLOSE,cleanup);</strong> }
The call to addEventListener(CLOSE,cleanup) is the new addition to the constructor.
What it does is it causes the inherited cleanup() method to always be called when the UcompOS Window instance on the UcompOS Portal that is represented by the UcompOSWindowProxy instance is closed.
Therefore, any event listeners you have attached to the UcompOSWindowProxy instance are automatically removed whenever the window is closed.
In 100% of the possible use cases for the UcompOSWindowProxy, this is the desired behavior.
The net result of this is you don’t have to worry about making your own calls to removeEventListener() for your particular UcompOSWindowProxy instances.
The same sort of behavior has been engineered into some of the other Proxy Components built into the UcompOS SDK including UcompOSAlertProxy, UcompOSDialogueProxy, UcompOSArtifactProxy, and UcompOSBrowserWindowProxy.
Consider this strategy when you are building your own Proxy Components and remember to always use removeEventListener() in all your other Flash applications whether you are deploying them in the UcompOS Portal or not.
Uploading Files to a UcompOSArtifactProxy Instance
In a major UcompOS Portal Application I am building, I place UcompOS Artifact instances that represent file volumes on the UcompOS Portal. Over this past weekend, I found myself with the need to enable the user to right-click on the file volume artifacts (revealing their context menus) and choose an “Upload Files” option with the goal of providing the user a way to upload files directly to the root directory of the particular file volume.
My initial approach to this was to attach a Context Menu to the artifact instances with an “Upload Files” option. I then created an event listener to listen for the UcompOSArtifactProxy.MENU_ITEM_SELECT event dispatched by the UcompOSArtifactProxy instance.
Once this event is dispatched, I reasoned I could then create a FileReferenceList instance and then call its browse() method and go from there.
However, when I attempted this, I was reminded of an important detail when an error was thrown once I called the FileReference.browse() method.
Just like the launching of AIR applications as well as the entry into Full Screen Mode, the opening of the file browse dialogue by the Flash Player must succeed a user-triggered mouse event.
In the context of the UcompOS Continuum, the entity where the mouse event occurs is the UcompOS Portal. This is a completely separate entity from the code that is calling the FileReference.browse() method.
In my implementation, I have a Flash application that is running as a background application that sets up the aforementioned UcompOS Artifact instances that represent file volumes.
So when the user right clicks on the artifact and selects the Context Menu item, they are actually operating on the UcompOS Portal itself.
An SDKEvent is then dispatched to the background application and then what follows is the call to FileReferenceList.browse().
However, as far as the Flash Player is concerned, in that scenario, the call to FileReferenceList.browse() does NOT proceed a user-triggered mouse event because the mouse event occurs in a totally different scope.
So I have engineered a new process into the UcompOS Portal to enable the goals I described above.
I think the use case I am speaking to here is one that has good merit to be repeated by many developers – i.e. a widget that you can upload files to. I can envision many scenarios where this could be useful such as file conversion utilities for one.
The model I have developed involves creating an uploadFiles property on the UcompOSArtifactProxy’s data Object property.
The value of this uploadFiles property must be the same String value as the label placed on a Context Menu item that is attached to the artifact.
What will happen in this case, when the user selects the context menu option on the artifact on the UcompOS Portal, the file browse dialogue will open, and the user will be able to select multiple files.
After the user selects the files, what happens next is very important.
The UcompOS Portal will dispatch to the UcompOSArtifactProxy instance an SDKEvent for each attached file.
The SDKEvent’s data property will have two properties: fileName:String and fileData:ByteArray, i.e. the name of the file and the contents of the file as a ByteArray.
From here you can do whatever you need to do with this information including upload the file to a remote server, do some sort of conversion, or anything else your specific use case requires.
Below, is a very simple code-based example of how you can create an Artifact and the user can change the artifact’s icon representation by uploading a new image to it.
The application is a UcompOS Flash application loaded into the UcompOS Portal as a background application.
package { import flash.display.Sprite; import com.ucompass.ucompos.sdk.proxycomponents.UcompOSArtifactProxy; import com.ucompass.ucompos.sdk.SDKClient; import com.ucompass.ucompos.sdk.events.SDKEvent; import flash.events.Event; public class Main extends Sprite { private static const UPLOAD_LABEL:String = "Upload a new artifact image"; public function Main() { // Instantiate the UcompOS SDK SDKClient.getInstance(this); // Create a UcompOS Artifact Proxy instance var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy(); // Listen for uploaded files artifact.addEventListener(UcompOSArtifactProxy.UPLOAD_FILE,uploadHandler); // Initialize the artifact using a pre-defined image artifact.add("RIGHT CLICK ON ME!",null,"http://desktop.ucompass.com/UploadToArtifact/cloud-48x48.png",100,100,true,true,{uploadFiles:UPLOAD_LABEL}); // Establish the context menu on the artifact with an Upload option artifact.setContextMenu(new XML("")); } private function uploadHandler(event:SDKEvent):void { var artifact:UcompOSArtifactProxy = event.target as UcompOSArtifactProxy; // Replace the artifact image with the content of the uploaded file artifact.setImage(event.data.fileData); // Show the name of the uploaded file as the label on the artifact artifact.setLabel(event.data.fileName); } } }
Also, here is a link to a movie that shows the simple application in action.
Building Full Screen Mode UcompOS Implementations
Since the release of Adobe Flash Player 9 in 2006, the Flash Player is capable of entering into what is known as “Full Screen Mode“.
In Full Screen Mode, the content playing in the Flash Player takes over the entire viewport of the display device such that the only content in view and capable of being interacted with is the content currently being executed in the Flash Player.
Depending on the nature of your application, this can in some circumstances create a much more focused and positive experience for your users.
The UcompOS Portal is configured to operate in Full Screen Mode and the UcompOS SDK provides a means for sending the UcompOS Portal into Full Screen Mode from one of your UcompOS applications or sub-applications.
Of course there are some rules and principles to observe when leveraging the power of Full Screen Mode in your UcompOS Applications.
In my blog posting on the Mechanics of UcompOS Desktop (AIR 2.0) Applications, we learned that the launching of an AIR application by the Flash Player must be preceded by a user-triggered mouse event.
The same rule applies to entering into Full Screen Mode.
The UcompOSGlobalManagerProxy class has two pertinent methods: enterFullScreenMode(); and exitFullScreenMode();.
Both of these methods accept an optional single input parameter, message, of type String.
When you call either of these methods from one of your UcompOS applications or sub-applications, in order to generate the compulsory user mouse click, the UcompOS Portal throws up an Alert dialogue asking the user if they want to allow the request to go into or out of full screen mode.
Of course having the dialogue appear for exitFullScreenMode(); calls is somewhat dubious as all the user needs to do is hit the Escape key on their computer to break out of Full Screen Mode but for continuity, I have decided to keep the mechanics of throwing the Alert in calls to both enterFullScreenMode(); and exitFullScreenMode();.
The optional message parameter lets you customize the text that is presented on the Alert dialogue.
When the UcompOS Portal breaks into or out of Full Screen Mode, a Continuum Event (an instance of the SDKEvent class) of type UcompOSGlobalManagerProxy.SCREEN_MODE_CHANGE is broadcast.
The data Object of the event will have a state property with a literal string value of “normal” or “fullScreen” so that your applications and sub-applications can behave accordingly when the user enters/exits Full Screen Mode.
In the scenario we discussed in my AIR 2.0 UcompOS Applications posting mentioned above, we saw we can leverage the UcompOSArtifactProxy class to create a clickable UcompOS Artifact that immediately launches a particular AIR application (with the aid of the UcompOSAIRProxy class).
This same concept is also available with Full Screen Mode implementations. You can create a UcompOS Artifact and assign its data Object special properties that tell the UcompOS Portal to launch or exit Full Screen Mode when the artifact is clicked on.
The property names will be enterFullScreenMode and exitFullScreenMode and both should be of type Boolean with a value of true.
They should be mutually exclusive and you should not have the enterFullScreenMode and exitFullScreenMode properties set on the artifact’s data Object simultaneously. If you do, the exitFullScreenMode property takes precedent.
Let’s look at a simple code-driven example:
private var artifact:UcompOSArtifactProxy; private function start():void { SDKClient.getInstance(this); UcompOSGlobalManagerProxy.getInstance().addEventListener (UcompOSGlobalManagerProxy.SCREEN_MODE_CHANGE,screenModeChangeHandler); artifact = new UcompOSArtifactProxy(); artifact.add(null,null,"http://www.server.com/enterFullScreenModeImage.png"); artifact.data = {enterFullScreenMode:true}; } private function screenModeChangeHandler(event:SDKEvent):void { switch(event.data.state) { case "fullScreen": artifact.data = {exitFullScreenMode:true}; artifact.setImage(null,"http://www.server.com/exitFullScreenModeImage.png"); break; case "normal": artifact.data = {enterFullScreenMode:true}; artifact.setImage(null,"http://www.server.com/enterFullScreenModeImage.png"); } }
An important point to make about Full Screen Mode implementations, at this time, UcompOS HTML content cannot be displayed while in full-screen mode. UcompOS HTML applications and sub-applications rely on an iframe implementation which is outside the visual scope of the Flash Player.
UcompOS HTML entities can still be interacted with via Proxy Components while in Full Screen Mode however.
The same applies to UcompOS AIR 2.0 content. It cannot be in view while the in Full Screen Mode but it can be interacted with by Proxy Component-driven interactions.
Building Drag and Drop Experiences in the UcompOS RXF
The UcompOS RXF couldn’t rightfully be called a “Rich Experience Framework” if it didn’t have a model to support drag and drop interactivity. Drag and Drop behavior could perhaps be considered one of the key characteristics of an application that helped to define the term “Rich Internet Application” in the early 2000s.
This discussion doesn’t focus on building drag and drop interactivity within a single UcompOS application. Obviously, you can implement whatever sort of drag and drop interactivity within a singular UcompOS HTML, Flash, Flex, or AIR application without restriction or consideration of UcompOS mechanics.
The real power in a UcompOS Rich Portal Application is in implementing inter-application drag and drop interactivity.
Dragging names from an address book application to an e-mail application, dragging images from a file manager to a text editor, highlighting multiple resources and dragging them to a widget to perform some operation on the items simultaneously – these are some of the experiences that can be created.
The mechanics of drag and drop UcompOS implementations are worthy of discussion. There are some important considerations that need to be made in order for the UcompOS Portal to enable your applications to be configured appropriately for inter-application dragging and dropping.
Sandboxing in the UcompOS RXF
The philosophy of the UcompOS RXF is to achieve the highest degree of sandboxing possible while still achieving our interaction objectives.
Our sandboxing is less for security purposes and more to create an isolated, self-contained environment for a UcompOS entity that is free from unintentional disruption by other UcompOS entities.
Communication between applications in the UcompOS RXF should exclusively occur using the classes built into the SDK.
In no way should you plan to, or should you need to, attempt to directly access classes, properties, or methods of other UcompOS entities within an individual UcompOS entity. You should exclusively rely on the powerful implementation of a UcompOS entity’s public API methods, Services Dictionary, and Proxy Components.
The one exception to this is the implementation of dragging and dropping across two different UcompOS entities. But the UcompOS Portal handles all the logic for you so that you don’t need to worry about anything other than what should be dragged and what should be allowed to be a drop target and how it should behave when receiving a drop.
The topic of sandboxing in the Flash Player and loading SWF content into other SWF content is a necessarily thorough and rigorous conversation.
In the UcompOS RXF, any SWF content – be it a UcompOS application or sub-application – is loaded into the UcompOS Portal with an implementation of the SWFLoader class.
The SWFLoader has some very important properties that essentially articulate the permissions the child SWF content has in terms of accessing information (classes, properties, methods) of the parent SWF content it was loaded into.
One of the chief goals of the UcompOS RXF is complete disaggregation. The framework wants you to be able to place resources at any network address without consequence.
Therefore, all SWF content is loaded into the UcompOS Portal with the trustContent property set with a true value.
There are three different ways SWF content is loaded into the UcompOS Portal as listed below:
- SWF-based UcompOS application loaded invisibly into the UcompOS run-time
- SWF-based sub-application loaded into a UcompOS Window
- SWF-based sub-application loaded into a UcompOS Artifact
When you load SWF content into the UcompOS Portal, you can articulate how tightly it is to be sandboxed.
As far as SWF-based UcompOS applications loading invisibly into the UcompOS run-time, you can set a sandbox=”true” or sandbox=”false” attribute to the root tag in that application’s manifest file. The default condition is sandbox=”true”.
Also, if you look at the signatures of the add(); methods of both UcompOSWindowProxy and UcompOSArtifactProxy, you’ll see they both have sandbox parameters that default to a true value.
By default, a SWF loaded into a UcompOS Window or UcompOS Artifact will take on the sandbox configuration of its root UcompOS Application.
From an implementation point of view, the only difference between the two configurations is SWF content loaded with the sandbox=”true” configuration has the following property set to the SWFLoader used to load the content:
swfLoader.loadForCompatibility = true;
According to the Adobe’s ActionScript 3 documentation:
“Set this property to true to indicate that the loaded application might be compiled with a different version of the Flex framework and you want your application to be able to interact with it. Setting the value of the loadForCompatibility property to true also causes the LoaderContext of the Loader to load the sub-application into a sibling application domain of the main application, rather than a child application domain.”
A full discussion of the LoaderContext and ApplicationDomain classes is outside the scope of this blog posting, but essentially, setting the loadForCompatibility property to true is a form of sandboxing in that you are able to load Flex content created with a different version of the SDK than the parent SWF content.
Unless you have very specific reasons, in most all cases you’ll leave the sandbox property in its default configuration (sandbox=true).
Our plan is that we will always keep the UcompOS Portal running on the latest public release of Flex 4 so leaving sandbox=true will insure you won’t have to continue to update your Flex-based UcompOS content.
Scenarios for when you would want to set sandbox=false are complex and sophisticated and will be covered in an upcoming posting.
The Marshall Plan
The implications laid out above are somewhat important to elaborate upon.
We want to be able to load SWF content created with any version of the Flex SDK into the UcompOS Portal, and then we still want to be able to enable it to participate in drag and drop interactivity with other SWF content, that may have been produced with still other versions of the Flex SDK.
How is this possible? After all, classes such as the DragManager are involved and certainly it seems we’ll run into compatibility issues.
The answer is taking advantage of a concept the people at Adobe have created that they call the Marshall Plan. I recommend you explore this important topic. It deals with how data is marshalled across the boundaries between two different SWFs.
As of the Beta 2 release of Flex 4, the classes that enable this marshalling to automatically occur are no longer automatically compiled into the SWF. You have to explicitly add them at compilation time.
This must be added as an argument to the Flex compiler for your application:
-includes=mx.managers.systemClasses.MarshallingSupport
Failure to add this to a Flex 4 Beta 2 UcompOS application that is set up for dragging and dropping will yield unpredictable results, and even run-time errors.
Building a Simple Drag and Drop Example
If you have two different UcompOS entities – one the drag source, the other the drag destination – you would set each of them up as if they were both in the same overall application.
You’d set up the drag source to specify the behavior of the drag initiation, and your drag destination to implement your desired behavior of when items are dragged and dropped onto the target.
There is another scenario however and it involves dragging and dropping to a UcompOS Artifact.
In our example, we want to build a very simple example that shows a UcompOS Flex application that employs a DataGrid. We then want to implement an artifact and enable the user to drag and drop an item from the DataGrid to the artifact.
When the item is dropped, we want to throw a simple HTML alert that outputs some information about the item that was just dropped.
Here are the three resources used to accomplish this task:
The Dock Manifest
<applications> <application background="true" default="true"> http://applications.ucompass.com/SampleApps/UcompOSExamples/assets/manifests/DragAndDropExample.xml </application> </applications>
The Application Manifest
<application selfLoading=”true” width=”206″ height=”250″ preloaderTitle=”Drag and Drop Example”> <source> <base>http://applications.ucompass.com/SampleApps/UcompOSExamples/bin-debug/DragAndDropExample.swf</base> </source> <titles> <title default=”true” locale=”en_US”>UcompOS Drag and Drop Example</title> </titles> <icons> <icon default=”true” locale=”en_US”> http://applications.ucompass.com/SampleApps/UcompOSExamples/assets/png/nature/Cloud-48×48.png </icon> </icons> </application>
The Application Code
<?xml version="1.0" encoding="utf-8"?> <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" applicationComplete="start();" height="200" width="200"> <fx:Script> <![CDATA[ import com.ucompass.ucompos.sdk.SDKClient; import com.ucompass.ucompos.sdk.events.SDKEvent; import com.ucompass.ucompos.sdk.proxycomponents.UcompOSArtifactProxy; import com.ucompass.ucompos.sdk.proxycomponents.UcompOSHTMLProxy; import mx.collections.ArrayCollection; [Bindable] private var _people:ArrayCollection = new ArrayCollection([ {Name:"Ed",Age:36}, {Name:"Max",Age:2}, {Name:"Mason",Age:1}, {Name:"Abigail",Age:1}]); private function start():void { SDKClient.getInstance(this); var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy(); artifact.add("Drag Here!",null, "http://applications.ucompass.com/SampleApps/UcompOSExamples/assets/png/nature/Cloud-48x48.png", 300,300); artifact.dragDropManager(true,"items",["Name","Age"]); artifact.addEventListener(UcompOSArtifactProxy.DRAG_DROP,dragDropHandler); } private function dragDropHandler(event:SDKEvent):void { var droppedItems:Array = event.data.dragDropData; var droppedItem:Object = event.data.dragDropData[0]; var h:UcompOSHTMLProxy = new UcompOSHTMLProxy(); h.alert("Your name is "+droppedItem.Name+" and you are "+droppedItem.Age+"."); } ]]> </fx:Script> <mx:DataGrid width="200" height="200" dataProvider="{_people}" dragEnabled="true"> <mx:columns> <mx:DataGridColumn dataField="Name"/> <mx:DataGridColumn dataField="Age"/> </mx:columns> </mx:DataGrid> </s:Application>
Video Demo
The Mechanics of UcompOS Desktop (AIR 2.0) Applications
One of the more important and high-impact features of the UcompOS Rich Experience Framework is the ability for UcompOS Rich Portal Applications to extend to the desktop.
The technology leveraged to accomplish this is Adobe AIR 2.0.
When you consider the presence of AIR 2.0’s new NativeProcess class, which enables an AIR application to target the native Operating System’s base functionality, the prospect of building industrial-strength applications that place very few limits on the developer and allow their imaginations to extend to new heights becomes very attainable.
In this post I want to talk a bit about the mechanics of AIR applications in the UcompOS RXF. Understanding these mechanics can help you conceptualize and then deploy the most compelling rich experiences for your UcompOS Rich Portal Application.
The first thing to understand is that in the context of the UcompOS RXF, any AIR application will simply be another UcompOS entity.
A UcompOS entity represents any application or sub-application running in a UcompOS implementation. The UcompOS Portal itself is a UcompOS entity. All the UcompOS entities running at one time in the UcompOS RXF comprise what I refer to as the UcompOS Continuum as you know if you’ve been reading my blog postings.
There are a few different ways to launch a UcompOS AIR entity – as an application from the UcompOS Application Dock, using the UcompOSAIRProxy class, or by creating a UcompOS Artifact the user can click on to launch the AIR application.
First, let’s understand the mechanics at work here. The UcompOS Portal is obviously a Flash-based browser entity. In order for a browser-based Flash application to launch an AIR application, a couple things need to happen.
First, the author of the AIR application has to articulate that the application is allowed to be launched by the browser.
This is very easy to accomplish.
You simply need to have the following element as a direct child of the root element in the application’s manifest descriptor file.
<allowBrowserInvocation>true</allowBrowserInvocation>
The manifest descriptor file is NOT the UcompOS application manifest for the application. It is the XML file that articulates the base-level behaviors and properties of an AIR application.
If you try to compile an AIR application that instantiates the UcompOS AIR SDK that does not have the above provision made, you’ll get a compilation error.
Does this mean that the only way your UcompOS AIR applications should be launched is by the browser via the UcompOS Portal?
Not necessarily. There are ways you can set it up so that when your UcompOS AIR application is launched directly by the end-user, it opens the UcompOS Portal to a precise configuration.
It can even be configured so that your AIR application can save custom file types on the user’s desktop that when double-clicked upon can launch the AIR application which in turn launches the UcompOS Portal and then feeds one or more applications with the data contained in the desktop file.
These are a bit more advanced topics that I’ll definitely devote coverage to these capabilities sometime in the next month or so.
The next thing we need to understand is that the browser can only launch an AIR application following a user-triggered mouse click event.
When you configure an AIR application as the base source for a UcompOS Application in that application’s UcompOS Application Manifest and have the application show up on the UcompOS Application Dock, the UcompOS Portal is configured such that the clicking of the application icon on the dock is the click that is used to immediately launch the AIR application.
When you configure the Application manifest that will use an AIR application as its base source code, there are some parameters you need to incorporate into the manifest.
Below is a sample application manifest from a UcompOS AIR application that provides an example of this:
<application> <source> <base>http://desktop.ucompass.com/Camera_Example/Camera_Example.air</base> <params> <param> <name>appId</name> <value>Camera-Example</value> </param> <param> <name>publisherId</name> <value>0E5CA255707A7E3F70F12D38B16B8D2A4C17413C.1</value> </param> </params> </source> <titles> <title locale="en_US" default="true">My Camera</title> </titles> <icons> <icon locale="en_US" default="true">http://desktop.ucompass.com/Camera_Example/icons/camera.png</icon> </icons> </application>
Note that you must at least include the appId and publisherId parameters.
There are a couple other ways to launch a UcompOS AIR application as a sub-application.
The first is with the UcompOSAIRProxy class which is built into the UcompOS SDK.
The UcompOSAIRProxy Class
The UcompOSAIRProxy class deserves some attention in this posting. It is a Proxy Component that is used to create a virtual representation of a UcompOS AIR application in a UcompOS entity. Inspecting the class is a good way to learn more about the mechanics of UcompOS AIR Applications.
Let’s look at the signature of the UcompOSAIRProxy’s constructor:
public function UcompOSAIRProxy(appSource:String, appId:String, publisherId:String, airVersion:String, host:String="127.0.0.1", operationPort:uint=0, validationPort:uint=0)
Let me touch on each of the parameters of the UcompOSAIRProxy’s constructor:
- appSource: This is the URL of the .air package file associated with the AIR application
- appId: This is the application id of the AIR file as it exists in the AIR application’s descriptor file
- publisherId: This is the value of the publisherid that is found in the file at $APP_INSTALL_DIR/Contents/Resources/META-INF/AIR/publisherid - WARNING: the publisherid will be deprecated in AIR 2.0 soon and I will then remove it as a required parameter in the UcompOSAIRProxy’s constructor at that time
- airVersion: This is the minimum version of AIR to run the application. AIR 2.0 is the UcompOS minimum requirement.
- host: UcompOS AIR Applications rely on the ServerSocket class to communicate with other UcompOS entities. By default, the UcompOS AIR application binds to 127.0.0.1 on the local machine and other UcompOS entities target that destination in socket transmissions. However, you can override this and bind to some public facing IP address. (NOTE: The implications here are remotely deployed UcompOS AIR Applications)
- operationPort and validationPort: UcompOS AIR Applications bind to two ports – one for validation purposes and the other for actual UcompOS data transmissions. By default, the UcompOS SDK will start with port number 1024, and climb upward using the first two openly available ports for operation and validation. These port numbers can be explicitly articulated.
A UcompOSAIRProxy class has three specific types of SDKEvent instances associated with it:
- UcompOSAIRProxy.AIR_APPLICATION_LAUNCHED: Dispatched when the AIR application has launched
- UcompOSAIRProxy.AIR_APPLICATION_QUIT: Dispatched when the AIR application has quit
- UcompOSAIRProxy.AIR_APPLICATION_STATUS: Dispatched following a call to the UcompOSAIRProxy instance’s getStatus(); method
An instance of UcompOSAIRProxy also has a getter/setter on the Boolean property status which returns true when the AIR application is running.
The UcompOSAIRProxy class has two methods key to our discussion: launchApplication(); and quitApplication();
You could use launchApplication(); to launch a UcompOS AIR Application as a sub-application.
When you do, however, the UcompOS Portal must find a way to meet the compulsory user-triggered mouse-click requirement mentioned above.
It does this by throwing an Alert onto the interface of the UcompOS Portal asking the user if they agree to allow the AIR application to launch and then by clicking “OK”, the user is providing the necessary mouse-click.
The full signature of the launchApplication(); method is as follows:
public function launchApplication(message:String=null):void
The message parameter allows you to display a custom message on the Alert used in this scenario.
There is an alternative way to launch a UcompOS AIR sub-application that I’ll cover next.
Using a UcompOS Artifact to launch an AIR Application
By now, you know that the UcompOSArtifactProxy class in the UcompOS SDK provides a way to implement the equivalent of “desktop widgets” on the UcompOS Portal interface. I prefer the term “Artifact” over “Widget” however as I feel widget has functionality implied, whereas a UcompOS Artifact can be functional and can be a full-fledged UcompOS sub-application or it can be strictly presentational.
As is the case with all Proxy Components (i.e. any class that extends AbstractProxyComponent), UcompOSArtifactProxy instances have a data property.
When you set the data property of a UcompOSArtifactProxy instance, this data property is housed on the actual artifact itself on the UcompOS Portal.
There are two special properties that can be added to this data Object: launchAIRApplication and quitAIRApplication
The values of these properties would be the uuid property of the UcompOSAIRProxy instance that was to be launched upon a mouse click of the artifact involved.
So the following code may be something you’d see in practical operation:
var myAIRAppProxy:UcompOSAIRProxy = new UcompOSAIRProxy("http://apps.mysite.com/myApp.air","My-App","My-Publisher-Id","2.0"); var myArtifactProxy:UcompOSArtifactProxy = new UcompOSArtifactProxy(); myArtifactProxy.add("Label for my Artifact",imageContent); myArtifactProxy.data = {launchAIRApplication:myAIRAppProxy.uuid};
In the above example, as soon as the artifact is clicked on, the AIR application will launch.
You could also do something like the following too:
private function launchHandler(event:SDKEvent):void { switch(event.type) { case UcompOSAIRProxy.AIR_APPLICATION_LAUNCHED: myArtifactProxy.setImage(imageContentAppOn); myArtifactProxy.data = {quitAIRApplication:myAIRAppProxy.uuid}; break; case UcompOSAIRProxy.AIR_APPLICATION_QUIT: myArtifactProxy.setImage(imageContentAppOff); myArtifactProxy.data = {quitAIRApplication:myAIRAppProxy.uuid}; break; } }
In the above example, we are listening to see when the AIR application is launched as well as when it quits. We then replace the artifact image with a status indicator using the UcompOSArtifactProxy’s setImage(); method so it easily shows the user if the associated AIR application is running or not.
As an example of how I am using this concept myself, in the Educator 2 Rich Portal Application I am building entirely on top of the UcompOS RXF, on the taskbar (an artifact container with a number of artifacts housed in it), there is an icon to launch the “Educator 2 Desktop”, which is obviously an AIR application.
When they click this icon, the Educator 2 Desktop immediately launches and the icon turns green indicating the feature is connected. When they click it again, the Educator 2 Desktop quits and the icon turns red indicating the feature is disconnected.
UcompOS Artifact Containers
In my last post a few minutes ago on UcompOS Artifacts, we learned that an artifact can be thought of as analogous to a desktop widget.
One of the parameters of the UcompOSArtifactProxy class’s add(); method is container which is of type UcompOSArtifactContainerProxy.
If the value of container is null, then the artifact instance is simply added to the UcompOS Portal interface positioned at the specified x, y coordinates where (0,0) is the upper-left origin of the main container.
However, an artifact container lets you arrange a group of related artifacts in a specific fashion.
There are currently three types of artifact containers: HBox, VBox, and Canvas – these names obviously are throwbacks to the Flex 3 container classes of the same name.
An artifact container is positioned and styled using CSS properties
Let’s see a simple example of the code behind the creation of a UcompOS artifact container.
The first step is to create an instance of UcompOSArtifactContainerProxy:
var container:UcompOSArtifactContainerProxy = new UcompOSArtifactContainerProxy();
Then we call the UcompOSArtifactContainerProxy’s add() method.
Let’s look at the signature of add():
add(type:String, styles:Array = null):void;
type is a String that should either be of value HBox, VBox, or Canvas. I plan to expand this to accept other properties such as HTileBox, VTileBox, etc.
styles is an Array of style objects where each style object has two properties: styleProp and newValue where styleProp is going to be a style that is available to the HBox, VBox, and Canvas containers in the Flex 3 framework.
An important note is that even though the UcompOS Portal is a Flex 4 application, the artifact containers are based on the Halo theme in the mx package.
Let’s see an actual code-based example:
var container:UcompOSArtifactContainerProxy = new UcompOSArtifactContainerProxy(); container.add("HBox",[{styleProp:"backgroundImage", newValue:"http://desktop.ucompass.com/someImage.png"}, {styleProp:"bottom",newValue:0},{styleProp:"right",newValue:0}]);
The above would create an artifact container that was given a background image of the specific URL that was positioned permanently at the far lower right of the UcompOS Portal.
Then when we create our artifacts, we can pass the UcompOSArtifactContainerProxy instance as the container parameter and the artifact will automatically be placed into the container. For instance:
var artifact:UcompOSArtifact = new UcompOSArtifact(); artifact.add("My Artifact",null,"http://desktop.ucompass.com/someImage.png",0,0,false,true,{},container);
Below is a simple example of an artifact container which has a transparent type background set with the backgroundImage style property that has 4 artifact instances attached to it. This example comes from the Educator 2 application I am building on top of the UcompOS Rich Experience Framework:
UcompOS Artifacts
In the UcompOS Rich Experience Framework, there is a model that supports the creation of a type of utility called an Artifact which can be thought of as similar to a desktop widget where the desktop is the main interface of the UcompOS Portal main container.
An Artifact is created in a UcompOS application with the UcompOSArtifactProxy class that is built into the UcompOS SDK.
Artifacts can be flash-based (SWF) or image-based (PNG, GIF, or JPG).
Artifacts can then have functionality or behaviors attached to them. Also, Flash-based artifacts can be UcompOS sub-applications so they can be Flash content that themselves have the UcompOS SDK implemented and can participate in transactions in the context of the UcompOS Continuum.
I am going to create a video tutorial today that shows how to build a UcompOS Artifact but for now, I’ll highlight in brief terms the code behind creating one.
The first step is creating a new instance of UcompOSArtifactProxy in a UcompOS application or sub application. This of course occurs after the UcompOS SDK has been instantiated.
In ActionScript:
var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy();
In JavaScript:
var artifact = new UcompOSArtifactProxy();
Then you call the add(); method of the UcompOSArtifactProxy instance:
Let’s take a look at the signature of the add(); method:
add(label:String = null, imageBytes:ByteArray = null, imageSource:String = null, x:uint = 0, y:uint = 0, draggable:Boolean = false, interactive:Boolean = true, data:Object = null, container:UcompOSArtifactContainerProxy = null, sandbox:Boolean = true):void
I’ll add that in the JavaScript SDK, there is no imageBytes paramater and the imageSource is how you articulate the SWF, JPG, GIF, or PNG content to be used for the artifact via its network URL.
The label property enables you to attach a label to the artifact. As far as the source of the image that represents the artifact, it can be a ByteArray which at current will automatically be treated as an image-based artifact and the ByteArray would represent the ByteArray of a PNG, GIF, or JPG image. If you don’t pass a ByteArray, you would pass the network URL of an image or SWF file. If you pass both a ByteArray and a URL the ByteArray will take precedence. If you pass neither a ByteArray or a URL, an IllegalOperationError will be thrown by the UcompOS SDK.
x and y let you position the artifact on the UcompOS Portal interface. draggable indicates whether the user should be able to drag and drop the artifact on the UcompOS Portal interface. interactive indicates if the artifact should accept mouseover, and click interactivity with the user. When this property is true, the useHandCursor property on the item is implemented with a true value.
data lets you house a data Object on the artifact for convenience purposes so for instance if you have a double click handler attached to the artifact instance, when the double click event is dispatched, the data Object attached to the artifact is packaged into the event Object.
container is the Artifact Container that the artifact should be placed into. I’ll be posting another blog this morning talking about UcompOS Artifact Containers and the UcompOSArtifactContainerProxy class. If this value is null, then the artifact is placed on the UcompOS Portal interface with 0,0 being the upper-left origin points.
Finally, for SWF-based artifacts, sandbox represents whether the SWF content should be allowed to participate in drag and drop operations with other entities in the UcompOS Continuum where a value of false would allow this.
Note that all artifacts regardless of their sandbox property can be configured to accept drag and drop interactions. But if you had something like a DataGrid in an artifact and you wanted to be able to drag and drop items from other SWF content into that DataGrid, you would need the sandbox property set to false.
In the example at left here, this represents an example of a number of artifacts that have been organized into an artifact container.
This is an example from my Educator 2 application I am building on top of the UcompOS Rich Experience Framework.
The first artifact labeled “My Workspace” represents the user’s remote Educator 2 File System (where each user essentially has their own Content Management System interface). The artifact labeled “Educator 1″ represents the user’s content area if their username also exists in our legacy Educator 1 product.
The remaining artifacts are all created with the aid of a class I’ll be discussing in a future posting called the UcompOSDesktopProxy which is able to talk to the end user’s desktop and each artifact represents a “mount point” on the end user’s computer.
In the case of these artifacts, they all have been implemented to support drag and drop behavior as well as double click behavior and I’ll showcase this functionality in an upcoming video tutorial I’ll create in the near future.
In this case here, when the user double clicks one of the artifacts, it launches a particular UcompOS application loaded into a UcompOS Window that showcases the file contents of each particular resource represented by the artifact.









