發現在家裡的時候用Android App裡的WebView開啟網站很慢,會有十幾秒甚至更長時間的卡住。
但是在電腦上開啟同樣的網頁卻很快。
尋找這個問題的過程比較曲折,記錄下來。
抓取Android網路資料
為了調試這個問題,首先要抓取Android的網路包資料。開始時,是想用Wireshark來抓包的,但是很麻煩,tcpdump在手機要root許可權。
於是轉換思路,能不能在Android上設定代理,來抓包?
但是fiddler沒有linux版本,於是轉用BurpSuite了。
設定Android代理方法:
在Android網路設定裡,長按串連,選擇“修改網路”,“顯示進階選項”,“代理”,“手動”,然後填上對應的代理的地址。
hosts和路由器配置的坑
抓取到http請求資料,發現訪問很快,比在手機上快多了。說明並不是網路問題。
再仔細觀察,發現了這個請求:
GET /gngo.js HTTP/1.1
Host: x.adpro.cn
回想起來,這個是以前屏蔽電信在網頁上插入的流氓廣告時配置了hosts:
127.0.0.1 adpro.cn
127.0.0.1 x.adpro.cn
於是在電腦上把這兩個hosts注釋掉之後,發現速度變慢了一點,但是不會像手機上那樣卡十幾秒。
再嘗試在電腦上的瀏覽器開啟http://x.adpro.cn/gngo.js,發現打不開。
ping x.adpro.cn
發現返回的結果是127.0.0.1
為什麼在hosts檔案裡把 x.adpro.cn的條目注釋掉了,返回的結果還是127.0.0.1?
折騰了一陣子,嘗試各種清除linux dns的方法,發現x.adpro.cn的解析結果還是127.0.0.1。
再次想起,以前在路由器上配置過防火牆,果然如下有配置了對adpro.cn的攔截:
在路由器裡把這個規則失效之後,果然ping x.adpro.cn能返回正確的IP了。
原來是路由器把dns相關的請求也攔截了,導致linux取不到新的dns解析結果,一直用的都是舊的結果,所以總是把x.adpro.cn解析為127.0.0.1。
搞清楚緣由之後,重新在路由器裡攔截adpro.cn的資料包,然後重新載入網頁,發現http://x.adpro.cn/gngo.js的請求會在十幾秒之後逾時:
這就是在手機上為什麼開啟網頁要十幾秒的原因了:
路由器把adpro.cn的資料包攔截了,從而socket完全沒有資料返回,所以http請求在十幾秒後逾時,Android WebView才渲染顯示出頁面。
為什麼電腦上很快?因為配置了127.0.0.1 x.adpro.cn,所以http請求直接返回失敗了,不會阻塞住。
非常影響體驗的電訊廠商廣告
在路由器上把攔截去掉,再在手機上訪問,又出現了一個坑爹的事情:
在WebWiew上會顯示電信插入的流氓廣告,把大部分地區都擋住了。
如何過濾掉電訊廠商的流氓廣告?黑名單還是白名單
如果不過濾掉的話,使用者還以後是網站自己彈的廣告。那麼如何在App裡過濾掉這些流氓廣告?
在WebView裡過濾某些url:
當url裡含有廣告地址時,直接返回一個空的回應。
http://developer.android.com/reference/android/webkit/WebViewClient.html#shouldInterceptRequest(android.webkit.WebView, java.lang.String) http://developer.android.com/reference/android/webkit/WebViewClient.html#shouldInterceptRequest(android.webkit.WebView, java.lang.String)
webView.setWebViewClient(new WebViewClient() {public WebResourceResponse shouldInterceptRequest(WebView view, String url) {if (url.contains("adpro.cn")) {return new WebResourceResponse(null, null, null);}return null;}
注意的是在api level 11上才可以重載上面的函數。
電訊廠商的廣告網域名稱都是相對固定的,可以用黑名單來排除掉。
當然,如果自己的服務都是在自己的網域名稱下的,那麼可以考慮採用白名單機制。
白名單機制還有一個額外的好處,可以算是一個有一定效果的防止XSS的方法了。
其它的一些東東:
Android上抓包的一些文章:
http://www.trinea.cn/android/android-network-sniffer/ Android利用Fiddler進行網路資料抓包
http://www.freebuf.com/articles/wireless/6517.html 即時抓取行動裝置上的通訊包(ADVsock2pipe+Wireshark+nc+tcpdump)