Dec
08
2010

 

The guide below is an extension of this tutorial:
http://www.permadi.com/blog/2010/12/using-facebook-open-graph-api-in-flash-as3/.

The function to get your profile picture is
[c]
Facebook.getImageUrl(uid);
[/c]

Where uid is the Facebook user id.

Once you establish a Facebook connection, your user id is available at Facebook.getSession().uid. So we can call:
[c]
Facebook.getImageUrl(Facebook.getSession().uid);
[/c]
This will give you the URL which ‘theoretically’ you can ask a Loader object to load the picture. But, are you tired of getting this error when loading a picture (such as your profile picture) into a swf?

[c]
SecurityError: Error #2122: Security sandbox violation: 
Loader.content: http://yourdomain/your.swf 
cannot access http://static.ak.fbcdn.net/rsrc.php/zo/r/UlIqmHJn-SK.gif?path=https%3A%2F%2Fgraph%2Efacebook%2Ecom%2F100001729250263%2Fpicture. 
A policy file is required, but the checkPolicyFile flag was not set when this media was loaded.
[/c]

In the old API, you can solve this by loading the crossdomain.xml file manually
[c]
Security.loadPolicyFile("http://profile.ak.fbcdn.net/crossdomain.xml");
[/c]
Or by assigning LoaderContext and tell it to load the policy file.

[c]
	var loaderContext: LoaderContext = new LoaderContext();
	loaderContext.checkPolicyFile = true;	
	loaderContext.securityDomain=SecurityDomain.currentDomain;
[/c]

None of them works with http://static.ak.fbcdn.net/ because it turns out that the crossdomain.xml in http://static.ak.fbcdn.net/ looks like this (December 2, 2010):

[c]
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="s-static.facebook.com"/>
<allow-access-from domain="static.facebook.com"/>
<allow-access-from domain="static.api.ak.facebook.com"/>
<allow-access-from domain="*.static.ak.facebook.com"/>
<allow-access-from domain="s-static.thefacebook.com"/>
<allow-access-from domain="static.thefacebook.com"/>
<allow-access-from domain="static.api.ak.thefacebook.com"/>
<allow-access-from domain="*.static.ak.thefacebook.com"/>
<allow-access-from domain="*.static.ak.fbcdn.com"/>
<allow-access-from domain="external.ak.fbcdn.com"/>
<allow-access-from domain="*.static.ak.fbcdn.net"/>
<allow-access-from domain="external.ak.fbcdn.net"/>
<allow-access-from domain="www.facebook.com"/>
<allow-access-from domain="www.new.facebook.com"/>
<allow-access-from domain="register.facebook.com"/>
<allow-access-from domain="login.facebook.com"/>
<allow-access-from domain="ssl.facebook.com"/>
<allow-access-from domain="secure.facebook.com"/>
<allow-access-from domain="ssl.new.facebook.com"/>
<allow-access-from domain="static.ak.fbcdn.net"/>
<allow-access-from domain="fvr.facebook.com"/>
<allow-access-from domain="s-static.ak.facebook.com"/>
<allow-access-from domain="www.latest.facebook.com"/>
<allow-access-from domain="www.inyour.facebook.com"/>
<allow-access-from domain="s-static.ak.fbcdn.net"/>
</cross-domain-policy>
[/c]

It doesn’t look like the policy allows external domains, that’s why you get the exception.

As a side note, here’s how the crossdomain.xml should looks like (from
http://profile.ak.fbcdn.net/crossdomain.xml , if you have used the OLD Rest API you might recognize this URL):

[c]
<cross-domain-policy>
<allow-access-from domain="*"/>
<site-control permitted-cross-domain-policies="master-only"/>
</cross-domain-policy>
</pre>
[/c]

Rather than relying on the cross-domain, the more reliable solution is to write a proxy loader on your own server which loads the image for you. Here's an example using PHP that loads the actual image then sends is to the SWF.

[c]
<?php
$path=$_GET['path'];
if (stristr($path, "fbcdn.")==FALSE && stristr($path, "facebook.")==FALSE)
{
echo "ERROR";
exit;
}
header("Content-Description: Facebook Proxied File");
header("Content-Type: image");
header("Content-Disposition: attachment; filename=".$path);
@readfile($path);
?>
[/c]

I saved the code above as facebookProxy.php and when I am loading an image from Facebook, I pass the URL of the image in path variable.

 

And then below I added the code to load the picture, by calling facebookProxy.php passing the path of the image in the URLVariables. Note: The code below is an extension of this tutorial:
http://www.permadi.com/blog/2010/12/using-facebook-open-graph-api-in-flash-as3/.

 

The code also checks to make sure path is either "facebook" or "fbcdn." Note: This is a bare-bone example. Reading, writing and prinitng files is a risky operations and a real application should add more security measures to prevent security breaches.

[c]
function loadMyPicture():void
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMyPictureLoaded, false, 0, true);

var request:URLRequest = new URLRequest("facebookProxy.php");
var variables:URLVariables = new URLVariables();
variables.path = Facebook.getImageUrl(Facebook.getSession().uid);
request.data = variables;

loader.load(request);

}

function onMyPictureLoaded(event:Event):void
{
var loader:Loader=event.target.loader;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onMyPictureLoaded);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onMyPictureLoadError);
var bitmap = Bitmap(loader.content);
bitmap.smoothing=true;

//Note: picturePlaceholder is just a blank movie clip on the Stage
bitmap.width=picturePlaceholder.width;
bitmap.height=picturePlaceholder.height;
picturePlaceholder.addChild(bitmap);
}
[/c]

The example can be accessed here in a stand alone state:
http://www.permadi.com/tutorial/as3-open-graph-example/?login.

You can use a similar method to load friend's profile picture. Here's an example of a game that uses your friend's pictures: http://apps.facebook.com/jigsaw-friends/ (you account must have several friends in order to see your friend photos).

14 Responses to “Loading Facebook Profile Picture Into Flash SWF Using Graph API”

  1. Thanks for the code samples. They are very helpful.

  2. [...] Loading Facebook Profile Picture Into Flash SWF Using Graph API [...]

  3. Thanks for the code samples!!

  4. Thanks for this, however, I found that routing all the image requests through the proxy gave a poor performance. I instead made a check for which host the image was stored at and only made the proxy request when the image wasn’t stored on http://profile.ak.fbcdn.net

  5. Hi Signar,
    That certainly is an approach that would work, too.

  6. Sorry my english not very good. Can you tell me why I get “1120: Access of undefined property onMyPictureLoadError”? Thank you.

  7. Hi Jamie,
    make sure you implemented the function onMyPictureLoadError in your class and make sure it’s set to public.

  8. [...] images from Facebook into Flash without any sandbox violations. It is taken from the guide here: http://www.permadi.com/blog/2010/12/loading-facebook-profile-picture-into-flash-swf-using-open-graph…. The relevant PHP code [...]

  9. permadi, you saved my day with this php code!! Many thx!!!

  10. Thank you for the file. I am using the code to create a video.
    The problem I am facing right now is that the profile picture and the profile name appear only if initiated from the first frame. If the picture of name is added in a frame post the first frame it does not show up.

    Can you please help me out.

  11. It shouldn’t matter which frame you call the script at. Without seeing your code, I can’t tell what you might have done incorrectly.

  12. The problem with getImageUrl is it points to a re-director script at Facebook, that forwards the request to a different final URL. I think Flash refuses to honor this re-direct since it could be a way for hackers to inject unexpected content.

    I used Firebug for Firefox, and watched the traffic. My call to Loader using the URL given by getImageUrl went to something like:

    https://graph.facebook.com/10000123456789/picture?type=small

    Facebook response with a 302 header that redirects to a URL like this:

    https://fbcdn-profile-a.akamaihd.net/hprofile-ak-snc4/47362_10000123456789_4557_t.jpg

    Firebug shows that the redirect actually works, and the final JPG image was retrieved. The problem is, Flash never gives any indication that it got a response, except for issuing an HTTPStatusEvent of 200 and type “httpStatus” (which means, “everything is OK”). Therefore, your COMPLETE event handler never gets called.

    I tried using the HTTPStatusEvent handler hoping I could find the URLRequestHeader containing the redirected URL, but Flash never returns it. There is never a status event of type “httpResponseStatus”, therefore there is never any way of getting the redirect URL.

    I hate it, but it looks like you have to use a PHP script to tunnel the results through your server.

  13. That’s right.

  14. [...] Loading the user picture: http://www.permadi.com/blog/2010/12/loading-facebook-profile-picture-into-flash-swf-using-open-graph… [...]

Leave a Reply

*