Getting your head around Flash on Facebook


Getting your head around Flash on Facebook







Recently I had the opportunity to take an Adobe AIR
application, nomee.com, and integrate a portion of it into Facebook. In this
article I'm going to cover some of the things that I learned along the way
while I was trying to understand exactly what I could and couldn't do inside of
Facebook.


The Nomee application


Figure 1. The Nomee application


First I'll start with an overview of the different places
you can put Flash applications on the Facebook site, followed by an overview of the
different ways to launch Flash applications in the Facebook Platform. Then I will talk about flashvars in the world of Facebook. I'll end with a quick overview of what you can't do
with Flash on Facebook.


Where you can run Flash


Facebook has a number of integration points throughout the
site. These are covered in more detail in the Facebook
developer wiki
page. The main points of integration are the Canvas page,
Application tab, Boxes tab, and Wall.


Important:
Except on your canvas page, Facebook restricts how Flash applications
can run. Before any Flash application can run on the Application or
Boxes tabs or Wall, the user has to click the placeholder to activate
the Flash movie. This is a lot like how YouTube places the big play
button on top of YouTube videos. Facebook does this so that developers
don't fill up Facebook pages with lots of animated, noise-making
applications running at the same time on a page. Because Flash can do
so much, users need to start the applications.


Luckily, Facebook gives you the ability to create your own
placeholder graphic that can tell users to click the graphic to start the
Flash movie. This is set with the <fb:swf imgsrc=""> attribute.


Canvas page


Every application is given a unique application URL by
Facebook when you register your application in the Developer section. This URL
starts with http://apps.facebook.com/ and is followed by a unique name of your choosing. Facebook will proxy requests
to this domain to your real web server so users will never need to know the URL
to your server. It also allows you to change your servers as needed without
breaking Facebook bookmarks.


For example, if you are requesting:


http://apps.facebook.com/<em>yourappname</em>/usersInfo.htm</pre>
<p>Facebook (behind the scenes) will request <kbd>userInfo.htm</kbd> from your server and return it to the user on Facebook. By doing it this way,
you are able to run Facebook Markup Language (FBML) on your pages even if the
application is hosted in an iFrame. </p>
<p>The main application page has the least amount of
restrictions on it. You can use URL parameters, you can run your own ads, and Facebook
doesn't sanitize the JavaScript you want to run. </p>
<p>You are given two choices when setting up your Facebook
application. You can run it as straight FBML or as an iFrame inside of the
Facebook page. When you run it as FBML you will get to see some benefits
from Facebook caching of the FBML page; however, you will also be slightly
limited on what you can do. Specifically, you won't be able to pass URL
parameters into your pages. </p>
<p>With the nomee application, our plan was to redirect a large
portion of the traffic back to our application page for two reasons: we have the
ability to run ads and, more importantly, we needed a guaranteed way to view a
user's nomee card. When users embed their cards on Facebook, from our AIR
client, we have no guarantees that they may actually add our application to
their profile pages. However they will now show up in searches and friends of
theirs may want to view their cards. By redirecting all of these views back to
the canvas page we can always show the card to their friends. </p>
<h4>Application tab</h4>
<p>Once users have authorized your application, they have the
ability to create a tab in their profile for your application. These are the
tabs you see when you visit your friends' profile pages. You can remind
users to add this tab. However, it's up to the user to create this tab in the
settings panel for your application or with the + sign next to the existing
tabs in his or her profile.</p>
<p class="note"><strong>Note:</strong> They have to do that in the
Facebook settings panel for your application. You cannot force the creation of
that tab through the API or FBML code. </p>
<p>When a user adds a tab for your application you need to
define a special page on your server for this tab. The code on this page needs
to be a straight FBML page served up to Facebook. However, you can still run
the request through a middleware server (such as ColdFusion, JSP, or ASP). </p>
<p>This tab page will be running as a section of the larger
Facebook page so you don't have to add the regular wrapper HTML to this page; I'm
referring to the <code><HTML><HEAD><BODY></code> tags. This is why it
needs to be a different page; however, since all of your logic may be in the
SWF file this could be as simple as a <code><fb:swf></code> tag. </p>
<h4>Boxes tab and Wall</h4>
<p>Another place that you can run your Flash movie, is on the
predefined Boxes tab for the user. The page on this tab has two columns, one
wide and one narrow. The user also has the option of taking any item on the Boxes
tab and moving into the left side column of their Wall page, too.</p>
<p>Again, users control where they want the box for your
application positioned in relationship to all of the other application boxes on
this page or their Wall pages.</p>
<p>The code for the Boxes tab and the Wall page work
differently than the Profile tab. For these pages you need to post the FBML to
Facebook beforehand. You do this with the <code>setFBML()</code> method of the
Facebook API:</p>
<pre>var profileWall = "<span class="asDoc"><a</span> <span class="asDoc">href=</span>''<span class="asDoc">><img</span /> <span class="asDoc">src=</span>'' <span class="asDoc">width=</span>'184' <span class="asDoc">height=</span>'250' <span class="asDoc">border=</span>'0'<span class="asDoc">></a></span><span class="mxmlTag">";</span><br /> <br />var profileBox = "<span class="asDoc"><a</span> <span class="asDoc">href=</span>''<span class="asDoc">><img</span /> <span class="asDoc">src=</span>'' <span class="asDoc">width=</span>'700' <span class="asDoc">height=</span>'250' <span class="asDoc">border=</span>'0'<span class="asDoc">></a></span><span class="mxmlTag">";</span><br /> <br />api.profile_setFBML(api.get_session().uid,<br />profileWide, null, null, profileNarrow, <br /> function(){}<br />);</pre>
<p>Facebook will then cache the FBML page and serve the content
directly to the user. This moves the server traffic load directly onto the
Facebook servers. However, it also means the data is cached on Facebook and you
need to reset the code with <code>setFBML</code> before Facebook knows about new code. </p>
<h3>Running Flash applications inside an FBML page</h3>
<p>When you are running Flash applications inside of an FBML page, either in
an Application tab or your Canvas page, you will launch your Flash application
with the <code><fb:swf></code> tag. This is the FBML tag that Facebook uses to control how and when the Flash
application starts as well as what parameters are passed to the Flash application. </p>
<p>You do have two options of how to invoke this tag. You can
do it directly with FBML markup, as shown in this snippet: </p>
<pre><fb:swf swfbgcolor="000000" <br /> imgstyle='color:white;"<br /> swfsrc='<URL TO YOUR SWF>'<br /> imgsrc='<URL TO PLACEHOLDER GRAPHIC>s' <br /> width='340' height='270' /></pre>
<p>Or you can do it in script with the <code>createElement("fb:swf")</code> tag:</p>
<pre><div id="swfContainer"></div> <br /><script> <br /> var swf = document.createElement('fb:swf'); <br /> swf.setId('my_swf_id'); <br /> swf.setWidth('100'); <br /> swf.setHeight('100'); <br /> swf.setSWFSrc('FULL_URL_TO_MY_SWF');<br /> document.getElementById('swfContainer').appendChild(swf);<br /></script> </pre>
<p>By doing it in script you have the option of dynamically
setting up the URL to the SWF file, place holder image, or any other parameters of
the Flash application. FBML itself doesn't have the ability to set properties
dynamically like you would in Flex with the {Binding} syntax. </p>
<p>Another thing to consider with FBML pages, including the
FBML for the Boxes tab and Wall, is that Facebook will parse your code before
serving it up and rewrite or (as I like to call it) sanitize the code.
Specifically, the JavaScript on the page is parsed for unauthorized code and
Facebook will also rename functions and variables as needed too. There are a
number of JavaScript functions that you are not allowed to run in an FBML page.
Facebook will strip these items out to protect their users from potentially
harmful application code. An indispensible tool when debugging Facebook
applications is the Firefox plug-in, <a href="http://getfirebug.com/" target="_blank">Firebug</a>. </p>
<h4>Running Flash applications inside a canvas page (iFrame)</h4>
<p>The canvas page is nice and I would recommend it because it
gives you full control of how your application runs. Because this page is
running in an iFrame, you can run any html or JavaScript that you need. </p>
<p>I've also found that URL parameters passed to the canvas
page are passed through to the iFrame; however, I was never able to find a way
to get access to these URL parameters in an FBML page, so this is another
benefit to using an iFrame page if you can. </p>
<p>To invoke Flash in an iFrame page you have a couple of
choices: You have the Facebook <code><fb:swf></code> tag and <code>createElement("fb:swf")</code> option, just like in the FBML page. You can also use the basic <code><div class="youtube-video"><object><embed></code> tags or a third-party JavaScript library like <a href="http://code.google.com/p/swfobject/" target="_blank">SWFObject</a>. One thing to note if
you don't use <code><fb:swf></code> to invoke the Flash application, then you will
need to pass in the Facebook URL parameters as <code>flashVars</code> youself (if
you need them). </p>
<p>Here is a simple sample that uses SWFObject and pulls out
any URL parameters and then passes them into the Flash movie as <code>flashVars</code>:</p>
<pre><script src=<span class="asReserved">"http://static.ak.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"</span> type=<span class="asReserved">"text/javascript"</span>></script><br /><script type=<span class="asReserved">"text/javascript"</span>><br /> <br /> <span class="asReserved">var</span> api_key <span class="asReserved">=</span> <span class="mxmlTag"><your api key></span>;<br /> // the xd_reciever.htm file needs to be on your website <br /> // relative to your facebook application pages.<br /> // For more information: <br /> // http://wiki.developers.facebook.com/index.php/Cross-domain_communication_channel<br /> <span class="asReserved">var</span> channel_path <span class="asReserved">=</span> <span class="mxmlTag">'xd_receiver.htm'</span>;<br /> <br /> FB_RequireFeatures([<span class="mxmlTag">"XFBML"</span>], <span class="asReserved">function</span>(){<br /> FB<span class="asReserved">.</span>Facebook<span class="asReserved">.</span>init(api_key, channel_path);<br /> });<br /> <br /> <br /> <span class="asReserved">var</span> queryString <span class="asReserved">=</span> window<span class="asReserved">.</span>location<span class="asReserved">.</span>search;<br /> <span class="asReserved">var</span> flashVars <span class="asReserved">=</span> {};<br /> queryString <span class="asReserved">=</span> queryString<span class="asReserved">.</span>substring(<span class="mxmlString">1</span>);<br /> <br /> <span class="asReserved">var</span> fields <span class="asReserved">=</span> queryString<span class="asReserved">.</span>split(<span class="mxmlTag">'&'</span>);<br /><span class="asReserved"> var</span> fb_sig_added <span class="asReserved">=</span> <span class="mxmlString">0</span>;<br /> <br /><span class="asReserved"> for</span> (<span class="asReserved">var</span> i <span class="asReserved">=</span> <span class="mxmlString">0</span>; i <span class="asReserved"><</span> fields<span class="asReserved">.</span>length; i<span class="asReserved">++</span>) {<br /> <span class="asReserved">var</span> index <span class="asReserved">=</span> fields[i]<span class="asReserved">.</span>indexOf(<span class="mxmlTag">'='</span>);<br /> <span class="asReserved">var</span> key <span class="asReserved">=</span> fields[i]<span class="asReserved">.</span>substring(<span class="mxmlString">0</span>, index);<br /> <span class="asReserved">var</span> value <span class="asReserved">=</span> fields[i]<span class="asReserved">.</span>substring(index <span class="asReserved">+</span> <span class="mxmlString">1</span>);<br /> <br /> <span class="asReserved">if</span> (key<span class="asReserved">.</span>toLowerCase() <span class="asReserved">==</span> <span class="mxmlTag">"fb_sig_added"</span>){<br /> fb_sig_added <span class="asReserved">=</span> value;<br /> }<br /> <br /> flashVars[key] <span class="asReserved">=</span> value;<br /> }<br /> <br /> // first check if they have authorized the app, if not<br /> // redirect them to the login page.<br /> <span class="asReserved">if</span> (fb_sig_added <span class="asReserved">==</span> <span class="mxmlString">0</span>)<br /> {<br /> window<span class="asReserved">.</span>parent<span class="asReserved">.</span>location <span class="asReserved">=</span> <span class="mxmlTag">"http://www.facebook.com/login.php?api_key="</span> <span class="asReserved">+</span> api_key <span class="asReserved">+</span> <span class="mxmlTag">"&next=index.htm&v=1.0&canvas=1"</span>;<br /> <br /> }<br /> else<br /> {<br /> // load the flash movie.<br /> swfobject.embedSWF(<span class="mxmlTag">"http://<your domain>/facebook/FacebookClient.swf"</span>, <span class="mxmlTag">"flashContent"</span>,<br /><span class="mxmlTag"> "700"</span>, <span class="mxmlTag">"650"</span>, <span class="mxmlTag">"10.0.0"</span>, <span class="mxmlTag">"expressInstall.swf"</span>, flashVars, null, null);<br /> }<br /> <br /><span class="asDoc"></script></span>

A note on flashVars and the Facebook Platform


When Facebook runs an FBML or iFrame application, a
number of parameters are available to you. If you are using the <fb:swf> tag,
parameters will be passed in as flashVars automatically.


Note: For a complete list of parameters, refer to the Facebook
Developers wiki
.


Pay close attention to the fb_sig_user, fb_sig_canvas_user,
, fb_sig_profile, fb_sig_profile_user parameters. Depending on the context of when and where your Flash application
is invoked or if the user hasn't authorized your application yet, any one of these
variables could be the Facebook uid of the user using your application.


What you can't do in Flash


The Facebook Platform API lets you do a lot, and most of
those things are easily doable inside of a Flash application; however, there
are still a few things that are FBML only and to the best of my knowledge there
is no way to do them through the API from inside of an Flash application. For these you
will need to put them in the HTML around the Flash application. Or on another
application page altogether. Two of these that I ran into are:


  • <fb:add-to-profile>: This is the FBML tag that users
    need to use to take the FBML you set in Facebook for the Boxes tab and Wall and
    actually add that to their Facebook pages; otherwise, users will never see the
    FBML you set.
  • <fb:request-form>/ <fb:multi-friend-selector>:
    Facebook recently launched a new Friend Selector UI control. Your application
    uses this control to allow users to select friends usually to send application
    invitations to. You can build your own Friend selector in Flash but you won't
    be able to send out Facebook invitations; instead, you'll need to send out your
    invitations as Facebook notifications.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License




About the author



Mike Nimer is the Director of Engineering and Architect of
the nomee.com application. Before joining
nomee, Mike has spent over a decade building web applications, the servers that
run web applications, as well as providing consulting and mentoring help for
development teams around the world. Mike was a founding partner of Digital
Primates IT Consulting Group, providing mentoring and development support on
the Adobe Flash Platform and ColdFusion. Prior to Digital Primates, Mike was a
member of the Adobe ColdFusion engineering team where he was responsible, in
part, for a number of key features, including PDF generation and the
integration of Flex 2 with ColdFusion Server.


此博客中的热门博文

咖啡加牛奶,对健康更有益

Chrome超越Firefox的20条技巧

林牧之女谈《烛烬梦犹虚》出版幕后点滴