2010年1月4日 星期一

Facebook Flash Application開發心得(5) - 新版的streamPublish


Facebook的api在之前偷偷的有更新過了一次,但是flash的swc似乎仍然沒有變動,基本上影響不大。
其中發佈到個人塗鴉牆的部份,Facebook打算捨棄原本的template,從原本FB.Connect.showFeedDialog改成FB.Connect.streamPublish,這樣也好,不然每次要弄一個新的format就要去註冊一個新的template,這樣真的很麻煩。由於舊方法目前還可以繼續使用,但是為了將來著想,最好還是將舊有的程式改寫成新方法會比較好。
說是對flash影響不大的原因,因為雖然flash api裡原本就有com.facebook.commands.feed.PublishTemplatizedAction這個類別來處理發佈到塗鴉牆的工作,但是如果使用者沒有去允許這個app擁有完整publish_stream的權限的話(一般來說使用者很少主動允許這個權限),從flash發佈出去的東西是不會主動呈現在使用者的塗鴉牆上的,需要使用者回到自己的塗鴉牆再去點選一次才會真的出現,因此實用性並不大,我也是通常都使用javascript來處理發佈的動作。

因此在這裡記錄一下streamPublish該怎麼處理好了。
新版的發佈動作是藉由javascript api裡的FB.Connect.streamPublish來進行的。
streamPublish(String user_message, Object attachment, Object action_links, String target_id, String user_message_prompt, Function callback, Boolean auto_publish, String actor_id)
這些參數的意義分別為:
1. user_message:要講的話,通常是空的,由使用者自己填寫。
2. attachment:這是一個Object,就是原本的template,用來制定塗鴉牆上顯示的格式,attachment的寫法是重點,待會再提。
3. action_links:塗鴉牆上的連結,一樣是Object型態,通常是[{ "text": "點這邊!!", "href": "http://www.yourdomain.com/xxx.html"}];
4. target_id:要發佈到誰的塗鴉牆上,如果是要發佈到使用者自己的塗鴉牆的話,這個值就要帶空值。
5. user_message_prompt:會出現在user_message之前的一個開頭語,例如『正在想』、『覺得』…etc這些東西。
6. callback:對話窗關閉後會回call的function,如果不打算接受這個事件就不用管。
7. auto_publish:如果使用者已經同意publish_stream的權限且auto_publish是帶true的話,那麼使用者將不會看到有對話窗跳出來,訊息會直接出現在塗鴉牆上。(個人十分討厭這種作法)
8. actor_id:這好像是粉絲頁面用的,可以選擇直接發佈到粉絲頁,但前提是這個使用者是該粉絲頁的管理者。


看起來是很簡單明瞭了。
所以主要的重點還是在attachment。其實attachment跟以前的template差別不大,分別只在於以前的template先制定好了『格式』,現在的attachment則是隨時可以帶入不同的Object,比較活。
官方wiki對於attachment的解說請參考這個網址
http://wiki.developers.facebook.com/index.php/Attachment_%28Streams%29

通常attachment會具有以下幾個properties:
1. name:就是主旨。
2. href:主旨點下去會連結的網址,通常是app或是某活動、官網的網址。
3. caption:跟name不一樣,也跟下面的description不一樣,這個caption通常會寫出誰誰誰做了什麼事,在caption裡加上{*actor*}的話這一串字串就會自動被取代成使用者的名稱,例如:『{*actor*}剛剛做了心理測驗』,出來的結果就會是『Jason剛剛做了心理測驗』
4. description:嗯,這個就是一大堆文字了,可以當成作文去寫,通常facebook裡那些心理測驗在解釋測驗結果的那一大堆話就是塞在這個屬性裡。
5. properties:這屬性我還沒實作過,功能還不明,跳過。
6. media:除了description以外最多人用也最有興趣的就是這個屬性了,這是一個陣列,定義了所有會出現的圖或flash或聲音,全都塞在這個陣列裡,陣列裡放的是Object,每一個Object會有三個屬性:type,src,href。type定義是什麼媒體,有image、flash及mp3三種,src則是這個媒體所在的網址,href就是點了之後會連到哪。所以media應該會是類似這樣的型態:[{'type': 'image', 'src': 'http://icanhascheezburger.files.wordpress.com/2009/03/funny-pictures-kitten-finished-his-milk-and-wants-a-cookie.jpg', 'href': 'http://icanhascheezburger.com/2009/03/30/funny-pictures-awlll-gone-cookie-now/'}, {'type': 'image', 'src': 'http://photos.icanhascheezburger.com/completestore/2009/1/18/128768048603560273.jpg', 'href': 'http://ihasahotdog.com/upcoming/?pid=20869'}]
7. 剩下的像comments_xid及自定義屬性,好像都是要用再更深入的機制上才會用到的,目前我也沒實作過,因此一樣跳過。
基本上attachment最常被使用到的就是這幾個屬性了,差不多瞭解了之後就可以很快的發佈屬於自己的塗鴉牆。


接下來,如何從Flash去呼叫FB.Connect.streamPublish,不用說一定是透過ExternalInterface,需要注意的是,因為attachment是一個Object,我試過直接用Flash丟Object出來給js,結果是失敗的,雖然js也是收到一個Object,但是其實這個Object已經不是原本的Object了,所以要嘛就是把要發佈的attachment先在js裡寫好,但是這麼一來整個code又變得很不活,也無法類別化,所以我都會改採另外一種方式:JSON。
在Flash裡,先產生相對映的Object,然後藉由Adobe as3corelib裡面com.adobe.serialization.json的package,JSONEncoder類別將Object轉換成JSON的字串後,用字串的方式傳遞給js,js裡再還原成Object就可以了,js裡字串還原成JSON的方法可以直接用eval,或是使用JSON.js來做parsing的動作(JSON.js可在此下載http://www.json.org/js.html)。
這樣做的好處是可以在flash裡動態的隨時產生不同的attachment,視不同的狀況發佈不同的塗鴉牆,比較靈活,js也不需要因為每個專案而再重新編寫。

17 則留言:

  1. 您好!!小弟開發FB程式從版主的網站學到了很多觀念與方法,終於成功的完成作品了,可是小弟遇到了一個窘境,最後的產品只有小弟看得到別人都無法使用,經小弟找了很久的終於查到原因,似乎是develop mode沒有取消,可是小弟完全找不到設定的地方,不知版主是否有遇到這個問題。

    回覆刪除
  2. 我自己是沒遇到這個問題,因為我很少去動那些奇怪的設定,
    不過我剛剛去看了一下, 會不會是Advacned -> Sandbox Mode被選為"啟用"的關係?

    回覆刪除
  3. 我解決了,哈哈,抱歉了,我後來找到官網說develop mode 和 Private Install 的設定已經取消了,所以我又轉回我的程式檢查,終於找到bug了,謝謝。

    我的作品
    http://apps.facebook.com/kyokuvideo

    我很多地方都是參考版主的教學才完成的,真的太感謝您了。

    回覆刪除
  4. 你好 小弟目前在研究塗鴉牆,我是用facebook ifarme方式想進行塗鴉動作,我把FB.Connect.streamPublish 放在html裡面。
    再利用ExternalInterface.call("(javascript函式)");
    當我執行flash方式進行動做的時候呼叫ExternalInterface.call 執行函式裡面的FB.Connect.streamPublish 卻沒有任何動作,是發生什麼問題呢?
    希望大大可以分享一些經驗 謝謝!

    回覆刪除
  5. Jimmy:
    因為streamPublish是FB.Connect裡的一個方法, 所以其實它是走Facebook Connect的, 你需要在你app的設定裡設定聯外通才行.

    回覆刪除
  6. 喔 那大大意思是說,我必須要在設定連外通那邊,設定call back道我自己的應用網站還是自己的server端呢?

    謝謝大大給的寶貴意見!

    回覆刪除
  7. 喔耶! 我成功了。感謝jason提供的資訊
    我設定了聯外通 路徑設在自己server端的地方,後來發現FB.Connect.treamPublish 其實需要用到一些funtion才可以做動作,
    FB.ensureInit(function() {//ensureInit 所需要的動作在於call back到 javascript api做動作
    這是他函式解說:function to call when Facebook is dynamically loaded.
    //再來就是把所要執行的動作寫成function後 post給facebook的javascript api FB.Connect.requireSession(function(){
    //requireSession 有2個參數,在jason大大教學裡面有提供,第一參數是要執行的動作,第二參數則是要不要強行開啟式窗
    var message = "9876543";
    FB.Connect.streamPublish(message);
    },true);
    });

    謝謝大大提供資訊! 不知道有哪邊解說不正確的,希望可以糾正。
    下一個目標就是要用flash先設定好所要輸入的資料,在call javascript post到facebook!! 並且以不彈出式窗直接post到塗鴉牆上面!!

    回覆刪除
  8. Jimmy,
    你描述的基本上沒什麼錯, 主要就是要初始化並登入Facebook Connect, streamPublish才會作用.
    至於不彈出視窗post到塗鴨牆上, 你需要先取得permission.

    回覆刪除
  9. jason好! 最近遇到facebook 難題!
    目前想把自己塗鴉牆上面自己最新狀態包函而外的連結檔案和其他訊息也抓到自己應用程式,目前只能抓取actionscript api 裡面的user.message
    也就是抓到塗鴉牆自己所打入的string,如果想抓取而外其他FB.Connect.streamPublish(),所填入的資料,要從哪裡下手呢?

    我在actionscript api 裡的stat 好像只給message,其它相關資料不知道哪邊才可抓取,希望大大能指點一些方向。

    回覆刪除
  10. actionscript的library所提供的api有限. js其實也一樣, 不過facebook有提供一個補足這些不夠用的api一個東西:FQL, 讓你可以透過SQL語法直接去對facebook取得資料(也允許關聯語法).
    讀取塗鴨牆的資料, 我自己本身就是使用FQL來取得的.

    回覆刪除
  11. 恩 那就是要用FQL方式讀取了 是在actionscript 用fql 還是用 javascript 呢 我也在試javascript 方式用fql

    回覆刪除
  12. Jason老師好 : 那請問怎麼讓user能同意publish_stream的權限?

    回覆刪除
  13. EricKuo:如果要跳出發佈視窗的話,是不需要取得publish_stream的權限的. 那如果你一定要取得publish_stream權限的話, 通常都是在登入時一並要求.
    假設你是使用導向登入的話, 就是將要取得的所有權限一併帶在網址後面導過去: https://graph.facebook.com/oauth/authorize?scope=read_stream,publish_stream&client_id=YOUR_APP_ID&redirect_uri=....

    那如果你是使用JS API去登入的話, 那就是參數裡多帶一個perms的變數:
    FB.login(response, {perms:"read_stream,publish_stream"});

    回覆刪除
  14. 恩..我在研究看看~謝謝Jason老師!

    回覆刪除
  15. 我想請問我是IOS連結到Facebook,是直接是Facebook的範列作修改.我想要輸入user_message的文字,讓使用者可以直接貼文,可是我的user_message跟user_message_prompt的資料都沒有顯示.

    NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
    kAppId, @"api_key",
    @"Share on Facebook", @"user_message_prompt",
    @"tes tuser_message", @"user_message",
    actionLinksStr, @"action_links",
    attachmentStr, @"attachment",
    nil];

    [_facebook dialog:@"stream.publish" andParams:params andDelegate:self];

    回覆刪除
  16. Jason您好,感謝您詳細的解說,有事想請教,小妹目前開發團隊開發了一款遊戲,放置FB上,但是畫布配置出了些問題,通常FB進入遊戲後畫面會顯示在正中間,而我們卻是顯示在最左方,請問可有解決方法?

    回覆刪除