目錄介紹
- 01.前沿說明
- 1.1 案例展示效果
- 1.2 該庫功能和優勢
- 1.3 相關類介紹說明
- 1.4 WebView知識點
- 02.如何使用
- 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.其他說明介紹
- 基于騰訊x5開源庫,提高webView開發效率,大概要節約你百分之六十的時間成本。該案例支援處理js的互動邏輯且無耦合、同時暴露進度條加載進度、可以監聽異常error狀态、支援視訊播放并且可以全頻、支援加載word,xls,ppt,pdf,txt等檔案文檔、發短信、打電話、發郵件、打開檔案操作上傳圖檔、喚起原生App、x5庫為最新版本,功能強大。項目位址: webView開源庫
- 同時,該案例中,04問題回報也記錄了絕大多數實際開發中遇到的問題,如果還有其他的問題,也可以發送給我,我收集起來放到一起,友善後期查閱。
- 可以說,該開源庫,以及附帶的webView基礎知識點,問題彙總,以及優化方案等筆記,相對來說比較系統而又全面的梳理webView的知識體系,相對而言也是比較實用的,也不乏參考了一些好的案例和部落格文章。
- WebView啟動過程大概分為以下幾個階段,這裡借鑒美團的一張圖檔
-
WebView開源庫終極方案
-
- 提高webView開發效率,大概要節約你百分之六十的時間成本,一鍵初始化操作;
- 支援處理js的互動邏輯,友善快捷,并且無耦合,操作十分簡單;
- 暴露進度條加載進度,結束,以及異常狀态(分多種狀态:無網絡,404,onReceivedError,sslError異常等)listener給開發者;
- 支援視訊播放,可以切換成全頻播放視訊,可旋轉螢幕,暴露視訊操作監聽listener給開發者;
- 內建了騰訊x5的WebView,最新版本,功能強大;
- 支援打開檔案的操作,比如打開相冊,然後選中圖檔上傳,相容版本(5.0);
- 支援加載word,xls,ppt,pdf,txt等檔案文檔,使用方法十分簡單;
- 支援設定仿微信加載H5頁面進度條,完全無耦合,操作簡單,極大提高使用者體驗;
- 支援使用者按照規範自定義WebViewClient和WebChromeClient,不影響js通信;
- 彙集絕大多數問題,以及解決方案,是學習和深入了解webView的一個比較全面的案例;
- 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
- 如何引用,該x5的庫已經更新到最新版本,引用最新1.2.0穩定版
implementation 'cn.yc:WebViewLib:1.2.0'
- 項目初始化
X5WebUtils.init(this);
- 最普通使用,需要自己做手動設定setting相關屬性
<BridgeWebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbarSize="3dp" />
- 也可以使用X5WebView,已經做了常見的setting屬性設定
<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和WebChromeClient
//主要是在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
- 關于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);
- 優化一下相關的操作
- 關于設定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; } }
- 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("回調資料");
- 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已經解析了标簽,這時候注入一定是成功的。在WebViewClient.onProgressChanged()實作js注入有幾個需要注意的地方:
- 1 上文提到的多次注入控制,使用了boolean值變量控制
- 2 重新加載一個URL之前,需要重置boolean值變量,讓重新加載後的頁面再次注入js
- 3 如果做過本地js,css等緩存,則先判斷本地是否存在,若存在則加載本地,否則加載網絡js
- 4 注入的進度門檻值可以自由定制,理論上10%-100%都是合理的,不過建議使用了75%到90%之間可以。
- WebViewClient.onProgressChanged()這個方法在dom樹渲染的過程中會回調多次,每次都會告訴我們目前加載的進度。
- 01.WebView加載html頁面
- 02.加載WebViewJavascriptBridge.js
- 03.分析WebViewJavascriptBridge.js
- 04.頁面Html注冊”functionInJs”方法
- 05.“functionInJs”執行結果回傳Java
- 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通路部分網頁崩潰問題
- 更多問題回報内容
- 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處理404、500邏輯
- 5.1.6 WebView判斷斷網和連結逾時
- 5.1.7 @JavascriptInterface注解方法注意點
- 5.1.8 使用onJsPrompt實作js通信注意點
- 5.1.9 Cookie同步場景和具體操作
- 5.2.0 shouldOverrideUrlLoading處理多類型
- 更多webView優化内容
- 感謝開源庫
- 參考部落格
- WebView性能、體驗分析與優化
- WebView詳解,常見漏洞詳解和安全源碼上
- WebView詳解,常見漏洞詳解和安全源碼下
- 如何設計一個優雅健壯的Android WebView
- 其他部落格,這裡隻是記錄一部分,感謝
關于部落格彙總連結
其他推薦
- 部落格筆記大彙總【15年10月到至今】,包括Java基礎及深入知識點,Android技術部落格,Python學習筆記等等,還包括平時開發中遇到的bug彙總,當然也在工作之餘收集了大量的面試題,長期更新維護并且修正,持續完善……開源的檔案是markdown格式的!同時也開源了生活部落格,從12年起,積累共計47篇[近100萬字],轉載請注明出處,謝謝!
- 連結位址: https://github.com/yangchong211/YCBlogs
- 如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起于忽微,量變引起質變!