Extending FacebookOAuthGraph Class

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;
Publishing feed using Graph API (docs, from facebook bugzilla):
- forget everything related to the old “media” stuff of the attachment
- put what you had in
swfsrcinto source (mandatory) - put what you had in
imgsrcinto picture (mandatory) - link is mandatory also and must points to the connect or canvas URL
- Feed arguments: message, picture, link, name, caption, description, source
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(bytes:ByteArray, message:String):MultipartURLLoader
{
var mpLoader:MultipartURLLoader = new MultipartURLLoader();
mpLoader.addVariable("message", message);
mpLoader.addFile(bytes, "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);
}
Tagging photos
This script uses photos.addTag – part of old REST api (some more reading):
var data:URLVariables = new URLVariables();
data.pid = photoID;
data.tag_uid = userID; // user on photo we are tagging
data.x = 50; // 50% means center
data.y = 50; // 50% means middle
call("method/photos.addTag", data, URLRequestMethod.GET, null, "https://api.facebook.com");
Important: Graph API upload call returns the object_id. In order to get pid you have to lookup in photo table:
SELECT pid FROM photo WHERE object_id=response.id
Catching verify token error
In order to catch the ERROR event with verifyToken() method Nils suggested the following:
override public function verifyToken(token:String):URLLoader
{
var loader:URLLoader = super.verifyToken(token);
loader.addEventListener(FacebookOAuthGraphEvent.ERROR,
function(event:FacebookOAuthGraphEvent):void
{
_authorized = false;
_me = null;
_token = null;
EventDispatcher(event.currentTarget)
.removeEventListener(event.type, arguments.callee);
var type:String = FacebookOAuthGraphEvent.UNAUTHORIZED;
dispatchEvent(new FacebookOAuthGraphEvent(type));
});
return loader;
}
[...] read article Extending FacebookOAuthGraph Class, where all the most comon extendings are [...]
Hi, I am using you class for a app I built and it works great as a webapp and as a canvas app but when I converted it over to FBML to use in a profile tab I am stuck. How can I get the token/login without using js/externalinterface since a facebook tabbed app has no script access? It seems like I would have to do something similar to your local connection method via js bridge or something. Any help would be great!
Thanks
UPDATE:
So I figured out how to get the token using the session_key thanks to this article: http://sambro.is-super-awesome.com/2010/05/28/facebook-access-tokens-from-canvas-apps/
and then passing that token to the FacebookOAuthGraph via the verifyToken() call.
Still not sure how to set up the login/application permissions from a tabbed app. Maybe call login.php and then retry the graph call on a timer? Can’t seem to find relevent documentation for this situation. I know this should probably go on the fb forums but since its using the FacebookOAuthGraph class for all of the graph calls it’s relevant.
Hi James,
glad you managed it to work. I am not very found in tabbed apps, I am not sure what parameters are sent into your .swf by facebook. But I guess this flow may work:
1. user clicks on your tab
2. you do not have access_token you redirect him to login.php (same window)
3. user allows app and is redirected to your callback (store access_token into some persistent place)
4. redirect user back to the tab and use access_token from your persistence
Hi jozef,
I can’t find where is define call function with 4 arguments…
This question is linked to your answer of yesterday (for wich i thank you) on facebook developers forum.
Etienne.
Sorry I posted too fast,
I directly make a facebook.call and it works.
I also managed to access profile pictures album through fql querry within the good extended permission session !!!
Thank you very much Jozef for your great work.
Hi Etienne,
make sure you have latest version of FacebookOAuthGraph class, call() method has been slightly changed (backward compatible). Feel free to paste here your fql solution + extended permissions you used, with your approval I can push it into the article.
Hi JC,
universal callback.swf (741 Bytes) main class seems to be a broken link.
Can I get this to work in Flex bymyself somehow?
Thanky you.
Great articles by the way!
Hi JC, maybe I posted a little too fast.
So, I created a Callback.swf from your code by using Flash CS4.
http://edutechwiki.unige.ch/en/AS3_Compiling_a_program
Hello Jozef, very nice articles.
Do possibly know how to implement the publishPost function so that a target_id and/or uid as in the php equivalents (http://wiki.developers.facebook.com/index.php/Stream.publish) can be handed over to the function call.
I would go absolutely nuts if I could get this to work somehow!
Ben Bee, link now fixed
Hi Boris B.,
indeed it can use that method, please read section “Publishing Feeds”, … you see? Now all you have to do is add target_id/uid parameter to data variable (just like message)
Hi Jozef,
Here is the call I make to get for exemple all the photos of all albums of 1 user.
Permission needed is only “user_photos”.
function getAllphotos(uid):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);
}
Etienne.
Hi Jozef,
So I am able to publish content on the wall of specific page via data.target_id = 1234567890 (thanks a lot for pointing that out!) – unfortunately the created posts however only appear on the page itself and not within the feeds of those people who like the page (unless of course they are befriended with the poster). I figure that this must be some sort of facebook settings issue but I cannot get to it. Do you know what I am talking about??? Do you have any idea how to get the desired results?
THANK YOU SO MUCH AGAIN!
OK. So as I now understand now only the pageadmin’s wallposts should appear on the users’ walls who like the particular page. So I figure that I might need to explicitly provide the session_key as well as uid to the data object instead of the target_id. But this ain’t working out so far either. Do you have any ***** idea what I am talking about? best wishes boris!
Hi Boris B., sure I know what you are talking about, I also use posting feed on page with onboard:
1. goto http://www.facebook.com/apps/application.php?id=110363680930 and like
2. goto the app http://onboard.yoz.sk/ and click facebook btn
3. there are 2 requests send to fb: 1st with no id (goes to your feed stream), 2nd with app page id goes to app page feed stream
… you are right only the page admin’s feed goes public and that is imho good, else people could use that app to spam, think about page/app with 100.000 users… Now you may want to “hack” your session so the request goes like from page admin, I suggest to do this on backend via php sdk (while you need to send your pwd) else anyone could hack your account
Hi Jozef,
thanks for posting so fast.
Very nice app. I Like it a lot.
As I see you are doing what I want to do.
So here is what I would like to do.
I am the admin of few pages with a lot of users.
So I naturally want to use my app to post to these pages – meaning that I want the app to post one of the pages wall and (thereby) post to the wall of all the people who like that page. Just like it would be the case if I as the admin would make a post on that page. Do I really need some sort of backend to provide a pw for this or is there another way to work this. And if I need some sort of extra authorization to demonstrate fb that I am the admin could you possibly be so kind and maybe give me some sort of advice on how to get there?
thank you very much for any thoughts or words of advice.
best wishes from germany,
Boris
@Boris B.
thnx,
I see what you are up to, but I have never done that… Anyway here is my idea:
1. make your app requring offline_access – this permission makes the access token returned by OAuth endpoint long-lived… not sure how long, maybe month maybe even longer
2. grant your app this permission while logged as admin and save generated access_token
3. prepare backend (php + curl) that would call the api with your saved access_token.
you can not make this token public because one could use it to harm your account, thats why you have to make calls from backend to facebook
Hi Jozef?
(is ur name Jozef?)
I am a flash developer from Singapore and I really want to drop a message and say a big thank you to you for what you have shared.
They have been so helpful!
Cheers!
Hi Terrence, yes my name is Jozef, I am glad you find it useful
Hi Jozef
In “Publish feed with flash” should the last line:
call(“method/stream.publish”, data, URLRequestMethod.POST, null, “https://api.facebook.com”);
be:
facebook.call(“method/stream.publish”, data, URLRequestMethod.POST, null, “https://api.facebook.com”);
Sorry, forget it. Nothings wrong
Hi Jozef,
I am wondering how to handle FB users as objects (as I did before the new API).
In particular getting and handling somebody’s friends, their account info and some additional app specific stuff can become a real mess if one has to extract the relevant information from seemingly endless strings.
Further on we are planning to save the user objects via remote. Do you have any sort of advice?
Thanks a lot.
Sam
@Sam the returned “string” is JSON, it is serialized object/array/values that is accessible like this:
// call(“me”)
private function callComplete(event:FacebookOAuthGraphEvent):void
{
trace(event.data.name);
trace(event.data.work[0].employer.name);
}
search for “JSON” in this article http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/
Hello,
I don’t know why, but http://apps.facebook.com/blogoauthgraph/ no longer works. Do you know if Facebook could changed some things?
Thanks for your feedbacks.
@Garcimore, yes, there have been some changes, please read:
http://blog.yoz.sk/2010/07/neverending-facebook-api-change/
thank you for noticing the changes
Hi,
Is it possible to include action links with our published feeds?
Thank you.
Koray
@Koray Hi, indeed it is. I have just updated the article, please read section “Publish feed with action links”
Thank you Jozef for your extremly fast response !!!
Facebook is also very fast in their changes :-s … Without notification, they have add a new option (automatically selected) for Facebook application configuration (in “migration” tab) to add a session information (that had deseapear yesterday…)
Your code works always ! It’s just for information.
Thanks.
Thank you Jozef
Hi Jozef,
Thanks for these wonderful articles. You really made my life so simple. Please keep up the good work.
Hey I had a small doubt on the publish stream example above. Suppose I want to prompt user for confirmation just before publishing the feed. May be a pop up window where user can add his personal comments before the feed is published on the wall.
Is it possible to do it with any simple modification in your example?
Koray, Amit you are welcome
Amit, I do not use facebook javascript sdk in my class so there is no method you could call to open the default publishing popup. However, you can create your own UI with text input and custom graphincs…
hi jozef i have some problems with uploading a picture to a specific album could you help me? here my code:
var jpg:JPGEncoder = new JPGEncoder();
var upImg:UploadImage = new UploadImage();
var obj1:Object = { byteArray: jpg.encode( bitmap ), fileName: TunnelConfig.baseUrl + “tunnelImages/images/” + box.userImageId.toString() + “.jpg”, imageTitle: box.userImageId.toString() + “.jpg”, message: “tunnel”};
var obj2:Object = { title: “Album: Tunnel ins Gesicht”, description: “Deine Freunde mit einem Tunnel im Gesicht”};
upImg.uploadImage( “Album: Tunnel ins Gesicht/photos”, obj1, obj2);
i tried to change “Album: Tunnel ins Gesicht/photos” to aid + “/photos” ( aid is the id from the album ), too
hi David, what library/sdk do you use? I do not find familiar any of these classes: UploadImage, TunnelConfig
hi jozef i’m using the UploadImage from http://blog.yoz.sk/examples/FacebookOAuthGraph/as/uploadImage.as and i’m using flash. In TunnelConfig is just a static link to the server where the images are.
i even tried to upload a image this way:
facebook.call( aid + “/photos”, dataObject, URLRequestMethod.POST );
but i’m getting a 500 Internal Server Error ? don’t know what i’m doing wrong
hi jozef, ^^ i got it to work with your / Seans Multiuploader Example
PS: This Page is realy awesome kepp it on
Hi Jozef. Thank you for all the great and helpful info. I was wondering if you could tell me if it’s possible to submit an array of friends’ ids to invite them to your application? I made a custom friend selector for a Flash site outside Facebook and want to be able to invite the selected friends to the application. I was thinking there might be a way via javascript or php request. Any help would be much appreciated. Thanks so much!
hi @gina, it is not possible to invite friends via api, you have to use FBML – Fb:request-form, please read http://blog.yoz.sk/2010/03/inviting-friends-into-facebook-application/
Hi Jozef,
Thanks for all these posts, they really mean a lot to all of us !
I ‘ve been toying with your OAuthGraph and I’m starting to build a framework around it (a bit similar, but far less advanced, to the one Adobe released), I’d be happy to share some of it later on…
the problem I’m facing is with your advanced crossdomain approach for local development.
I can’t make the callback work like intended. It seems the javascript breaks on :
if(window.opener && window.opener.confirmFacebookConnection)
When testing locally the script never makes it to the ‘else’ statement. Maybe you’ve seen this before, I really can’t get my head around it…
The only way I can make it work is to leave the if else out of there, and always embed the swf…
Thanks anyway for all the advice !
You may now close this window.
Hi Dmonkey, thank you
there were some reports that javascript in callback.html does not get executed correctly on macs:
http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/#comment-1779
is that your case?
Hi Jozef.
I’m trying to find out a way to logout / catch a logout using your method.
openGraph documentation explain how to do the connection / authentification, but i cannot find anything on disconnect / logout.
Have you ever test it ?
Thank you
Hi @daweed, please read http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/#comment-2001 and other comments containing “logout” phrase
Thans Jozef.
[...] Extending FacebookOAuthGraph Class [...]
[...] Facebook Graph API & OAuth 2.0 & Flash (update) Extending FacebookOAuthGraph Class [...]
Hey Jozef great job you did here.
I was wondering how can i make fql multiqueries? Here is whta i try
data.queries = {“links”:”SELECT title, summary, url FROM link WHERE owner = “+uid+” limit 10″,”infos”:”SELECT name, pic FROM user WHERE uid=”+uid};
and then the call
var loader:URLLoader = facebook.call(“method/fql.multiquery”,data,URLRequestMethod.POST,……
It seems like they is a problem with my queries, the way that i format the data. i’m confused. Has anyone tryed.
I have several calls to make, so if i could do everything in only on call, with only one json at the end.
Hi @meda, you should post url variables as string, the docs sais “method takes a JSON-encoded dictionary called ”queries”” … so I guess:
data.queries = JSON.encode({“links”:”SELECT title, summary, url FROM link WHERE owner = “+uid+” limit 10″,”infos”:”SELECT name, pic FROM user WHERE uid=”+uid});
… should work
Ok and thanks for you’re real quick answer i only had the time to compile once.
I’ll qive it a try.
It WORK GREAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!
That made my day.
Thanks man
hi Jozef,
thanks for your awesome posts.
i was wondering if there is a Flash (.fla) example available how to post a bitmapData attachment to Facebook via the class.
thanks,
Tom
Hi @Tom, Uploading a photo upload should not be a problem with fla application, steps:
- copy the code from “Uploading Photo” section of this article
- convert BitmapData to ByteArray via jpeg encoder ( http://blog.yoz.sk/2009/10/bitmap-bitmapdata-bytearray/ )
- you can only upload bytes when uploading a photo into photo album, you can not upload bytes with feed stream
I am trying to use this class to build an app that will run in a standalone website (ala Facebook Connect). We had this working with the old API, but now I seem to keep running into problems.
The problem I;m running into now has to do with getting the connection to work in the first place.I have followed your instructions for getting the access token from the callback.html, and then pasting it into the app manually, but everytime I run the app, I get the following error:
{
“error”: {
“type”: “OAuthException”,
“message”: “Invalid access token signature.”
}
}
This is the URL it’s trying to hit:
https://graph.facebook.com/me?access%5Ftoken=127166517335601%7C2%2EyLHY7i30y5M3iVDNm2fzlQ%5F%5F%2E3600%2E1285120800%2D1145997626%7CMB5%5F7cYO49NhqQ7m0on1MV3wjlw
Here is the code I have in my app:
http://pastebin.ca/1946244
Help please.
@Adam,
are your facebook application settings correct? http://blog.yoz.sk/examples/FacebookOAuthGraph/settings.png
@Jozef,
Thank for the great work!
I’m very new to whole api so there are a few things that threw me off about your uploading example.
Just so you know this blog has helped me learn how to do basic calls like me/image, me, me/feed, so no need to cover that.
But none of the examples for here uses the token or the apiSecuredPath which show up in your example uploadImageCall method.
Could you give more details about how to use your uploadImageCall method. I know how to encode the ByteArray and the message is easy to figure out, but why do I pass a path if me/photos is already in the call and where do I get the token and apiSecurePath from?
Thanks for everything.
- Josh Chernoff.
hi @Josh
the process is very easy, the class can use apiSecuredPath or apiUnsecuredPath (unsecured only allowed by facebook API for calls without token). By defining FacebookOAuthGraph.useSecuredPath=true you make default the secured one. Later in FacebookOAuthGraph.call(), the secured one is used if you do not specify different (you can force the unsecured by setting apiPath as 5th argument)… so if you do not specify 5th argument of call() method, the engine takes care becasue the call() is a part of FacebookOAuthGraph class.
Now you are able to construct your own fully-customized requests, like the one with MultipartURLLoader.load(). If you wrap this process inside some method that takes care of apiPath by itself you dont have to specify it with your requests anymore.
- the token you receive from facebook and is accessible via FacebookOAuthGraph.token
- apiSecurePath, apiUnsecuredPath are predefined variables in FacebookOAuthGraph
Hey @Jozef.
I got it working now, thanks for your help.
One thing that I just read that is kinda disappointing is the I cant set Likes. Any details you know why that is?
Thanks again
- Josh C
@Josh, yes like button is pain… there is no “Like” method in current API
Hi Jozef, after anything i wanna apologie for my english. Im from Argentina, so I will try to make me understand.
I have a problem with de upload photo. When i call to the UploadCallImage the first time its doesnt seem to work, buy if i execute it again it works… but upload two image intead of one.
Do you know wich could be the problem?
The link to test it is http://www.busymindstudio.com/fb/
Thanks for all!!
Great great great work
Marco
Hi Marco,
does it throw any flash exception / server exception? what exactly do you mean by “doesnt seem to work”
can you debug the process up to where it fails? does the request to facebook execute (see in proxy)?
just thinking … may it be some delay in facebook that shows your photoalbum few seconds later after creating?
Hi Jozef,
I have a problem in the application when other users
seeking access to it, this message appears when they
attempting to access the application: “You may now close this
window. “strange thing is that to me connecting perfectly. I could guide it happens.
Hi MauroX, I guess this is the case when popup windown does not close. It has been reported as safari issue, please read comments on http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/ – search safari
Hi Jeff,
This is the same thing from here http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/ but with best practices right?
I need to send my application settings to this instance like this?
var facebook:Facebook = Facebook.instance;
facebook.clientId = clientId;
…
Just one more thing: when developing i want to test my app locally, is this possible? If i can, what variables do i need to fill?
I know i need this ones:
clientId
redirectURI
permissions
What about this line: facebook.autoConnect(parameters)?
Thanks once again!
PS: You should make available some donation account for guys like me thank you for the help with a little extra money.
Hi PVieira, in fact you are right, here are some code that can be used with FacebookOAuthGraph. You can develop it locally, just read the section “Advanced Crossdomain Working Authorization”, you gonna need the same values as for real released version (just change callback.html and add callback.swf)
if you grant offline_access for your app, facebook.autoConnect(parameters) will sign you in automaticaly, else pls read:
http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/#comment-3269
PS: thank you for the donation tip, I am considering that, but you know, just do not want to look like I am doing it for money = bitch
Hi again.
Having some problems with this local thing..
When i click “allow” in this authorization window, this should redirect to my local file of callback, right? So, where do i define this local path? I’ve tried in my html wrapper but it keeps showing me this message: “redirect_uri isn’t an absolute URI. Check RFC 3986.”
And i don’t understand why we need this callback.swf locally. Couldn’t be the app redirected to my hmtl wrapper again?
PS: I think that anybody would think that from someone who was so available to the community.
Hi PVieira.
Facebook will redirect you to your public domain only. Setup correctly domain for your facebook app and make your redirect to that domain. When facebook redirects you to the advanced callback, the callback.swf passes token into your main app via LocalConnection… you can not use javascript because your main app is local and popup is on some domain (XSS)
Is it possible to upload photos to a page album, instead of a profile?
@PVieira, sure, just change the uid in url (…/me/…) for the album id (…/12345/…)
Hey Jozef,
I want to implement your code on my Facebook connect page.
How do I get the user id, after somebody connected to facebook from my page?
regards,
daniel
@Daniel, you do mostly do not need user ID when using graph api, because you can use “me” … e.g. https://graph.facebook.com/me/friends… etc. In order to get your id you can call https://graph.facebook.com/me
@Jozef:
Okay, got it working with this URLRequest: ‘https://graph.facebook.com/me?access_token=’+ _token
Put a getter Method in the facebook class which returns the token.
Fine!
But now I have a strange issue.
Your example is working totally fine if I execute it locally on my computer, connects and upload a picture to my facebook account.
But if I put the .swf + .html on a server, the swf does not register that I am connected to facebook, and when I click on the init button, the callback windows opens, but the swf does not get a connection and the window message remains “… connecting”.
Do you have any idea why this is so? crossdomain.xml issue?
cheers,
daniel
@Daniel,
you do not need token at all… it is assigned into all your requests via call() function
the issue with connection: does your redirect url targets the same domain as your main .swf file? if no, you have to use advanced callback… read “Advanced Crossdomain Working Authorization”
Hi Josef,
As I can do that every time you enter my site and connect to the Facebook
user having to login. I put in the Token Null and False the Authorize,
but whenever I connect if I am once again enter the site
automatically logs and do not want to happen. Any suggestions.
Hi MauroX,
please read FAQ here:
http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/
“When I connect with this app in one browser (firefox), and I run another browser (chrome) I get automatically connected. Why?”
logout function may look something like this:
http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/#comment-2001
Hi,
i have this Code Snippet directly inside my Facebook Singelton and execute it during first initialisation. I thought the alert wouldn’t be fired, if I run my app on facebook, but yet it is. Is this an error on my side / app?
var parameters:Object = FlexGlobals.topLevelApplication.parameters;
if(!parameters.session) {
Alert.show(“Taking static token”);
parameters.session = JSON.encode({access_token:FacebookSettings.TOKEN});
}
autoConnect(parameters);
Greeetings,
Se
hi SeDev,
what is the FacebookSettings.TOKEN value? Is it valid token, requested by using “offline_access” permission? You have to palm there a valid one, use hackToken method on order to fix some characters withind token string
hello Jozef, in
Advanced Crossdomain Working Authorization where do i put facebook.as class. can i copy these lines of code to http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/
code like
function init(){
if(!localConnection)
{
localConnection = new LocalConnection();
localConnection.client = this;
localConnection.allowDomain(“*”);
localConnection.allowInsecureDomain(“*”);
localConnection.connect(“_facebookConnector”);
facebook.clientId = clientId;
facebook.redirectURI = redirectURI;
facebook.scope = scope;
facebook.useSecuredPath = true;
facebook.addEventListener(FacebookOAuthGraphEvent.AUTHORIZED, authorized);
}
}
function authorized(event:FacebookOAuthGraphEvent):void
{
connected = true;
log.text += “authorized\n”;
try
{
localConnection.close();
localConnection = null;
}
catch(error:Error){}
}
facebook.as is a new class??
shammi, Facebook class is recommended singleton extending FacebookOAuthGraph. Read the whole article from the beginning. You are not using any namespace with your functions I guess you are working on timeline of Flash CS authoring tool. its not very good to mix OOP with timeline code …
Hi Josef,
I would like to learn how you can make a tag of a person in a photo from an album that I believe in facebook from my application. Not if you understand me?
Hi MauroX,
you have to use REST api method for this “photos.addTag”
http://developers.facebook.com/docs/reference/rest/photos.addTag
call(“photos.addTag”, data, URLRequestMethod.GET, null, “https://api.facebook.com”);
where data is an object consisting of: pid, tag_uid, tag_text, x, y, callback, tags, owner_uid …
Hi Josef, not whether it be too much trouble, but I wanted to ask a more clear example
how to tag a photo. I’ve been researching and have not achieved a tag.
MauroX:
var data:URLVariables = new URLVariables();
data.pid = photoID;
data.tag_uid = userOnPhotoID;
data.x = 50; // 50% means center
data.y = 50; // 50% means middle
call(“photos.addTag”, data, URLRequestMethod.GET, null, “https://api.facebook.com”);
with official as fb api you could do that just like:
var call:FacebookCall = fbook.post(new AddTag(pid, fbook.uid, “”, 50, 45));
call.addEventListener(FacebookEvent.COMPLETE, tagPhotoComplete);
this is my code:
var data:URLVariables = new URLVariables();
data.pid = “4559295470510948230″;
data.tag_text = “Test Tag”;
data.x = 200;
data.y = 200;
var loader:URLLoader = super.call(“photos.addTag”, data, URLRequestMethod.GET, null, “https://api.facebook.com”);
loader.addEventListener(FacebookOAuthGraphEvent.DATA, tagged,false,0,true);
which could be the problem?
I try
var call:FacebookCall = new AddTag(“4559295470510948230″, _meId, “”, 50, 45);
call.addEventListener(FacebookEvent.COMPLETE, tagPhotoComplete);
but not works.
MauroX, you can not have 200×200, it is not pixels! its percent values. in the middle means 50, 50, read the docs… anyway, what is the response from facebook?
Hi Josef,
Here my problems i hope you can help me.
http://www.megaupload.com/?d=JGO58FM3
This link has a. Rar that has three pictures with the problem of Tag,
what a shame so much trouble.
MauroX it seems like you are getting 404 (Not Found) response it means there is some mistake in the url … based on doc you should use:
https://api.facebook.com/method/photos.addTag?
access_token=…
so try changing the first parameter into:
super.call(“method/photos.addTag”
it is enough for me to see the request+response headers+content, no images required
WOW man Thanks you are the best
Hi Jozef
Thank you for all your great articles!
Just a little update, for “Catching verify token error”
there need to be:
return loader;
at the end of the script.
Danila, thnx fixed
Hi Joz, first of all thanks for your classes, thay have helped me a lot!
I’m currently struggling with uploading a Photo and adding a tag to that photo after it has been uploaded but I’m getting an error.
When the upload is complete it returns me the following json:
{
“id”: XXXXXXXXXX
}
Then I try to add a tag this way:
var respuesta:Object = JSON.decode(evt.currentTarget.loader.data);
var data:URLVariables = new URLVariables();
data.pid = respuesta.id;
data.tag_uid = MovieClip(root).arrImagenes[j].fbId;
data.x = 50;
data.y = 50;
var call:URLLoader = MovieClip(root).facebook.call(“method/photos.addTag”, data, URLRequestMethod.GET, null, “https://api.facebook.com”);
The response this call is giving me is:
Invalid photo id
Do you know how to build a valid photo id based on the id returned by facebook graph API?
Thank you so much.
The funny thing is that calling the graph api with the photo id returned by the upload does show me the information of the uploaded image.
Juan, if you are really using correct photo id and have correct permissions (user_photos), it sounds like a facebook issue. You should fill a bug in http://bugs.developers.facebook.net/
Hi Jozef, thanks for your response, it turns out that the Graph API upload call was returning the object_id so I made a query to the photo table with that object_id to get the pid, something like:
“SELECT pid FROM photo WHERE object_id=”+respuesta.id
Now my code is working fine.
Thanks again for taking the time to answer all our questions!
Hi Juan, thanks for letting me know. I am updating the article with this stuff
Hi Josef,
You can upload a video to the user on Facebook and how you can post messages to the wall of friends from the Graph API.
MauroX you can upload videos using this method:
http://developers.facebook.com/docs/reference/rest/video.upload (REST api)
posting messages to friends: /PROFILE_ID/feed more here:
http://developers.facebook.com/docs/api
Hi Josef,
The documentation on the method video.upload and had this, I
concern is the note on the REST API. Try to make it equal to the image upload
you did, but I understand it complicates. I hope you can make an example
with this issue. I code in JavaScript to send a post to friends and
works, this is the code:
directShare function (MyPerson, phrase, image, link) {
wall_post = {var
name: “Test Name MauroX Java Script”
message: “TEST POST PICTURE”
picture: Image
link: Link
description: “DESCRIPTION”
caption: “Caption”
actions: {name: “MauroX” link:
“Http://www.quatiodevelopments.com/TestFacebook/”}
}
/ / Alert (‘Object’ wall_post)
FB.api (‘/’ MyPerson ‘/ feed’, ‘post’, wall_post,
function (response) {
if (! response | | response.error) {
alert (“error occurred:
“Response.error)
Else {}
alert (“Successful Posting”);
}
});
}
But I like to do in Flash and do not know how to make this call:
FB.api (‘/’ MyPerson ‘/ feed’, ‘post’, wall_post,
function (response) {
if (! response | | response.error) {
alert (“error occurred:
“Response.error)
Else {}
alert (“Successful Posting”);
}
});
Thank you very much for all your contributions.
hi MauroX,
make sure you read this whole article. especialy section “Publishing Feeds”
Hi Jozef,
Great class, thanks for this, we’ve been using PHP solution for FB apps, but I think we’ll start using your solution from now on!
Have one question though..
It’s about autoconnect function.. It has a event callback : “AUTHORIZED” when the user get’s successfully authorised. Is there a callback when autoconnect couln’t authorise the user ?
I’ve tried almost everything.. adding UNAUTHORIZED event to facebook instance, DATA event – none of the them get called on autoconnect fail..
Also tried adding listeners to URLLoader instance returned from facebook.autoconnect (DATA, COMPLETE) no luck..
Any idea how to solve this ?
Thanks.
Hi Slavo,
I like to hear that you like it. I hope we can fix the issues now…
there is an autoConnect() function that can take parameters (flashvars):
- if parameters contains session and access_token the lib tries to verifyToken()
- if it does not containt session lib uses token stored in sharedObject to verifyToken()
verifyToken() creates URLLoader contacting facebook to see if the token is valid:
- if the response is valid verifyTokenSuccess() is called dispatching AUTHORIZED on FacebookOAuthGraph instance
- if the response is not valid there is no handler for this by default. you can extend verifyToken() function to receive error events over URLLoader…
I am just reading that you are already able to handle events here (on autoConnect()), so what you have to do is, listen for HTTPStatusEvent and IOErrorEvent. I believe facebook responses with error when the authorization fail, that is why you failed with catching it like Event.COMPLETE
Jozef:
IOErrorEvent.IO_ERROR did catch the autoconnect fail. Thanks for your help!
I try the crossdomain solution, but FlashPlayer always return an error:
#2082: Connect failed because the object is already connected.
PS :
thanks for this great class !
Jerome, you can not establish 2 LocalConnections with the same connectionName. make sure to close my blog or any other flash that may collide with your app
Hello again Jeff!
Tell me something, we still can’t invite friends to use the application?
If you can’t, is there any way to send a message, event or something similar to some id (writing the invitation there)?
Cheers
When i say we can’t invite friends, i mean without using that standard FBML code.
Hi PVieira,
see http://blog.yoz.sk/2010/03/inviting-friends-into-facebook-application/ for inviting friends, there is no other option
Thanks Josef, i will try to use the light popup (i want to integrate this feature in a existing app).
Hi Josef,
I have a problem using the method video.upload, that parameter should not go to [no name]- data – The file for the video data. This is a ByteArray? I hope you can help as facebook returns me this error “error_code”: 7, “error_msg”: “This method must-run on api-video.facebook.com. If possible an example on using this method would be helpful. Thank you for your attention.
Hi Garo,
based on documentation you have to make video upload calls to http://api-video.facebook.com use MultipartURLLoader (see “Uploading Photo”) to insert bytes into request content
Hello,
As Garo’m confused when trying to upload video to Facebook, this is my code:
First call the method this way:
var file: FileReference = FileReference (event.target);
trace (file.dat is ByteArray);
/ / Video Uploader
face.uploadVideoCall (file.data, “Video Test”);
UploadVideoCall function is this:
public function uploadVideoCall (bytes: ByteArray, message: String): void
{
trace (“Video UPLOADER”);
var mpLoader: MultipartURLLoader MultipartURLLoader = new ();
mpLoader.addEventListener (Event.COMPLETE, onMultiPartVideoLoader, false, 0, true);
mpLoader.addVariable (“message”, message);
mpLoader.addFile (bytes, “Video.flv”, “Test Video”);
super.loaderAddListeners (mpLoader.loader)
trace (“String GRAPH API:” + apiSecuredPath + “/ me / videos? access_token =” + _token)
mpLoader.load (apiSecuredPath + “/ me / videos? access_token =” + _token)
}
onMultiPartVideoLoader private function (e: Event): void {
trace (“Upload Sucefull)
}
The error I get is:
Error # 2044: uncontrolled ioError: text = Error # 2032: Error sequence. URL:
https: / / graph.facebook.com / me / videos?
access_token = 127807137233234 | 2.gDyuwi_sPsqbg2QBkgE6tg__.86400.1292518800-
1061543699 | U7XoBuXfxiDo0xhONxVQzpoCsxU
Josef could tell me where I am failing to solve this problem.
In this case, that part is not using the method “video.upload” because in this way was like I got a facebook pictures and it works, I think the method used in this case is this http://developers. facebook.com / docs / reference / api / video, seeing the image works with this http://developers.facebook.com/docs/reference/api/photo honestly I feel very lost on this problem I hope suggestions.
Hahahaha, MauroX I did this:
var file: FileReference = FileReference (event.target);
face.uploaderVideo (face.uploadVideo (file.data, “Video”));
Wherein the method UploaderVideo:
uploaderVideo public function (data: MultipartURLLoader): void {
trace (“Data:” + data);
var data: URLVariables URLVariables = new ();
data.dat = data;
data.title = “Video Title”;
data.description = “Video Description”;
var loader: URLLoader = super.call (“method / video.upload”, data, URLRequestMethod.GET, null, “http://api-video.facebook.com”);
loader.addEventListener (FacebookOAuthGraphEvent.DATA, videoComplete, false, 0, true);
}
videoComplete private function (event: FacebookOAuthGraphEvent): void {
trace (“Video Complete”);
}
This is the Method of Josef Upload Image modified to Video:
public function uploadVideo (bytes: ByteArray, message: String): MultipartURLLoader
{
var mpLoader: MultipartURLLoader MultipartURLLoader = new ();
mpLoader.addVariable (“message”, message);
mpLoader.addFile (bytes, “videos.flv” “videos”);
super.loaderAddListeners (mpLoader.loader)
mpLoader.load (apiSecuredPath + “/ me / videos? access_token =” + _token)
mpLoader return;
}
And I came out the following error:
Security Sandbox Error.
Well, I managed to repair the problem that i had to type IOError, Facebook has managed to answer me upload the video to Facebook, but
review and did not. And started to lose hope jajajajaja.
Hi Josef,
I think here I come … This code is supposed to upload a video to Facebook,
//Call Video Graph API
public function uploadVideoCall(bytes:ByteArray, message:String):void
{
trace(“Video UPLOADER”);
var mpLoader:MultipartURLLoader = new MultipartURLLoader();
mpLoader.addEventListener(Event.COMPLETE,onMultiPartVideoLoader,false,0,true);
mpLoader.addEventListener(IOErrorEvent.IO_ERROR,onMultiPartVideoLoader,false,0,true);
mpLoader.addEventListener(ProgressEvent.PROGRESS,onMultiPartVideoLoaderProgress,false,0,true);
mpLoader.addVariable(“message”, message);
mpLoader.addFile(bytes, “Video.flv”, “Test Video”);
super.loaderAddListeners(mpLoader.loader);
mpLoader.load(apiSecuredPath + “/me/videos?access_token=”+ _token);
}
private function onMultiPartVideoLoader(e:Event):void{
trace(“Sucefull Upload: “+e.currentTarget);
}
private function onMultiPartVideoLoaderError(e:IOErrorEvent):void{
trace(“IO ERROR: “+e.currentTarget);
}
private function onMultiPartVideoLoaderProgress(event:ProgressEvent):void{
trace(“\n” + event.bytesLoaded + ” bytes de ” + event.bytesTotal + ” bytes subidos.”);
}
///////////////////////////////////////////////////////////////////////
the problem is that I receive Uploaded response, but does not really. I think the problem is due to deliver a missing parameter type, but honestly not which is (I tried uploading a picture and works perfectly using this code and only changing mpLoader.load (apiSecuredPath “/ me / photos? access_token =” _token)) I have read and found that it is possible that this method or called in facebook is bad, I like me’d say if it’s true or not the video upload is still not well done on facebook. I await your response and I apologize for so much spam
MauroX, Garo hi guys
I really think you should use old rest api method for now for this. read
http://developers.facebook.com/docs/reference/rest/video.upload
what you should do is to use the proper arguments with the request resulting in something like this:
mpLoader.load(“http://api-video.facebook.com/method/video.upload”);
I could not remove this error, any ideas?
*** Security Sandbox Violation ***
Has stopped connecting to http://api-video.facebook.com/method/video.upload
- not permitted from
http://www.quatiodevelopments.com/TestFacebook/FacebookMauroX.swf
Security Error: Error # 2048: Security Sandbox Violation:
http://www.quatiodevelopments.com/TestFacebook/FacebookMauroX.swf can not
load data from http://api-video.facebook.com/method/video.upload.
Hi Josef,
I tried everything:
This is my Cross Domain:
Also I’ve put
Security.loadPolicyFile (“https://graph.facebook.com/crossdomain.xml”);
but nothing … this is what I’ve read, but I failed to take this error:
http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html # _Findi
ng_and_Fixing
http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm
? context = LiveDocs_Parts & file = 00000349.html
http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html
if you got any suggestions, I appreciate.
MauroX, it really seems like there is an restrictive crossdomain on:
http://api-video.facebook.com/crossdomain.xml
so you will only be able to test it when running debug build from your local… what you should do is to try everything works there, and than make server side proxy using php or something you are more familiar with:
http://efreedom.com/Question/1-3257729/Uploading-Video-Old-Facebook-REST-API
Hi again Jeff.
I’m thinking about this method to post to wall and i was wondering: it’s only possible to post to the current user wall? Is not possible to post to his wall and to some page (for example the app profile page)?
Cheers!
Hi PVieira,
check out
http://blog.yoz.sk/2010/06/extending-facebookoauthgraph-class/#comment-2336
and other material over this article with “target_id”
Hello Jozef
Thanks for your great blog!
Here is my problem :
The html page that wraps the swf is in domainA.com and declared in the facebook app, but the swf is in domainB.com (caching server, cdn with transparent redirection). When I try to connect to facebook, the auhorisation fails. Any idea?
P.S. When the html and the swf are in the same domain, everything worksfine…
Thanks for your help!
Here is the link:
http://www.monstromatic.com/bin/index.html
@Ben,
I can see you defined .swf script access for crossdomain for both .swf files, as well as localconnection name with underscore correctly. Popup opens and closes by itself (however I am not able to find close command in javascript – maybe injected from callback.swf?) … I can also see the redirect from facebook to
http://www.monstromatic.com/bin/callback.html#access_token=***********&expires_in=4560
so window.location.hash should contain correct info… I believe there is some issue with handling hash value in your flash. You should debug that
Hi – I’m able to authorize in my flash only app using your great code – dumb question tho – I have this return object where I can get first name , last name like so
var obj:Object = event.currentTarget.me as Object;
_firstname = obj.first_name;
_lastname = obj.last_name;
I’m confused about how to get access to the profile pic of the user tho – when i try the callComplete portion of the code – a status update gets posted but the result is event.rawdata is not recognized as a ByteArray – any idea what I might be doing wrong?
Cheers
mike, you can not access ByteArray without correct crossdomain.xml hosted on facebook domains, please follow:
http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/#comment-2450 or other comments and responses containing “profile picture”
Hi Jozef Chúťka,
I could post on authenticated user’s friends wall successfully only when the pop-up window (normal callback.html) closed automatically. Firefox and crome browsers are able to close the callback.html after authentication, but Internet explorer unable to close the callback.html automatically.
please suggest !
I would also like to know the purpose of Advanced callback.html
-Gopi
Hi Gopi,
In order to make calls to api you need a token. When you authorize your app in popup, the token is pushed in the last step into callback.html. Now callback.html hast to push it back to your main app (via javascript-simple or LocalConnection-advanced callback). It it succeed with sending the token to the main app, it tries to close itself using javascript window.close() method. Could you somehow debug the issue with IE and send some report where the javascript fails?
Hi, Jozef..
Please, i used the photo uploading code through the graph API but i don’t know how i used it in my project..
can you send me the step by step code for this with file names in which i have to update the code..
hi Vaishali
have a look at “Uploading Photo” section. copy and paste the conde into your Facebook class (extends FacebookOAuthGraph). you may be missing MultipartURLLoader dependency, you can download it from internet. everything else should be selfexplanatory
Hi Jozef
Great Job. Tanx. When I try to Publishing Feeds, all data is posted beside the image. No image is posted. I followed your code “as is”. Please advice.
Hi Ronen,
It may be caused by deprication of the rest api stream.publish ( https://developers.facebook.com/docs/reference/rest/stream.publish/ ) is replaced by graph api /feed … read section “Publishing feed using Graph API (docs, from facebook bugzilla):” in this article