2012年2月19日 星期日

Phone gap Facebook plugin一直要求重新登入,怎麼辦?

PhoneGap是一個讓你可以在行動裝置上能夠以HTML/CSS/JS開發的框架。支援了包括iOS,Android,Windows Mobile,甚至是BlackBerry等。但是如果你真的天真的相信它真的能夠達到跨平台的話,我大概只能祝你好運。首先Native Code的部分勢必是需要重寫的。再來每個平台的瀏覽器支援JS/CSS的程度也不同,所以光是跨iOS與Android就會有很大的問題了。更別說還要考慮Android上各種螢幕尺寸的問題。

我之所以用了PhoneGap的唯一原因是因為可以快速的實作出想要的App樣子。在有限的時間內要在單一平台上開發出一個完整App,這還是一個值得考慮的Solution。

但這裡沒有要寫教學文,網路上應該已經很多了,不過要小心的是大部分都是舊版的。PhoneGap從1.3之後有很大的改變,因此要特別小心你看的Tutorial文章用的是哪一個版本。

這裡其實是要抱怨Dave Johnson, Nitobi CTO釋放的Facebook Plugin有一個很基本但是卻很重大的問題。那就是登入過後的session cache處理有問題啊,這會導致每次app開起來都必須重新做一次facebook登入認證,然後導致很差的使用者經驗。

在罵之前還是要先說一下好話,Dave Johnson包裝的版本已經可以幫很多人省下很多的功了,只是還是不太應該埋下這個bug啊。

以下是pg-plugin-fb-connect.js中完整的source code:

PG = ( typeof PG == 'undefined' ? {} : PG );
PG.FB = {
  init: function(apiKey, fail) {
    // create the fb-root element if it doesn't exist
    if (!document.getElementById('fb-root')) {
      var elem = document.createElement('div');
      elem.id = 'fb-root';
      document.body.appendChild(elem);
    }
    PhoneGap.exec(function() {
      var session = JSON.parse(localStorage.getItem('pg_fb_session') || '{"expires":0}');
      if (session && session.expires > new Date().valueOf()) {
        FB.Auth.setSession(session, 'connected');
      }
      console.log('PhoneGap Facebook Connect plugin initialized successfully.');
    }, (fail?fail:null), 'com.phonegap.facebook.Connect', 'init', [apiKey]);
  },
  login: function(params, cb, fail) {
    params = params || { perms: '' };
    PhoneGap.exec(function(e) { // login
        localStorage.setItem('pg_fb_session', JSON.stringify(e.session));
        FB.Auth.setSession(e.session, 'connected');
        if (cb) cb(e);
    }, (fail?fail:null), 'com.phonegap.facebook.Connect', 'login', params.perms.split(',') );
  },
  logout: function(cb, fail) {
    PhoneGap.exec(function(e) {
      localStorage.removeItem('pg_fb_session');
      FB.Auth.setSession(null, 'notConnected');
      if (cb) cb(e);
    }, (fail?fail:null), 'com.phonegap.facebook.Connect', 'logout', []);
  },
  getLoginStatus: function(cb, fail) {
    PhoneGap.exec(function(e) {
      if (cb) cb(e);
    }, (fail?fail:null), 'com.phonegap.facebook.Connect', 'getLoginStatus', []);
  }
};


主要的問題就在標紅字的session.expires > new Date().valueof()那裡。
這邊的流程是每次App開起來會call init,然後如果call login去做Facebook OAuth,之後會把Facebook傳回的session存到瀏覽器的local storage。所以下一次App打開的時候在init的地方就會嘗試用之前存下的session去做初始化的動作。而問題就在這,每次在紅字這一行的condition check都是false啊。原因就在session.expires是日期字串,而new Date().valueof()是數值啊。剛剛又到GitHub上看了一下,還是沒人改掉。看來晚一點要來Push一個版本上去。

修掉這個問題的方法很簡單,只要用Date Object去parse session.expires轉成timestamp之後再做condition checking就可以了。

如下修正:
var eventStamp = Date.parse(session.expires);
if (eventStamp = new Date().valueOf())



--
Kenny Lee <kswlee@gmail.com>

沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...