Home >
Welcome back! Finally we will work on a real world application that will go live. The application that we will be creating will be named “Movie Expert”. One reason why I chose it is because I am an avid Movie fan and I will have lots of motivation to work on it in detail. The other reason is because it is really a sample that has the potential to utilize the facebook actionscript 3 library the proper way.
So, what does “MovieExpert” at all? Here is a small introduction. As an avid Movie Fan, I visit www.imdb.com a lot a read about mistakes and goofs in movies. First I could not believe there are so many mistakes in movies! I noticed that there are always at least 10 to 20 mistakes in movies. So, why not make a game out of it? Quickly I got the idea that I could create a small game where the game would display videos containing those mistakes. The goal of the player would be to spot those mistakes. If the player finds all mistakes in one clip, he reaches the next level. How much levels are there is now not really important. The more videos we add, the more levels the application will have. Also, it would be great if we could maintain the application, add new videos when we want, remove ones etc.
It is also worth mentioning that the application really has a high fun value and on the other side, it has a bigger audience. The application topic, namely movies, is liked by males and females, young and old. There are really millions of movie fans across the world, so it’s worth jumping on that bandwagon.
Here is one image from the application that we will be creating through the next 5 articles:
Looks nice, but that is just the sneak peek. What we see on the image is the YouTube window placed in the facebook application canvas. Also, we can see the controls on the image that are used to control the video. On the top of the image we see the typical facebook canvas with the navigational buttons.
Since we have the raw idea of the application and since we took the look into the app interface, we are now ready to prepare ourselves for the application development. We need to make sure all parts are in place when the actual development starts.
Those are the ideas that are important for the application to be completed:
- YouTube video needs to be integrated into the SWF
- Player must be able to click on "spots" (mistakes) in videos
- Admin must be able to insert new videos
- Admin must be able to add new “spots” (mistakes) to videos
- Every video will represent a new “level” of the game
- Player must be able to continue throughout levels and may not start over again
- Player must be able to collect points to advance through levels
- Once the user has found all spots and collected points, he is allowed to continue in game
Now, we need to make sure we download the YouTube ActionScript 3 library that we will use throughout the application. There are several ones out there online but this one made me sooo happy: http://code.google.com/apis/youtube/articles/youtube_as3_chromeless.html.
This is the screenshot of the ActionScript 3.0 YouTube library in action somewhere on the web. Make sure you download it on the location here (http://youtubechromelesswrapper-as3.googlecode.com/files/ActionScript_3_YouTube_Wrapper_v1.0.zip). We are now equipped with the tool that will help us integrate videos from YouTube right inside our swf.
We know that the official facebook library was written in AS2, that's the problem. This library is a solid workaround.
Cool, now that we have the library, let’s make sure we set up the new application inside facebook.
Make sure you create your own app with your own pair of application keys and secrets. Unfortunately, you need to name your application other then MovieExpert, you can select a similar name like "ActionMovieExpert" or similar stuff, the point is only that you have to have a different name, in order not to collide with the name of my application that already exists on facebook.
Let's move on. Now that we the name of the application, we need to add other parameters.
Replace the canvas page url with your own unique application name. If you named your application “ActionMovieExpert”, the canvas page url would be http://apps.facebook.com/actionmovieexpert/. The canvas callback would be the path to the index page of the application on your server. Like http://www.yourserver.com/yourMovieExpert/index.php. Next important thing is that we need to select the iFrame (not FBML) render option.
With that, we have one important part already finished! We have the facebook canvas ready for the actual application development.
So, now that we are finished with the Facebook canvas setup, we can move on to the setup of the FLA.
Create a new FLA.
Save it as main.fla in the project folder.
Let’s talk about the dimensions of the application swf. In my case, I decided to resize the swf 750 to 400 px. Don’t know what lead me to this decision, but it seem to fit the requirements.
Cool, the stage is set. We should now have a lot of space here in the swf to insert videos, add buttons etc. What should we do now, is to save our work and try to upload it to the web server.
Since we never worked with iFrames before (we always used the FBML embed method), we need to discuss it a bit. There is an article it online I read few days ago where facebook engineers recommend rather to use iFrame the FBML to embed the swf application. I will not create a debate here about this, but the reason we use iFrame here is because of the YouTube integration. The YouTube ActionScript 3 wrapper uses JavaScript to communicate with YouTube and from my standpoint, it is better to use iFrames just becuase of the JavaScript used for YouTube. Trust me, it will work.
Creating the index.php page
The index page that is defined as the starting page of the application, is the major point in the application. The structure of the page is very important for us since it looks a bit different then the previous index pages. Here is the complete html, don’t get discouraged when you see this:
<?php
//include facebook api etc.
require_once("facebook/client/facebook.php");
require_once("keys.php");
//create new facebook instance
$facebook = new Facebook(API_KEY, SECRET);
//invite users if the app is installed for the first time
if($_GET["installed"] == 1){
$facebook->redirect("http://apps.facebook.com/movieexpert/invite.php");
}
//propmpt the user to login
$fb_user = $facebook->require_login();
//check if the user has added the app
if (!$facebook->api_client->users_isAppUser()) {
//if not, redirect him to add it
$facebook->redirect($facebook->get_add_url());
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>ActionScript 3 YouTube Wrapper</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="author" content="The Chopping Block, Inc." />
<meta name="geo.country" content="US" />
<meta name="dc.language" content="en" />
<meta name="keywords" content="YouTube, ActionScript 3.0, JavaScript, Wrapper, Flash, choppingblock, The Chopping Block, Demo" />
<meta name="description" content="The ActionScript 3.0 Wrapper for YouTube Chromeless Player leverages ActionScript's ExternalInterface class and YouTube's JavaScript API to create a reliable approach to integrating the YouTube API into your ActionScript 3.0 projects." />
<script type="text/javascript" src="_assets/js/swfobject.js"></script>
<script type="text/javascript" src="_assets/js/youTubeLoader.js"></script>
<script type="text/javascript">
var flashvars = {};
var params = {
menu: "false",
allowScriptAccess: "always",
scale: "noscale"
};
var attributes = {};
swfobject.embedSWF("http://www.yourServer.com/yourAppName/main.swf", "flashcontent", "700", "450", "9.0.0", "http://www.yourServer.com/yourAppName/_assets/swf/expressInstall.swf", flashvars, params, attributes);
//init the youTubeLoader javascript methods
SWFID = "flashcontent"
</script>
<script type="text/javascript">
function updateHTML(elmId, value) {
document.getElementById(elmId).innerHTML = value;
}
function setytplayerState(newState) {
updateHTML("playerstate", newState);
}
// PLEASE NOTE: For the purpose of this demo:
// This method is called from the onYouTubePlayerReady method inside _assets/js/youTubeLoader.js
function secondaryOnYouTubePlayerReady(playerId) {
ytplayer = document.getElementById(SWFID);
setInterval(updateytplayerInfo, 250);
updateytplayerInfo();
ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
}
// PLEASE NOTE: For the purpose of this demo:
// This method is called from the onytplayerStateChange method inside _assets/js/youTubeLoader.js
function secondaryOnytplayerStateChange(newState) {
setytplayerState(newState);
}
function updateytplayerInfo() {
updateHTML("bytesloaded", getBytesLoaded());
updateHTML("bytestotal", getBytesTotal());
updateHTML("videoduration", getDuration());
updateHTML("videotime", getCurrentTime());
updateHTML("startbytes", getStartBytes());
updateHTML("volume", getVolume());
}
function alertEmbed () {
alert( getEmbedCode() );
}
function alertVideoUrl () {
alert( getVideoUrl() );
}
function unloadVideo () {
stop();
clearVideo();
}
</script>
</head>
<body>
<div id="flashcontent">
<h1>Alternative content</h1>
<p><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
</div>
</body>
</html>
We really don’t need to look at the first lines since we worked with them for so many times. It does the usual stuff known from the previous articles. This is the part that needs to be reviewed:
<script type="text/javascript">
var flashvars = {};
var params = {
menu: "false",
allowScriptAccess: "always",
scale: "noscale"
};
var attributes = {};
swfobject.embedSWF("http://www.yourServer.com/yourAppName/main.swf", "flashcontent", "700", "450", "9.0.0", "http://www.yourServer.com/yourAppName/_assets/swf/expressInstall.swf", flashvars, params, attributes);
//init the youTubeLoader javascript methods
SWFID = "flashcontent"
</script>
First you need to replace the path to match your server configuration. Next you need to replace the path to the assets folder. The assets folder contains the necessary expressInstall.swf that is used by SWFObject to install missing flash players. We really don't need to discuss the rest of the html. It is the JavaScript code that will be accessed by our AS3 code to control YouTube videos that will be loaded into our swf.
So, now save this page as “index.php” in the project folder.
Since there are so many includes in the index.php file, we need to make sure we have them ready for upload. What files do we need? We need the files that are in the /_assets folder that came with the download of the YouTube AS library.
So, the folder structure on the server needs to look like this:
Of course along with the index.php, which is not visible here in the screen shot. Now, we need to make sure the page we just created actually works. The goal is to see the facebook canvas page along with the swf. So, upload index.php, main.swf and the _assets folder to the root folder of your remote facebook application folder. Here is what we should see when we open http://apps.facebook.com/movieExpert (Where MovieExpert needs to match your name):
Creating the invite screen
Well, the window is there and we see the swf as soon as we add the application. But in fact this is not the natural flow of application usage on facebook. We are all used to see all kinds of invite screen right after the installation of the application. Here is a sample image:
We are used to see this screen as soon as we install an application on facebook. Now the challange for us is to create the same invitation screen just by using HTML, not the simple FBML. There is a workaround for this using XFBML.
So what exactly is XFBML?
XFBML is (according to the wiki) “a way for you to incorporate FBML (Facebook Markup Language, an extension to HTML) into an HTML page on a Facebook Connect site or an iframe application”.
This is exactly what we want, since we defined the application to use iFrame, not FBML, the standard FBML for invites:
<fb:request-form action="index.php" method="POST" invite="true" type="MovieExpert" content="Tell your friends to use MovieExpert <fb:req-choice url='http://apps.facebook.com/movieexpert/' label='Ok:-)'/>">
<fb:multi-friend-selector showborder="false" actiontext="Invite your friends to use MovieExpert" condensed="false" exclude_ids="<?php $friends = $facebook->api_client->friends_getAppUsers(); foreach ($friends as $friend) { echo "$friend,"; } ?>">
</fb:request-form>
will not render in the browser.
So, how does the XFBML approach look like? Well, here is first the complete invite.php that is rendered as pure HTML:
<?php
//include facebook api etc.
require_once("facebook/client/facebook.php");
require_once("keys.php");
//create new facebook instance
$facebook = new Facebook(API_KEY, SECRET);
//propmpt the user to login
$fb_user = $facebook->require_login();
//check if the user has added the app
if (!$facebook->api_client->users_isAppUser()) {
//if not, redirect him to add it
$facebook->redirect($facebook->get_add_url());
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<body>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"></script>
<script type="text/javascript">
FB_RequireFeatures(["XFBML"], function(){ FB.Facebook.init("YOUR_API_HERE", "xd_receiver.htm"); });
</script>
<fb:serverfbml style="width: 730px;">
<script type="text/fbml">
<fb:fbml>
<fb:request-form action="http://www.yourserver.com/fb_redirector.php" target="top" method="POST" invite="true" type="XFBML" content="Do you think you can spot mistakes in movies? <fb:req-choice url='http://apps.facebook.com/movieexpert/' label='Let me check' /> " > <fb:multi-friend-selector showborder="false" actiontext="Invite your friends to use MovieExpert.">
</fb:request-form>
</fb:fbml>
</script>
</fb:serverfbml>
</body>
</html>
The first line of code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
must come in front of all code in the page because with this directive, we do not only tell the page where the find the HTML xmlns, but also the FBML xmlns that is located on the facebook servers! This way, we are able to actually use FBML tags inside our facebook canvas.
Next important line of code is:
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"></script>
is the cool line of code that load the JavaScript necessary to create the FBML items in the HTML page. According to the wiki: “For the best performance, put this code right after the tag in the file.” This is what we did in our code.
The next important line of code is:
<script type="text/javascript"> FB_RequireFeatures(["XFBML"], function(){ FB.Facebook.init("YOUR_API_HERE", "xd_receiver.htm"); }); </script>
Like it can be read from the code, it initializes the JavaScript library that was loaded before. We just need to put the appropriate API key, download the xd_receiver.htm file from http://www.somethingtoputhere.com/xd_receiver.htm and upload it to our facebook application folder.
Finally we place the FBML tag:
<fb:serverfbml style="width: 755px;">
<script type="text/fbml">
<fb:fbml>
<!-- invite friends form -->
<fb:request-form action="http://www.yourserver.com/fb_redirector.php" target="top" method="POST" invite="true" type="XFBML" content="Do you think you can spot mistakes in movies? <fb:req-choice url='http://apps.facebook.com/movieexpert/' label='Let me check' /> " > <fb:multi-friend-selector showborder="false" actiontext="Invite your friends to use MovieExpert.">
</fb:request-form>
</fb:fbml>
</script>
</fb:serverfbml>
<html>
<head>
</head>
<body>
<script type="text/javascript">
top.location = "http://apps.facebook.com/movieexpert/";
</script>
</body>
</html>
Please don’t ask now what it is, but it is a workaround for a bug in XFBML.
So, let’s try to play around with it a bit. When we upload the file to the folder and call the URL via the application canvas (http://apps.facebook.com/movieexpert/invite.php) we see the following screen:
Cool, this is exactly what we wanted! Pure FBML in pure HTML iFrame application! It matches exactly the look and feel of the application.
We are almost done with the preparation of the application. But still, we have two files in the application folder, invite.php and index.php. What is the default landing page? We said that it is the index.php. We need a mechanism that will redirect us to the invite.php page only if the user just installed the application. How is that accomplished? Open index.php and check the following line of code:
//invite users if the app is installed for the first time
if($_GET["installed"] == 1){
$facebook->redirect("http://apps.facebook.com/movieexpert/invite.php");
}
If the payer installs the application for the first time, he will be redirected to the invite.php page. Let’s test that!
Go to the application overview page of your application:
Go to the bottom of the page and remove the application for a moment:
Then, after the application has been removed, click on "Go To Application" button.
After the, we should see the introduction screen:
Voila! Now the user can simply skip the page (forced invites are not allowed) or invite few friends to use the application :-) After both actions, the user is redirected to index.php, where the action begins!
To view the entire series please visit http://www.insideria.com/series-facebook-dev.html




Facebook Application Development
I've been reading all your facebook series tuts, thanks so much for all the great help. I'm having trouble finding out how to prompt a user to publish an event to their feed. Something like when you take a quiz app and on completion you are prompted to post your results with some added comment by the user. I'm interested in what that AS3.0 API call might be. I really appreciate any help/direction
Great Tut, but I get the following error after uploading the "fb_redirector.php" file to the root of my server: "The requested URL /moviefail/index.phpinvite.php was not found on this server."
Any idea why this is happening?
I am able to make the invite form visible, but when clicking on the "send invitation" button, nothing happens .... i tried everything :(