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.     }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章