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的實際「滑鼠有效範圍」就會被改變了。

2009年6月17日 星期三

Facebook Flash Application開發心得(前言)


Facebook的API很久以前就有了,嗯。
不過前一段時間,就在Adobe跟Facebook正式宣佈要一起建構什麼新型態的社交平台之後,終於有了CS3版本的swc。(之前都是Flex版的)
基本上我仍然十分習慣在CS3之下工作,還不是很喜歡打開Flex。所以一看到有CS3的版本後就開始把玩了起來。

說真的,目前為止,我個人覺得Facebook的API說明文件寫得真的不是很好,有太多東西需要開發者自己去摸索。其實我可以理解Facebook針對client端語言的一些限制,畢竟權限以及預防API的被濫用是他們很大的一個課題,只是這些東西我都是要google好久才發現原來我必需要繞一條路去跑。

另一個部份是Application的設定問題,倒是也花了我不少時間才搞清楚什麼東西要怎麼設。

接下來應該會花幾篇的功夫記錄我這幾天在Facebook上開發flash application的心得。Adobe官網上的文章在某方面可以一看,但是更進階的部份卻更新十分緩慢,O’Reilly Inside RIA裡Mirza Hatipovic寫的幾篇文章倒是給了我一些方向,有興趣的可以先從他的文章開始。
http://www.oreillynet.com/pub/au/3675
他似乎是預計要寫二十篇來做教學,但是似乎很不巧的在他寫到一半時Facebook for Flash的API有了一些改變,但是我想基本原理不變。


至於我的部份,純粹會是記錄我在實際設定以及執行上遇到的一些問題及解決方法,一來讓我可以自己將來回頭再來翻閱,而來如果有人也需要這些資訊的話希望可以幫上一點忙。

之後新增的有關Facebook開發的文章將會列舉連結在下面:
-----------

Facebook Flash Application開發心得(1) - FB Connect - how to start
Facebook Flash Application開發心得(2) - FB Connect - 接上Flash
Facebook Flash Application開發心得(3) - 由Flash Api從Facebook取得資料
Facebook Flash Application開發心得(4) – Iframe的架構下取得Session
Facebook Flash Application開發心得(5) - 新版的streamPublish

2009年6月11日 星期四

Loader跨網域讀取圖檔,以及讀取Picasa的限制


Loader在跨網域讀取圖檔基本上是不需要crossdomain policy的,只是純粹當個乖乖的DisplayObject是沒什麼問題的,但是如果一但需要使用BitmapData對它做draw的動作時,flash player的安全性原則會封鎖這個動作。

這個問題很常見,之前也遇到過好幾次,但是一直沒有白紙黑字記下來,所以搞得自己常常忘記。
基本上要避開這個問題會需要用到LoaderContext這個類別。

通常我們在使用Loader讀取圖片或swf時:
public function load(request:URLRequest, context:LoaderContext = null):void

第一個參數URLRequest一定要的,第二個LoaderContext一般來說我們常常省略不下。不過現在要解決上述的問題時,我們就需要用到它了。
將LoaderContext. checkPolicyFile設成true再帶入就ok。但前題是遠端網域那邊要有允許你crossdomain才行 ,不然的話依舊沒輒。


順帶一提跟Picasa有關的,當Loader在讀取Picasa相簿裡的大圖時,很奇怪的事會發生。
開發時都很正常,丟到FireFox上也可以跑,但是一但用IE(測試的版本是IE 6)就怎樣都會遇到http 404,可是網址copy出來直接用IE開就又讀得到。
後來才知道在IE裡Loader如果去讀Picasa裡尺寸大於800 pixels的圖檔就會這樣,這似乎是Picasa的限制,只對外提供最大尺寸為800的圖(只是我不懂為什麼只有IE會這樣...)。

總之要解決這個問題就只能在Picasa大圖的網址後面加上「?imgmax=800」就好了。

2009年6月9日 星期二

URLLoader取得的bytesLoaded有可能大於bytesTotal!?


無意中發現了這一個很奇怪但是我目前為止無法解釋的現象。
我現在並不認為這是URLLoader的「Bug」,因為我覺得這種情況是有點複雜的,也許並不完全是URLLoader的問題。


情況如下:
今天手癢想寫個類別把我自己在Picasa相簿裡的一些照片資訊取出,讓自己以後可以方便編寫相簿瀏覽的介面。
因為在本機開發還不需要顧慮到crossdomain的問題,所以一開始我是直接取用Picasa的RSS,起初都還挺順利的,RSS的解析也都寫得差不多了,但是當我改讀另一個照片比較多的相簿時,就發現要將URLLoader.data給轉型成XML時一直出錯。
這個RSS的URL如下:
http://picasaweb.google.com/data/feed/base/user/jason.tseng76/albumid/5243914003216812001?alt=rss&kind=photo&hl=zh_TW

第一個反應就是,會不會是RSS的檔太大了? 導致RSS在還沒被完全讀取完全之前URLLoader的COMPLETE事件就被觸發了?
所以我就多監聽了一下ProgressEvent.PROGRESS事件,結果就很有趣了,trace出來的結果是bytesLoaded的值居然比bytesTotal還大。就看著ProgressEvent硬生生的把破表的值給丟了出來。
我也試過把URLLoader.data的值給trace出來,但是可能真的太大了,每次trace就每次當。

於是我也只能再次懷疑是不是檔頭或什麼的東西造成了URLLoader的判別出錯,直接把URLLoader.data轉型成XML出問題恐怕一定是整個資料讀取不完全(或是讀到多的東西!!?)。
所以我只好改走Picasa專門提供給Flash使用的RSS(有crossdomain policy的路)。
http://code.google.com/intl/zh-TW/apis/picasaweb/reference.html#Flash

轉換過後原本RSS的URL會變成這樣:
http://photos.googleapis.com/data/feed/base/user/jason.tseng76/albumid/5243914003216812001?alt=rss&kind=photo&hl=zh_TW

再try一次。
過了!
但是bytesTotal永遠都是顯示為0…。
好吧… 只能說至少work了。
至於為什麼bytesTotal會是0? 我想這已經有點超出我知識的範圍了…。