Android深入理解WebView——上

目錄(?)[+]

摘要

作爲Android開發者,我們都知道在手機中內置了一款高性能 webkit 內核瀏覽器,在 SDK 中封裝爲一個叫做 WebView 組件。今天就爲大家講講Android中WebView的詳細使用方法        
本文原創,轉載請註明地址:http://blog.kymjs.com/

作爲Android開發者,我們都知道在手機中內置了一款高性能 webkit 內核瀏覽器,在 SDK 中封裝爲一個叫做 WebView 組件。
在開發過程中應該注意幾點:
1.這是最基本的 AndroidManifest.xml 中必須添加訪問網絡權限。
2.如果訪問的頁面中有 Javascript,則 WebView 必須設置支持 Javascript。

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. WebView.getSettings().setJavaScriptEnabled(true);  

3.如果頁面中鏈接,如果希望點擊鏈接繼續在當前browser中響應,而不是新開Android的系統browser中響應該鏈接,必須覆蓋 WebView的WebViewClient對象.

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     public boolean shouldOverrideUrlLoading(WebView view, String url){   
  3.         view.loadUrl(url);  
  4.         return true;  
  5.     }  
  6. });  

4.如果不做任何處理 ,瀏覽網頁,點擊系統“Back”鍵,整個 Browser 會調用 finish()而結束自身,如果希望瀏覽的網頁回退而不是推出瀏覽器,需要在當前Activity中處理並消費掉該 Back 事件.(代碼有些精簡)

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. public boolean onKeyDown(int keyCode, KeyEvent event) {  
  2.     if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) {   
  3.         mWebView.goBack();  
  4.         return true;  
  5.     }  
  6.     return super.onKeyDown(keyCode, event);  
  7. }  

與js互調

既然可以顯示網頁,那麼當然也可以讓網頁操作本地方法。(由於一行寫不下,縮進我調整了一下)

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. public class WebViewDemo extends Activity {   
  2.     private WebView mWebView;  
  3.     private Handler mHandler = new Handler();   
  4.       
  5.     public void onCreate(Bundle icicle) {   
  6.   
  7.     setContentView(R.layout.WebViewdemo);  
  8.     mWebView = (WebView) findViewById(R.id.WebView);   
  9.     WebSettings webSettings = mWebView.getSettings();   
  10.     webSettings.setJavaScriptEnabled(true);   
  11.     mWebView.addJavascriptInterface(new Object() {  
  12.       public void clickOnAndroid() {  
  13.           mHandler.post(new Runnable() {  
  14.               public void run() {   
  15.                   mWebView.loadUrl("javascript:wave()");  
  16.               }  
  17.           });  
  18.       }  
  19.     }, "demo");   
  20.     mWebView.loadUrl("file:///android_asset/demo.html");   
  21.       
  22.     }  
  23. }  

我們看 addJavascriptInterface(Object obj,String interfaceName)這個方法 ,該方法將一個java對象綁定到一個javascript對象中,javascript對象名就是 interfaceName(demo),作用域是Global.這樣初始化 WebView 後,在WebView加載的頁面中就可以直接通過javascript:window.demo訪問到綁定的java對象了. 來看看在html中是怎樣調用的.

[html] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. <html>  
  2. <script language="javascript">  
  3.   function wave() {  
  4.     document.getElementById("droid").src="android_waving.png";  
  5.   }  
  6. </script>  
  7. <body>  
  8.   <a onClick="window.demo.clickOnAndroid()">  
  9.   <img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br> Click me! </a>  
  10. </body>  
  11. </html>  

這樣在 javascript 中就可以調用 java 對象的 clickOnAndroid()方法了,同樣我們可以在此對象中定義很多方法(比如發短信,調用聯繫人列表等手機系統功能),這裏 wave()方法是 java 中調用 javascript 的例子.

需要說明一點:addJavascriptInterface方法中要綁定的Java對象及方法要運行另外的線程中,不能運行在構造他的線程中,這也是使用 Handler 的目的.

深入使用WebView

讓js調用Android代碼

  1. 首先簡述 WebView、WebViewClient、WebChromeClient 之間的區別:
    在 WebView 的設計中,不是什麼事都要 WebView類乾的,有些雜事是分給其他人的,這樣 WebView 專心幹好 自己的解析、渲染工作就行了.WebViewClient 就是幫助 WebView 處理各種通知、請求事件等 ,WebChromeClient 是輔助 WebView 處理 Javascript 的對話框,網站圖標,網站 title.

  2. 功能實現:
    利用 android 中的 WebView 加載一個 html 網頁,在 html 網頁中定義一個按鈕,點擊按鈕彈出一 個 toast.

  3. 實現步驟:
    首先定義一個接口類,將上下文對象傳進去,在接口類中定義要在 js 中實現的方法。
    接着在assets資源包下定義一個 html 文件,在文件中定義一個 button.button 的點擊事件定義爲一個 js 函數. 
    之後在 xml 中定義一個 WebView 組件,在活動類中獲取 WebView 並對 WebView 參數進行設置,此處特別注意要設置 WebView 支持 js 且將定義的 js 接口類添加到 WebView 中去,此後在 js 中就可以利用該接口類中定義的 函數了.即:

    myWebView.getSettings().setJavaScriptEnabled(true); 

    myWebView.addJavascriptInterface(new JavaScriptinterface(this),”android”); 

最後利用 WebView 加載本地 html 文件的方法是:

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. 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 刪除緩存

其實已經知道緩存保存的位置了,那麼刪除就很簡單了,獲取到這個緩存,然後刪掉他就好了。
//刪除保存於手機上的緩存

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. private int clearCacheFolder(File dir,long numDays) {   
  2.   int deletedFiles = 0;  
  3.   if (dir!= null && dir.isDirectory()){  
  4.     try {  
  5.       for (File child:dir.listFiles()){  
  6.           if (child.isDirectory()) {  
  7.             deletedFiles += clearCacheFolder(child, numDays);  
  8.         }  
  9.         if (child.lastModified() < numDays) {  
  10.           if (child.delete()) {  
  11.            deletedFiles++;   
  12.           }  
  13.         }  
  14.       }  
  15.     } catch(Exception e) {  
  16.       e.printStackTrace();   
  17.     }  
  18.   }  
  19.   return deletedFiles;   
  20. }  

是否啓用緩存功能也是可以控制的

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. //優先使用緩存:   
  2.     WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);   
  3.     //不使用緩存:   
  4.     WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);  

在退出應用的時候加上如下代碼,可以完整的清空緩存

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. File file = CacheManager.getCacheFileBaseDir();  
  2. if (file != null && file.exists() && file.isDirectory()) {  
  3.     for (File item : file.listFiles()) {  
  4.         item.delete();}file.delete();  
  5.     }  
  6. context.deleteDatabase("WebView.db");   
  7. context.deleteDatabase("WebViewCache.db");  

WebView 處理 404 錯誤

顯示網頁還會遇到一個問題,就是網頁有可能會找不到,WebView當然也是可以處理的(代碼如果全部貼出來實在太多了,這裏就只貼重要部分了)

[java] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. public class WebViewActivity extends Activity {  
  2.     private Handler handler = new Handler() {  
  3.         public void handleMessage(Message msg) {  
  4.               if(msg.what==404) {//主頁不存在  
  5.                   //載入本地 assets 文件夾下面的錯誤提示頁面 404.html  
  6.                   web.loadUrl("file:///android_asset/404.html");        
  7.               }else{          
  8.                   web.loadUrl(HOMEPAGE);        
  9.               }      
  10.           }};  
  11.       @Override  
  12.       protected void onCreate(Bundle savedInstanceState) {  
  13.         web.setWebViewClient(new WebViewClient() {        
  14.             public boolean shouldOverrideUrl(WebView view,String url) {   
  15.         if(url.startsWith("http://") && getRespStatus(url)==404) {        
  16.             view.stopLoading();        
  17.             //載入本地 assets 文件夾下面的錯誤提示頁面 404.html         
  18.             view.loadUrl("file:///android_asset/404.html");      
  19.         }else{        
  20.             view.loadUrl(url);      
  21.         }        
  22.     return true;      
  23.     }    
  24.     });    
  25.     new Thread(new Runnable() {      
  26.         public void run() {    
  27.         Message msg = new Message();    
  28.         //此處判斷主頁是否存在,因爲主頁是通過 loadUrl 加載的,    
  29.         //此時不會執行 shouldOverrideUrlLoading 進行頁面是否存在的判斷   
  30.         //進入主頁後,點主頁裏面的鏈接,鏈接到其他頁面就一定會執行shouldOverrideUrlLoading 方法了   
  31.             if(getRespStatus(HOMEPAGE)==404) {        
  32.                 msg.what = 404;    
  33.             }    
  34.             handler.sendMessage(msg);    
  35.         }).start();    
  36.     }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章