Detecting your Flash Player Version

March 10, 2009

The Capabilitiesย Class in theย flash.system package is perhaps a class that most people do not use. It is a very useful class that contains several useful properties and functions that can provide a world of information. I use the class regularly for finding the screen-resolution for my AIR apps using the screenResolutionX and screenResolutionY properties.

Here’s a small app using the class that detects the Flash Player Version and the player type – Debug or Release. This can be used as a FlashPlayer Version Checker.

Application | Source

Advertisements

sandbox violation – find answers to your Flex questions…

February 17, 2009

  • How can we speed up the performance of DataGrid when there is a lot of data?
  • How do we reduce SWF size so that the download times are lesser?
  • My Flex application works fine when run from Flex Builder, but when deployed to server, I get security related errors. Why?

You always had questions like this and never knew where to go to get answers? Anirudh Sasikumar, a Technical Evangelist at Adobe has created a project called sandboxviolation. In his own words, sand box violation isย  “for the flex and flash community where users can post questions / answers and vote a question or answer up or down earning reputation points along the way”.

Its available in 2 flavors:

Flex App on Google App Engine | An AIR app with offline support

Check it out, benefit from it, post your questions, answer other’s questions, vote answers up/ down and help the community churn high quality content…

Addendum: Anirudh’s written a Syntax Highlighting in AS3 as part of the above project which is awesome and then opensourced the code which has now created quite a buzz. Check it out too ๐Ÿ™‚


High Performance AIR Applications

February 17, 2009

Oliver Goldman from the AIR Team did a presentation at MAX on “High Performace AIR Applications”. In case you missed it, catch it here.


Sorry for the outage…

January 9, 2009

Hi All,

I am moving my examples to an adobe hosting now. The sample files may not be available for a couple of days. If you cannot find anything, drop me a mail, I will fix it and send you the link…

Raghu


Assigning different behaviors on click & doubleClick

August 10, 2007

This interesting issue was posted by Arpan on the flex_india group (Read it here). He says…

In my application i have a datagrid with itemrenderer as charts and I need have to perform two operations – one on single click and one on double click – on the chart. But most of the times double click event is not fired and if fired then single click is also fired. Can I stop single click event if double click event is fired ?

I investigated this and found this to be true. Once you enable doubleClick (by setting the doubleClickEnabled flag), whenever it occurs, a click event is also fired with it… I discussed this with Sreeni and he said that this is because the framework intends not to skip any event (because a double click is actually a click followed by a doubleClick event).

This may be useful in a lot of cases, but in Arpan’s case, this was causing havoc. The way to work around this is to write a Timer/Interval and use it to work around the problem. The following is the execution path…

  • On click, in the click handler, reset and initiate the timer which on complete, calls the deferredClickHandler (where the actual clickHandler code sits
  • If doubleClick does not occur, the timer completes and then executes the deferredClickHandler (I have kept my timer to be 300 mS)
  • If doubleClick occurs, it goes to the doubleClick handler, where you clear the timer (so that timer does not complete and execute the deferredClickHandler) and execute the doubleClickHandler code…

Caution: Do not forget to save the initial click Event if you need it later..

In Arpan’s case… he needs to use itemClick and itemDoubleClick events (of type ListEvent) instead of click & doubleClick (of type MouseEvent), as it is a DataGrid. The code below handles the case for both a DG & a Button… I have used the setInterval() method to implement the timer, you may as well use the Timer class…

Application | Source

Thanks to Sameer & Harish who helped me get to the bottom of this…


Jump cuePoints in a Video

August 3, 2007

This was another of those questions that was posted to me by a Flex user in Germany. Thought I’ll share it with all…

The person wants a way, by which you can jump from one cue point to another, in a video. While this is not difficult, I wanted to give a way to tap into all kinds of cue points in this way, namely the ones added thru AS, thru MXL and those which are encoded into the video using the Flash Video Encoder

The application below has a video that has 3 embedded cuepoints (done during encoding time), 2 AS cuepoints and 2 MXML cuepoints. The following are the steps required…

  1. Create a cueArray Object to hold the details of the cuePoints
  2. On creationComplete, access the cuePoints property of VideoDisplay (which is an array), loop thru it and store the ‘time‘ property of the cuePoint into the cueArray object
  3. Then, listen to the metadataReceived event on VideoDisplay and access myVD.metadata.cuePoints to get the embedded cuePoints. Do the same there… (Important: The metadata property on VideoDisplay is only available on Flex3. If you do not have Flex3, skip this step, or better still, go get it)
  4. Once you have the cueArray ready, have an index property that keeps track of the index of the latest cuePoint fired. This is done by tapping into the cuePoint event and then updating the index as…
    index = cueArray.indexOf(event.cuePointTime);
  5. When the user tries to jump to the next cue, set the playHeadTime from the appropriate index and you are done ๐Ÿ™‚

CAUTION: What you need to remember here, is the way, the playHeadTime property works…

When you set playHeadTime to say 2.54s, the VideoDisplay tries to set this. But a video can seek only key-frames in a FLV (which is decided by the encoded video data rate on the FLV encoder. This decides the resolution of the FLV). So, even though you set the playHeadTime to 2.54s, it may seek to the closest key-frame in the FLV which may be 2s or 4s (depending on the resolution of encoding)

You can see it here in the app… First let the video play fully, so you can see where all the cue points are. Now, click the “Jump to Next Cue” button and compare the playHeadTime to the cuePoint time. You will not only see that they are different, but also 3 cuePoints at 2.347, 2.45 & 2.6s, all default to 3.5s due to the above design.

Here’s the application and the source (The FLV might take some time to load… its > 2MB in size)

Application | Source

 


Persisting DataGrid column order

August 1, 2007

I found this very interesting question the Flex SDK Forum. The person, wanted to persist the users selection of the re-ordered columns across visits. A very useful addition towards a site for personalization… Here’s the scenario

The user hits your site and gets a DG(DataGrid) with multiple columns. He goes ahead and re-arranges them to his liking and leaves the app. Next time he comes back, he sees the same old screen, with his selections garbled, as the app has now re-started. Is there a way to personalize the DG for him and persist it across SWF re-loads?…

Yes… you can. I had a bit of trouble figuring it out, but got it. I first did what Rob had suggested him to do, which was to push the columns array of the DG to a shared object and to set it back when the app reloads. As he says in his code…

save it as…

var settings:SharedObject = SharedObject.getLocal(“customColumns“);
settings.data.dgColumns = dgXT.columns;

and retrieve it as…

var settings:SharedObject = SharedObject.getLocal(“customColumns“);
if (settings.data.dgColumns != null)
{
dgXT.columns = settings.data.dgColumns;
}

This doesn’t work because, trying to cast the Object to type DataGridColumn, the framework fails and throws a Run Time Error…

Then i tried to get each object from the SharedObject (which involves looping thru the SharedObject as it is of type Array) and then to cast each of the children explicitly, using the ‘as‘ operator as below, but it failed again…

var settings:SharedObject = SharedObject.getLocal(“customColumns“);
if (settings.data.dgColumns != null){
for (var i:int=0; i<settings.data.dgColumns.length; i++){
dgXT.columns[i] = settings.data.dgColumns[i] as DataGridColumn;
}
}

The third attempt was to loop through each of the items in the SharedObject array and then loop thru the object, get the properties and set it to the columns…

for (var i:int=0; i<settings.data.dgColumns.length; i++){
for (var j:* in settings.data.dgColumns[i]){
dgXT.columns[i][j] = settings.data.dgColumns[i][j]
}

}

Still it failed as some of the internal complex types (like IFactory), failed to be cast. I think, the reason is because the SharedObject , considers all the stored objects as purely Objects and does not preserve the type which they belong to.

Then Swaroop gave me an idea… why not save only those values which you require and set them back. I created an object for each of the DG columns which has details on those properties that i need to set back. Then at load-time.. I set them back.

In the method where i save the settings…

var columnArray:Array = new Array();

for(var i:int; i<dgXT.columns.length;i++){
var columnObject:Object = new Object();
columnObject.columnDataField = dgXT.columns[i].dataField as String;
columnObject.columnHeader = dgXT.columns[i].headerText as String;
columnArray.push(columnObject);
}
var settings:SharedObject = SharedObject.getLocal(“customColumns”);
settings.data.dgColumns = columnArray;

And while setting them back…

var settings:SharedObject = SharedObject.getLocal(“customColumns”);
if (settings.data.dgColumns != null)
{
var columnArray:Array = settings.data.dgColumns;
for(var i:int=0;i<columnArray.length;i++){
dgXT.columns[i].dataField = columnArray[i].columnDataField;
dgXT.columns[i].headerText = columnArray[i].columnHeader;
}
dgXT.invalidateList(); //This is to redraw the list
}

And lo… it works ๐Ÿ™‚ Feel free to add any more attributes of the column that you would like to save (for starters, may be the columnWidth). You can find the app and the source at the links below (better than the code above as it is documented ๐Ÿ˜‰ )

Application | Source

If you have a better solution… I would like to know ๐Ÿ™‚