spacer

Labs.byHook

Scripts, Tools & Methods Developed at Hook

spacer spacer
spacer

This blog is created and maintained by the technical team at Hook in an effort to preserve and share the insights and experience gained during the research and testing phases of our development process. Often, much of this information is lost or hidden once a project is completed. These articles aim to revisit, expand and/or review the concepts that seem worth exploring further. The site also serves as a platform for releasing tools developed internally to help streamline ad development.

spacer
spacer

Hook is a digital production company that develops interactive content for industry leading agencies and their brands. For more information visit www.byhook.com.

spacer

Facebookery, the Flash and Facebook How-To

spacer
Posted on May 19th, 2010 by Jake
spacer

* AS OF 10/12/10, THIS METHOD NO LONGER WORKS DUE TO A CHANGE IN FACEBOOK SECURITY. THE ACCESS_TOKEN PARAMETER IS NO LONGER ACCESSIBLE FROM THE URL.

* PLEASE GO HERE labs.byhook.com/2010/11/08/facebook-canvas-app-oauth-authentication/ FOR OUR NEW OAUTH EXAMPLE!

There has been quite an onset of controversy surrounding Facebook as of late. Privacy issues, security issues, leaked IM messages, chats that can be seen by people not involved in the chat, Zynga threatening to leave, and the like. Seems like just the right time to jump in head first and make some wall spamming apps don’t you think? So we figured we would sit down, see how it works, and try to come up with an easy way to allow for flash apps to talk to the all mighty Facebook API/Data… So here goes nothin’!

The theory goes like this: Lets make a loader swf that will be the communications layer. Whenever the main application needs access to facebook data, it will ask the loader to provide the data. This way the portal access can be kept isolated from the rest of the project. This is useful for when Facebook changes their API (oh and they will, without warning), or if you want to take the app to a different social portal. Now you won’t have to change much if any of the code inside of your main app. Just simply swap out the loader, on a per portal basis.

A quick but important word of warning. This project is still in the very early stages, but we thought there was enough here to be useful to people as is. So we will try to keep the code updated on this post, as we improve it.

A second word or warning. Facebook has a few ways of accessing their data, and a few ways of letting a developer build an app for their platform. This is simply one way, using the old REST api and the new GRAPH api to access the data, while the app itself is using a Facebook br canvas.

While working on figuring out how to do this, we realized there isn’t much in the way of a simple tutorial to get you started with flash and facebook. So with this post we will attempt to fill that gap a bit. Hopefully this will help some people get started that may have otherwise just skipped it. This post is comprised of three sections, “The Pain”, “The Suffering”, “The Joy”. Hopefully there will be enough info in those three sections to get you up and running.

To see what we will be going on about, hit up our live example here:
apps.facebook.com/hookfbloaderexample

And grab the source code here:
labs.byhook.com/source/FBLoaderExampleSource.zip

I am kind of a “Bad News First” kinda guy. So lets get the most frustrating and least interesting parts out of the way first.

The Pain
This part isn’t horribly bad by any means, but if you have never done it, it can be frustrating.. so First things first, Become a facebook developer.
To do that go here:
www.facebook.com/developers/createapp.php

If you do not already have the “Developer” application installed, you will be greeted with a window that looks similar to this:
spacer

Once you click “Allow”, you will be redirected to the “Facebook Developers” home page. Here at the bottom right you will see a Status section. Keep an eye on this as often as possible, because this seems to be one of the only places to get a bit of a heads up on changes and bug fixes to the api.

Above that you will see a list of your applications. At this point you may not have any, but thats about to change! spacer

As a quick note, if you hop back to your facebook home, you should now see “Developer” as an application on the left in your applications list. You can click that to get to the developers homepage.

Go back to the developers homepage if you have left, and click the “Set Up New Application” button. This will start the application creation process.

spacer

Type in the name you want to give your application, select Agree (after reading the Facebook Terms of course), and click Create Application.

This will bring you to your application settings:
spacer

Most of the settings in the “Basic” section are fairly self explanatory. The important parts are the Application ID, API Key, and Secret. These will be used to identify your application and authorize your application to access the user’s data.

You can also add other developers that can access this page, by Typing in a friend’s name in the Add Developers box. This will send a notification to them to join. It will show up along with the millions of Farmville requests in their profile.

Lets move to the Canvas section, where all the important stuff is.
spacer

The “Canvas Page URL” is the link that you can give out to people to play your app on facebook, it needs to be a unique name, and not contain any spaces or capital letters.

The “Canvas Callback URL” is the url to the html/php page that facebook will load into its br for your app. Please note that if you are using flash, this URL must be a secure HTTPS link. This is because the graph.facebook.com/crossdomain.xml file does not allow for none secure links. (this just changed recently, like last week, but its a change for the better really, just wish they would have mentioned it someplace). Please be aware that this link needs to end with a “/” or a “?”.

Yes, this means that you have to host your content yourself, facebook doesn’t host anything for you. This means you will need a public facing webserver capable of serving from HTTPS. Before you release this to the wild wild internet, you will need to purchase a proper Certificate for your domain as well, from some place like VeriSign or GoDaddy, or wherever. You can however, create a self signed certificate for testing purposes. See the “The Suffering” section for some basic instructions on how to do this.

The “Post_Authorize Redirect URL” is a link that facebook will redirect the user to, once they have authorized the application. We are going to leave it blank in our case, since we will handle the redirect ourselves.

For now, just leave the rest of the settings as they are.

Lastly go the “Advanced” section. Here you want to set your “Application Type” to “web” and set “Sandbox Mode” to “enabled”. Turning on “Sandbox Mode” will limit access to view your application to only developers assigned to the application. When you want other people to test it out, you can turn that off, so that anyone can see/use the app.

Once you are all done with your application (not just the facebook side, but the flash side as well) and you want to release it to the public, go back to the My Applications page, and click the “submit it” click at the top of the page. This will submit your application to the application directory so people can find it in the application searches.

Congratulations! You now have a registered facebook application. Next we have to build a bridge for the flash application.

The Suffering
This part doesn’t fit well into any of the sections, so we are just going to lay it out here.
As you may or may not know, your swf can’t directly access data from another domain, unless there is a crossdomain.xml file that resides in the root of that remote domain. Thankfully facebook has one of these, otherwise, we wouldn’t really be able to use flash. Their crossdomain file for graph.facebook.com looks like this:
spacer

This setup basically says, that any domain is allowed to request data from the graph.facebook.com domain. However since the line secure=”false” is not there, that means that secure=”true”. With secure set to “true”, it instructs flash to disallow data retrieval if the swf is not hosted on a server without SSL. If you are interested in learning more about the crossdomain files you can look here:
code.google.com/p/doctype/wiki/ArticleFlashSecurityCrossDomain
and
www.adobe.com/devnet/flashplayer/articles/flash_player_9_security.pdf

So for this reason, our server must host our facebook app through a HTTPS link. As stated before you will eventually want to get a proper certificate, but for now you can create a self-signed one. The downside to this, is when you first connect to your application, your browser will warn you that the certificate may not be authentic, as it is self signed, and you will need to set a security exception for that certificate. You should not see that message again after allowing the certificate.

If you are using an apache server you can create and install a self signed certificate by following these instructions:
www.akadia.com/services/ssh_test_certificate.html
and
www.digicert.com/ssl-certificate-installation-apache.htm

Now with all of the IT stuff out of the way, lets get the basic setup on the webserver, so that we may finally get to the fun part.

Before we dig into the files, we need to discuss the authentication steps a bit.

The newest version of the REST api (which is old) and the new GRAPH api, require that you at least send whats called an Access Token with each request. Your application will be given this token when the user “logs into” your application. In order to get the user to log into your application, you must direct them to a URL that looks like this:

https://graph.facebook.com/oauth/authorize?client_id=123456789101112&redirect_uri=apps.facebook.com/mysweetfacebookapp/&type=user_agent&display=popup

(as a quick note, the client_id parameter is the Application ID of your app)

This will tell facebook that the user would like to use your app, and then facebook sends a bunch of parameters to your index.html file, and loads the result into its br. The properties that are currently passed in are these:

  • access_token
  • fb_sig_in_br
  • fb_sig_br_key
  • fb_sig_locale
  • fb_sig_in_new_facebook
  • fb_sig_time
  • fb_sig_added
  • fb_sig_profile_update_time
  • fb_sig_expires
  • fb_sig_user
  • fb_sig_session_key
  • fb_sig_ss
  • fb_sig_cookie_sig
  • fb_sig_ext_perms
  • fb_sig_api_key
  • fb_sig_app_id
  • fb_sig

Some of these are self explanatory, and some of them I have no idea what they are used for, but the majority of the parameters are used to create the access_token, which is what we need to do anything with the GRAPH API.

Thankfully the full access_token is passed in as its own parameter, so we don’t have to build it from the other params.

What we are going to do then, is take that access token, and pass that into flash through the flashvars parameter.

But I hear you crying “That URL is long and crappy, I don’t want to give that out to users! Can’t we use the apps.facebook.com link?”.

The answer is yes we can, but like we stated before, we will need to do some redirection.

Now is probably a good time to start talking specifics.

Download our example source here. (To get the example running, copy everything from the “Publish” folder to the location your canvas is looking to load your app from and edit the index.html file to match your app data)
labs.byhook.com/source/FBLoaderExampleSource.zip

When you unzip it and go into the Publish folder, you will get an “index.html” file, an images folder, a “swf” folder, and a “js” folder.

When you are done editing the files you will want to ftp all of those to your webserver in the directory that you pointed your facebook app to during the app setup.

There are some changes we need to make to the index.html file. So pop it open and see whats crawling around in there.

Lets skip the “CHANGE ME TO THE NEW APP’s ID” section for a minute, and head down to where it says

if(getParams()["access_token"] == undefined)

What this is doing is using getParams() (defined in the js/jaclib.js file) to parse out all of the parameters passed into our html page. It then looks to see if the “access_token” property has been defined. If has not, that means that the user used the “apps.facebook.com/mysweetapp” link to get to our content. That in return means that no access token was created. If this is in fact the case, we redirect them to the auth link stated above. (https://graph.facebook.com/oauth/authorize?client_id=123456789101112&redirect_uri=apps.facebook.com/mysweetfacebookapp/&type=user_agent&display=popup)

When the redirect happens, facebook sends all of those “sig” parameters to your page, and we now have an access token to use with our requests, and that is the hawtness.

Lets get back to the “CHANGE ME” part at the top of the file.
To make this loader work with your swf, we need to edit those settings in that section:

  • APP_ID is your application ID provided by facebook on your application developer page.
  • MAIN_SWF property is the complete URL to the swf you want to load in with the loader.
  • MAIN_SWF_WIDTH and HEIGHT are the width and height properties of the swf you want to load in.
  • LOADER_SWF_VER is the minimum flash version required for the loader (not the loaded in swf).
  • REDIRECT_URL is the url you want face book to redirect the user to after authentication. In our case its the same url as the one given out to the users.
  • APP_SCOPE is a comma separated list of the extended access your app will need. When the user first goes to your app, they will be presented with a box that will let them know your app will access these features of their profile.

A complete list of these extended permissions can be found here:
developers.facebook.com/docs/authentication/permissions

Those few properties should be all you have to change to get things working. But lets take a quick look at the swf embed part of the html file.

The embed is done using SWFObject, simply because its cleaner and easier to work with. The first thing you see in the embed section is a check to see if there is an access_token passed to our page. If there is, we can load the swf.

Next we set up a flashvars object, and save off each of the parameters that are passed into our index.html file. All of these parameters will then be accessible from the FacebookManager, which we will get into in the next section.

Lastly we call on swfobject to do the actual embed. This will get the loader into the page, which will then load up your application! w00t!

So that is pretty much what it takes to get a flash app running in a facebook br. In the next section we will talk about the FacebookManager, and how to use the loader and framework to retrieve and publish data to facebook.

THE JOY
Again, before we start the fun part, I want to reiterate that this library/framework is not complete, but there should be enough there to get you started. Basically you can just add more of the same to make it more complete. Enough with the whiny disclaimers, on with the code!

Download the Library here.
FBLoaderExample
Live Demo here.

This example also makes use of our Log library which can be found here:
labs.byhook.com/2010/04/05/logs-theyre-better-than-bad-theyre-good/

Most of the example code below is pulled from the FBTestMain example contained in that zip. You can look there for reference to what we are talking about. Most of the stuff that will be required in your application is in the com.app.FBTestMain document class.

With that downloaded we can jump right in. In the document class of your application (not the loader, but the swf that will be loaded in) you will need these imports:

import com.jac.facebook.events.FacebookEvent;
import com.jac.facebook.FacebookManager;
import com.jac.facebook.IFBApp;

Next you must implement the IFBApp marker interface. All that you need to do for that is simply add
“implements IFBApp” to your document class declaration like so:

public class FBTestMain extends MovieClip implements IFBApp

Next you will need to get a reference to the FacebookManager.
To do this, all you need to do is dispatch an event:

//Init (when dispatched, the loader will call "init" and pass in the facebook manager reference)
dispatchEvent(new FacebookEvent(FacebookEvent.GET_FACEBOOK, "initFacebook"));

The “initFacebook” parameter is the name of a public function that will be called when the FacebookManager is ready. A reference to the FacebookManager will be passed in as an argument when the function is called.

Lastly you will need to define that “initFacebook” function:

public function initFacebook(fb:FacebookManager):void
{//initFacebook
//Save off reference to Facebook Manager (from loader)
_fb = fb;
init();
}//initFacebook

This assumes of course that you have _fb defined in the class someplace.

Using the predefined FacebookManager example methods:
Now you can do something like this:

_fb.getMe(handleMe);
private function handleMe(e:FBRequestEvent):void
{//handleMe
 
if (e.successResult.success)
{//good
_welcomeText.text = ("Welcome " + String(e.fbObj["first_name"]) + "!");
}//good
}//handleMe

The getMe(callback:Function) method is defined on the FacebookManager object. This makes the proper request to the facebook API, handles the result, including errors, and calls your callback (the handleMe() method in this case) when the result is returned. It passes in a FBRequestEvent object to your callback, which has a few useful properties.

The “successResult” property is of type FBSuccessResult, which has a success:Boolean property, a message:String property, and an errorCode:String property.

If successResult.success is false, then there was an error with the request. That error code, and error message will be stored in the successResult.errorCode and successResult.message properties.

If the result is a success, then the fbObj property will contain a decoded JSON object that was created from the returned JSON from the Facebook API.
(Please read the “Using Returned Data” section for more information about the specific properties on a FBRequestEvent object)

So in the example above we are taking the result from facebook, and getting the value of “first_name”. There is quite a bit of data returned with the “me” request, and the facebook docs seem to be a little skimpy on that kind of thing.

So if you want to trace out the full response from facebook, you can use the FBRequestEvent.result property, which is the raw data facebook returned to your request.

Getting data about yourself is all well and good, but what is facebook without the wall post. To do that you can call:

_fb.postToFeed(handlePost, "me", "I just learned how to build flash apps for Facebook!", "Hook FBLoader Example", "labs.byhook.com", "This is the Hook Labs Post that goes along with this example.");

postToFeed() takes a bunch of optional arguments:

public function postToFeed(callback:Function, profileID:String, message:String="", name:String="", link:String="", description:String="", pic:String=""):void

It takes a callback function like all of the requests and a profileID. The profileID is the USER ID from facebook of the person’s wall you want to write to (assuming you have access). As before the callback function will be called when the request completes, and it will have the FBRequestEvent object passed to it with all of the needed info.

The other optional arguments are message:String, name:String, link:String, description:String, and pic:String. These are all things that get formatted into the post. The message is the main message of the post. Name, refers to what will show up as the link that the user can click on. Link is a link out to something else. Description is the description for the link, and pic is a URL to an image to post with the link. At this point however, the picture option doesn’t seem to work as expected. If you post a link, with not picture defined, it grabs a seemingly random one for you, but if you define one, it doesn’t show up. Which leads me to my next point…

The Facebook API seems to be in constant flux. The GRAPH api is very new, and it appears they are still working out the kinks. So, there is also a way to access the old REST API, to help fill the gap.

Currently in FacebookManager, there is only one predefined/example method that uses the REST API. The is getMeClassic(callback:Function). From the perspective of a class that is using the FacebookManager as the means of contacting facebook, the results are the same. But what happens underneath is fairly different.

“Bbbbuuuuuuttttt Jake!” you cry, “what about all of the other things you can do with the facebook API?”. For that we are going to talk about how to send your own requests from FacebookManager. The getMe(), and postToFeed() methods are basically examples of how to use the framework. To make real use of the framework, you are going to want to call the fbRequest(), fbClassicRequest(), and fbBinaryRequest() methods.

Using the custom request methods
Here is where it would be very beneficial to take a gander at the Facebook API pages:

GRAPH API
developers.facebook.com/docs/api
and
REST API
developers.facebook.com/docs/reference/rest/

The most immediately useful sections are the “Publishing to Facebook” and the “Introduction” sections of the GRAPH API page.

In the “Introduction” section, it explains a bit about how to access data. All that you will really need to know from this section is how the object IDs work. Those are the things at the end of the urls in the “All objects in Facebook can be accessed in the same way” section. Those numbers and names (with the addition of “me”) are the itemIDs that you will need to pass to the methods in the FacebookManager class.

The next section is the “Connection Types” section. these are what you will pass to the “apiCall” parameter for the request methods. A full example looks like this:

_fb.fbRequest(handleRequest, "me", "friends");

In this case, “me” is the object ID, and “friends” is the connection type/api call. This will return a list of the logged in user’s friends. So for instance in the demo app (apps.facebook.com/hookfbloaderexample) if you put in “me” for the itemID and “friends” for the GRAPH API Call, it will call that exact method and return the list of friends.

Another example would be if you put in “cocoacola” for the ID and “feed” for API call it will make this request:

_fb.fbRequest(handleRequest, "cocoacola", "feed");

Cocoacola is a facebook page, so facebook will resolve that to the correct ID, and then get the “Feed” data from that page.

You will see the result in the example app after you click Get Info. In the Publishing to Facebook section, you will find a slightly deeper list of API calls.

This is all well and good, “But how do I POST with the fbRequest() method!?” you say.

Well, if you look in the Publishing to Facebook section, you will see in the chart what is required to post to the feed. We see that it takes a Profile ID, and a list of arguments. So lets plug that into our fbRequest method().

_fb.fbRequest(handleRequest, "me", "feed", {"message":"message to post", "link":"link to awesomeness", "name":"A name for the link", "description":"A description for the link", "picture":"www.urltoawesomeimage.com"});

As you can see, we simply build a generic object with the arguments we want to pass to the API, and Presto! we get data in return.

Using the returned data
Cool, we now have data, so how do we deal with it?

When defining a callback for the fbRequest() methods, you will notice that you must have it accept a FBRequestEvent object as its argument. This object contains all kinds of goodies. Specifically it has these four properties: result:String, successResult:FBSuccessResult, fbObj:Object, and bindaryData:ByteArray.

The “result” property contains the raw string data returned from Facebook. If the returned data happens to be binary, the “result” property will contain the string “binarydata”. The next and probably most important property is the successResult object. The FBSuccessResult object has three properties of its own, errorCode:String, message:String, and success:Boolean. If “success” if false, then there will be an error code either from facebook or from flash in the “errorCode” property. There will also be the raw error message in the “message” property. So in your callback functions, please make sure successResult.success is true, before trying to do anything with the data.

The next two properties are an “either / or” kind of thing. If fbObj is not null, then binaryData is null, and vise verse. If fbObj is not null, that means the result was text data. This is generally how you will get data back from Facebook. The FBRequestEvent object will deal with the raw data string and build a generic object from it for easier access in your code. The binaryData will be non-null for when you are requesting things like images from facebook. Please be aware if you want to get an image, you must call the FacebookManager.fbBinaryRequest(), and not the standard fbRequest() method.

Lets say you make a _fb.fbRequest(handleRequest, “me”) request. Your handleRequest method could look like this:

if (e.successResult.success)
{//Grab First Name
_welcomeText.text = ("Welcome " + String(e.fbObj["first_name"]));
}//Grab First Bame

Here we are taking the fbObj, and getting the “first_name” property from it. This is how the “Welcome” text at the top of the example is populated with the logged in user’s name.

Its also probably worth noting that some of the old REST API’s require more info, such as a session key when making a request. All you need to do is put that in the generic object

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.