Adobe GraphAPI ActionScript 3 SDK 1.5 for Facebook Platform Pure AS3 Example

If like me you've struggled through the countless Flex and AIR examples of the Adobe ActionScript 3 Facebook SDK, trying to figure out how to get a simple, no-nonsense AS3 version working as part of a Facebook canvas iframe app... this page is for you!

This example uses GraphAPI version 1.5, available here.

It's a simple, barebones Flash movie with two TextFields, one of which is attached to a Sprite that acts as a button to log the app user in and out of Facebook, asking for extended permissions to write to the user's stream, etc. in the process. The other TextField is just a place to dump notes about the state of the app so you can see what's happening. The code should be self-explanatory. This example is similar to many examples included with GraphAPI 1.5 documentation and to the outdated tutorials on Adobe's site, only without all the MXML/Flex/Air malarky.

Because really... if you found this page, you want to wrap a swf into an iframe on Facebook as an app and get users to give you permission to post pictures of adorable lost farm animals to their stream. You could care less about developing some desktop AIR application that uses Facebook as a user login system.

First, the AS3 file:

MyApp.as

package {


import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.net.*;

import com.facebook.graph.Facebook;
import com.facebook.graph.data.FacebookSession;
import com.facebook.graph.net.FacebookRequest;


public class MyApp extends Sprite {
   
    private var screen:Bitmap;
    
    private var debug:TextField;
    
    private var button:Sprite;
    private var buttonText:TextField;

    public function MyApp() {
        
        //background screen
        screen = new Bitmap(new BitmapData(640, 480, false, 0xCCCCCC));
        addChild(screen);
        
        debug = new TextField();  //to trace state of session
        debug.x = 10;
        debug.y = 10;
        debug.width = 600;
        debug.height = 20;
        debug.text = 'Nothing Happened Yet';
        addChild(debug);
        
        button = new Sprite();
        buttonText = new TextField();
        buttonText.selectable = false;
        buttonText.width = 70;
        buttonText.height = 20;
        buttonText.text = "LOGIN";
        button.addChild(buttonText);
        button.mouseChildren = false;
        button.buttonMode = true;
        button.x = 10;
        button.y = 50;
        addChild(button);
        
        button.addEventListener(MouseEvent.CLICK, buttonClickListener);
        
        //Initilize the Facebook library
        Facebook.init("Application_ID", handleInit);  //naturally, replace Application_ID with your Application ID
		
    }
    
    private function writeDebug(s:String):void {
        //append s to debug textfield
        debug.text = debug.text + ',' + s;
    }
    
    private function handleInit(result:Object, fail:Object):void {
        if (result) {
            writeDebug('Arrived Logged In');
            buttonText.text = "LOGOUT";
        } 
        else {
            writeDebug('Arrived Logged Out');	
        }
    }
    
    private function onLogin(result:Object, fail:Object):void {						
        if (result) {
            writeDebug('Logged In');
            buttonText.text = "LOGOUT";
        } 
        else {
            writeDebug('Did Not Log In');
        }
    }
	
    private function onLogout(success:Boolean):void {						
        writeDebug('Logged Out');
        buttonText.text = "LOGIN";
    }
	
    private function buttonClickListener(e:MouseEvent):void {
        if (buttonText.text == "LOGOUT") {
            Facebook.logout(onLogout);
        }
        else {
            Facebook.login(onLogin, {perms:"publish_stream,user_interests,user_photos"});
        }
    }

}


}

The resultant swf must be embedded in an app iframe inside Facebook and the "Application_ID" string must match the ID that Facebook generated for your app.

The result of Facebook.login() is a popup window, so you can only call it from a user event, such as a mouseclick. Hence the MouseEvent.CLICK listener. Calling it without any user interaction will result in the browser blocking the popup window.

If you'd like to ask the user for a particular extended permission, such as the all-important ability to post to his/her stream, refer to the list on this page. They're sent as the comma-separated string perms inside the second optional argument in the Facebook.login() function.

The biggest frustration I had in figuring out Adobe's SDK was Facebook.init() failing silently and/or ignoring its callback function. Based on Adobe's forums and the SDK discussion pages, many others have that problem as well, and there are no answers anywhere. However it turns out that you have to be very particular about how you embed the swf in the web page. You must use the swfobject.js embedSWF() function as shown below:

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">

<head>	 	
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
	<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>	
</head>

<body>
	<div id="fb-root"></div>
	<div id="flashContent">
		<h1>You need at least Flash Player 9.0 to view this page.</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>  
	<script type="text/javascript">
		swfobject.embedSWF("MyApp.swf", "flashContent", "640", "480", "9.0", null, null, null, {name:"flashContent"}); 			
	</script>
</body>
	
</html>

This html file sits at the Canvas URL you gave Facebook when you created your app, and is what is shown inside the iframe when users visit http://apps.facebook.com/YourAppName.

Why wasn't Facebook.init() responding? My previous attempts at getting a bare-bones example working all used some legacy swfobject.js code with swfobject's write() command to replace content. Unfortunately that was causing the Adobe Facebook SDK and Facebook's all.js to have communication problems, with the result that nothing happened when init() was called. So if you're having a problem with Facebook.init() doing nothing, look at how you're embedding the swf in the page. Do it exactly as in the index.html example above. An <embed> tag probably won't work. Older versions of swfobject.js probably won't work.

Update: In my case, that fixed the issue. However it seems others are still having problems with Facebook.init() silently failing. The issue is being tracked here.

Also, note that FBJSBridge.js has been depreciated, though you'd never know since Adobe mentions that fact absolutely nowhere and their Adobe Flash Platform tutorials still direct you to use it. Nevertheless, you no longer need it if you're using version 1.5 of the SDK, as it has been replaced by AS3.

Just in case you were wondering where the SDK was in all of this, it's here:

compile.bat

C:\FlexSDK\bin\mxmlc.exe MyApp.as -output MyApp.swf -compiler.include-libraries "GraphAPI_Web_1_5.swc"
@ECHO OFF
echo.
pause

This Windows .bat file uses the free Flex mxmlc.exe command line compiler from Adobe to assemble MyApp.swf. But I'm sure if you use Flex proper or FlashDevelop or some crazy toolchain I don't know about you can figure out how to add GraphAPI_Web_1_5.swc to your project. The hard part is getting a grasp on the SDK.

Finally, if you like you can download the three files I used in this example:
FacebookActionScript3SDKExample.zip

I hope this page is of use to someone out there. It certainly would have been to me!

Aaron Maupin
maupin@pastrytech.com
January 3, 2011
I fully expect the information on this page to be out of date by tomorrow afternoon.

homepage