
While The Facebook Graph API article becomes pretty popular and a lot of developers keep asking me to publish some practices I use, I managed to create this blog post. Here is a list o some functions you may want to extend FacebookOAuthGraph Class with.
Extending & Singletonize
First, lets make our class singleton, so the whole flash project can simply access and use one instance
public class Facebook extends FacebookOAuthGraph
{
private static const _instance:Facebook = new Facebook();
public function Facebook()
{
super();
useSecuredPath = true;
if(instance)
throw new Error("Use Facebook.instance!");
}
public static function get instance():Facebook
{
return _instance;
}
....
}
Now anywhere in your project:
var facebook:Facebook = Facebook.instance;
Auto Execution After Authorization:
Lets say, when user clicks on publish post before your application is connected, just make connect() followed by desired function:
if(!facebook.authorized)
facebook.connect();
facebook.publishPost(...)
publishPost() automatically executes again after connected thanks to Callbacks class
import sk.yoz.utils.Callbacks;
private function onAuthorized(event:FacebookOAuthGraphEvent):void
{
Callbacks.execute("FBstuff");
}
public function publishPost(...):void
{
if(!authorized)
return Callbacks.add(this, arguments.callee, arguments, "FBstuff");
// here continues the function code
...
}
Application Friends
Lets get list of friends using the application:
private function getAppFriends():void
{
var data:URLVariables = new URLVariables();
data.query = "SELECT uid, name, pic_square " +
"FROM user " +
"WHERE uid IN " +
"(SELECT uid2 FROM friend WHERE uid1=" + me.id + ") " +
"AND is_app_user";
var loader:URLLoader = call("method/fql.query", data,
URLRequestMethod.POST, null, "https://api.facebook.com");
loader.addEventListener(FacebookOAuthGraphEvent.DATA, onGetAppFriends);
}
private function onGetAppFriends(event:FacebookOAuthGraphEvent):void
{
var xml:XML = new XML(event.rawData);
var ns:Namespace = xml.namespace();
default xml namespace = ns;
xml.namespace(ns.prefix);
xml.ignoreWhite = true;
for each(var user:XML in xml.user)
{
user.uid.toString();
user.name.toString();
...
}
default xml namespace = new Namespace("");
}
Publishing Feeds
Publish feed with image:
public function publishPost(message:String, attachmentName:String,
attachmentDescription:String):void
{
var media:Object = {};
media.src = "http://mydomain.com/feedimage.jpg";
media.href = "http://apps.facebook.com/myapp";
media.type = "image";
var attachment:Object = {};
attachment.name = attachmentName;
attachment.href = "http://apps.facebook.com/myapp";
attachment.description = attachmentDescription;
//attachment.caption = "test caption";
attachment.media = [media];
var data:URLVariables = new URLVariables();
data.message = message;
data.attachment = JSON.encode(attachment);
call("method/stream.publish", data, URLRequestMethod.POST,
null, "https://api.facebook.com");
}
Publish feed with flash:
public function publishFlash(message:String, href:String, swfSrc:String,
mediaSrc:String, attachmentName:String, attachmentCaption:String,
attachmentDescription:String, properties:Object=null):void
{
var media:Object = {};
media.type = "flash";
media.swfsrc = swfSrc;
media.imgsrc = mediaSrc;
//media.width = "80";
//media.height = "80";
media.expanded_width = "460";
media.expanded_height = "460";
var attachment:Object = {};
attachment.name = attachmentName;
attachment.href = href;
attachment.caption = attachmentCaption;
attachment.description = attachmentDescription;
attachment.media = [media];
attachment.properties = properties; // action links
// properties {prop1:{text: "value 1", href:"http://"}, prop2:...};
var data:URLVariables = new URLVariables();
data.message = message;
data.attachment = JSON.encode(attachment);
call("method/stream.publish", data, URLRequestMethod.POST, null,
"https://api.facebook.com");
}
Publish feed with action links:
var properties:Object = {};
properties.MOVE = {
text: "mouse drag",
href:config.urlManager.boardURL};
properties.ZOOM = {
text: "double click, [Page Up], [Page Down]",
href:config.urlManager.boardURL};
properties.ROTATE = {
text: "[Ctrl] + mouse move",
href:config.urlManager.boardURL};
attachment.properties = properties;
Uploading Photo
This is a piece of working code from Sean, more upload handling functions and album creating can be found here. thnx Sean:
// MultipartURLLoader by Eugene Zatepyakin can be found here: http://bit.ly/9wx4q7
public function uploadImageCall(path:String, ba:ByteArray, message:String, token:String=null):MultipartURLLoader
{
var mpLoader:MultipartURLLoader = new MultipartURLLoader();
mpLoader.addVariable("message", message);
mpLoader.addFile(ba, "image.jpg", "image");
loaderAddListeners(mpLoader.loader);
mpLoader.load(apiSecuredPath + "/me/photos?access_token="+ token);
return mpLoader;
}
Palming Token
When localy debuging your app you may want to palm off custom access_token:
if(parameters.debug)
facebook.hackToken(parameters, "110363ABXY..."); // copypaste from callback.html hash
facebook.autoConnect(parameters);
in Facebook.as:
public function hackToken(parameters:Object, token:String):Object
{
if(!parameters.session)
parameters.session = JSON.encode({
access_token:String(token).replace(/\%7C/g, "|")});
return parameters;
}
Advanced Crossdomain Working Authorization
Or if you prefer or need advanced callback, that works crossdomain, and also for local debuging: callback.html
<!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" xml:lang="sk" lang="sk" dir="ltr">
<head>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript">
<!--
if(window.opener && window.opener.confirmFacebookConnection){
window.opener.confirmFacebookConnection(window.location.hash);
self.close();
}else{
var flashvars = {};
flashvars.connectionName = "_facebookConnector";
flashvars.methodName = "confirmConnection";
flashvars.hash = window.location.hash;
swfobject.embedSWF("flash/Callback.swf", "flash", "1", "1", "10.0.0",
"expressInstall.swf", flashvars, {}, {});
}
//-->
</script>
</head>
<body>
<p>You may now close this window.</p>
<div id="flash"></div>
</body>
</html>
universal callback.swf (741 Bytes) main class:
package
{
import flash.display.Sprite;
import flash.net.LocalConnection;
public class Callback extends Sprite
{
public function Callback()
{
super();
var parameters:Object = loaderInfo.parameters
var localConnection:LocalConnection = new LocalConnection();
localConnection.send(
parameters.connectionName,
parameters.methodName,
parameters.hash);
}
}
}
facebook.as class:
private var localConnection:LocalConnection;
override public function connect():void
{
super.connect();
if(!localConnection)
{
localConnection = new LocalConnection();
localConnection.client = this;
localConnection.allowDomain("*");
localConnection.allowInsecureDomain("*");
localConnection.connect("_facebookConnector");
}
}
private function onAuthorized(event:FacebookOAuthGraphEvent):void
{
// listener defined in Facebook constructor:
// addEventListener(FacebookOAuthGraphEvent.AUTHORIZED, onAuthorized);
try
{
localConnection.close();
localConnection = null;
}
catch(error:Error){}
}
Getting All The Photos Of All Albums Of 1 User
Credits to Etienne, thnx
function getAllphotos(uid:String):void {
var data:URLVariables = new URLVariables();
data.query = "SELECT src_small, src_big " +
"FROM photo " +
"WHERE aid IN ( SELECT aid FROM album WHERE owner='"+HERE PUT THE USER ID+"' )"
var loader:URLLoader = facebook.call("method/fql.query", data,URLRequestMethod.POST,
null, "https://api.facebook.com");
loader.addEventListener(FacebookOAuthGraphEvent.DATA, onGetAllphotos);
}