AS3: Creating Facebook Application
Facebook became one of the most popular social platforms these days. I just finished a flash based game that uses their API and decided to share my experience.
The example that I created is a simple one, but illustrates the basic usage of the Facebook's API. It looks like that: [1] The flash shows your name, avatar and your friends if you click on Get Friends button. The full source code of the tutorial is available here http://krasimirtsonev.com/files/facebookapplication/source.zip. When I started to work on the project I searched for a AS3 library. And I found one, written by Adobe - http://code.google.com/p/facebook-actionscript-api/. It looks good in the beginning, but after few hours work with it I found it a little bit buggy. I checked some of its code and I found that the version that I needed actually uses ExternalInteface to communicate with Facebook. Last few months I worked with Facebook's JavaScript SDK a lot and to be honest the result was sufficient. So instead of trying to solve bug after bug I decided to skip the AS3 library. All the requests to Facebook were made by JavaScript code and once the data is ready I just sent it to the flash application. The other tricky part was the developing process. Every Facebook application is connected with a specific Site URL and Site Domain. Let's say that the official version of the game will be hosted on http://gamesite.com. In this case we will set Site URL to http://gamesite.com and Site Domain to gamesite.com. The application will work, but for every little change we will have to upload the files to http://gamesite.com. That's why it's good to have two versions - one official (connected with http://gamesite.com) and one development version (connected with localhost). For this tutorial I created only the second one.
1. Creating the Facebook application
Before being able to create Facebook applications your account should be verified. If it's not, probably you will see the following message:
Your account must be verified before you can take this action.
Please verify your account by adding your mobile phone or credit card.
I used my mobile phone and suggest you to do the same. Once you verify your account go to http://developers.facebook.com and click on the Apps link in the header. [2] Choose + Create New App on the next screen. [3] Fill the name of your application, agree with the Facebook's terms and click Continue. [4] At this time the only one setting that you have to do is to set your Site URL and Site Domain. You can do that by going to Web->Site URL & Domain. As you can see on the next image my application is located at http://localhost/KrasimirTestApplication. The domain is localhost. In order to initialize the Facebook's API is the application ID. Get it from this page also. [5]
2. The JavaScript part
I prefer to work with OOP JavaScript. That's why I created a class called FacebookApp.js, which will manage all the things. Here is the initial HTML Code.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
... meta data here ...
<title>AS3: create Facebook application</title>
<script type="text/javascript" src="js/SWFObject.js"></script>
<script type="text/javascript" src="js/json2.js"></script>
<script type="text/javascript" src="js/FacebookApp.js"></script>
</head>
<body>
<div id="fb-root"></div>
<div id="animation"></div>
<script type="text/javascript">
var F;
window.onload = function() {
F = new FacebookApp();
(function()
{
var e = document.createElement("script"); e.async = true;
e.src = document.location.protocol + "//connect.facebook.net/en_US/all.js?xfbml=1";
document.getElementById("fb-root").appendChild(e);
}()
);
}
window.fbAsyncInit = function() {
F.init();
F.getLoginStatus();
}
</script>
</body>
</html>
As you can see I added three .js files in the page: a) SWFObject.js - flash embeding b) json2.js - the data from Facebook comes in a JSON format. It should be converted to a string and this library helped a lot. c) FacebookApp.js - managing the Facebook processes When I'm working with JavaScript my starting point is always window.onload event. By doing that I'm sure that all the neccessary resources are fully loaded. What I did here is to create an instance of FacebookApp and after that place the loading of the Facebook's library. So far, for me the code above seems the best way to do this. When the all.js is loaded, a window.fbAsyncInit is called which triggers the execution of custom method init and getLoginStatus of FacebookApp class. The constructor of the class:
var FacebookApp = function() {
this.appID = "[YOUR APP ID HERE]"; // the application's ID (provided by Facebook)
this.currentUser = null; // a JSON object that will hold the current user's data
this.token = null; // the access token of the current Facebook session
};
Don't forget to replace [YOUR APP ID HERE] with your actual ID. Calling the init method of the Facebook's API:
init:function() {
log("init appID=" + this.appID);
FB.init({
appId : this.appID,
status: true,
cookie: true,
xfbml: true,
channelUrl: "channel.html"
});
}
Checking if there is a Facebook session and if not, promps the login popup.
getLoginStatus:function() {
log("getLoginStatus");
FB.getLoginStatus(function(response) {
if (response.session) {
log("Logged in.");
F.token = response.session.access_token;
F.getCurrentUserInfo();
} else {
log("Not logged in.");
FB.login(function(response) {
if(response.session) {
log("Logging successful.");
F.token = response.session.access_token;
F.getCurrentUserInfo();
} else {
log("Logging failed.");
}
});
}
});
}
Some browsers restrict the opening of the Facebook's login popup. Be sure that your blocker is turned off while you are testing. Once we have a session we can use the Facebook Graph API. The method getCurrentUserInfo gets the current user data, like account id and name.
getCurrentUserInfo:function() {
log("getCurrentUserInfo");
FB.api('/me', function(response) {
if(response) {
F.currentUser = response;
F.showFlash(response);
} else {
log("getCurrentUserInfo failed");
}
});
}
If everything is ok we have enough information to embed the flash.
showFlash:function(currentUser) {
log("showFlash");
var rand = Math.floor(Math.random()*1000000);
var swf = new FlashObject("facebook.swf?tmp=" + rand, "animationSwf", "550", "550", "9", "#FFFFFF");
swf.addVariable("userName", currentUser.name);
swf.addVariable("userID", currentUser.id);
swf.write("animation");
}
As you can see I sent the user's name and id to the flash application. I added one more method which is called from the AS3.
getFriends:function() {
log("getFriends");
FB.api('/me/friends', function(response) {
if(response) {
F.getFlash().onGetFriends(JSON.stringify(response));
} else {
log("getFriends failed");
}
});
}
getFriends gets the current user's friends list, converts it to a string and sends it to the flash application. The full source code of FacebookApp.js could be seen here.
3. ActionScript3 part
The constructor of the document class:
public function App() {
debug("App constructor");
_currentUserName = loaderInfo.parameters.userName || "Krasimir Stefanov Tsonev";
_currentUserID = loaderInfo.parameters.userID || "617578836";
loadCurrentUserAvatar();
showCurrentUserName();
addControls(); // adds the button and the text area on the stage
ExternalInterface.addCallback("onGetFriends", onGetFriends);
}
To be able to test the application in the Flash enviroment I set my own Facebook name and id by default. In a big project, it's a good idea to load this data from an external xml or script for example. I also added the callback of onGetFriends. This method is fired when the JavaScript gets the friends' list. The loading of the avatar:
private function loadCurrentUserAvatar():void {
var url:String = "http://graph.facebook.com/" + _currentUserID + "/picture";
_avatar = new Loader();
_avatar.load(new URLRequest(url));
_avatar.x = _avatar.y = 20;
addChild(_avatar);
}
The avatar of every Facebook's user is accessable with a simple request to http://graph.facebook.com/\[USER ID]/picture. Showing the current user's name and adding the controls:
private function showCurrentUserName():void {
var tf:TextFormat = new TextFormat();
tf.font = "Verdana";
tf.size = 12;
tf.color = 0x000000;
_nameField = new TextField();
_nameField.defaultTextFormat = tf;
_nameField.text = _currentUserName;
_nameField.x = 80;
_nameField.y = 20;
_nameField.width = 300;
_nameField.height = 30;
addChild(_nameField);
}
private function addControls():void {
_controls = new AppControls();
_controls.x = 20;
_controls.y = 83;
_controls.b1.addEventListener(MouseEvent.CLICK, getFriends);
addChild(_controls);
}
Getting the friends' list:
private function getFriends(e:Event):void {
ExternalInterface.call("F.getFriends");
}
private function onGetFriends(result:String):void {
var friends:Array = JSON.decode(result).data;
var text:String = "";
if(friends && friends.length > 0) {
var numOfFriends:int = friends.length;
for(var i:int=0; i<numOfFriends; i++) {
text += friends[i].name + " <u><a href='http://www.facebook.com/profile.php?id=" + friends[i].id + "' target='_blank'>view profile</a></u>
";
}
} else {
text = "Problem reading friends' list.";
}
_controls.area.htmlText = text;
}
getFriends method is called when the user clicks on the button. Once the JavaScript part responds we converted the result string to an array. I used similar library for JSON operations like in the json.js. It's available here. The full source code of the document class could be seen here. Example's source code - http://krasimirtsonev.com/files/facebookapplication/source.zip Facebook JavaScript SDK - http://developers.facebook.com/docs/reference/javascript/ Facebook Graph API - http://developers.facebook.com/docs/reference/api/