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


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 πŸ™‚


Subtitle Video

July 25, 2007

Some time back, there was a talk of how youTube can make money by showing Ads on its video itself using an overlay. MSN Video also does it (but not as a overlay, which doesnt look good, in my opinion). BrightCove used the overlay mechanism to show/hide their video controls.

Then i came across a blog entry, where he does a rather innovative use of the overlay, to show Subtitles for the video and in different languages. Cool… See it Here

I thought of providing a generalized container overlay to the video and the user can put any renderer he wants, pretty much like the itemRenderers on the FLEX List Componenet. So he can include ads, subtitles and pretty much anything on the overlay. Its still in draft quality, but i thought i’ll share it with you. What i want to impress here is that it can do a lot more with less. Like Ad support. What i mean is, by just changing the renderer in the component, you should be able to switch between subtitles and advertisements on the video… I’ll publish the code as a component when it reaches production quality πŸ™‚

This is the first example, where I have used a custom Box with Anjali’s Marquee component inside it as the containerRenderer. This probably can be used as overlays for videos in various languages to provide subtitles in english

(click on the pic or here to view the application)

The second example is one where 2 ads are being shown alternating while the video plays. What’s to note here, is that we can even synchronize the ads with the content if the videos are tagged. Web2.0 rocks ! I’m not good at Flash Animations and hence the lousy Ads… πŸ™‚


(click on the pic or here to view the application)


Elliptical Video Display

June 5, 2007

There are cases where one might require the video to be, say elliptical, instead of the usual rectangular appearance, as below…

This is how to do it. A very easy trick, using the basic drawing APIs of Flash. We just create a mask and then ask the VideoDisplay to wear it. Follow the steps below…

  1. Create a Sprite instance (say myMask)
  2. Use the graphics APIs to draw the required mask – I have used beginFill() and drawRoundRect() functions on the myMask.graphics Object
  3. Set the x & y properties of the mask
  4. Add it to the VideoDisplay instance
  5. Set the mask property on the VideoDisplay instance to myMask

In my app, I have done the Sprite object generation and addition to the component, on creationComplete itself, as I am providing a way of dynamically changing the mask. Because of this, one will find a myMask.graphics.clear(), each time the applyMask() method runs… I have also added code to add drop-shadow to the Video, using the filters property, to increase the “Flex Appeal” πŸ™‚

View the Application | Download Source


JSON to ASON

June 2, 2007

I have blogged about JSON before but forgot to provide an example for getting JSON into AS. I saw a query on FlexIndia on JSON, so I thought I’ll post it now. The problem is to convert JSON to ActionScript Objects (or ASON). You can first try the demo application to see if this is what you are looking for…

In the app, you can either paste a URL (provided you have the security permissions) of a JSON to convert or paste your own JSON into the textarea and convert it.

This is what you need to do to get this working…

  1. Go to AS3CoreLib on Google Code and download the corelib-.90.zip file and extract it
  2. Get the corelib.swc from the /bin directory
  3. Download the app source or write your own code πŸ™‚
  4. Do one of the following:
    If you are using FlexBuilder:

    1. Right click on your project go to Properties
    2. Navigate to Flex Build Path -> Libraries Tab -> Add SWC
    3. Now add the corelib.swc to your project
    4. Confirm that you have the line “import com.adobe.serialization.json.JSON;” in the code
    5. Run and Have Fun πŸ™‚

    If you are using the command-line compiler:

    1. Place the swc in the directory of your mxml code
    2. Confirm that you have the line “import com.adobe.serialization.json.JSON;” in the code
    3. Type the following on the command line
    4. mxmlc -include-libraries=corelib.swc JSONTest.mxml
    5. Run and Have Fun πŸ™‚