ActionScript (Dictionary) object hasKey

When using a (dictionary) object or assocative array in AS3, there is no such thing as a hasKey() method to determine whether it contains any given key.

However there is a similar way to do this by using the hasOwnProperty() method.

var dict:Dictionary=new Dictionary(); // OR var dict:Object={}; OR var dict:Array=new Array();
				
dict["key1"]="This is the first value";
dict["key2"]="This is the second value";
dict["key3"]="This is the third value";

trace(dict.hasOwnProperty("key22") + " - " + dict["key22"]);
trace(dict.hasOwnProperty("key2") + " - " + dict["key2"]);

//Output:
//false - undefined
//true - This is the second value

This is great for some simple example and usage.

But whenever you find yourself in need of better Map support (and other collections),
I would advise you to take a look at the AS3Commons Collections package.

, , , ,

1 Comment

SourceMate for Flash Builder

Another very nice eclipse plugin I have started using recently is SourceMate

The feature summary is quite impressive.
Some of these features really do speed up your development process or provide extra functionality to Flash Builder 4.
Since we are already at an advanced stage of the lifecycle of the Flex IDE, these are all features which for some inconceivable reason have not been built into Flash Builder nor the plugin version.
Not even the premium version!

There is a 30-day trial version available, so it might be worth checking out :)
Also, the full version is available at a reasonable price. Keep in mind though that SourceMate is licensed per developer.

The features I personally use most are:

  1. Code generation of getters/setter and constructors
  2. TODO, FIXME, and XXX Task Markers
  3. Code Templates that you can also share with your fellow code monkeys
  4. And last but not least the metadata content assist, metadata compilation validation and metadata configuration

The last one described is particularly nice for the developer who uses frameworks all the time.
This will enable you to have autocompletion on metadata tags, for instance [Bindable], [Event],…
Furthermore, it will even validate your metadata tags at compilation time to make sure your code is how you intend it to be.
Custom tags can also be imported and even shared with others.

Some renowned Flex frameworks like Spring Actionscript already offer custom configuration files that you can import from their website.
Also, you can find configuration files for frameworks like Parsley, Swiz,… created by other developers without any effort.

To make a long story short, SourceMate can be a nice asset for the developer who demands more of his Flash Builder installation.

, , ,

No Comments

Auto formatting flex files in Flash Builder

The last few months,

I have been using the flex formatter plugin for eclipse to automagically format my .mxml and .as files.
It can be found here
I find it a bit surprising that such a feature has not been built into flash builder by default.

It has a couple of nice features:
- You can fully customize the way you want flash builder to format your files by changing the settings
- You can save a properties files to store and share your formatting settings with your fellow developers
- The plugin has the ability to synchronize your properties with a file on any given location (say for example the project’s sources)
- There are some command line support jars, which are great for doing text formatting while using an ANT script to build your project or to format at checkin-time
- Automatically organize the order in which mxml attribute tags should occur
- Automatically delete obsolete blank lines
- Automatically format code blocks
- …

I am sure that I am forgetting some other nice features here, but the plugin is definitely worth checking out.
In my humble opinion it is a must have for any flex developer and a valuable asset for any development team.
It keeps your code consistent, readable and nice and tidy.
Just the way we like it!

, , ,

No Comments

Adobe Flex 4 with AIR ACE

Last week,

I finally took my Flex 4 with AIR exam and aced it ;)
This means I now get to add a badge to my blog, saying kudos to myself.
Total awesomeness :D

However I must say it was not at all what I expected from the exam.
It was not very tough since I prepared myself well, but still I thought some questions were asked in such an ambiguous way that they were a bit hard to answer.
Also some questions were a bit too much into details about class hierarchies etc.

Anyway, I prepared myself using the official exam description you can find at the adobe website, concerning all the items you should certainly cover.
I also found a link there for an exam simulation tool, that will help you get prepared. It is called Attest and can be found here

It has a free limited trial version and links to the adobe livedocs to make studying easier for you.
The full version is not free ($20) and offers you the chance to take practice exams and evaluate yourself afterwards.
Do not expect to get all the questions as they will be on the exam, rather you should see it as a tool to find your weaknesses and do some extra studying in the area you need it the most.
All in all, 20 bucks is a small price to pay and should really help you forward.

, , ,

No Comments

Flex custom preloader not working

Lately,

I encountered a problem involving flex custom preloaders.

The context I was using was as follows:
- I created a preloader.swf in flash with a 100 frames to show a progressbar evolution.
- I embedded that preloader.swf in my flex app. Read more about this here

This all worked fine when I ran my application locally.
However, the problem showed itself when deploying my app to my webserver (thus no longer running it locally).
The unintended behavior was that the preloader would not show up until my app was nearly fully loaded, and it then popped up for about a second @ 100% full.

I tried all sorts of different approaches.
- Extending mx.preloaders.DownloadProgressBar
- Creating a new MovieClip that implemented IPreloaderDisplay. More about this here
- Creating a loader .swf that contained the preloader, and loading in my app from there
- Using Charles to monitor request and responses

However none of these solutions seemed to work.

After searching a long time for what the fudge could be causing this problem, I stumbled upon the following blog posts:
http://patrickmcd.com/2009/04/20/flash-preloading-errors-turn-off-gzip/
http://www.flash-db.com/Board/index.php?topic=19252.0

As it turns out, the problem isn’t caused by Flash Player or by Flex. It is caused by your server setup.
If you have gzip compression enabled on your server (for speeding up requests and responses), the problem occurs.
What the gzip compression does is compress your already compressed binary .swf file, thus screwing up the loading procedure from an actionscript point of view.
Actually gzip compression doesn’t enhance performance in any way because a .swf is as compressed as it can be.
This also counts for numerous other already compressed files that can’t be compressed any further (.jpg,.gif,.flv,.png,..)

So the solution is rather simple. You can just add a .htaccess file to the root of your public directory to ensure that .swf files (and any other already compressed files) will no longer be compressed.
All that has to be in this file is the following:

# Don't compress images/flash
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png|swf|flv)$ no-gzip dont-vary

Et voila, you have disabled the gzip compression and fixed your preloader bug because it’s working now.

This really was a pain in the *ss for me, as I spent 2 days looking for a solution.
I hope this post can save you the trouble I went through :)

, , , ,

5 Comments

New Job

2 weeks ago, I started working at iDA mediafoundry.

This will allow me to be part of some of the most challenging Flex / Java/ … projects in Belgium.
I must say that these are exciting times for me.

This transition implicates that I will be able to do what I love most.
Livecycle, Merapi, Cairngorm, PureMVC, FlexUnit, …
You name it and I’ll get the chance to be doing this in a professional environment.

Alot mor technical stuff means a lot more blogposts :P

http://www.ida-mediafoundry.be

,

No Comments

Youtube video in AS3 FLVPlayback Update(2)

After the update of yesterday,

Youtube changed the way on how to retreive the video from it’s html page again.
This implies, that the 2 old versions of the proxy no longer worked and that videos could no longer be retreived.

After a quick peek, the solution was rather simple.
Here’s the code for the new and improved proxy:

<?php
    $id = trim($_REQUEST['id']);
	
    $url = "http://www.youtube.com/watch?v=" . $id . "&fmt=18";

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $info = curl_exec($ch);

    if (!preg_match('#\'SWF_ARGS\': (\{.*?\})#is', $info, $matches))
    {
        echo "Check the YouTube URL : {$url} <br/>\\n";
        die("Couldnt detect swfArgs");
    }

    if (function_exists(json_decode)) # >= PHP 5.2.0
    {
	$swfArgs = json_decode($matches[1]);
        $video_id = $swfArgs->video_id;
        $t = $swfArgs->t;
    }
    else
	{
        preg_match('#"video_id":.*?"(.*?)"#is', $matches[1], $submatches);
        $video_id = $submatches[1];

        preg_match('#"t":.*?"(.*?)"#is', $matches[1], $submatches);
        $t = $submatches[1];
    }
	
	curl_close($ch);
	
	$fullPath = "http://www.youtube.com/get_video.php?video_id=" . $video_id . "&t=" . $t; // construct the path to retreive the video from
	
	$headers = get_headers($fullPath); // get al headers from the url
	
	foreach($headers as $header){ //search the headers for the location url of youtube video
		if(preg_match("/Location:/i",$header)){
			$location = $header;			  
		}
	}
	
	header($location); // go to the location specified in the header and get the video
?> 

That’s all there is to it.

This file will also be updated again in the source and files download of the original post.

, , , , ,

9 Comments

AS3 Google Weather API lib – Updated

A while ago, I needed to integrate a weather forecast into an actionscript application I was developing.

After some initial searching, I quickly stumbled upon the yahoo weather API.
I dug into this some more and even found an AS3 library for getting the weather forecast! But then, the dissapointment came. When implementing this, you could only get a basic forecast for the current date, with a link to go to the full weather forecast. As demonstrated here.

After some more searching for the right API to suit our needs (a very basic one), I found the google weather API.
The use of the API is as follows:
1) you send a http request like the following : http://www.google.com/ig/api?weather=Paris,France&hl=fr to the API
2) you receive an XML response containing weather forecast data for the next 4 days for a given location
So actually you could say it is more like a feed than an API.

But this seemed to be exactly what I needed to get the job done.
The main problem I ran into was that the API was not officially documented, so I had to do some scraping (monitoring requests and responses with charles) to find out how it worked. And of course putting the pieces together reading several blogs / forums etc.
More unofficial documentation can be found here
Also, I never found a proper actionscript library that enables us to retreive this data. That’s why I decided to stop wasting precious time and just make it myself.

Basically all I did was create a wrapper library that does the request, gets the response and handles errors in an easy to use manner.
This resulted in a fully functional AS3 library for use in flash or flex to retreive weather forecast data from google weather.

Note: When loading the xml and images from an external source, make sure to use a proxy in order to avoid flash player security issues.
In some cases, you also need to put a crossdomain.xml on your server in order to enable your swf to acces external content.

I tried to put comments in the example as much as I could to make everything as clear as possible.
Feel free to use this library in your projects / play around with it.
If you have any remarks, additions, request, questions… just post them here.

This is the basic result, just displaying the data received from the api. Nothing less, nothing more:

UPDATE

Google made changes to the API, causing the standard images not to show anymore.
A minor fix in the GoogleWeatherService.as class solved the issue.

Changed

public static const BASE_IMAGE_URL:String = "http://www.google.com/ig";

to

public static const BASE_IMAGE_URL:String = "http://www.google.com";

View the new example here
Or download the SWC and source files with the above usage example here: AS3 Google Weather lib (5603)

, , , ,

59 Comments

Youtube video in AS3 FLVPlayback

Lately,
I’ve been busy trying to get youtube movies to play in the standard FLVPlayback component.

Getting this to work was really a pain in the butt now and then, especially because while I was working on this,
youtube changed some stuff on their side undoing all my previous work. But hey, stuff happens!
In the end perseverance and a lot of patience finally resulted in a working solution.

I will break up the solution into several pieces, describing the steps that need to be taken in order for this to work.

1) We need to get the video (.flv) from the youtube server.

To achieve this, one must of course understand how to get this video.
To start off, just navigate to a youtube movie. e.g. http://www.youtube.com/watch?v=vE_WqdKbTvY , then right-click anywhere in page and watch the page source code.

In the source code, search for the string “swfArgs”, which will look something like this:

var swfArgs = {
"q": "top%20gear%20carrera%20gt",
"fexp": "903500,900130", 
"invideo": true, 
"sourceid": "ys",
"video_id":"vE_WqdKbTvY", 
"l": 478,
"fmt_map": "18/512000/9/0/115,34/0/9/0/115,5/0/7/0/0", 
"sk": "PbB4AIyvqpbLl0DYyCX5rpmXcQe-FEcZC", 
"is_doubleclick_tracked": "1", 
"usef": 0,
"t": "vjVQa1PpcFO6TnxVA4_nkqbqKN-z4CoWJgWn2Pfu77I=", 
"hl": "en", 
"plid": "AARoEenKN8A9FYLn", 
"vq": null, "ad_module": "http://s.ytimg.com/yt/swf/ad-vfl91517.swf", 
"cr": "NL", 
"tk": "j7SixOLxSJ1xxBIwWubnN9sXiu7hrejTmRv4ruMx4N3OaeyhN0xImQ=="};

As you can see this is an object, containing data about the swf and thus the .flv played at the youtube html page.
The video_id is the identifier of the movie and t is a token set by youtube that enables you to view / download the video.
This token expires after a given period of time, so I can’t place a permanent download link for the flv file here.

So now that we have the parameters of the video we need to fill them in as follows into a fixed url, used by youtube to retreive the flv video:

http://www.youtube.com/get_video.php?video_id=[id]&t=[t]

In our case:

http://www.youtube.com/get_video.php?video_id=vE_WqdKbTvY&t=vjVQa1PpcFO6TnxVA4_nkqbqKN-z4CoWJgWn2Pfu77I=

When navigating to this url with your browser, the video will start downloading

Don’t bother trying to open this last link, because as stated before, the token will probably have expired by the time you read this.
(Also the token is linked to the IP that first requested it, which in this case would be mine. More about this later)
If you would like to test if and how this works, just follow all the steps described above and see for yourself.
Pretty cool huh?

Now that we know how to get the .flv video of any youtube movie, we need to find a way to automatically do this, without the need to go through all the steps again.
We will use a php proxy script that eliminates all sandbox issues, accepts any youtube url and then returns the physical video (.flv) as if it were present on our own server.
However, this script will be a mere redirect to the location of the video on youtube servers, the file will not be physically downloaded by your server.

To create a script like this, I did some searching and quickly stumbled upon a script I found here.
This worked fine at first, but as I was saying youtube changed some things server side along the way.
That’s why i needed to search for a solution and needed to modify the script in order to getting it to work again.

The problem was caused because youtube changed the token idea.
A token is now linked to an IP address, meaning that the video can only be downloaded by the IP address that first requested the token.
This is a problem when trying to do this in-browser, where the browser is on the localhost, and the script is on a server and thus causing an IP mismatch. The result is that the file cannot be accessed.
After alot of searching around the final solution is to retreive the headers from the youtube download url and extracting the location of the flv that is embedded.

The result for the php proxy script:

<?php
    $id = trim($_REQUEST['id']);
	
    $url = "http://www.youtube.com/watch?v=" . $id;

    $url = $url . "&fmt=18"; //Gets the movie in High Quality, uncomment this line to get it in normal quality

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $info = curl_exec($ch);

    if (!preg_match('#var swfArgs = (\{.*?\})#is', $info, $matches))
    {
        echo "Check the YouTube URL : {$url} <br/>\n";
        die("Couldnt detect swfArgs");
    }

    if (function_exists(json_decode)) # >= PHP 5.2.0
    {
	$swfArgs = json_decode($matches[1]);
        $video_id = $swfArgs->video_id;
        $t = $swfArgs->t;
    }
    else
    {
        preg_match('#"video_id":.*?"(.*?)"#is', $matches[1], $submatches);
        $video_id = $submatches[1];

        preg_match('#"t":.*?"(.*?)"#is', $matches[1], $submatches);
        $t = $submatches[1];
    }
	
    curl_close($ch);
    
    $fullPath = "http://www.youtube.com/get_video.php?video_id=" . $video_id . "&t=" . $t; // construct the path to retreive the video from
	
    $headers = get_headers($fullPath); // get all headers from the url
	
    foreach($headers as $header){ //search the headers for the location url of youtube video
	if(preg_match("/Location:/i",$header)){
	    $location = $header;			  
	}
    }
    header($location); // go to the location specified in the header and get the video
?> 

An example of correct usage:

Navigate to http://www.dennisjaamann.com/demo/youtubeFLVPlayback/php/getYoutubeFLV.php?id=[videoID],
where the videoID is the id from the youtube movie http://www.youtube.com/watch?v=vE_WqdKbTvY
In this case: http://www.dennisjaamann.com/demo/youtubeFLVPlayback/php/getYoutubeFLV.php?id=vE_WqdKbTvY
When navigating to the url above, you will notice that the script will redirect you to the physical location of the .flv file.This will start the download prompt.

Isn’t this exactly what we need? :)

2) Workaround for FLVPlayback

When we take the url retreived above and try to play it in the standard FLVPlayback component as follows:

var videoPlayer:FLVPlayback = new FLVPlayback();
addChild(videoPlayer);
videoPlayer.source = "http://www.dennisjaamann.com/demo/youtubeFLVPlayback/php/getYoutubeFLV.php?id=vE_WqdKbTvY";
videoPlayer.play();

The video doesn’t play and we get the following error:
VideoError: 1005: Invalid xml: URL: “http://www.dennisjaamann.com/demo/youtubeFLVPlayback/php/getYoutubeFLV.php?id=vE_WqdKbTvY&FLVPlaybackVersion=2.1″ No root node found; if url is for an flv it must have .flv extension and take no parameters
at fl.video::SMILManager/http://www.adobe.com/2007/flash/flvplayback/internal::xmlLoadEventHandler()
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()

Which is kind of a suprise, because when we open the source url in our browser there is clearly an .flv file there.

However, when analyzing the error message we can clearly see the problem. The key part here is:
“if url is for an flv it must have .flv extension and take no parameters”
When taking a look at our url http://www.dennisjaamann.com/demo/youtubeFLVPlayback/php/getYoutubeFLV.php?id=vE_WqdKbTvY,
it is obvious that it doesn’t end on .flv and that our url accepts parameters.

This behaviour is caused by a few lines of code in the NCManager class used by the FLVPlayback component.
There, the check is done whether the url ends on .flv and that the url does not accept parameters.

This leaves us 2 options:
- Extend the NCManager, overwrite this behaviour and make the FLVPlayback use this custom class
- Find a way to give the NCManager a correctly formatted url, so that it can stop nagging

I prefer the second option because it leaves the NCManager unmodified and hereby we can eliminate any unwanted behaviour.
Also, since I have a little php experience, I quickly realized that this had the funky smell of url rewriting.
With url rewriting you can take any url and format it to the format required which is exactly what we need here…

So we need to change the original url
http://www.dennisjaamann.com/demo/youtubeFLVPlayback/php/getYoutubeFLV.php?id=vE_WqdKbTvY
to

http://www.dennisjaamann.com/demo/youtubeFLVPlayback/videos/vE_WqdKbTvY.flv

This can be achieved by adding a .htaccess file to your project folder on the web server.
The code below is also included in the source files at the bottom of this post. But please note, not all operating systems show a .htaccess file.
This is because that it sometimes is a hidden file type.

Here’s the code for that:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^videos/([^/]+).flv php/getYoutubeFLV.php?id=$1 [NC]

And that’s all folks!
When we now execute our code again with the modified url, the NCManager has stopped nagging and the videoplayer plays the wanted video.

var videoPlayer:FLVPlayback = new FLVPlayback();
addChild(videoPlayer);
videoPlayer.source = "http://www.dennisjaamann.com/demo/youtubeFLVPlayback/videos/vE_WqdKbTvY.flv";
videoPlayer.play();

This workaround took like a minute or so to be succesful, leaves the the NCManager unchanged and does the trick.
That’s why I’ve chosen this solution because it is simple and elegant.

Read more about basic url rewriting here

3) Create the player.

All that is left now is to create our application. I have prepared an example in flex (sdk 3.3)

This is the result:

View the full example with source here
Or download the example source files here: youtubeFLVPlayback (6115)

, , , , ,

55 Comments

Flex cumulative Arraycollection.filterfunction

Earlier today I was working on some app @ boulevart

I had a datagrid containing a set of data, which i needed to be able to filter given various parameters.
I quickly found out that i could use the standard Arraycollection.filterfunction on the dataprovider to do so easily…
At least I thought :)

When applying only one filter on the dataprovider, this worked like a charm
It soon became clear that when you want to apply multiple filters at the same time, the whole dataprovider was passed to the second filter function instead of the already filtered dataprovider. With this, undoing the first filter and showing only the filter results of the last used filter.

I made my own “workaround” which involved some redundant and crappy coding :)
So the next step was some basic googling. It didn’t take long to find a solution by Cristian Rotundu. It can be found here

I like this solution because it enables flexibility by simply extending the standard flex Arraycollection and adding the functionality we need.
So it’s rather brilliant in its simplicity.

Two thumbs up for Cristian!

, , ,

2 Comments