[WebView學習之四]:遷移到Android4.4版本的WebView

 

 

Android4.4(API版本19)提供瞭一個基於Chromium版本的新版本WebView。該變化提高瞭WebView的性能,並且和最新的Web瀏覽器支持最新的HTML5,CSS3樣式以及Javascript標準。當在Android4.4或者更高的版本上面運行時,任何使用WebView的application會繼承使用這些特性。本文章主要描述瞭一下WebView的新特性。如果你設置targetSdkVersion為19或者更高時,那你就需要特別的註意。

[註]:當你設置targetSdkVersion為18或者更低的時候,WebView會運行quirks mode來避免下面一些問題的發生(當優化提高App性能以及更新Web標準)。特別是 single and narrow column layouts(單行柵欄佈局)和defalut zoom levels(默認縮放比例)在Android4.4中不支持,可能還會存在其他一些不確定的差異。所以如果你設置targetSdkVersion版本為18或者更低的時候,一定要把應用程序在Android4.4或者更高的版本中進行測試。

你可以通過設置setWebContentsDebuggingEnabled()來在Chrome桌面上面進行遠程調試,這樣當我們遷移app到Android4.4版本WebView中,可以幫助解決一些出現的問題。WebView這個新特性可以幫助我們檢查和分析Web內容,腳本以及網絡活動。有關調試的更多請查看下一篇文章《Android的遠程調試》

 

(一):用戶代理更改(UseerAgent Changes)

如果你的WebView內容是基於用戶代理的,你應該發現用戶代碼的內容已經發生瞭輕微的變化,現在的版本已經包含瞭Chrome版本:

Mozilla/5.0(Linux; Android 4.4; Nexus 4 Build/KRT16H) AppleWebKit/537.36
(KHTML,like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36

如果你需要檢索查詢用戶代理,但是不需要存儲或者不想要實例化WebView,那麼你應該使用靜態方法,getDefaultUserAgent()。 但是如果你需要修改WebView的用戶代理,那麼你應該去使用getUserAgentString()方法。

 

(二):多線程和線程阻塞(Multi-threadingand Thread Blocking)

如果你在其他線程調用WebView中的方法,而不是App的UI線程,這個可能出現一些意想不到的錯誤。如果你的App使用多線程,你可以使用runOnUiThread()方法來確定確定你的代碼在UI線程中執行。

 

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // Code for WebView goes here
    }
});

 

同時我們應該確保永遠不要阻塞UI線程,有時候當我們在等待javascript回調的時候,有些App會發生這個錯誤。例如:不要寫如下的代碼.

// This code is BAD and will block the UI thread
webView.loadUrl(javascript:fn());
while(result == null) {
  Thread.sleep(100);

}

你可以使用evaluateJavascript()來進行異步運行Javascript.

 

(三):自定義URL處理(Custom URL Handing)

當我們請求資源以及處理自定義URL結構鏈接的時候,新的WebView也提供額外的限制。例如:如果我們實現shouldOverrideUrlLoading()以及shouldInterceptRequest()這些回調方法,這樣可以保證WebView隻會回調合法的URLs。如果你橫在使用一個自定義URL結構或者基於URL,有時候在Android4.4中接收加載數據失敗。就要確保URL符合RFC 3986編碼。

例如:下面的例子新版本的WebView可能不會調用shouldOverrideUrlLoading()方法。用戶點擊以下這些鏈接的時候情況可能會不同:

1.如果你通過使用一個不合法或者空的URL來調用loadData()或者loadDataWithBaseURL(),此時頁面上面的鏈接類型可能不會回調shouldOverrideUrlLoading()方法。

[註]:如果你使用loadDataWithBaseURL(),其中base URL不合法或者為空時,所有的鏈接地址都需要為絕對地址。

2.如果你通過調用loadUrl()或者提供一個合法的base URL來調用loadDataBaseURL()加載頁面。那麼此時對該該頁面地址回調shouldOverrideUrlLoading()方法,但是你收到是絕對地址。例如:這邊你講獲取到http://www.example.com/showProfile而不僅僅是showProfile。

除瞭上面使用的那種鏈接地址類型,你還可以使用如下的那種自定義類型的URL:

Show Profile

你可以在shouldOverrideUrlLoading()方法中進行處理這個URL:

// The URL scheme should be non-hierarchical (no trailing slashes)
private static final String APP_SCHEME = example-app:;

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith(APP_SCHEME)) {
        urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), UTF-8);
        respondToData(urlData);
        return true;
    }
    return false;
}

如果你不能改變HTML,那麼你可以調用loadDataWithBaseURL()並且設置一個base URL。通過自定義類型和一個合法的主機名進行組成.例如:

example-app://。例如:

 

webView.loadDataWithBaseURL(example-app://example.co.uk/, HTML_DATA,
        null, UTF-8, null);

 

該主機名(host name)應該符合RFC3986規范,並且最重要的是該以斜杠結尾。否則任何加載頁面的請求都會意外終止。

 

(四)視圖改變(ViewPortChanges)

1.視圖窗體目標屏幕密度不在支持(Viewprot target-desitydpi no longersupported)

之前WebView支持指定“target-desitydpi”屬性讓網頁設置指定的屏幕密度。現在該屬性已經不在支持瞭,現在你應該圖片資源以及CSS樣式來進行解決。

2.當小屏幕的時候視圖窗體自動縮放(Viewport zoomsin when small)

之前如果你的viewport寬度的值小於或等於320,這將設置為成device-width,如果viewport的高度的值小於或等於WebView的高度.這將設置為device-height。現在當我們運行新的WebView的時候,WebView的寬和高會自動縮放來充滿整個屏幕。

3 .多視圖窗體標簽不在支持(Multiple vieport tags not supported)

以前在一個Web頁面上面如果包含多個viewport標簽,WebView將會合並這些屬性標簽。在新的WebView中,隻會使用最後的viewport標簽,其他都會被忽略。

4.默認縮放被棄用(Default zoom is deprecated)

在界面 getDefaultZoom()和setDefaultZoom()來進行設置和獲取頁面縮放比例的方法將不會在支持。你應該在Web頁面上面定義合適的viewport。

[註]:在Android4.4或者更高的版本中這些APIs將不會被支持,即時你的targetSdkVersion設置成18或者更低,也不會起作用瞭。

如果定義HTML的viewport屬性的有關信息請想看:Pixel-PerfectUI in the WebView.

如果你不能設置HTML的視圖窗體的寬度,你應該調用setUserWideViewPort()以確保頁面能夠合適的顯示。例如:

WebSettings settings = webView.getSettings();
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);

 

五)樣式風格變化(Styling Changes)

1.The backgroundCSS shorthand overrides background-size

2.使用CSS樣式中的像素而不是屏幕像素大小(Sizes are in CSS pixels instead ofscreen pixels)

之前例如window.outerWidth和window.outerHeighet返回寬高屬性是屏幕像素大小值。在新的WebView中,該返回是CSS樣式中定義的像素值大小。

通常糟糕的設計就是嘗試和計算物理尺寸大小。然而如果你設置原始縮放值為1.0並且禁止縮放,然後你可以使用window.devicePixelRatio獲取縮放比例,然後乘以CSS定義的像素值大小。相反的你也可以綁定javascript來獲取WebView的尺寸大小。

 

(六)窄列以及單列不在被支持(NARROW_COLUMNS and SINGLE_COLUMN nolonger supported)

在新的WebView中WebSettings.LayoutAlgorithm的NARROW_COLUMNS值將不再被支持。

[註]:在Android4.4或者更高的版本中這些APIs將不會被支持,即時你的targetSdkVersion設置成18或者更低,也不會起作用瞭。

通過以下方面可以處理這種變化:

1.改變程序風格(Alter the styles of your application)

如果你控制編寫頁面的HTML和CSS樣式文件,改變設計內容可能是最有效的方法。例如:

   

如果你沒有為你的頁面定義viewport屬性,這個設置將是特別有用的。

2.使用新的文本自動大小縮放佈局算法:(Using the new TEXT_AUTOSIZING layoutalgorithm)

如果你使用narrow columns來讓一個桌面網頁在移動設備上面更具可讀性並且不能改變HTML的內容,那麼是哦那個TEXT_AUTOSIZING algorithm可能更加適合而不是使用narrow columns方法。

此外之前棄用的SINGLE_COLUMNS在新版本WebView中也不支持使用瞭。

 

(七)在Javascript中處理用戶觸摸事件(Handing touch Events in Javascript)

如果你的網頁在WebView中直接處理觸摸事件,並且確定也處理touchcancel事件。但是有些場景touchcance調用也會出現一些問題。

1.當控件元素被觸摸(touchstart和touchmove被調用)或者頁面滾動的時候,touchcancel可能會拋出異常。

2.當控件元素被觸摸(touchstart被調用)但是event.preventDefault()不被調用之前,touchcancel可能會拋出異常(WebView可能會認為你不想使用觸摸事件)。

 

後面的文章一系列知識點,會專門封裝一個WebView組件,這樣用起來更加方便點,敬請期待…

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。