星期一, 4月 23, 2012

增加取消登入 FB 在 Adobe Air Mobile 發生錯誤


在Air上面使用 FB Mobile Api遇到一個問題...
就是預設的 FB 登入畫面並沒有取消登入的按鈕 所以就自己加了一顆按鈕在 FB 登入視窗的 StageWebView 外面(右上角X)
本想要讓 USER 點了按鈕後可以將 StageWebView 給拿掉 不管是改變 viewport 或是直接 dispose
所以一開始就先宣告了一個 StageWebView 使用這個 StageWebView 來處理有關 FB 的部分
private var _swv:StageWebView;

當點了取消登入 就去
_swv.viewport=new Rectangle();

不過有時要做這動作時 都會發生錯誤 錯誤原因是原本給 FB 用的 StageWebView 已經變成 null 當然就沒法進行操作

看了一下 當登入成功或失敗 在 MobileLoginWindow.as 的 handleLocationChange() 會將原本的 StageWebView 給 dispose
所以這時就不能再對餵給 FB 的 StageWebView 進行操作 看起來似乎沒有問題 不過 如果這時 USER 執行登出 並再次登入
因為原本的 _swv 已經被 dispose 所以當要再重新指定 viewport 或餵給 FB 就會發生錯誤

所以改了一下 FB 的 API

MobileLoginWindow.as
protected function handleLocationChange(event:Event):void
{
 var location:String = webView.location;
 if (location.indexOf(FacebookURLDefaults.LOGIN_FAIL_URL) == 0 || location.indexOf(FacebookURLDefaults.LOGIN_FAIL_SECUREURL) == 0)
 {
  webView.removeEventListener(Event.COMPLETE, handleLocationChange);
  webView.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, handleLocationChange);
  loginCallback(null, FacebookDataUtils.getURLVariables(location).error_reason);
  userClosedWindow =  false;
  //webView.dispose();
  //webView=null;
 }

 else if (location.indexOf(FacebookURLDefaults.LOGIN_SUCCESS_URL) == 0 || location.indexOf(FacebookURLDefaults.LOGIN_SUCCESS_SECUREURL) == 0)
 {
  webView.removeEventListener(Event.COMPLETE, handleLocationChange);
  webView.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, handleLocationChange);
  loginCallback(FacebookDataUtils.getURLVariables(location), null);
  
  userClosedWindow =  false;
  //webView.dispose();
  //webView=null;
 }
}

另外在 FacebookMobile.as 的 login() 不知WHY要每次呼叫登入都會產生一個新的 MobileLoginWindow
((可能是 FB 認為每次 StageWebView 都是全新的))
protected function login(callback:Function, stageRef:Stage, extendedPermissions:Array, webView:StageWebView = null, display:String = 'touch'):void {
 this.loginCallback = callback;
 this.stageRef = stageRef;
 if (!webView) {
  this.webView = this.createWebView();
 } else {
  this.webView = webView;
  this.webView.stage = this.stageRef;
 }
 this.webView.assignFocus();
 if (applicationId == null) {
  throw new Error(
   'FacebookMobile.init() needs to be called first.'
  );
 }
 //開過了就不再多開了
 if (loginWindow == null) {
  loginWindow = new MobileLoginWindow(handleLogin);
  loginWindow.open(this.applicationId,
   this.webView,
   FacebookDataUtils.flattenArray(extendedPermissions),
   display
  );
 }else {
  loginWindow.directShowWindow();
 }   
}

還有
protected function handleLogin(result:Object, fail:Object):void {
 //loginWindow.loginCallback = null; //因為不重複開LOGINWINDOW所以不清掉CALLBACK
....


回到 MobileLoginWindow.as 加上
public function directShowWindow():void {  
 showWindow(loginRequest);
}


這樣就 OK 了~
之後要關閉 FB 登入視窗 就直接 _swv.viewport=new Rectangle();
記得原本登入成功或失敗 都會去 call 的 loginCallback 自己加上 _swv 的後續處理
不太確定這方法對不對 還是有誤會 FB 原本的用法 但至少目前用起來還蠻 OK 的~

沒有留言: