WebView開源庫終極方案

目錄介紹

  • 01.前沿說明css

    • 1.1 案例展現效果
    • 1.2 該庫功能和優點
    • 1.3 相關類介紹說明
    • 1.4 WebView知識點
  • 02.如何使用html

    • 2.1 如何引入
    • 2.2 最簡單使用
    • 2.3 經常使用api
    • 2.4 使用建議
    • 2.5 異常狀態類型區分
    • 2.6 該庫流程圖
  • 03.js調用前端

    • 3.1 Java調用js方法
    • 3.2 js調用java方法
    • 3.3 js的調用時機分析
    • 3.4 js交互原理分析
  • 04.問題反饋
  • 05.webView優化
  • 06.關於參考
  • 07.其餘說明介紹

01.前沿說明

  • 基於騰訊x5開源庫,提升webView開發效率,大概要節約你百分之六十的時間成本。該案例支持處理js的交互邏輯且無耦合、同時暴露進度條加載進度、能夠監聽異常error狀態、支持視頻播放而且能夠全頻、支持加載word,xls,ppt,pdf,txt等文件文檔、發短信、打電話、發郵件、打開文件操做上傳圖片、喚起原生App、x5庫爲最新版本,功能強大。項目地址:webView開源庫
  • 同時,該案例中,04問題反饋也記錄了絕大多數實際開發中遇到的問題,若是還有其餘的問題,也能夠發送給我,我收集起來放到一塊兒,方便後期查閱。
  • 能夠說,該開源庫,以及附帶的webView基礎知識點,問題彙總,以及優化方案等筆記,相對來講比較系統而又全面的梳理webView的知識體系,相對而言也是比較實用的,也不乏參考了一些好的案例和博客文章。

1.1 案例展現效果

  • WebView啓動過程大概分爲如下幾個階段,這裏借鑑美團的一張圖片java

    • image

1.2 該庫功能和優點

  • 提升webView開發效率,大概要節約你百分之六十的時間成本,一鍵初始化操做;
  • 支持處理js的交互邏輯,方便快捷,而且無耦合,操做十分簡單;
  • 暴露進度條加載進度,結束,以及異常狀態(分多種狀態:無網絡,404,onReceivedError,sslError異常等)listener給開發者;
  • 支持視頻播放,能夠切換成全頻播放視頻,可旋轉屏幕,暴露視頻操做監聽listener給開發者;
  • 集成了騰訊x5的WebView,最新版本,功能強大;
  • 支持打開文件的操做,好比打開相冊,而後選中圖片上傳,兼容版本(5.0);
  • 支持加載word,xls,ppt,pdf,txt等文件文檔,使用方法十分簡單;
  • 支持設置仿微信加載H5頁面進度條,徹底無耦合,操做簡單,極大提升用戶體驗;
  • 支持用戶按照規範自定義WebViewClient和WebChromeClient,不影響js通訊;
  • 聚集絕大多數問題,以及解決方案,是學習和深刻理解webView的一個比較全面的案例;

1.3 相關類介紹說明

  • BridgeHandler 接口,主要處理消息回調邏輯
  • BridgeUtil 工具類,靜態常量,以及獲取js消息的一些方法,final修飾
  • BridgeWebView 自定義WebView類,主要處理與js之間的消息
  • CallBackFunction js回調
  • DefaultHandler 默認的BridgeHandler
  • InterWebListener 接口,web的接口回調,包括常見狀態頁面切換【狀態頁面切換】,進度條變化【顯示和進度監聽】等
  • Message 自定義消息Message實體類
  • ProgressWebView 自定義帶進度條的webView
  • WebViewJavascriptBridge js橋接接口
  • X5WebChromeClient 自定義x5的WebChromeClient,處理進度監聽,title變化,以及上傳圖片,後期添加視頻處理邏輯
  • X5WebUtils 工具類,初始化騰訊x5瀏覽器webView,及調用該類init方法
  • X5WebView 可使用這個類,方便統一初始化WebSettings的一些屬性,若是不用這裏的,想單獨初始化setting屬性,也能夠直接使用BridgeWebView
  • X5WebViewClient 自定義x5的WebViewClient,若是要自定義WebViewClient必需要集成此類,必定要繼承該類,由於注入js監聽是在該類中操做的
  • WebProgress 仿微信加載H5頁面的WebView進度條

1.4 WebView基礎知識點

  • 01.經常使用的基礎介紹
  • 02.Android調用Js
  • 03.Js調用Android
  • 04.WebView.loadUrl(url)流程
  • 05.js的調用時機分析
  • 06.清除緩存數據方式有哪些
  • 07.如何使用DeepLink
  • 08.爲何WebView那麼難搞
  • 09.如何處理加載錯誤
  • 10.應用被做爲第三方瀏覽器打開
  • 11.理解WebView獨立進程
  • 12.使用外部瀏覽器下載
  • 13.tel,sms等協議用法
  • 更多內容看wiki

02.如何使用

2.1 如何引入

  • 如何引用,該x5的庫已經更新到最新版本,引用最新1.2.0穩定版android

    implementation 'cn.yc:WebViewLib:1.2.0'

2.2 最簡單使用

  • 項目初始化git

    X5WebUtils.init(this);
  • 最普通使用,須要本身作手動設置setting相關屬性github

    <BridgeWebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbarSize="3dp" />
  • 也可使用X5WebView,已經作了常見的setting屬性設置web

    <X5WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbarSize="3dp" />
  • 若是想有帶進度的,可使用ProgressWebView面試

    <可使用ProgressWebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbarSize="3dp" />
  • 如何使用本身的WebViewClient和WebChromeClientjson

    //主要是在X5WebViewClient和X5WebChromeClient已經作了不少常見的邏輯處理,若是不知足你使用,能夠以下這樣寫
    MyX5WebViewClient webViewClient = new MyX5WebViewClient(webView, this);
    webView.setWebViewClient(webViewClient);
    MyX5WebChromeClient webChromeClient = new MyX5WebChromeClient(this);
    webView.setWebChromeClient(webChromeClient);
    
    private class MyX5WebViewClient extends X5WebViewClient {
        public MyX5WebViewClient(BridgeWebView webView, Context context) {
            super(webView, context);
        }
        
        //重寫你須要的方法便可
    }
    
    private class MyX5WebChromeClient extends X5WebChromeClient{
        public MyX5WebChromeClient(Activity activity) {
            super(activity);
        }
        
        //重寫你須要的方法便可
    }
  • 針對相似購物的商品詳情頁面的webView

    • 當WebView在最頂部或者最底部的時候,不消費事件,則可使用VerticalWebView

2.3 經常使用api

  • 關於web的接口回調,包括常見狀態頁面切換,進度條變化等監聽處理

    mWebView.getX5WebChromeClient().setWebListener(interWebListener);
    private InterWebListener interWebListener = new InterWebListener() {
        @Override
        public void hindProgressBar() {
            pb.setVisibility(View.GONE);
        }
    
        @Override
        public void showErrorView(@X5WebUtils.ErrorType int type) {
            //設置自定義異常錯誤頁面
        }
    
        @Override
        public void startProgress(int newProgress) {
            //該方法是是監聽進度條進度變化的邏輯
            pb.setProgress(newProgress);
        }
        
        @Override
        public void showTitle(String title) {
            //該方法是監聽h5中title
        }
    };
  • 關於視頻播放的時候,web的接口回調,主要是視頻相關回調,好比全頻,取消全頻,隱藏和現實webView

    x5WebChromeClient = x5WebView.getX5WebChromeClient();
    x5WebChromeClient.setVideoWebListener(new VideoWebListener() {
        @Override
        public void showVideoFullView() {
            //視頻全頻播放時監聽
        }
    
        @Override
        public void hindVideoFullView() {
            //隱藏全頻播放,也就是正常播放視頻
        }
    
        @Override
        public void showWebView() {
            //顯示webView
        }
    
        @Override
        public void hindWebView() {
            //隱藏webView
        }
    });
  • 其餘api說明

    //X5WebView中
    //設置是否開啓密碼保存功能,不建議開啓,默認已經作了處理,存在盜取密碼的危險
    mWebView.setSavePassword(false);
    //是否開啓軟硬件加速
    mWebView.setOpenLayerType(false);
    //獲取x5WebChromeClient對象
    x5WebChromeClient = mWebView.getX5WebChromeClient();
    //獲取x5WebViewClient對象
    x5WebViewClient = mWebView.getX5WebViewClient();
  • 關於如何使用仿微信加載H5頁面進度條

    • 前端頁面時受到網路環境,頁面內容大小的影響有時候會讓用戶等待好久。顯示一個加載進度條能夠說很大程度上提高用戶的體驗。
    private WebProgress pb;
    //顯示進度條
    pb.show();
    //設置進度條過分顏色
    pb.setColor(Color.BLUE,Color.RED);
    //設置單色進度條
    pb.setColor(Color.BLUE);
    //爲單獨處理WebView進度條
    pb.setWebProgress(newProgress);
    //進度完成後消失
    pb.hide();
  • 設置cookie和清除cookie操做

    //同步cookie
    X5WebUtils.syncCookie(this,"url",cookieList);
    //清除cookie
    X5WebUtils.removeCookie(this);

2.4 使用建議

  • 優化一下相關的操做

    • 關於設置js支持的屬性
    @Override
    public void onResume() {
        super.onResume();
        if (mWebView != null) {
            mWebView.getSettings().setJavaScriptEnabled(true);
        }
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        if (mWebView != null) {
            mWebView.getSettings().setJavaScriptEnabled(false);
        }
    }
    • 關於destroy銷燬邏輯
    @Override
    protected void onDestroy() {
        try {
            if (webView != null) {
                webView.stopLoading();
                webView.destroy();
                webView = null;
            }
        } catch (Exception e) {
            Log.e("X5WebViewActivity", e.getMessage());
        }
        super.onDestroy();
    }

2.5 關於web頁面異常狀態區分類型

  • 對於web加載異常,分爲多種狀態,好比常見的有,沒有網絡;404加載異常;onReceivedError,請求網絡出現error;在加載資源時通知主機應用程序發生SSL錯誤

    @Override
    public void showErrorView(@X5WebUtils.ErrorType int type) {
        switch (type){
            //沒有網絡
            case X5WebUtils.ErrorMode.NO_NET:
                break;
            //404,網頁沒法打開
            case X5WebUtils.ErrorMode.STATE_404:
                break;
            //onReceivedError,請求網絡出現error
            case X5WebUtils.ErrorMode.RECEIVED_ERROR:
                break;
            //在加載資源時通知主機應用程序發生SSL錯誤
            case X5WebUtils.ErrorMode.SSL_ERROR:
                break;
            default:
                break;
        }
    }

2.6 該庫流程圖

  • java調用js的流程圖

    • 第一步操做:mWebView.callHandler("functionInJs", "小楊逗比", new CallBackFunction() {//這裏面是回調});
    • 第二步操做:將handlerName,data,responseCallback,封裝到Message對象中,而後開始分發數據,最後webView執行_handleMessageFromNative;
    • 第三步操做:去WebViewJavascriptBridge.js類中找到_handleMessageFromNative方法,js根據"functionInJs"找到對應的js方法而且執行;
    • 第四步操做:js把運行結果保存到message對象中,而後添加到js消息隊列中;
    • 第五步操做:在_dispatchMessageFromNative方法中,能夠看到,js向native發送 "消息隊列中有消息" 的通知;
    • 第六步操做:webView執行js的_fetchQueue(WebViewJavascriptBridge.js類)方法;
    • 第七步操做:js把消息隊列中的全部消息都一塊兒回傳給webView;
    • 第八步操做:webView收到全部的消息,一個一個串行處理,注意其中包括 "functionInJs"方法運行的結果的消息;
  • js調用Android的流程圖

    • 第一步操做:mWebView.registerHandler("toPhone", new BridgeHandler() { //回調});
    • 第二步操做:調用messageHandlers.put(handlerName, handler),將名稱和BridgeHandler對象放到map集合中
    • 第三步操做:在shouldOverrideUrlLoading方法中攔截url,與網頁約定好一個協議,匹配則執行相應操做,也就是利用WebViewClient接口回調方法攔截url
    • 第四步操做:若是是url.startsWith(BridgeUtil.YY_RETURN_DATA)則有數據返回;若是是BridgeUtil.YY_OVERRIDE_SCHEMA則刷新消息隊列
    • 第五步操做:經過BridgeHandler對象,將data和callBackFunction返回交給開發者

03.js交互操做

3.1 Java調用js的使用方法

  • 代碼以下所示,下面updateAttentionStatus表明js這邊的方法名稱

    • webView.callHandler(「updateAttentionStatus」, …, new CallBackFunction());這是Java層主動調用Js的」updateAttentionStatus」方法。
    mWebView.callHandler("updateAttentionStatus", attention, new CallBackFunction() {
        @Override
        public void onCallBack(String data) {
    
        }
    });

3.2 js調用java的使用方法

  • 代碼以下所示,下面中的toPhone表明的是Android這邊提供給js的方法名稱

    • webView.registerHandler(「toPhone」, …);這是Java層註冊了一個叫」toPhone」的接口方法,目的是提供給Js來調用。這個」toPhone」的接口方法的回調就是BridgeHandler.handler()。
    mWebView.registerHandler("toPhone", new BridgeHandler() {
        @Override
        public void handler(String data, CallBackFunction function) {
            try {
                JSONObject jsonData = new JSONObject(data);
                String phone = jsonData.optString("phone");
                //todo 打電話
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });
  • 如何回調數據給web那邊

    //注意,這裏回傳數據目前只是支持String字符串類型
    function.onCallBack("回調數據");

3.3 js的調用時機分析

  • onPageFinished()或者onPageStarted()方法中注入js代碼

    • 作過WebView開發,而且須要和js交互,大部分都會認爲js在WebViewClient.onPageFinished()方法中注入最合適,此時dom樹已經構建完成,頁面已經徹底展示出來。但若是作過頁面加載速度的測試,會發現WebViewClient.onPageFinished()方法一般須要等待好久纔會回調(首次加載一般超過3s),這是由於WebView須要加載完一個網頁裏主文檔和全部的資源纔會回調這個方法。
    • 能不能在WebViewClient.onPageStarted()中注入呢?答案是不肯定。通過測試,有些機型能夠,有些機型不行。在WebViewClient.onPageStarted()中注入還有一個致命的問題——這個方法可能會回調屢次,會形成js代碼的屢次注入。
    • 從7.0開始,WebView加載js方式發生了一些小改變,官方建議把js注入的時機放在頁面開始加載以後
  • WebViewClient.onProgressChanged()方法中注入js代碼

    • WebViewClient.onProgressChanged()這個方法在dom樹渲染的過程當中會回調屢次,每次都會告訴咱們當前加載的進度。

      • 在這個方法中,能夠給WebView自定義進度條,相似微信加載網頁時的那種進度條
      • 若是在此方法中注入js代碼,則須要避免重複注入,須要加強邏輯。能夠定義一個boolean值變量控制注入時機
    • 那麼有人會問,加載到多少才須要處理js注入邏輯呢?

      • 正是由於這個緣由,頁面的進度加載到80%的時候,實際上dom樹已經渲染得差很少了,代表WebView已經解析了<html>標籤,這時候注入必定是成功的。在WebViewClient.onProgressChanged()實現js注入有幾個須要注意的地方:
      • 1 上文提到的屢次注入控制,使用了boolean值變量控制
      • 2 從新加載一個URL以前,須要重置boolean值變量,讓從新加載後的頁面再次注入js
      • 3 若是作過本地js,css等緩存,則先判斷本地是否存在,若存在則加載本地,不然加載網絡js
      • 4 注入的進度閾值能夠自由定製,理論上10%-100%都是合理的,不過建議使用了75%到90%之間能夠。

3.4 js交互原理分析

  • 01.WebView加載html頁面
  • 02.加載WebViewJavascriptBridge.js
  • 03.分析WebViewJavascriptBridge.js
  • 04.頁面Html註冊」functionInJs」方法
  • 05.「functionInJs」執行結果回傳Java
  • 更多內容看wiki

04.問題反饋

  • 4.0.0 WebView進化史介紹
  • 4.0.1 提早初始化WebView必要性
  • 4.0.2 x5加載office資源
  • 4.0.3 WebView播放視頻問題
  • 4.0.4 沒法獲取webView的正確高度
  • 4.0.5 使用scheme協議打開連接風險
  • 4.0.6 如何處理加載錯誤
  • 4.0.7 webView防止內存泄漏
  • 4.0.8 關於js注入時機修改
  • 4.0.9 視頻播放寬度超過屏幕
  • 4.1.0 如何保證js安全性
  • 4.1.1 如何代碼開啓硬件加速
  • 4.1.2 WebView設置Cookie
  • 4.1.3 開啓硬件加速致使的閃爍問題
  • 4.1.4 webView加載網頁不顯示圖片
  • 4.1.5 繞過證書校驗漏洞
  • 4.1.6 allowFileAccess漏洞
  • 4.1.7 WebView嵌套ScrollView問題
  • 4.1.8 WebView中圖片點擊放大
  • 4.1.9 頁面滑動期間不渲染/執行
  • 4.2.0 被運營商劫持和注入問題
  • 4.2.1 解決資源加載緩慢問題
  • 4.2.2 判斷是否已經滾動到頁面底端
  • 4.2.3 使用loadData加載html亂碼
  • 4.2.4 WebView下載進度沒法監聽
  • 4.2.5 webView出現302/303重定向
  • 4.2.6 webView出現302/303白屏
  • 4.2.8 onReceiveError問題
  • 4.2.9 loadUrl在19以上超過2097152個字符失效
  • 4.3.0 WebViewJavascriptBridge: WARNING
  • 4.3.1 Android與js傳遞數據大小有限制
  • 4.3.2 屢次調用callHandler部分回調函數未被調用
  • 4.3.3 字符串轉義bug探討
  • 4.3.8 Javascript調用原生方法會偶現失敗
  • 4.3.9 dispatchMessage運行主線程問題
  • 4.4.0 怎麼實現WebView免流方案
  • 4.4.1 Channel is unrecoverably broken and will be disposed!
  • 4.4.2 定製js的alert,confirm和prompt對話框
  • 4.4.3 x5長按圖片如何操做
  • 4.4 4 x5長按文字內容如何自定義彈窗
  • 4.4.5 webView.goBack()會刷新頁面嗎
  • 4.4.6 mWebView.scrollTo(0, 0)回頂部失效
  • 4.4.7 部分手機監聽滑動頂部或底部失效
  • 4.4.8 prompt的一個坑致使js掛掉
  • 4.4.9 webView背景設置爲透明無效探索
  • 4.5.0 如何屏蔽掉WebView中長按事件
  • 4.5.1 WeView出現OOM影響主進程如何避免
  • 4.5.2 WebView域控制不嚴格漏洞
  • 4.5.3 下載文件時的路徑穿越問題
  • 4.5.4 WebView中http和https混合使用問題
  • 4.5.5 調用系統EMAIL發送郵件崩潰
  • 4.5.7 WebView訪問部分網頁崩潰問題
  • 更多問題反饋內容

05.webView優化

  • 5.0.1 視頻全屏播放按返回頁面被放大
  • 5.0.2 加快加載webView中的圖片資源
  • 5.0.3 自定義加載異常error的狀態頁面
  • 5.0.4 WebView硬件加速致使頁面渲染閃爍
  • 5.0.5 WebView加載證書錯誤
  • 5.0.6 web音頻播放銷燬後還有聲音
  • 5.0.7 DNS採用和客戶端API相同的域名
  • 5.0.8 如何設置白名單操做
  • 5.0.9 後臺沒法釋放js致使發熱耗電
  • 5.1.0 能夠提早顯示加載進度條
  • 5.1.1 WebView密碼明文存儲漏洞優化
  • 5.1.2 頁面關閉後不要執行web中js
  • 5.1.3 WebView + HttpDns優化
  • 5.1.4 如何禁止WebView返回時刷新
  • 5.1.5 WebView處理40四、500邏輯
  • 5.1.6 WebView判斷斷網和連接超時
  • 5.1.7 @JavascriptInterface註解方法注意點
  • 5.1.8 使用onJsPrompt實現js通訊注意點
  • 5.1.9 Cookie同步場景和具體操做
  • 5.2.0 shouldOverrideUrlLoading處理多類型
  • 更多webView優化內容

06.關於參考

07.其餘說明介紹

關於博客彙總連接

其餘推薦

  • 博客筆記大彙總【15年10月到至今】,包括Java基礎及深刻知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug彙總,固然也在工做之餘收集了大量的面試題,長期更新維護而且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計47篇[近100萬字],轉載請註明出處,謝謝!
  • 連接地址:https://github.com/yangchong2...
  • 若是以爲好,能夠star一下,謝謝!固然也歡迎提出建議,萬事起於忽微,量變引發質變!
相關文章
相關標籤/搜索