2009年7月29日 星期三

Facebook Flash Application開發心得(1) - FB Connect - how to start


使用Facebook的api來開發的應用程式基本上有很多種,Adobe這邊有大概的說明:
http://www.adobe.com/devnet/facebook/


其實說穿了就大概可以分成四大種,
1. 在Facebook裡的應用程式
2. 在Facebook裡的iframe應用程式
3. 不在Facebook裡的應用程式 (例如你自己的website)
4. 桌面應用程式 (就AIR囉)

為什麼要分種類呢? 因為四種的api寫法都有一點點不同,需要注意的地方也不一樣,不過就我玩了這一段時間,如果是要專心於用Flash當主題來開發的話,也許有些事情會簡單一點(雖然還是很麻煩!)。
Adobe官網也有一些簡單的入門教學,可以大概看一下,不過好像都是針對第1、2種的方式在做入門就是了,但是不無小補。

一、下載Facebook flash api:
OK,首先要做的當然是去下載Facebook flash api。
http://code.google.com/p/facebook-actionscript-api/


二、申請Facebook應用程式:
接著就是到Facebook登記一個自己的應用程式,取得API金鑰及Application Secret code。
http://www.facebook.com/developers/

登記好應用程式後就要先進行一些設定:
1. 基本資料的部份 -> 應用程式名稱 -> 就是填你的應用程式名稱…
2. 驗證、個人檔案、Widgets以及進階的部份先不用管沒關係,不影響開發。
3. 如果是要開發在Facebook裡的應用程式的話,就要去填「畫布(Canvas)」裡的資料,如果是要開發不在Facebook裡的應用程式,那就要去填「Connect」裡的資料。
4. 畫布(Canvas) -> 畫布頁面網址 -> 使用者打這個網址就會連到你的應用程式
5. 畫布(Canvas) -> Canvas Callback URL -> 你的應用程式「實際上」的網址。
6. 畫布(Canvas) -> 呈現方法 -> 選iframe或是FBML (就是最上面第一種跟第二種的差別)
7. Connect -> Connect URL -> 你應用程式「實際上」的網址。
8. 先填選Connect吧,從Connect入手我覺得比較快,而且一但Connect的部份上手了之後,再轉成iframe應該很多部份會很快。

基本上由於目前我只試過用iframe及connect的方法開發,為什麼我不用FBML? 因為我不太會php…,所以我為了怕以後需要用asp或asp.NET整合時會發生的問題,因此我一開始玩Facebook api的時候就是先玩iframe,之後才試著玩connect。
所以我之後會記錄在這裡的一些經驗大多都會是以這iframe及connect為主。
這一篇則會是以Connect做為開始,因為如果開發iframe application話,關於畫布(Canvas)裡的很多設定就要去處理,也要瞭解每個設定為什麼要這麼設(為了try這些設定的不同真的很花時間),而Connect的大部份api寫法都跟在iframe裡的差別不會很大,所以我才會想說先從Connect application下手應該會是比較好的方法。


三、建立一個crossdomain policy:
由於facebook的api需要許多的認證,因此他們有他們自己的crossdomain檔,不像flash一樣都是用crossdomain.xml。這個facebook的crossdomain檔我通常都沒去改它的名字 - xd_receiver.htm。
把xd_receiver.htm它放在你application「實際存在」的空間裡,當facebook需要時自然會來讀它,例如:如果你的Application是位於http://iamjason.com/demo/,那麼你就可以把它丟在這兒就好。
xd_receiver.htm會長成像這個樣子:

你可以自己寫一個,或者是乾脆到這裡下載,裡面什麼東西都不用改。


四、來個Hello World:
請注意,這個Hello World是使用Connect的方式,因此請注意如果在application裡的設定沒有填寫Connect URL的話會有點問題。

1. 建立一個index.htm,使用Connect的話,html的宣告需要依照facebook的標準,如下:


2. 即使我們要用Flash來開發,但是Facebook的一些限制,我發現很多時候需要借用Facebook的javascript api才能達到一些功能(例如邀請朋友以及獲得某些授權...等等),所以我們要引用需要的javascript檔進來:

3. 編寫需要的javascript,初始化facebook connect,並判斷登入狀態:

這邊寫完大概就可以放上去測試一下了,如果你的Connect URL填寫的是
http://iamjason.com/demo/
那麼就把這個htm放到這裡去,然後打開瀏覽器輸入這個網址,理論上你就會得到一個”not connected”的alert。

4. 加入一個登入的鈕:
Facebook允許它的javascript去render一些需要的視覺控制元件,這邊我們使用登入鈕來做測試。
在<body>裡加上一個div,裡面塞入登入鈕:


然後改寫一下剛剛的javascript裡onConnected及onNotConnected的function,讓還沒登入時出現登入鈕,登入後就把登入鈕隱藏起來:

完成了,這樣基本上就可以測試一下了。
會看到一個facebook的制式藍色登入鈕,點了它之後會跳出一個小視窗,登入後就會把登入鈕隱藏起來。
由於Facebook是用session的方式來驗證登入狀態,因此一但登入後,只要這個瀏覽器的session沒有改變,重新整理畫面的話仍然會被視為是登入狀態。不過我遇到一個狀況,如果重新整理畫面,onNotConnected會先被觸發,過一陣子才會觸發onConnected,不過我想這很正常,應該是連到Facebook去驗證的時間差,所以順道提一下,之後在開發時盡量避免被這問題卡到。

另外,要初始化Facebook api的方法其實很多,大部份看到的都是用new一個FB.ApiClient來處理,但是當FB.ApiClient被new出來的時候,Facebook如果判斷使用者的狀況是尚未登入的話就會馬上將使用者導去登入,可是如果我們使用Connect來建立application時,常常的情況是要將Facebook的api用在自己的網站上,又不想使用者一來就馬上就先被要求登入,所以我才會選擇使用FB.init的方式進行初始化,然後在真的需要使用者登入的時候再進行登入的動作。
這兩種作法要採用哪一種方法,我想就是看當時要開發的需求而定了,之後在進行iframe的application開發的時候,將會採用new FB.ApiClient的方式。(因為一定要先登入)

現在我們有了Hello World,下一篇就是準備把Flash給帶進來了。

下一篇
Facebook Flash Application開發心得(2) - FB Connect - 接上Flash

2009年7月17日 星期五

DisplayObject上層擋到下層滑鼠事件問題


有一個常遇到但是一但遇到老是不求甚解的就把它解決掉的問題,這幾天在處理一個案子的時候又遇到了。
在AS3裡,位於上層的DisplayObject會阻擋滑鼠事件,所以會導致較下層的物件無法接收到滑鼠事件。這理論上看起來是合理的,只是問題的發生點通常都是在我們常會忽略掉的地方,那就是透明圖層。
設計師們常常會利用PNG的透明背景來處理一些效果,而我們也常常忘了這個PNG其實是一個方形的存在,因此就會在Runtime時遇到明明看起來沒東西的地方但是滑鼠事件就是不會work的狀況。

Ok,解決的方法就是將擋到的DisplayObjec的mouseChildren及mouseEnabled設為false。通常這樣也都可以解決問題。
但是這次我遇到的狀況比較不一樣,才發現事實沒這麼簡單。
我這次的狀況是,場景上一個MovieClip(簡稱MC_A)裡面有動畫,其中有一個按鈕。但是很不幸的這些動畫擋到了場景上的另一個MovieClip(簡稱MC_B)裡的按鈕。(請注意MC_A及MC_B是位於同一個DisplayObjectContainer裡)
很直覺的我用一個迴圈將所有MC_A裡除了按鈕以外的DisplayObject的mouseChildren及mouseEnabled都設為false,感覺這樣就可以解決問題,但是很遺憾發佈後MC_B還是一樣被MC_A的一些東西擋住(這些東西我都已經設成mouseChildren及mouseEnalbed為false了)。
於是我做了一些實驗,我在MC_A裡把MC_A的按鈕都放到最低的層級裡,把動畫都拉上來,如果我沒跑迴圈去將動畫的mouseChildren及mouseEnalbed設為false的話,MC_A裡的按鈕及MC_B裡的按鈕都不能work。但如果我有跑迴圈,那麼只有MC_B裡的按鈕會無法work。
有些人也許已經知道是怎麼回事了。

照這種情況看起來,MC_A裡面的DisplayObject其mouseChildren及mouseEnabled屬性只會在MC_A這個DisplayObjectContainer裡生效,對於MC_B這個與MC_A存在於同樣一個層級的物件來說,MC_A的「滑鼠有效範圍」仍然是整個MC_A的所有範圍。
因此在MC_A裡不管怎樣的最裡面的mouseChildren或mouseEnabled做操作,對於MC_A以外的物件來說,它們只認識MC_A自己的mouseChilren及mouseEnabled。

在這個案例裡,由於我的MC_A裡還有按鈕,所以我不可能將整個MC_A自己的mouseChilren及mouseEnabled設為false,因為這樣一來我MC_A裡的按鈕也跟著廢掉了。
最後我才知道我忽略了一個很簡單的解決方法,那就是直接將MC_A的hitArea屬性設為按鈕實際的感應區域就好了。這樣子對MC_B來說,MC_A的實際「滑鼠有效範圍」就會被改變了。