在XX項目中解決android webkit處理漢字編碼問題的總結html
問題:java
服務器經過302重定向方式發送給客戶端重定向地址,地址中的漢字採用原數據方式發送,沒有通過任何編碼。由於其中存在漢字,因此在android端通過webkit解碼編碼以後,最終沒法正常在服務器端請求正確數據。Android中默認使用utf-8編碼。android
Android在framework中解析http信息,Request.java的函數readResponse經過AndroidHttpClientConnection.java的函數parseResponseHeader解析response的header部分。程序員
存儲數據使用的是org.apache.http.util.CharArrayBuffer中的CharArrayBuffer。使用SessionInputBuffer的readline來讀取一行,進行解析。web
咱們主要關心的是Location部分,由於重定向主要是經過Location的值從新去請求url。Android中也是這麼作的,不會去html的body中解析標記A的herf。apache
讀取的每一行都會被傳入到Headers.java中進行解析。Location地址被轉換爲String存儲到mHeaders[IDX_LOCATION]中。數組
在從CharArrayBuffer變成String的時候,有個值得注意的地方,經過String的源碼能夠看到,若是使用char[]的方式傳入給String構造參數,String中不會再次編碼(encode),而使用byte[]方式傳入的話,會通過編碼轉化之後存儲到String的value中。默認編碼方式是utf-8.服務器
咱們這裏的CharArrayBuffer裏面爲char[]方式,因此直接存儲,不會通過編碼。微信
Android會將獲得的Location地址存儲在Header的String數組中。網絡
Request.java的函數readResponse會在最後調用LoadListener的endData結束解析。
在endData中通過一系列的消息轉發以後最終走到doRedirect中,從字面意思也能看出來是重定向。從以前存儲的Header中取出Location,而後調用native接口將url傳送到webcore jni中調用底層進行url解析。將從新解析過的url返回到java層,最後進行http請求。
問題出在jni中進行解析部分。WebCoreResourceLoader的RedirectedToUrl拿到url後會構造KURL對象,KURL在構造函數中通過init,會進行相應的編碼,默認編碼方式爲utf-8。因此漢字的元數據通過此次編碼後變爲utf-8編碼。返回到java部分進行http請求,因此在抓包中出現的%C2%BA%C3%BA%C3%91%C3%A5%C2%B1%C3%B3是「胡彥斌」的元數據0xba, 0xfa,0xd1, 0xe5, 0xb1, 0xf3通過utf-8編碼後的結果。
服務器默認的編碼應該是gb2312。因此咱們發送給服務器後,服務器將按照gb2312去解析,因此就會出現亂碼:潞煤�氓滷貿
修改方法:
對整個已經通過utf-8編碼的url進行utf-8解碼。在KURL中有現成的解碼函數,默認解碼方式爲utf-8.:decodeURLEscapeSequences(String)
基於android4.0
注:webkit中的網絡模塊爲libcurl,android中使用的是本身的網絡模塊,framework中。
技術人員都有本身的情懷,深陷其中而不被理解,歡迎關注我的微信公衆平臺:程序員互動聯盟(coder_online),一個開發人員的家,來訴說本身的故事。