Android WebView 全面解析

一、簡介

為了方便開發(fā)者實現(xiàn)在app內(nèi)展示網(wǎng)頁并與網(wǎng)頁交互的需求,Android SDK提供了WebView組件。它繼承自AbsoluteLayout,展示網(wǎng)頁的同時,也可以在其中放入其他的子View?,F(xiàn)如今,Hybrid應用似乎占據(jù)的APP的主流類型,那么關(guān)于WebView的使用就變得越發(fā)的重要。從Android 4.4(KitKat)開始,原本基于WebKit的WebView開始基于Chromium內(nèi)核,這一改動大大提升了WebView組件的性能以及對HTML5,CSS3,JavaScript的支持。

二、相關(guān)類及API

1、WebView

基本:

  • String getUrl():獲取當前頁面的URL。
  • String getTitle():獲取當前頁面的標題。
  • Bitmap getFavicon():獲取當前頁面的favicon
  • int getProgress():獲取當前頁面的加載進度
  • setInitialScale(int scaleInPercent):設(shè)置初始縮放比例

加載網(wǎng)頁:

  • loadUrl(String url):加載URL指定的網(wǎng)頁
  • loadUrl(String url, Map<String, String> additionalHttpHeaders):攜帶http headers加載URL指定的網(wǎng)頁
  • postUrl(String url, byte[] postData):使用POST請求加載指定的網(wǎng)頁
  • reload():重新reload當前的URL,即刷新。
  • loadData(String data, String mimeType, String encoding):加載內(nèi)容
  • loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl):使用baseUrl加載內(nèi)容

導航:

  • boolean canGoBack():用來確認WebView里是否還有可回退的歷史記錄。通常我們會在WebView里重寫返回鍵的點擊事件,通過該方法判斷WebView里是否還有歷史記錄,若有則返回上一頁。
  • boolean canGoForward():用來確認WebView是否還有可向前的歷史記錄。
  • boolean canGoBackOrForward(int steps):以當前的頁面為起始點,用來確認WebView的歷史記錄是否足以后退或前進給定的步數(shù),正數(shù)為前進,負數(shù)為后退。
  • goBack():在WebView歷史記錄后退到上一項。
  • goForward():在WebView歷史記錄里前進到下一項。
  • goBackOrForward(int steps):以當前頁面為起始點,前進或后退歷史記錄中指定的步數(shù),正數(shù)為前進,負數(shù)為后退。
  • WebBackForwardList copyBackForwardList():復制一份BackForwardList
  • clearHistory():清除當前webview訪問的歷史記錄。

JavaScript:

  • addJavascriptInterface(Object object, String name):注入Javascript對象
  • removeJavascriptInterface(String name):移除已注入的Javascript對象,下次加載或刷新頁面時生效
  • evaluateJavascript(String script, ValueCallback<String> resultCallback):對傳入的JS表達式求值,通過resultCallback返回結(jié)果。此函數(shù)添加于API19,必須在UI線程中調(diào)用,回調(diào)也將在UI線程

其他:

  • findAllAsync (String find):異步執(zhí)行查找網(wǎng)頁內(nèi)包含的字符串并設(shè)置高亮,查找結(jié)果會回調(diào)
  • findNext (boolean forward): 查找下一個匹配的字符串
  • setFindListener(FindListener listener):設(shè)置網(wǎng)頁查找結(jié)果回調(diào)
  • clearMatches():清除網(wǎng)頁查找的高亮匹配字符串
  • saveWebArchive(String filename):保存網(wǎng)頁(.html)到指定文件
  • saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback):保存網(wǎng)頁(.html)到文件
  • pageUp(boolean top):將WebView展示的頁面滑動至頂部。
  • pageDown(boolean bottom):將WebView展示的頁面滑動至底部。
  • zoomBy(float factor):縮放
  • zoomIn():放大
  • zoomOut():縮放
  • clearCache(boolean includeDiskFiles):清空網(wǎng)頁訪問留下的緩存數(shù)據(jù)。需要注意的時,由于緩存是全局的,所以只要是WebView用到的緩存都會被清空,即便其他地方也會使用到。該方法接受一個參數(shù),從命名即可看出作用。若設(shè)為false,則只清空內(nèi)存里的資源緩存,而不清空磁盤里的。
  • clearFormData():清除自動完成填充的表單數(shù)據(jù)。需要注意的是,該方法僅僅清除當前表單域自動完成填充的表單數(shù)據(jù),并不會清除WebView存儲到本地的數(shù)據(jù)。
  • clearSslPreferences():清除SSL偏好
  • onPause():當頁面被失去焦點被切換到后臺不可見狀態(tài),需要執(zhí)行onPause操作,該操作會通知內(nèi)核安全地暫停所有動作,比如動畫的執(zhí)行或定位的獲取等。需要注意的是該方法并不會暫停JavaScript的執(zhí)行,若要暫停JavaScript的執(zhí)行請使用接下來的這個方法。
  • onResume():在先前調(diào)用onPause()后,我們可以調(diào)用該方法來恢復WebView的運行。
  • pauseTimers():該方法面向全局整個應用程序的webview,它會暫停所有webview的layout,parsing,JavaScript Timer。當程序進入后臺時,該方法的調(diào)用可以降低CPU功耗。
  • resumeTimers():恢復pauseTimers時的所有操作。
  • destroy():銷毀WebView。需要注意的是:這個方法的調(diào)用應在WebView從父容器中被remove掉之后。我們可以手動地調(diào)用
  • getContentHeight():該方法返回整個HTML頁面的高度,但該高度值并不等同于當前整個頁面的高度,因為WebView有縮放功能, 所以當前整個頁面的高度實際上應該是原始HTML的高度再乘上縮放比例

2、WebSettings

  • setDomStorageEnabled(boolean flag):啟用HTML5 DOM storage API,默認值 false
  • setDatabaseEnabled(boolean flag):啟用Web SQL Database API,這個設(shè)置會影響同一進程內(nèi)的所有WebView,默認值 false,此API已不推薦使用
  • setAppCacheEnabled(boolean flag):啟用Application Caches API,必需設(shè)置有效的緩存路徑才能生效,默認值 false,此API已廢棄
  • setAppCachePath(String appCachePath):設(shè)值緩存路徑
  • setGeolocationEnabled(boolean flag):啟用定位
  • setSaveFormData(boolean save):是否保存表單數(shù)據(jù)
  • setNeedInitialFocus(boolean flag):是否當webview調(diào)用requestFocus時為頁面的某個元素設(shè)置焦點,默認值 true
  • setUseWideViewPort(boolean use):是否支持viewport屬性,默認值 false, 頁面通過<meta name="viewport" ... />自適應手機屏幕
  • setLoadWithOverviewMode(boolean overview):是否使用overview mode加載頁面,默認值 false,當頁面寬度大于WebView寬度時,縮小使頁面寬度等于WebView寬度
  • setLayoutAlgorithm(LayoutAlgorithm l):布局算法,默認是LayoutAlgorithm#NARROW_COLUMNS
  • setJavaScriptEnabled(boolean flag):是否支持Javascript,默認值false
  • setSupportMultipleWindows(boolean support):是否支持多窗口,默認值false
  • setJavaScriptCanOpenWindowsAutomatically(boolean flag):是否可用Javascript(window.open)打開窗口,默認值 false
  • setAllowContentAccess(boolean allow):/是否可訪問Content Provider的資源,默認值 true
  • setAllowFileAccess(boolean allow):是否可訪問本地文件,默認值 true
  • setAllowFileAccessFromFileURLs(boolean flag):是否允許通過file url加載的Javascript讀取本地文件,默認值 false
  • setAllowUniversalAccessFromFileURLs(boolean flag):是否允許通過file url加載的Javascript讀取全部資源(包括文件,http,https),默認值 false
  • setLoadsImagesAutomatically(boolean flag):是否自動加載圖片
  • setBlockNetworkImage(boolean flag):禁止加載網(wǎng)絡(luò)圖片
  • setBlockNetworkLoads(boolean flag):禁止加載所有網(wǎng)絡(luò)資源
  • setSupportZoom(boolean support):是否支持縮放
  • setBuiltInZoomControls(boolean enabled):是否使用內(nèi)置縮放機制
  • setDisplayZoomControls(boolean enabled):是否顯示內(nèi)置縮放控件
  • setDefaultTextEncodingName(String encoding):設(shè)置文本編碼
  • setDefaultFontSize(int size):設(shè)置默認字體大小
  • setDefaultFixedFontSize(int size):默認等寬字體尺寸
  • setMinimumFontSize(int size):最小文字尺寸,默認值 8
  • setMinimumLogicalFontSize(int size):最小文字邏輯尺寸,默認值 8
  • setTextZoom(int textZoom):文字縮放百分比,默認值 100
  • setStandardFontFamily(String font):標準字體,默認值 "sans-serif"
  • setSerifFontFamily(String font):襯線字體,默認值 "serif"
  • setSansSerifFontFamily(String font):無襯線字體,默認值 "sans-serif"
  • setFixedFontFamily(String font):等寬字體,默認值 "monospace"
  • setCursiveFontFamily(String font):手寫體,默認值 "cursive"
  • setFantasyFontFamily(String font):幻想體,默認值 "fantasy"
  • setMediaPlaybackRequiresUserGesture(boolean require):用戶是否需要通過手勢播放媒體(不會自動播放),默認值 true
  • setOffscreenPreRaster(boolean enabled):是否在離開屏幕時光柵化(會增加內(nèi)存消耗),默認值 false
  • setCacheMode(@CacheMode int mode):用來設(shè)置WebView的緩存模式。當我們加載頁面或從上一個頁面返回的時候,會按照設(shè)置的緩存模式去檢查并使用(或不使用)緩存。
    緩存模式有四種:
    • LOAD_DEFAULT:默認的緩存使用模式。在進行頁面前進或后退的操作時,如果緩存可用并未過期就優(yōu)先加載緩存,否則從網(wǎng)絡(luò)上加載數(shù)據(jù)。這樣可以減少頁面的網(wǎng)絡(luò)請求次數(shù)。
    • LOAD_CACHE_ELSE_NETWORK:只要緩存可用就加載緩存,哪怕它們已經(jīng)過期失效。如果緩存不可用就從網(wǎng)絡(luò)上加載數(shù)據(jù)。
    • LOAD_NO_CACHE:不加載緩存,只從網(wǎng)絡(luò)加載數(shù)據(jù)。
    • LOAD_CACHE_ONLY:不從網(wǎng)絡(luò)加載數(shù)據(jù),只從緩存加載數(shù)據(jù)。
      通常我們可以根據(jù)網(wǎng)絡(luò)情況將這幾種模式結(jié)合使用,比如有網(wǎng)的時候使用LOAD_DEFAULT,離線時使用LOAD_CACHE_ONLY、LOAD_CACHE_ELSE_NETWORK,讓用戶不至于在離線時啥都看不到

3、WebViewClient

從名字上不難理解,這個類就像WebView的委托人一樣,是幫助WebView處理各種通知和請求事件的

  • public boolean shouldOverrideUrlLoading(WebView view, String url)
    攔截頁面加載,返回true表示宿主app攔截并處理了該url,否則返回false由當前WebView處理
    此方法在API24被廢棄,不處理POST請求

  • public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
    攔截頁面加載,返回true表示宿主app攔截并處理了該url,否則返回false由當前WebView處理
    此方法添加于API24,不處理POST請求,可攔截處理子frame的非http請求

  • public WebResourceResponse shouldInterceptRequest(WebView view, String url)
    此方法廢棄于API21,調(diào)用于非UI線程攔截資源請求并返回響應數(shù)據(jù),返回null時WebView將繼續(xù)加載資源。注意:API21以下的AJAX請求會走onLoadResource,無法通過此方法攔截

  • public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
    此方法添加于API21,調(diào)用于非UI線程,攔截資源請求并返回數(shù)據(jù),返回null時WebView將繼續(xù)加載資源

  • public void onPageStarted(WebView view, String url, Bitmap favicon)
    頁面(url)開始加載

  • public void onPageFinished(WebView view, String url)
    頁面(url)完成加載

  • public void onLoadResource(WebView view, String url)
    將要加載資源(url)

  • public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
    此方法廢棄于API23, 主框架加載資源時出錯

  • public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)
    此方法添加于API23,加載資源時出錯,通常意味著連接不到服務器。由于所有資源加載錯誤都會調(diào)用此方法,所以此方法應盡量邏輯簡單

  • public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse)
    此方法添加于API23, 在加載資源(iframe,image,js,css,ajax...)時收到了 HTTP 錯誤(狀態(tài)碼>=400)

  • public void onFormResubmission(WebView view, Message dontResend, Message resend)
    是否重新提交表單,默認不重發(fā)

  • public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
    加載資源時發(fā)生了一個SSL錯誤,應用必需響應(繼續(xù)請求或取消請求), 處理決策可能被緩存用于后續(xù)的請求,默認行為是取消請求

  • public void onReceivedClientCertRequest(WebView view, ClientCertRequest request)
    此方法添加于API21,在UI線程被調(diào)用, 處理SSL客戶端證書請求,必要的話可顯示一個UI來提供KEY。
    有三種響應方式:proceed()/cancel()/ignore(),默認行為是取消請求
    如果調(diào)用proceed()或cancel(),Webview 將在內(nèi)存中保存響應結(jié)果且對相同的"host:port"不會再次調(diào)用 onReceivedClientCertRequest
    多數(shù)情況下,可通過KeyChain.choosePrivateKeyAlias啟動一個Activity供用戶選擇合適的私鑰

  • public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
    處理HTTP認證請求,默認行為是取消請求

  • public void onReceivedLoginRequest(WebView view, String realm, String account, String args)
    通知應用有個已授權(quán)賬號自動登陸了

  • public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
    給應用一個機會處理按鍵事件,如果返回true,WebView不處理該事件,否則WebView會一直處理,默認返回false

  • public void onScaleChanged(WebView view, float oldScale, float newScale)
    通知應用頁面縮放系數(shù)變化

一些關(guān)鍵方法調(diào)用流程:

  • loadUrl()無重定向時

    onPageStarted->onPageFinished

  • loadUrl()網(wǎng)頁A重定向到B時

    onPageStarted->shouldOverrideUrlLoading->onPageStarted->onPageFinished->onPageFinished

  • 在已加載的頁面中點擊鏈接,加載頁面A(無重定向)

    shouldOverrideUrlLoading->onPageStarted->onPageFinished

  • 在已加載的頁面中點擊鏈接,加載頁面A(頁面A重定向至頁面B)

    shouldOverrideUrlLoading->onPageStarted->shouldOverrideUrlLoading->onPageStarted->onPageFinished->onPageFinished

  • 執(zhí)行g(shù)oBack/goForward/reload方法

    onPageStarted->onPageFinished

  • 發(fā)生資源加載

    shouldInterceptRequest->onLoadResource

  • 頁面加載

    shouldOverrideUrlLoading
    onProgressChanged[10]
    shouldInterceptRequest
    onProgressChanged[...]
    onPageStarted
    onProgressChanged[...]
    onLoadResource
    onProgressChanged[...]
    onReceivedTitle/onPageCommitVisible
    onProgressChanged[100]
    onPageFinished
    onReceivedIcon

4、WebChromeClient

  • public void getVisitedHistory(ValueCallback<String[]> callback)
    獲得所有訪問歷史項目的列表,用于鏈接著色。

  • public Bitmap getDefaultVideoPoster()
    <video /> 控件在未播放時,會展示為一張海報圖,HTML中可通過它的'poster'屬性來指定。
    如果未指定'poster'屬性,則通過此方法提供一個默認的海報圖。

  • public View getVideoLoadingProgressView()
    當全屏的視頻正在緩沖時,此方法返回一個占位視圖(比如旋轉(zhuǎn)的菊花)。

  • public void onProgressChanged(WebView view, int newProgress)
    接收當前頁面的加載進度

  • public void onReceivedTitle(WebView view, String title)
    接收文檔標題

  • public void onReceivedIcon(WebView view, Bitmap icon)
    接收圖標(favicon)

  • public void onShowCustomView(View view, CustomViewCallback callback)
    通知應用當前頁進入了全屏模式,此時應用必須顯示一個包含網(wǎng)頁內(nèi)容的自定義View

  • public void onHideCustomView()
    通知應用當前頁退出了全屏模式,此時應用必須隱藏之前顯示的自定義View

  • public boolean onJsAlert(WebView view, String url, String message, JsResult result)
    顯示一個alert對話框

  • public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
    顯示一個confirm對話框

  • public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
    顯示一個prompt對話框

  • public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result)
    顯示一個對話框讓用戶選擇是否離開當前頁面

  • public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback)
    指定源的網(wǎng)頁內(nèi)容在沒有設(shè)置權(quán)限狀態(tài)下嘗試使用地理位置API。
    從API24開始,此方法只為安全的源(https)調(diào)用,非安全的源會被自動拒絕

  • public void onGeolocationPermissionsHidePrompt()
    當前一個調(diào)用 onGeolocationPermissionsShowPrompt() 取消時,隱藏相關(guān)的UI。

  • public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
    通知應用打開新窗口

  • public void onCloseWindow(WebView window)
    通知應用關(guān)閉窗口

  • public void onRequestFocus(WebView view)
    請求獲取取焦點

  • public void onPermissionRequest(PermissionRequest request)
    通知應用網(wǎng)頁內(nèi)容申請訪問指定資源的權(quán)限(該權(quán)限未被授權(quán)或拒絕)

  • public void onPermissionRequestCanceled(PermissionRequest request)
    通知應用權(quán)限的申請被取消,隱藏相關(guān)的UI。

  • public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams)
    為'<input type="file" />'顯示文件選擇器,返回false使用默認處理

  • public boolean onConsoleMessage(ConsoleMessage consoleMessage)
    接收JavaScript控制臺消息

5、CookieManager

  • CookieManager getInstance():獲得一個CookieManager實例
  • String getCookie(String url):根據(jù)url獲取Cookie,以字符串形式返回Cookie
  • void setCookie(String url, String value):為url設(shè)置Cookie
  • void setCookie(String url, String value, ValueCallback<Boolean> callback)
    callback的onReceiveValue方法獲取的參數(shù)如果是true,代表本次設(shè)置成功,否則代表設(shè)置失敗。如果并不關(guān)心執(zhí)行結(jié)果,為callback參數(shù)傳入null即可
  • void setAcceptCookie(boolean accept):設(shè)置WebView是否允許使用Cookie,這個方法針對的是當前應用的所有WebView。
  • void setAcceptThirdPartyCookies(WebView webview, boolean accept):設(shè)置WebView是否允許設(shè)置第三方Cookie,Android 5.0(API 21)以下默認為true,Android 5.0及以上默認為false
  • void removeSessionCookie():移除所有Session Cookies ,Android 5.0(API 21)已棄用
  • void removeSessionCookies(ValueCallback<Boolean> callback):移除所有Session Cookies(異步執(zhí)行),在執(zhí)行完移除操作后,會回調(diào)onReceiveValue方法
  • void removeAllCookie():移除所有Cookies ,Android 5.0(API 21)已棄用
  • void removeAllCookies(ValueCallback<Boolean> callback):移除所有Cookies(異步執(zhí)行)
  • boolean hasCookies():判斷是否存在Cookies
  • void removeExpiredCookie():移除過期的Cookies

三、特殊場景介紹

1、視口(viewport)

視口是一個為網(wǎng)頁提供繪圖區(qū)域的矩形。
你可以指定數(shù)個視口屬性,比如尺寸和初始縮放系數(shù)(initial scale)。其中最重要的是視口寬度,它定義了網(wǎng)頁水平方向的可用像素總數(shù)(可用的CSS像素數(shù))。
多數(shù) Android 上的網(wǎng)頁瀏覽器(包括 Chrome)設(shè)置默認視口為一個大尺寸(被稱為"wide viewport mode",寬約 980px)。
也有許多瀏覽器默認會盡可能縮小以顯示完整的視口寬度(被稱為"overview mode")

// 是否支持viewport屬性,默認值 false
// 頁面通過`<meta name="viewport" ... />`自適應手機屏幕
// 當值為true且viewport標簽不存在或未指定寬度時使用 wide viewport mode
settings.setUseWideViewPort(true);
// 是否使用overview mode加載頁面,默認值 false
// 當頁面寬度大于WebView寬度時,縮小使頁面寬度等于WebView寬度
settings.setLoadWithOverviewMode(true);

viewport 語法

<meta name="viewport"
      content="
          height = [pixel_value | "device-height"] ,
          width = [pixel_value | "device-width"] ,
          initial-scale = float_value ,
          minimum-scale = float_value ,
          maximum-scale = float_value ,
          user-scalable = ["yes" | "no"]
          " />

通過WebView設(shè)置初始縮放(initial-scale)

// 設(shè)置初始縮放百分比
// 0表示依賴于setUseWideViewPort和setLoadWithOverviewMode
// 100表示不縮放
web.setInitialScale(0)

2、長按保存圖片或者撥打電話

一般瀏覽器都有長按保存圖片或者撥打圖片的功能,實現(xiàn)這個功能和WebView.HitTestResult這個類有關(guān),這個類會將你觸摸網(wǎng)頁的地方的類型和其他信息反饋給你。

WebView.HitTestResult的常用方法:

  • HitTestResult.getExtra():獲取額外的信息。
  • HitTestResult.getType():獲取所選中目標的類型,可以是圖片,超鏈接,郵件,電話等等。
    WebView.HitTestResult.UNKNOWN_TYPE //未知類型  
    WebView.HitTestResult.PHONE_TYPE //電話類型
    WebView.HitTestResult.EMAIL_TYPE //電子郵件類型
    WebView.HitTestResult.GEO_TYPE //地圖類型
    WebView.HitTestResult.SRC_ANCHOR_TYPE //超鏈接類型
    WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE //帶有鏈接的圖片類型
    WebView.HitTestResult.IMAGE_TYPE //單純的圖片類型
    WebView.HitTestResult.EDIT_TEXT_TYPE //選中的文字類型
    
  1. 給WebView設(shè)置長按監(jiān)聽事件;
  2. 獲取WebView長按時的WebView.HitTestResult的事件類型,如果是圖片,則做處理。
webView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View view) {
        WebView.HitTestResult result = ((WebView) view).getHitTestResult();
        if(result != null){
            switch (result.getType()){
                case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
                    String imgUrl = result.getExtra();
                    ...
                    return true;
                ...
            }
        }
        return false;
    }
});

3、與Javascript交互

啟用Javascript

// 是否支持Javascript,默認值false
settings.setJavaScriptEnabled(true); 

注入對象到Javascript

// 注入對象'jsobj',在網(wǎng)頁中通過`jsobj.say(...)`調(diào)用
web.addJavascriptInterface(new JSObject(), "jsobj") 

在API17后支持白名單,只有添加了@JavascriptInterface注解的方法才會注入JS

public class JSObject {
    @JavascriptInterface
    public void say(String words) {
      // todo
    }
}

移除已注入Javascript的對象

web.removeJavascriptInterface("jsobj")

執(zhí)行JS表達式

// 彈出提示框
web.loadUrl("javascript:alert('hello')");
// 調(diào)用注入的jsobj.say方法
web.loadUrl("javascript:jsobj.say('hello')"); 

在API19后可異步執(zhí)行JS表達式,并通過回調(diào)返回值

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    vWeb.evaluateJavascript("111+222", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            // value => "333"
        }
    });
}

4、全屏(Fullscreen)

  • 當H5請求全屏時,會回調(diào) WebChromeClient.onShowCustomView 方法
  • 當H5退出全屏時,會回調(diào) WebChromeClient.onHideCustomView 方法
  1. manifest
    自己處理屏幕尺寸方向的變化(切換屏幕方向時不重建activity)
    WebView播放視頻需要開啟硬件加速
<activity
    android:name=".WebViewActivity"
    android:configChanges="orientation|screenSize"
    android:hardwareAccelerated="true"
    android:screenOrientation="portrait" />
  1. 處理全屏回調(diào)
CustomViewCallback mCallback;
View vCustom;

@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
    setFullscreen(true);
    vCustom = view;
    mCallback = callback;
    if (vCustom != null) {
        ViewGroup parent = (ViewGroup) vWeb.getParent();
        parent.addView(vCustom);
    }
}

@Override
public void onHideCustomView() {
    setFullscreen(false);
    if (vCustom != null) {
        ViewGroup parent = (ViewGroup) vWeb.getParent();
        parent.removeView(vCustom);
        vCustom = null;
    }
    if (mCallback != null) {
        mCallback.onCustomViewHidden();
        mCallback = null;
    } 
} 
  1. 設(shè)置全屏,切換屏幕方向
void setFullscreen(boolean fullscreen) { 
    if (fullscreen) {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        vToolbar.setVisibility(View.GONE);
        vWeb.setVisibility(View.GONE);
    } else {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        vToolbar.setVisibility(View.VISIBLE);
        vWeb.setVisibility(View.VISIBLE);
    }
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
}

參考:
1、Android WebView 詳解
2、WebView·開車指南
3、Android WebView 常用API參考手冊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容