2010-03-29

寫了個方便處理 FacebookSession 的類別

承上一篇「Flash Builder 4 寫 Facebook Apps」,有自行測試者應該都會覺得在開發 Facebook appa上,除錯顯得很麻煩。必須先把 AppKey 和 AppSecret 填入程式中,測試完,拿掉 AppKey 和 AppSecret,編譯再上傳測試,中間會來來回回很多次。時間應該浪費在美好的事物上,玩 Games 應該比寫 Codes 美好 :P。
可以將 AppKey 和 AppSecret 放到一個檔案裡,再載入。URL-encoded 的文字檔是個選擇,為了讓本篇看起來有深度點(誤),在此採用SWF。若要更有深度可以用ZIP、DOC...,也可以修改副檔名偽裝一下。
若可以載入 Key 檔,表示是在開發過程,必須連一下 Facebook 取得 Session。若無法載入 Key 檔,表示己經發佈了。

Step 1: 製作 Key 檔,如下的類別檔,用FlashDevelop搭Flex編譯成SWF
package 
{
 import flash.display.Sprite;
 public class FbastutorialKey extends Sprite
 {
  public static var appapikey:String = '::AppKey::';
  public static var appsecret:String = '::AppSecret::';
 }
}

Step 2: 將 AppKeyLoader 和 SessionGetter 複製到專案裡。AppKeyLoader 是載入 Key 檔,若有取得 Keys,丟出個 complete 事件;若沒取得,丟出個 ioError 事件。SessionGetter會使用AppKeyLoader,依 Keys 取得的方式,做不用的處理,丟出個 connect 事件。接到 connect 事件再去拿 facebookSession 或 facebook 物件即可。
package lin.shinder.facebook.utils
{
 import flash.display.Loader;
 import flash.events.Event;
 import flash.events.EventDispatcher;
 import flash.events.IOErrorEvent;
 import flash.net.URLRequest;
 import flash.system.ApplicationDomain;
 import flash.system.LoaderContext;
 import flash.utils.getDefinitionByName;

 [Event(name="complete", type="flash.events.Event")]
 [Event(name="ioError", type="flash.events.IOErrorEvent")]
 
 /**
  * ...
  * @author shinder.lin
  * @date 2010/03/28
  */
 public class AppKeyLoader extends EventDispatcher
 {
  private var loader:Loader;
  private var loaderContext:LoaderContext;
  private var request:URLRequest;
  private var keyClassName:String;
  
  private var _appapikey:String;
  private var _appsecret:String;
  private var _loaded:Boolean;
  
  public function AppKeyLoader(keyClassName:String) {
   this.keyClassName = keyClassName;
   loader = new Loader;
   loaderContext = new LoaderContext;
   loaderContext.applicationDomain = ApplicationDomain.currentDomain;
   
   request = new URLRequest(keyClassName + ".swf");
   loader.load(request, loaderContext);
   loader.contentLoaderInfo.addEventListener(Event.COMPLETE, eventHandler);
   loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, eventHandler);
  }
  
  private function eventHandler(event:Event):void {
   if (event.type == Event.COMPLETE) {
    var KeyClass:Class = getDefinitionByName(keyClassName) as Class;
    _appapikey = KeyClass.appapikey;
    _appsecret = KeyClass.appsecret;
    _loaded = true;
   } else
   if (event.type == IOErrorEvent.IO_ERROR) {
    _loaded = false;
   }
   dispatchEvent(event);
  }
  public function get appapikey():String {
   return _appapikey;
  }
  public function get appsecret():String {
   return _appsecret;
  }
  public function get loaded():Boolean {
   return _loaded;
  }
 }
}
package lin.shinder.facebook.utils
{
 import com.facebook.Facebook;
 import com.facebook.events.FacebookEvent;
 import com.facebook.utils.FacebookSessionUtil;
 
 import flash.display.LoaderInfo;
 import flash.events.Event;
 import flash.events.EventDispatcher;
 import flash.events.IOErrorEvent;
 import flash.net.URLRequest;
 import flash.net.navigateToURL;
 
 import mx.controls.Alert;
 import mx.core.FlexGlobals;
 
 import spark.components.Application;
 
 [Event(name="connect", type="com.facebook.events.FacebookEvent")]
 
 /**
  * ...
  * @author shinder.lin
  * @date 2010/03/28
  */
 public class SessionGetter extends EventDispatcher
 {
  private var session:FacebookSessionUtil;
  private var appKeyLoader:AppKeyLoader;
  private var application:Application;
  private var loaderInfo:LoaderInfo;
  
  public function SessionGetter(keyClassName:String) {
   application = Application(FlexGlobals.topLevelApplication);
   loaderInfo = application.loaderInfo;
   
   appKeyLoader = new AppKeyLoader( keyClassName );
   appKeyLoader.addEventListener(Event.COMPLETE, getSessionBySWFKey);
   appKeyLoader.addEventListener(IOErrorEvent.IO_ERROR, getSessionByURLKey);
  }
  
  private function getSessionBySWFKey(event:Event):void {
   var appapikey:String = appKeyLoader.appapikey;
   var appsecret:String = appKeyLoader.appsecret;
   session = new FacebookSessionUtil(appapikey, appsecret, loaderInfo);
   session.addEventListener(FacebookEvent.WAITING_FOR_LOGIN, whenWaitingForLogin);
   session.addEventListener(FacebookEvent.CONNECT, onSessionConnect);
   session.login();
  }
  
  private function whenWaitingForLogin(event:FacebookEvent):void {
   var alert:Alert = Alert.show("登入 Facebook 後點按 OK!","登入");
   alert.addEventListener(Event.CLOSE, onAlertClosed);
  }
  private function onAlertClosed(event:Event):void {
   session.validateLogin();
  }
  
  private function getSessionByURLKey(event:Event):void {
   var appapikey:String = loaderInfo.parameters.fb_sig_api_key;
   var appsecret:String = null;
   session = new FacebookSessionUtil(appapikey, appsecret, loaderInfo);
   session.addEventListener(FacebookEvent.WAITING_FOR_LOGIN, whenWaitingForLogin);
   session.addEventListener(FacebookEvent.CONNECT, onSessionConnect);
   
   if(loaderInfo.parameters.fb_sig_added == true){
    session.verifySession();
   } else if(loaderInfo.parameters.fb_sig_added == false){
    navigateToURL(new URLRequest("http://www.facebook.com/login.php?api_key="+appapikey),"_top");
   } else {
    session.login();
   }
  }
  
  private function onSessionConnect(event:FacebookEvent):void {
   dispatchEvent(event);
  }
  
  public function get facebookSession():FacebookSessionUtil{
   return session;
  }
  
  public function get facebook():Facebook{
   return session.facebook;
  }
 }
}

Step 3: 接著使用起來就很方便了。
private function init():void {
    sessionGetter = new SessionGetter("FbastutorialKey");
    sessionGetter.addEventListener(FacebookEvent.CONNECT, onSessionConnect);
}

private function onSessionConnect(event:FacebookEvent):void {
    facebook = sessionGetter.facebook;
    var call:FacebookCall = facebook.post( new GetFriends() );
    call.addEventListener(FacebookEvent.COMPLETE, onGetFriendsComplete);
}
原始檔同樣在此按右鍵→View Source。

Step 4: 發佈時,記得不要把 Key 檔放上去。

沒有留言:

FB 留言