雖然titanium一向號稱可以使用同樣的程式碼同時製作出android跟ios的app,但實際上事情總不是這麼的歡樂….
像是一個簡單的是用twitter帳號來進行登入的動作,由於api的工程師是使用cookie跟CSRF token配對好的金鑰來跟api端進行認證,ios因為webview跟HTTPClient會自動共用cookie,所以只要在webview登入twitter後,就可以以新建立的HTTPClient來跟api索取token然後進行跟api端的互動。
只是到了android的時候,webview與HTTPClient不再自動共用cookie,所以我們得要在HTTPClient把object傳送到api之前利用setRequestHeader帶入Cookie,才有辦法取得正確的token。
所以問題就在於怎麼在登入成功的webview中,取出當時的cookie。接著google會告訴我們在這邊有這麼一個方法:
webView.addEventListener('load',function(e) { var cookies = webView.evalJS("document.cookie").split(";"); Ti.API.info( "# of cookies -> " + cookies.length ); for (i = 0; i <= cookies.length - 1; i++) { Ti.API.info( "cookie -> " + cookies[i] ); } }); |
可惜我所得到的卻始終是空值(NULL)。
但其實這個方法原來還是是對的,原因出在系統的登入成功頁面中的cookie被設下了「httponly」這個參數。所以雖然我們可以利用工具來讀到正確的cookie但是卻無法透過evalJS的方法得到cookie!!
所以在請系統方的工程師拿掉httponly參數後,就順利的取得了我們所需要的cookie,然後在使用HTTPClient:
function doXHR(callback, seedObj, api, method) { Ti.App.fireEvent("loading:lock"); var xhr = Titanium.Network.createHTTPClient({ autoEncodeUrl: false }); var dialog = Ti.UI.createAlertDialog({ buttonNames : ['Try again','Cancel'], title : 'ERROR' }); dialog.addEventListener('click', function(e) { if(e.index == 0) doXHR(callback, seedObj, api, method); }); xhr.setTimeout(30000); xhr.onerror = function(e) { Ti.App.fireEvent("loading:unlock"); Ti.API.info('IN ERROR ' + e.error); dialog.message = '「'+api + '」 with ERROR :' + e.error+"@status: "+xhr.status; dialog.show(); }; xhr.onload = function(e) { Ti.App.fireEvent("loading:unlock"); var res = JSON.parse(this.responseText); callback(res); }; xhr.onsendstream = function(e){ Ti.API.info('ONSENDSTREAM - PROGRESS: ' + e.progress); }; var getway = prop.get('utilsURL') + api; xhr.open(method, getway); var cookie = prop.get('cookie'); if (cookie !== null && cookie !== '' && cookie !== undefined) { cookie = cookie.replace(/;.+/, ';'); xhr.setRequestHeader('Cookie',cookie); } xhr.send(seedObj); } |