WebView的使用

WebView簡介

  • String getUrl():獲取當前頁面的URL。

  • reload():重新reload當前的URL,即刷新。

  • boolean canGoBack():用來確認WebView里是否還有可回退的歷史記錄。通常我們會在WebView里重寫返回鍵的點擊事件,通過該方法判斷WebView里是否還有歷史記錄,若有則返回上一頁。

  • boolean canGoForward():用來確認WebView是否還有可向前的歷史記錄。

  • boolean canGoBackOrForward(int steps):以當前的頁面為起始點,用來確認WebView的歷史記錄是否足以后退或前進給定的步數,正數為前進,負數為后退。

  • goBack():在WebView歷史記錄后退到上一項。

  • goForward():在WebView歷史記錄里前進到下一項。

  • goBackOrForward(int steps):以當前頁面為起始點,前進或后退歷史記錄中指定的步數,正數為前進,負數為后退。

  • clearCache(boolean includeDiskFiles):清空網頁訪問留下的緩存數據。需要注意的時,由于緩存是全局的,所以只要是WebView用到的緩存都會被清空,即便其他地方也會使用到。該方法接受一個參數,從命名即可看出作用。若設為false,則只清空內存里的資源緩存,而不清空磁盤里的。

  • clearHistory():清除當前webview訪問的歷史記錄。

  • clearFormData():清除自動完成填充的表單數據。需要注意的是,該方法僅僅清除當前表單域自動完成填充的表單數據,并不會清除WebView存儲到本地的數據。

  • onPause():當頁面被失去焦點被切換到后臺不可見狀態,需要執行onPause操作,該操作會通知內核安全地暫停所有動作,比如動畫的執行或定位的獲取等。需要注意的是該方法并不會暫停JavaScript的執行,若要暫停JavaScript的執行請使用接下來的這個方法。

  • onResume():在先前調用onPause()后,我們可以調用該方法來恢復WebView的運行。

  • pauseTimers():該方法面向全局整個應用程序的webview,它會暫停所有webview的layout,parsing,JavaScript Timer。當程序進入后臺時,該方法的調用可以降低CPU功耗。

  • resumeTimers():恢復pauseTimers時的所有操作。

  • destroy():銷毀WebView。需要注意的是:這個方法的調用應在WebView從父容器中被remove掉之后。我們可以手動地調用

rootLayout.removeView(webView);
webView.destroy();
  • getScrollY():該方法返回的當前可見區域的頂端距整個頁面頂端的距離,也就是當前內容滾動的距離。

  • getHeight():方法都返回當前WebView這個容器的高度。其實以上兩個方法都屬于View。

  • getContentHeight():該方法返回整個HTML頁面的高度,但該高度值并不等同于當前整個頁面的高度,因為WebView有縮放功能, 所以當前整個頁面的高度實際上應該是原始HTML的高度再乘上縮放比例。因此,準確的判斷方法應該是

if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
    //已經處于底端
}

if(webView.getScrollY() == 0){
    //處于頂端
}
pageUp(boolean top):將WebView展示的頁面滑動至頂部。

pageDown(boolean bottom):將WebView展示的頁面滑動至底部。

WebSettings

WebSettings是用來管理WebView配置的類。當WebView第一次創建時,內部會包含一個默認配置的集合。若我們想更改這些配置,便可以通過WebSettings里的方法來進行設置。

WebSettings對象可以通過WebView.getSettings()獲得,它的生命周期是與它的WebView本身息息相關的,如果WebView被銷毀了,那么任何由WebSettings調用的方法也同樣不能使用。

獲取WebSettings對象

WebSettings webSettings = webView.getSettings();
WebSettings常用方法

(幾乎所有的set方法都有相應的get方法,這里就只介紹set了。另,所有未寫方法返回值類型的皆為空類型)

  • setJavaScriptEnabled(boolean flag):設置WebView是否可以運行JavaScript。

  • setJavaScriptCanOpenWindowsAutomatically(boolean flag):設置WebView是否可以由JavaScript自動打開窗口,默認為false,通常與JavaScript的window.open()配合使用。

  • setAllowFileAccess(boolean allow):啟用或禁用WebView訪問文件數據。

  • setBlockNetworkImage(boolean flag):禁止或允許WebView從網絡上加載圖片。需要注意的是,如果設置是從禁止到允許的轉變的話,圖片數據并不會在設置改變后立刻去獲取,而是在WebView調用reload()的時候才會生效。
    這個時候,需要確保這個app擁有訪問Internet的權限,否則會拋出安全異常。
    通常沒有禁止圖片加載的需求的時候,完全不用管這個方法,因為當我們的app擁有訪問Internet的權限時,這個flag的默認值就是false。

  • setSupportZoom(boolean support):設置是否支持縮放。

  • setBuiltInZoomControls(boolean enabled):顯示或不顯示縮放按鈕(wap網頁不支持)。

  • setSupportMultipleWindows(boolean support):設置WebView是否支持多窗口。

  • setLayoutAlgorithm(WebSettings.LayoutAlgorithm l):指定WebView的頁面布局顯示形式,調用該方法會引起頁面重繪。默認值為LayoutAlgorithm#NARROW_COLUMNS。

  • setNeedInitialFocus(boolean flag):通知WebView是否需要設置一個節點獲取焦點當WebView#requestFocus(int,android.graphics.Rect)被調用時,默認為true。

  • setAppCacheEnabled(boolean flag):啟用或禁用應用緩存。

  • setAppCachePath(String appCachePath):設置應用緩存路徑,這個路徑必須是可以讓app寫入文件的。該方法應該只被調用一次,重復調用會被無視~

  • setCacheMode(int mode):用來設置WebView的緩存模式。當我們加載頁面或從上一個頁面返回的時候,會按照設置的緩存模式去檢查并使用(或不使用)緩存。

緩存模式有四種:

1、LOAD_DEFAULT:默認的緩存使用模式。在進行頁面前進或后退的操作時,如果緩存可用并未過期就優先加載緩存,否則從網絡上加載數據。這樣可以減少頁面的網絡請求次數。

2、LOAD_CACHE_ELSE_NETWORK:只要緩存可用就加載緩存,哪怕它們已經過期失效。如果緩存不可用就從網絡上加載數據。

3、LOAD_NO_CACHE:不加載緩存,只從網絡加載數據。

4、LOAD_CACHE_ONLY:不從網絡加載數據,只從緩存加載數據。

通常我們可以根據網絡情況將這幾種模式結合使用,比如有網的時候使用LOAD_DEFAULT,離線時使用LOAD_CACHE_ONLY、LOAD_CACHE_ELSE_NETWORK,讓用戶不至于在離線時啥都看不到。

  • setDatabaseEnabled(boolean flag):啟用或禁用數據庫緩存。

  • setDomStorageEnabled(boolean flag):啟用或禁用DOM緩存。

  • setUserAgentString(String ua):設置WebView的UserAgent值。

  • setDefaultEncodingName(String encoding):設置編碼格式,通常都設為“UTF-8”。

  • setStandardFontFamily(String font):設置標準的字體族,默認“sans-serif”。

  • setCursiveFontFamily:設置草書字體族,默認“cursive”。

  • setFantasyFontFamily:設置CursiveFont字體族,默認“cursive”。

  • setFixedFontFamily:設置混合字體族,默認“monospace”。

  • setSansSerifFontFamily:設置梵文字體族,默認“sans-serif”。

  • setSerifFontFamily:設置襯線字體族,默認“sans-serif”

  • setDefaultFixedFontSize(int size):設置默認填充字體大小,默認16,取值區間為[1-72],超過范圍,使用其上限值。

  • setDefaultFontSize(int size):設置默認字體大小,默認16,取值區間[1-72],超過范圍,使用其上限值。

  • setMinimumFontSize:設置最小字體,默認8. 取值區間[1-72],超過范圍,使用其上限值。

  • setMinimumLogicalFontSize:設置最小邏輯字體,默認8. 取值區間[1-72],超過范圍,使用其上限值。

以上就是一些WebSettings的常用方法,具體的使用以及一些緩存的問題會在接下來的代碼以及文章中有更加直觀的說明。

WebViewClient

從名字上不難理解,這個類就像WebView的委托人一樣,是幫助WebView處理各種通知和請求事件的,我們可以稱他為WebView的“內政大臣”。

  • onLoadResource(WebView view, String url):該方法在加載頁面資源時會回調,每一個資源(比如圖片)的加載都會調用一次。

  • onPageStarted(WebView view, String url, Bitmap favicon):該方法在WebView開始加載頁面且僅在Main frame loading(即整頁加載)時回調,一次Main frame的加載只會回調該方法一次。我們可以在這個方法里設定開啟一個加載的動畫,告訴用戶程序在等待網絡的響應。

  • onPageFinished(WebView view, String url):該方法只在WebView完成一個頁面加載時調用一次(同樣也只在Main frame loading時調用),我們可以可以在此時關閉加載動畫,進行其他操作。

  • onReceivedError(WebView view, WebResourceRequest request, WebResourceError error):該方法在web頁面加載錯誤時回調,這些錯誤通常都是由無法與服務器正常連接引起的,最常見的就是網絡問題。 這個方法有兩個地方需要注意:

1.這個方法只在與服務器無法正常連接時調用,類似于服務器返回錯誤碼的那種錯誤(即HTTP ERROR),該方法是不會回調的,因為你已經和服務器正常連接上了(全怪官方文檔(︶^︶));

2.這個方法是新版本的onReceivedError()方法,從API23開始引進,與舊方法onReceivedError(WebView view,int errorCode,String description,String failingUrl)不同的是,新方法在頁面局部加載發生錯誤時也會被調用(比如頁面里兩個子Tab或者一張圖片)。這就意味著該方法的調用頻率可能會更加頻繁,所以我們應該在該方法里執行盡量少的操作。

  • onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse):上一個方法提到onReceivedError并不會在服務器返回錯誤碼時被回調,那么當我們需要捕捉HTTP ERROR并進行相應操作時應該怎么辦呢?API23便引入了該方法。當服務器返回一個HTTP ERROR并且它的status code>=400時,該方法便會回調。這個方法的作用域并不局限于Main Frame,任何資源的加載引發HTTP ERROR都會引起該方法的回調,所以我們也應該在該方法里執行盡量少的操作,只進行非常必要的錯誤處理等。

  • onReceivedSslError(WebView view, SslErrorHandler handler, SslError error):當WebView加載某個資源引發SSL錯誤時會回調該方法,這時WebView要么執行handler.cancel()取消加載,要么執行handler.proceed()方法繼續加載(默認為cancel)。需要注意的是,這個決定可能會被保留并在將來再次遇到SSL錯誤時執行同樣的操作。

  • WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request):當WebView需要請求某個數據時,這個方法可以攔截該請求來告知app并且允許app本身返回一個數據來替代我們原本要加載的數據。

比如你對web的某個js做了本地緩存,希望在加載該js時不再去請求服務器而是可以直接讀取本地緩存的js,這個方法就可以幫助你完成這個需求。你可以寫一些邏輯檢測這個request,并返回相應的數據,你返回的數據就會被WebView使用,如果你返回null,WebView會繼續向服務器請求。

  • boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request):哈~ 終于到了這個方法,在最開始的基礎演示時我們用到了這個方法。從實踐中我們知道,當我們沒有給WebView提供WebViewClient時,WebView如果要加載一個url會向ActivityManager尋求一個適合的處理者來加載該url(比如系統自帶的瀏覽器),這通常是我們不想看到的。于是我們需要給WebView提供一個WebViewClient,并重寫該方法返回true來告知WebView url的加載就在app中進行。這時便可以實現在app內訪問網頁。

  • onScaleChanged(WebView view, float oldScale, float newScale):當WebView得頁面Scale值發生改變時回調。

  • boolean shouldOverrideKeyEvent(WebView view, KeyEvent event):默認值為false,重寫此方法并return true可以讓我們在WebView內處理按鍵事件。

WebChromeClient

如果說WebViewClient是幫助WebView處理各種通知、請求事件的“內政大臣”的話,那么WebChromeClient就是輔助WebView處理Javascript的對話框,網站圖標,網站title,加載進度等偏外部事件的“外交大臣”。

  • onProgressChanged(WebView view, int newProgress):當頁面加載的進度發生改變時回調,用來告知主程序當前頁面的加載進度。

  • onReceivedIcon(WebView view, Bitmap icon):用來接收web頁面的icon,我們可以在這里將該頁面的icon設置到Toolbar。

  • onReceivedTitle(WebView view, String title):用來接收web頁面的title,我們可以在這里將頁面的title設置到Toolbar。

以下兩個方法是為了支持web頁面進入全屏模式而存在的(比如播放視頻),如果不實現這兩個方法,該web上的內容便不能進入全屏模式。

  • onShowCustomView(View view, WebChromeClient.CustomViewCallback callback):該方法在當前頁面進入全屏模式時回調,主程序必須提供一個包含當前web內容(視頻 or Something)的自定義的View。

  • onHideCustomView():該方法在當前頁面退出全屏模式時回調,主程序應在這時隱藏之前show出來的View。

  • Bitmap getDefaultVideoPoster():當我們的Web頁面包含視頻時,我們可以在HTML里為它設置一個預覽圖,WebView會在繪制頁面時根據它的寬高為它布局。而當我們處于弱網狀態下時,我們沒有比較快的獲取該圖片,那WebView繪制頁面時的gitWidth()方法就會報出空指針異常~ 于是app就crash了。。

這時我們就需要重寫該方法,在我們尚未獲取web頁面上的video預覽圖時,給予它一個本地的圖片,避免空指針的發生。

  • View getVideoLoadingProgressView():重寫該方法可以在視頻loading時給予一個自定義的View,可以是加載圓環 or something。

  • boolean onJsAlert(WebView view, String url, String message, JsResult result):處理Javascript中的Alert對話框。

  • boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result):處理Javascript中的Prompt對話框。

  • boolean onJsConfirm(WebView view, String url, String message, JsResult result):處理Javascript中的Confirm對話框

  • boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams):該方法在用戶進行了web上某個需要上傳文件的操作時回調。我們應該在這里打開一個文件選擇器,如果要取消這個請求我們可以調用filePathCallback.onReceiveValue(null)并返回true。

  • onPermissionRequest(PermissionRequest request):該方法在web頁面請求某個尚未被允許或拒絕的權限時回調,主程序在此時調用grant(String [])或deny()方法。如果該方法沒有被重寫,則默認拒絕web頁面請求的權限。

  • onPermissionRequestCanceled(PermissionRequest request):該方法在web權限申請權限被取消時回調,這時應該隱藏任何與之相關的UI界面。

Js與WebView交互

既然嗨鳥應用大行其道,那么毫無疑問Android與JavaScript的交互我們也必須了解清楚,下面來介紹一下JavaScript與Android是如何互相調用的。

利用WebView調用網頁上的JavaScript代碼

在WebView中調用Js的基本格式為webView.loadUrl("javascript:methodName(parameterValues)");

現有以下這段JavaScript代碼

  function readyToGo() {
      alert("Hello")
  }

  function alertMessage(message) {
      alert(message)
  }

  function getYourCar(){
      return "Car";
  }
  1. WebView調用JavaScript無參無返回值函數
String call = "javascript:readyToGo()";
webView.loadUrl(call);
  1. WebView調用JavScript有參無返回值函數
String call = "javascript:alertMessage(\"" + "content" + "\")";
webView.loadUrl(call);
  1. WebView調用JavaScript有參數有返回值的函數
@TargetApi(Build.VERSION_CODES.KITKAT)
private void evaluateJavaScript(WebView webView){
    webView.evaluateJavascript("getYourCar()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String s) {
            Log.d("findCar",s);
        }
    });
}

JavaScript通過WebView調用Java代碼

從API19開始,Android提供了@JavascriptInterface對象注解的方式來建立起Javascript對象和Android原生對象的綁定,提供給JavScript調用的函數必須帶有@JavascriptInterface。

演示一 JavaScript調用Android Toast方法

  1. 編寫Java原生方法并用使用@JavascriptInterface注解
@JavascriptInterface
public void show(String s){
    Toast.makeText(getApplication(), s, Toast.LENGTH_SHORT).show();
}

2.注冊JavaScriptInterface

webView.addJavascriptInterface(this, "android");

addJavascriptInterface的作用是把this所代表的類映射為JavaScript中的android對象。

3.編寫JavaScript代碼

function toastClick(){
window.android.show("JavaScript called~!");
}
演示二 JavaScript調用有返回值的Java方法

1.定義一個帶返回值的Java方法,并使用@JavaInterface:

@JavaInterface
public String getMessage(){
    return "Hello,boy~";
}

2.添加JavaScript的映射

webView.addJavaScriptInterface(this,"Android");

3.通過JavaScript調用Java方法

function showHello(){
    var str=window.Android.getMessage();
    console.log(str);
}

以上就是Js與WebView交互的一些介紹,希望能對你有幫助。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,238評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,430評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,134評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,893評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,653評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,136評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,212評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,372評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,888評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,738評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,482評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,179評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,588評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,829評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,610評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,916評論 2 372

推薦閱讀更多精彩內容