評分: 

邊做邊學 Facebook 開發 系列 1 - Facebook SDK Part 1

文/黃忠成


Facebook 的熱潮

   這些日子來,即使從來不碰觸電腦的人,也常由新聞、報章雜誌中得知,有個網站叫 Facebook,用戶高達 350 萬人,只要上面的遊戲或用戶有點風吹草動,媒體便會大肆報導。

   對於 MSDN 的讀者而言,Facebook 自然不陌生,多少也有耳聞其上有個小遊戲叫【開心農場】(開心農民....哈!),台灣玩這個遊戲的人高達 320 萬之譜,先不管這個遊戲所引起的員工解雇、公務人員禁玩的後續效應,光是看 320 萬這個數字,就足以讓人不得不折服 Facebook 強大的社群影響力,其背後所隱藏的商機更是難以估計。

   在以往,我們很難想像,有個 Flash Game 的使用者高達 320 萬之譜,這已經大大超越了許多傳統線上遊戲的用戶人數,Facebook 究竟有何魅力來吸引這麼多人,而這個遊戲又怎麼樣讓使用者愛不釋手呢?

   若剖析 Facebook 的成功,我們會發現微網誌只是其中的基底,真正將 Facebook 推到巔峰的其實是那些簡單、短時間操作、長時間關注、與朋友互動的小遊戲,這些遊戲有幾個共同的特徵。

  • 簡單
    圖像化的介面,簡單的遊戲規則,讓中年、少年都能輕易上手。
  • 短時間操作
    與傳統遊戲不同,這些小遊戲不需要使用者一直在該遊戲中,也就是不需要一直開啟瀏覽器停在遊戲頁面,幾分鐘的操作後,遊戲便會自己進行下去,種菜、餐廳便是如此。
  • 長時間關注
    與傳統遊戲不同,這些遊戲沒有終點,但也不需使用者花費太多時間在上面,也因為如此,所以使用者會把它當成是每日必做的功課,就跟吃飯、洗澡般直覺。
  • 互動
    使用者可以與朋友互動,例如偷菜、撿垃圾、惡作劇等等,讓人們在溝通上多一個話題,同時這些動作可以與微網誌結合,進而提升了應用程式的可見度,這也是 Facebook 用戶可以快速成長的關鍵原因之一。

  假設日後的線上遊戲能與 Facebook 整合,那麼其推出時的假想用戶數就有 320 萬,這是多麼可觀的商機呀!

Microsoft Facebook SDK 3.0

  身為宅男一族的筆者,自然也當過農夫 (好吧!我承認我種過草、放過蟲、偷過菜....),但我更好奇的是這樣的應用程式是如何撰寫出來的,這些小遊戲又是如何與 Facebook 主機溝通的呢?只是苦於時間的安排,一直沒能深入窺探其究。正巧 Microsoft 於日前推出了 Facebook SDK 3.0,為 Silverlight 應用程式提供一組 Library,讓 Silverlight 應用程式也能輕鬆的躍動於 Facebook 上,這才讓筆者興起了研究 Facebook SDK 的念頭。

   其實,Facebook SDK 已經發展了一段時間,最早的名稱是 Facebook Develop Toolkit 1.0,推出於 2007 年的 5 月,之後於 2008 年推出 2.0,接著便是各位現在所看到的 3.0 了。

   在 Facebook SDK 3.0 中,除了支援將 ASP.NET 應用程式與 Facebook 整合外,還為新加入的兩個成員:ASP.NET MVC 及 Silverlight 添加了新的 Library,其中以 Silverlight 的角色最有趣,因為以往在 Facebook 上的遊戲絕大多數都是以 Flash 開發的,Facebook SDK 3.0 的出現,將引領 Silverlight 進入 Facebook 平台中與 Flash 一較長短,擁有多點觸控技術的 Silverlight 3.0,必然能引發一股創新遊戲的熱潮。

   當然,除了在 Web 上的應用外,Facebook SDK 也沒漏掉桌面應用程式的支援,其提供了 Windows Form 的整合介面,讓設計師可以在自己的應用程式中與 Facebook 溝通,但美中不足的是,原本於發展期間曾經支援的 .NET Compact Framework,在 Facebook SDK 3.0 被移除了,這意味著 Windows Phone 應用程式還是得乖乖的使用 REST API 來與 Facebook 溝通,我想未來 Microsoft 應該會補上這部份。

 

Facebook Platform 概覽

   Facebook Platform 是 Facebook 所提供應用程式整合的平台統稱,其內包含了圖1 的角色。

圖1

  • Facebook REST API

      Facebook 所提供的 API 是以 REST 方式呈現,設計師可透過 C#、C++、Java、PHP 等程式語言以 HTTP 途徑送出特定的 JSON/XML 格式來呼叫指定的 API 函式來取得資料。舉例來說,我們可以呼叫 friends.getLists 這個 API 函式來取得朋友清單,使用 status.get 來取得用戶狀態,所有支援的 API 函式列表可以下列網址取得。

     

  • Facebook JavaScript SDK

      由 Facebook 所提供的 JavaScript Library,設計師於撰寫 Facebook 應用程式網頁時,可以利用這組 Library 來與 Facebook 溝通,那這跟 Facebook REST API 有何不同呢?本質上,JavaScript SDK 也是透過 Facebook REST API 運作的,只是提供了一個包裝,讓設計師不需要自己使用 AJAX 來送出 REST API。另一個不同處是,Facebook REST API 多半是由伺服器端發出的,也就是網頁應用程式所在的伺服器,此時用的是伺服器的網路頻寬,當使用 JavaScript SDK 時,Facebook REST API 呼叫就會由使用者端發出,與伺服器端無關。

  • IFrame

      Facebook 支援三種 Web Application 架構,其一是 IFrame,這種型態的應用程式與 Facebook 完全整合,當使用者以 http://apps.facebook.com/xxx/ 來進入應用程式時,Facebook Server 會產生出一個包含 IFrame 的 HTML 網頁送回給使用者,這個 IFrame 就是連結到指定的網頁,也就是我們的應用程式,下例是一個模擬 Facebook 輸出 IFrame 的 HTML 碼。

<iframe id="app173906708350_iframe_canvas" name="iframe_canvas" src="http://localhost:2618?fb_sig_in_iframe=1......."></iframe>
  • FBML (Facebook Markup Language)

      IFrame 類應用程式的缺點是,應用程式要與 Facebook 溝通時就得發出 REST API 需求,在特定的應用下,這並不是很有效率的動作 (舉例來說,取得所有朋友所發佈的內容,每取得一個朋友的發佈內容,就需送出一次 REST API 呼叫,當朋友數多時,效能會相當的差)。 所以 Facebook 提供了另一種 Web Application 架構:FBML Application,FBML Application 與 IFrame 不同,其運作流程是,當使用者要求應用程式頁面時,Facebook Server 會發出一個 POST 要求至指定的 FBML Application (這意味著這個 Application 得掛載在一個可視於網際網路的 Web Server 上),然後針對其回傳內容進行剖析,最後產生出一個網頁來,下例是一個 FBML Application 網頁的例子,其透過 Facebook Server 解譯後,會產生導向登入頁面的網頁。

<fb:redirect url="http://www.facebook.com/login.php?api_key=2f2342d7e79ddbbce2ff8f93d741484b&v=1.0"/>
  • Facebook Connect

      Facebook Connect 提供了多樣化的整合,如果設計師不想使用 FBML、IFrame,只想將自己的應用程式與 Facebook 整合,那麼就可以使用 Facebook Connect 架構,這是 Facebook Web Application 所支援的第三種架構,使用 Facebook Connect,網頁應用程式不需要掛在 apps.facebook.com/xxx 下,而是維持在你自己的網域下,當需要與 Facebook 溝通時,便可透過 JavaScript SDK 或是 REST API 來完成。注意,Facebook Connect 架構不僅適用於 Web Application,同時也適用於桌上型及裝置應用程式,這也意味著,如果開發的是 Windows Form 的線上遊戲,那麼就能使用 Facebook Connect 與 Facebook 整合,例如得到特定寶物或闖過關卡時,貼上一個訊息到 Facebook,別輕忽這簡單的動作,它可以讓這個用戶的朋友得知他正在玩這個遊戲,進而提升遊戲的能見度。

  • FQL

      FQL 的全名是 Facebook Query Language,主要是提供一組類似於 SQL 的語法規則,讓設計師可以簡單的查詢所要的資料,下例是一個簡單的 FQL 語句例子。

SELECT name 
FROM group 
WHERE gid IN ( SELECT gid 
             FROM group_member 
             WHERE uid=''u1'' 
             AND 
             gid IN (SELECT gid 
             FROM group_member 
WHERE uid=''u2''))

FQL 可以有效的解決因呼叫過多 REST API 所造成的應用程式緩慢問題,日後筆者會專文介紹這個機制。

  • FBJS

      FBJS (Facebook JavaScript),由 Facebook 所提供的 JavaScript 處理機制,用於解決當 FBML 中含有 JavaScript 時,可能會與外部產生衝突的問題。FBJS 同時也提供了 Facebook 常用的物件及 DOM 處理。

  • XFBML

      為 IFrame 應用程式加上 FBML 的支援,如前面所提及,FBML 應用程式的好處是其取得資料時不需透過 REST API,而 IFrame 則一定得透過 REST API,兩者間形成了效能的差距,但對某些應用程式而言,FBML 這種預定義的樣式實在很難發揮設計師的創意,因此為了讓 IFrame 與 FBML 間的效能更接近,Facebook 提供了 XFBML 格式,簡單的說!就是允許設計師在 IFrame 的應用程式中使用部份的 FBML。

從架構面看 Facebook SDK

   看了前面的敘述後,相信讀者們對於 Facebook Platform 已有了一定的了解,現在來看 Microsoft 所推出的 Facebook SDK 架構圖 (圖2)。

圖2

Facebook SDK 由 5 個 Assembly 所組成,分別支援了 ASP.NET、ASP.NET MVC、Windows Form、Silverlight 四種平台。

  • Facebook.dll

    包含了對 Facebook 的基礎支援,提供了 Facebook REST API 的封裝,登入的控制等機制。

  • Facebook.Web.dll

    包含了 FBML Server Control,及協助撰寫 Facebook 上 ASP.NET 應用程式的基礎支援,例如擁有 IFrame/FBML 支援的 CanvasIFrameMasterPage、CanvasFBMLMasterPage 等等。

  • Facebook.Web.Mvc.dll

    包含了協助設計師以 ASP.NET MVC Framework 撰寫 Facebook 上應用程式的基礎支援。

  • Facebook.WinForms.dll

    提供 Windows Form/WPF 與 Facebook 溝通的支援,其同時提供了一組 Facebook 常用的 UI 控件,協助設計師撰寫桌上型的應用程式。

  • Facebook.Silverlight.dll

    提供 Silverlight 與 Facebook 溝通的支援,這是一個特殊的 Assembly,其它如 Facebook.Web、Facebook.Web.Mvc、Facebook.WinForms 都是利用 Facebook.dll 的基礎支援向上發展的,唯獨 Facebook.Silverlight.dll 是單獨存在的。

Facebook SDK 能做什麼?

   從實際面上來看 Facebook SDK,讀者們最想知道的應該是我能用這組 SDK 做什麼?圖3 是一個假想圖。

圖3

舉幾個實際應用的例子來說吧。

  • 網路書店

    使用 Facebook Connect (REST API) 與 Facebook 進行帳號整合,讓使用者買書的記錄發佈在 Facebook 上,讓其朋友可以得知他 (她) 買了那些書,以此達到行銷目的。

  • 桌上型應用程式/線上遊戲

    使用 Facebook Connect (REST API) 取得 Facebook 帳號狀態及朋友現況。

  • IFrame Application

    使用 Facebook 應用程式平台,撰寫例如遊戲、股票等網站應用程式。

  • Silverlight Application

    使用 Facebook 應用程式平台,撰寫 RIA 的遊戲,例如開心 XX。

  • FBML Application

    使用 Facebook 應用程式平台裝載 Flash 遊戲。

申請成為 Facebook Developer

  不管想寫的是什麼型態的應用程式,首先得到 Facebook 申請一個帳號,然後加入 Facebook Developer 的行列,在申請 Facebook 帳號後,請至以下網址。

 

此時會出現圖4 的視窗。

圖4

點選同意後,即會進入圖5 的畫面。

圖5

至此你已經準備好開發 Facebook 應用程式的所有動作了,接著就讓筆者引領各位讀者,一步步的開發第一個 Facebook 應用程式。

申請 Facebook Application

首先請於圖5 的畫面中點選 Set Up New Application 按紐,來到圖6 畫面。

圖6

此處請填入應用程式名稱,注意,不能有 face、facebook 等字樣,按下 Create Application 按紐後來到圖7 畫面。

圖7

此處有兩個重要資訊,API 金鑰及秘密金鑰,存取 REST API 時必須用到這兩個金鑰,別擔心,我們稍後用到時再回來看就好了,現在請切到 Canvas 頁籤。

圖8

這是 IFrame Application 的設定,第一個重要設定是【畫布頁面網址】,此處需填入一個不會與其它 Facebook Application 重覆的識別字,這裡我用了 testapp_tw_r,注意!請不要照填,否則你的 Application 會與我的重覆。接著要填入 Canvas Callback URL,這裡指的是應用程式的網址,就 IFrame 網頁來說,Facebook 會輸出一個包含 IFrame 的 HTML 給使用者,此時這個 IFrame 連結的便是此處所填的網址,這裡多半是輸入根目錄名,由於現在還沒建構這個程式,我們稍後再回來填,請留下此瀏覽器不關。

 

下載 Facebook SDK 與安裝

  在開始開發應用程式前,讀者們得先下載 Facebook SDK,可於下列位置下載。

 

圖9

下載得到的是一個 zip 壓縮檔,請於硬碟建一目錄,然後將其內含的 5 個 Assembly 置入。

圖10

建構 Canvas Application (IFrame)

  待 Facebook 安裝完成後,請啟動 Visual Studio 2008,並建立一個 ASP.NET 應用程式,我們要建立的是如以下影片所示的應用程式。

 

圖11

於參考部份加入 Facebook.dll 及 Facebook.Web.dll。

圖12

接著新增一個 Master Page (主版頁面)。

圖13

在其原始碼部份填入程式1 的內容。

Default.Master
................................
<body>   
    <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"></script>  
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
        </asp:ContentPlaceHolder>
   <script type="text/javascript">
       FB_RequireFeatures(["XFBML"], function() {
              FB.Facebook.init("<API 金鑰>", 
                         "channel/xd_receiver.htm");
       });
    </script>
..................

請注意,其中的 API 金鑰部份請填入建立應用程式時,Facebook 所給你的 API 金鑰。接著切換到程式頁,加入程式2 的內容。

程式2

Default.Master.cs
...................
using Facebook;
using Facebook.Web;
............
    public partial class Default : Facebook.Web.CanvasIFrameMasterPage
    {
        public Default()
        {
            RequireLogin = true;
        }
    }
}

然後將 Default.aspx 刪除,添加一個 Web Content (Web 內容表單) 項目,挑選 Default.Master 為主版頁面,接著於原始碼處填入程式3 內容。

程式3

Default.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Default.Master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="FrameDemo.Frame1" %>

<%@ Register Assembly="Facebook.Web" Namespace="Facebook.Web.FbmlControls" TagPrefix="fb" %>
<%@ Register Assembly="Facebook.Web" Namespace="Facebook.Web" TagPrefix="cc1" %>
<%@ MasterType VirtualPath="~/Default.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <p>
    </p>
    <form id="form" runat="server">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"
        ForeColor="#333333" GridLines="None" 
        OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
        <RowStyle BackColor="#E3EAEB" />
        <Columns>
            <asp:ImageField DataImageUrlField="pic_small">
            </asp:ImageField>
            <asp:BoundField DataField="name" HeaderText="Name" />
        </Columns>
        <FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
        <PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Center" />
        <SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333" />
        <HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
        <EditRowStyle BackColor="#7C6F57" />
        <AlternatingRowStyle BackColor="White" />
    </asp:GridView>    
    </form>
</asp:Content>

切換至程式部份,填入程式4 內容。

程式4

Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Facebook.Web;
using Facebook.Rest;
using Facebook.Session;
using System.Configuration;

namespace FrameDemo
{
    public partial class Frame1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                List<FacebookInfo> list = new List<FacebookInfo>();
                //呼叫 REST API 取得朋友清單
                var users = Master.Api.Friends.GetUserObjects();
                foreach (Facebook.Schema.user user in users)
                {
                    list.Add(new FacebookInfo()
                    {
                        name = user.name,
                        pic_small = user.pic_small,
                        uid = (long)user.uid
                    });
                }
                GridView1.DataSource = list;
                GridView1.DataBind();
            }
        }
        protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
        {
        }
    }

    public class FacebookInfo
    {
        public string name { get; set; }
        public string pic_small { get; set; }
        public long uid { get; set; }
    }
}

這段程式其實很簡單,就是利用 Facebook 的 REST API 來取得朋友清單,並與 GridView 做繫結後顯示。接著請開啟 web.config 檔,加入程式 5 的內容。

程式5

Web.config
................
<appSettings>
		<add key="APIKey" value="<API 金鑰>"/>
		<add key="Secret" value="<祕密金鑰>"/>
		<add key="Callback" value="http://localhost:2618"/>
		<add key="Suffix" value=" testapp_tw_r"/>
	</appSettings>
...................

請於此填入之前 Facebook 提供的 API 金鑰及秘密金鑰,接著 Callback 部份要填入此應用程式啟動時的網址,注意!你的程式啟動時的 Port 不見得與我的相同,請於 Visual Studio 2008 按下 F5 後觀察右下角來取得 Port。

圖14

這個 Port 也要填到圖8 中的 Canvas Callback URL 欄位 (以本例來說就是 http://localhost:2618),Suffix 部份則是填入申請 Application 時填入的名稱,以本例而言就是 testapp_tw_r。完成後按下 F5 啟動應用程式,待完成 Facebook 登入後,並允許 testapp_tw_r 存取你的資訊後,就可看到朋友列表。

圖15

那麼如何透過 Facebook 來啟動程式呢?簡單,只要於網址上輸入以下內容即可。

http://apps.facebook.com/testapp_tw_r/

 

圖16

 

簡單背後的知識

  歸功於 Facebook SDK,所以我們能用這麼短的時間及少量的步驟來完成這個應用程式,但其背後其實隱藏了許多的知識,圖17 是由程式架構面來看的詳細運作過程。

圖17

  當使用者要求我們的網頁時,首先會經過繼承 CanvasIFrameMasterPage 類別的 Default.Master,此處會依據設定 (RequireLogin) 來決定是否轉向 Facebook 的登入網頁,一般來說,如果使用者於登入 Facebook 有勾選記錄密碼的話,就不會再看到登入網頁,反之則進入登入網頁。

  當登入動作完成後,Facebook 會自動再導回我們的網頁,此時回導時會帶回一個 Session Key 做為識別,之後呼叫 REST API 的動作都必須傳入這個 Session Key 做為憑證。

後記

  請注意,本文所開發的程式僅能在開發本機上瀏覽,如果要讓朋友或其它人也能使用此應用程式,那麼就必須使用真正可在網際網路上存取的網址。

 

【範例資源下載】