1. 程式人生 > >android webview 在專案中的那些坑

android webview 在專案中的那些坑

在專案開發過程中,webview常用於顯示網頁或h5頁面,這樣可以實時更新,遇到問題可以迅速修復。由於android碎片化嚴重,所以webview在每個版本都有修改,因此在開發過程中遇到過各種各樣的坑,現在總結一些曾經遇到的坑。

1,載入完成回撥不正確。

onPageStarted與onPageFinished次數不一致,如果你在start中進行進度條載入處理,finish中結束,會導致進度條一直不消失。因此可以在onProgressChanged進行處理。當newProgress為100時表示頁面載入完成。

對於WebViewClient.onPageFinished()。你永遠無法確定當WebView呼叫這個方法的時候,網頁內容是否真的載入完畢了。當前正在載入的網頁產生跳轉的時候這個方法可能會被多次呼叫,StackOverflow上有比較具體的解釋(
How to listen for a Webview finishing loading a URL in Android?
), 但其中列舉的解決方法並不完美。所以當你的WebView需要載入各種各樣的網頁並且需要在頁面載入完成時採取一些操作的話,可能WebChromeClient.onProgressChanged()比WebViewClient.onPageFinished()都要靠譜一些。

2,檔案選擇函式修改。 // FILE UPLOAD <3.0 publicvoidopenFileChooser(ValueCallback<Uri> uploadFile) {
chooseFile(uploadFile, null, null); } /** * 4.x * @param uploadFile * @param acceptType * @param capture */ publicvoidopenFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) { chooseFile(uploadFile, acceptType, capture); }
Android 5.0+ 重寫 onShowFileChooser 生效;

3,跨域cookie讀取

   什麼是跨域,簡單的說就是不同的域名,我們都知道在pc上我們用瀏覽器訪問網址,不同的網址都會在本地儲存一些cookie資訊,這樣就可以實現比如自動登入等功能,在pc上不同域名是不能相互讀取其他域下的cookie資訊的(非web專業開發人員,如果理解有誤,歡迎指出)。

       但是在Android上在api 23之前,是可以跨域讀取cookie的,比如A域寫入一個userId的cookie,B域可以讀取該值。但是在23時,系統將該值設定成了false,不再讓跨域讀取了。如果你的應用有跨域讀取需求,怎麼辦?可以採用如下方式進行開啟:

    /**
     * 設定跨域cookie讀取
     */
    public final void setAcceptThirdPartyCookies() {
        //target 23 default false, so manual set true
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

       這裡我們來看看setAcceptThirdPartyCookies的註釋:

Sets whether the {@link WebView} should allow third party cookies to be set. 
Allowing third party cookies is a per WebView policy and can be set 
differently on different WebView instances. 


Apps that target {@link android.os.Build.VERSION_CODES#KITKAT} or below 
default to allowing third party cookies. Apps targeting 
{@link android.os.Build.VERSION_CODES#LOLLIPOP} or later default to disallowing 
third party cookies.

4,http/https混合載入

     在現階段,很多網站都改成了https進行訪問,https可以提升訪問網站的安全性,防止資訊被竊取,如果所有的網頁都是https且網頁內的連結也是都是https,那就沒有混合載入(文字區域https,圖片檔案http載入)的問題了。但是很多資源現階段還沒有改變成https訪問,往往頁面都嵌入了http的連結。這種混合網頁如果不進行處理,直接載入是會出現錯誤的。怎麼解決這個問題?

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

       這也是一個分版本的函式,在api 23之前,預設是可以混合載入的,但是在23時,預設值改成了MIXED_CONTENT_NEVER_ALLOW,因此如果你有混合載入的需求,設定setMixedContentMode為MIXED_CONTENT_ALWAYS_ALLOW。

5,閃屏

       WebView如果開啟了硬體加速,多次開啟,會導致介面花屏,或者介面繪製有殘留。這個在5.0剛出來的時候發生過多次,但是當時忘記截圖了。當時也沒有打算要把這些給記錄下來。這裡我已經復現不了了。如果你遇到了。關閉硬體加速就好了。關閉硬體加速這種情況會好很多,但無法獲得很好的瀏覽體驗,你會感覺網頁滑動的時候一卡一卡的,不跟手。

6,資源的及時釋放和耗電問題

當你的程式呼叫了WebView載入網頁,WebView會自己開啟一些執行緒(?),如果你沒有正確地將WebView銷燬的話,這些殘餘的執行緒(?)會一直在後臺執行,由此導致你的應用程式耗電量居高不下。必要時要手動釋放

@Override

protectedvoidonDestroy() {

super.onDestroy();

if (webView != null) {

root.removeView(webView);

webView.removeAllViews();

webView.destroy();

}

}

7,webview元件忽略SSL證書驗證錯誤漏洞

漏洞描述

Android WebView元件載入網頁發生證書認證錯誤時,會呼叫WebViewClient類的onReceivedSslError方法[1],如果該方法實現呼叫了handler.proceed()來忽略該證書錯誤,則會受到中間人攻擊的威脅,可能導致隱私洩露

測試方法

實現onReceivedSslError的處理,漏洞程式碼樣例:

    ...
    mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(new JsBridge(mContext), JS_OBJECT);
        mWebView.loadUrl("http://www.example.org/tests/addjsif/");
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed(); // Ignore SSL certificate errors
            }
        });
    ...

如上程式碼在onReceivedSslError處理時沒有進行cancel,還是使用了proceed(),忽略掉了發生的SSL異常。

解決方案

當發生證書認證錯誤時,採用預設的處理方法handler.cancel(),停止載入問題頁面。當然,如果你的專案對安全性要求不高,對體驗要求高,可以用proceed()處理忽略。