深入理解WebView
大小:0.6 MB 人氣: 2017-10-11 需要積分:1
作為Android開發者,我們都知道在手機中內置了一款高性能 webkit 內核瀏覽器,在 SDK 中封裝為一個叫做 WebView 組件。今天就為大家講講Android中WebView的詳細使用方法。
作為Android開發者,我們都知道在手機中內置了一款高性能 webkit 內核瀏覽器,在 SDK 中封裝為一個叫做 WebView 組件。
在開發過程中應該注意幾點:
1.這是最基本的 AndroidManifest.xml 中必須添加訪問網絡權限。
2.如果訪問的頁面中有 Java,則 WebView 必須設置支持 Java。
WebView.getSettings().setJavaEnabled(true);
3.如果頁面中鏈接,如果希望點擊鏈接繼續在當前browser中響應,而不是新開Android的系統browser中響應該鏈接,必須覆蓋 WebView的WebViewClient對象。
mWebView.setWebViewClient(newWebViewClient(){ publicbooleanshouldOverrideUrlLoading(WebView view, String url){ view.loadUrl(url); returntrue; } });
4.如果不做任何處理 ,瀏覽網頁,點擊系統“Back”鍵,整個 Browser 會調用 finish()而結束自身,如果希望瀏覽的網頁回退而不是推出瀏覽器,需要在當前Activity中處理并消費掉該 Back 事件。(代碼有些精簡)
publicboolean onKeyDown(intkeyCode, KeyEvent event) { if((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) { mWebView.goBack(); returntrue; } returnsuper.onKeyDown(keyCode, event); }
與js互調
既然可以顯示網頁,那么當然也可以讓網頁操作本地方法。(由于一行寫不下,縮進我調整了一下)
publicclassWebViewDemoextendsActivity{privateWebView mWebView; privateHandler mHandler = newHandler(); publicvoidonCreate(Bundle icicle) { setContentView(R.layout.WebViewdemo); mWebView = (WebView) findViewById(R.id.WebView); WebSettings webSettings = mWebView.getSettings(); webSettings.setJavaEnabled(true); mWebView.addJavaInterface(newObject() { publicvoidclickOnAndroid() { mHandler.post(newRunnable() { publicvoidrun() { mWebView.loadUrl(“java:wave()”); } }); } }, “demo”); mWebView.loadUrl(“file:///android_asset/demo.html”); } }
我們看 addJavaInterface(Object obj,String interfaceName)這個方法 ,該方法將一個java對象綁定到一個java對象中,java對象名就是 interfaceName(demo),作用域是Global.這樣初始化 WebView 后,在WebView加載的頁面中就可以直接通過java:window.demo訪問到綁定的java對象了。 來看看在html中是怎樣調用的。
《html》《language=“java”》functionwave(){document.getElementById(“droid”).src=“android_waving.png”; } 《/》《body》《aonClick=“window.demo.clickOnAndroid()”》《imgid=“droid”src=“android_normal.png”mce_src=“android_normal.png”/》《br》Click me! 《/a》《/body》《/html》
這樣在 java 中就可以調用 java 對象的 clickOnAndroid()方法了,同樣我們可以在此對象中定義很多方法(比如發短信,調用聯系人列表等手機系統功能),這里 wave()方法是 java 中調用 java 的例子。
需要說明一點:addJavaInterface方法中要綁定的Java對象及方法要運行另外的線程中,不能運行在構造他的線程中,這也是使用 Handler 的目的。
深入使用WebView
讓js調用Android代碼
首先簡述 WebView、WebViewClient、WebChromeClient 之間的區別:
在 WebView 的設計中,不是什么事都要 WebView類干的,有些雜事是分給其他人的,這樣 WebView 專心干好 自己的解析、渲染工作就行了.WebViewClient 就是幫助 WebView 處理各種通知、請求事件等 ,WebChromeClient 是輔助 WebView 處理 Java 的對話框,網站圖標,網站 title.
功能實現:
利用 android 中的 WebView 加載一個 html 網頁,在 html 網頁中定義一個按鈕,點擊按鈕彈出一 個 toast.
實現步驟:
首先定義一個接口類,將上下文對象傳進去,在接口類中定義要在 js 中實現的方法。
接著在assets資源包下定義一個 html 文件,在文件中定義一個 button.button 的點擊事件定義為一個 js 函數。
之后在 xml 中定義一個 WebView 組件,在活動類中獲取 WebView 并對 WebView 參數進行設置,此處特別注意要設置 WebView 支持 js 且將定義的 js 接口類添加到 WebView 中去,此后在 js 中就可以利用該接口類中定義的 函數了。即:
myWebView.getSettings().setJavaEnabled(true); myWebView.addJavaInterface(newJavainterface(this),”android”);
最后利用 WebView 加載本地 html 文件的方法是:
myWebView.loadData(htmlText,“text/html”, “utf-8”);
此處的htmltext 是以字符串的方式讀取 assets 報下 html中的內容。
4.實現利用返回鍵返回到上一頁:
設置 WebView 的按鍵監聽,監聽到期返回鍵并判斷網頁是否能夠返回 ,利用 WebView 的 goBack()返回到上一頁。
WebView 緩存
在項目中如果使用到 WebView 控件,當加載 html 頁面時,會在/data/data/包名目錄下生成 database 與 cache 兩個文件夾(我的手機沒有root,就不截圖了)。
請求的 url 記錄是保存在 WebViewCache.db,而 url 的內容是保存在 WebViewCache 文件夾下。 大家可以自己動手試一下,定義一個html文件,在里面顯示一張圖片,用WebView加載出來,然后再試著從緩存里把這張圖片讀取出來并顯示 。
WebView 刪除緩存
其實已經知道緩存保存的位置了,那么刪除就很簡單了,獲取到這個緩存,然后刪掉他就好了。
//刪除保存于手機上的緩存privateintclearCacheFolder(File dir,longnumDays) { intdeletedFiles = 0; if(dir!= null&& dir.isDirectory()){ try{ for(File child:dir.listFiles()){ if(child.isDirectory()) { deletedFiles += clearCacheFolder(child, numDays); } if(child.lastModified() 《 numDays) { if(child.delete()) { deletedFiles++; } } } } catch(Exception e) { e.printStackTrace(); } } returndeletedFiles; }
是否啟用緩存功能也是可以控制的
//優先使用緩存: WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //不使用緩存: WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
在退出應用的時候加上如下代碼,可以完整的清空緩存
File file= CacheManager.getCacheFileBaseDir(); if(file!= null && file.exists() && file.isDirectory()) { for(File item : file.listFiles()) { item.delete(); } file.delete(); } context.deleteDatabase(“WebView.db”); context.deleteDatabase(“WebViewCache.db”);
WebView 處理 404 錯誤
顯示網頁還會遇到一個問題,就是網頁有可能會找不到,WebView當然也是可以處理的(代碼如果全部貼出來實在太多了,這里就只貼重要部分了)
publicclassWebView_404extendsActivity{privateHandler handler = newHandler() { publicvoidhandleMessage(Message msg) { if(msg.what==404) {//主頁不存在//載入本地 assets 文件夾下面的錯誤提示頁面 404.html web.loadUrl(“file:///android_asset/404.html”); }else{ web.loadUrl(HOMEPAGE); } } }; @OverrideprotectedvoidonCreate(Bundle savedInstanceState) { web.setWebViewClient(newWebViewClient() { publicbooleanshouldOverrideUrl(WebView view,String url) { if(url.startsWith(“http://”) && getRespStatus(url)==404) { view.stopLoading(); //載入本地 assets 文件夾下面的錯誤提示頁面 404.html view.loadUrl(“file:///android_asset/404.html”); }else{ view.loadUrl(url); } returntrue; } }); newThread(newRunnable() { publicvoidrun() { Message msg = newMessage(); //此處判斷主頁是否存在,因為主頁是通過 loadUrl 加載的,//此時不會執行 shouldOverrideUrlLoading 進行頁面是否存在的判斷 //進入主頁后,點主頁里面的鏈接,鏈接到其他頁面就一定會執行shouldOverrideUrlLoading 方法了 if(getRespStatus(HOMEPAGE)==404) { msg.what = 404; } handler.sendMessage(msg); }).start(); } }
判斷 WebView 是否已經滾動到頁面底端
在View中有一個getScrollY()方法,可以返回當前可見區域的頂端距整個頁面頂端的距離,也就是當前內容滾動的距離。
還有getHeight()或者 getBottom()方法都返回當前 View 這個容器的高度
在ViewView中還有getContentHeight() 方法可以返回整個 html 頁面的高度,但并不等同于當前整個頁面的高度 ,因為 WebView 有縮放功能。你可以通過如下代碼來啟動或關閉webview的縮放功能。
mWebView.getSettings().setSupportZoom(true);mWebView.getSettings().setBuiltInZoomControls(true);
所以當前整個頁面的高度實際上應該是原始 html 的高度再乘上縮放比例。 因此,更正后的結果 ,準確的判斷方法應該是:
// 如果已經處于底端if(WebView.getContentHeight*WebView.getScale()-(webvi ew.getHeight()+WebView.getScrollY())){ //XXX}
WebView獲取服務器中的 session 問題
接下來我們講如下兩個問題:
Android 中的 WebView 如何獲取服務器頁面的 jsessionid 的值Android 的 WebView 又是如何把得到的 jsessionid 的值在 set 到服務器中,一致達到他們在同一個 jsessionid 的回話中。
其實非常非常簡單,只不過是幾個方法罷了:
CookieManager cm = CookieManager.getInstance(); cm.removeAllCookie();cm.getCookie(url);cm.setCookie(url, cookie);
另外還有個 CookieSyncManager,也許你會在一些舊的項目中看到它。從名字來理解,它實際上應該是一個異步緩存器。不過我們看到這個方法已經被標記為過時了,查看源碼可以看到過時原因是現在WebView已經是自動的異步緩存了,所以這個類已經沒有存在的意義了。 CookieSyncManager
WebView清除本地cookies
首先,要清除肯定要會添加,這里給大家提供一個工具方法:
/*** * 如果用戶已經登錄,則同步本地的cookie到webview中 */publicvoidsynCookies() { if(!CacheUtils.isLogin(this)) return; CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.removeSessionCookie();//移除String cookies = PreferenceHelper.readString(this, AppConfig.COOKIE_KEY, AppConfig.COOKIE_KEY); KJLoger.debug(cookies); cookieManager.setCookie(url, cookies); CookieSyncManager.getInstance().sync(); }
在使用網頁版淘寶或百度登錄時,WebView會自動登錄上次的帳號!(因為WebView 記錄了帳號和密碼的cookies) 所以,需要清除 SessionCookie也是有必要的。
那么CookieManager同樣也為我們提供了清除cookie的方法
CookieManager.getInstance().removeSessionCookie();
這里順便說一下WebView本身也是會記錄html緩存的,上一篇博客中我講了一種通過文件操作去清理緩存的方法,后來我又發現,其實webview本身就提供了清理緩存的方法,其中參數true是指是否包括磁盤文件也一并清除,傳true就和我們昨天的講的效果是一樣的了:
webview.clearCache(true);webview.clearHistory();
講一個案例
講了這么多的理論知識,最后講一個使用案例。WebView在實際使用中可以分為兩種使用方法,第一種就是類似于QQ微信那種,使用loadUrl直接去顯示一個鏈接,這種方式太簡單了,傳一個url就行,我就不多說了。
那么需要詳細講的是第二種,類似的實現大家可以看看開源中國客戶端,網易新聞客戶端,愛看博客,等客戶端的實現方式,它們實際上也是通過webview來顯示的一個網頁內容,但是并不是單純的loadurl,而是以字符串的形式去加載一個已經獲取到了的html源代碼。這樣做的好處在于顯示的頁面可以完全的根據自己喜好來定義,比如我想在末尾添加一張圖片,那么簡單,在這個html字符串的末尾插入一個img標簽就可了。至于使用方法,其實我們在上一篇博客的時候有提到過:
myWebView.loadData(htmlText,”text/html”, “utf-8”);
其中htmltext就是我們需要加載的html字符串,使用這個方法可以直接將這個字符串作為網頁來顯示。
最后總結一下兩種方法的適用場景,前一種載入鏈接的方法適合一個界面(Activity或Fragment)只有一個WebView或者說WebView占很大一塊的時候,同時我們要顯示的內容是未知的,那么自然是使用loadurl方法更合適,例如QQ聊天的時候對方發送一條鏈接,當QQ解析出這個文本是一個網址時就通過webview去加載它。而后一種則適合于定制化內容,一般是那種你可以明確的制度網頁內容以及要顯示的內容時使用,至于好處就是上面說的,定制性要好很多。
?
非常好我支持^.^
(0) 0%
不好我反對
(0) 0%