android之WebView及与js的交互

来源:互联网 发布:mac待机时间设置 编辑:程序博客网 时间:2024/06/03 18:35

在Android手机中内置了一款高性能webkit内核浏览器,在SDK中封装为一个叫做WebView组件。 

什么是webkit
 

WebKit是Mac OS X v10.3及以上版本所包含的软件框架(对v10.2.7及以上版本也可通过软件更新获取)。 同时,WebKit也是Mac OS X的Safari网页浏览器的基础。WebKit是一个开源项目,主要由KDE的KHTML修改而来并且包含了一些来自苹果公司的一些组件。
 

传统上,WebKit包含一个网页引擎WebCore和一个脚本引擎JavaScriptCore,它们分别对应的是KDE的KHTML和KJS。不过, 随着JavaScript引擎的独立性越来越强,现在WebKit和WebCore已经基本上混用不分(例如Google Chrome和Maxthon 3采用V8引擎,却仍然宣称自己是WebKit内核)。
 

这里我们初步体验一下在android是使用webview浏览网页,在SDK的Dev Guide中有一个WebView的简单例子 。
 

在开发过程中应该注意几点:
 
    1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。
    2.如果访问的页面中有Javascript,则webview必须设置支持Javascript。
        webview.getSettings().setJavaScriptEnabled(true);  
    3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。

 

  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事件。

 

  1. public boolean onKeyDown(int keyCode, KeyEvent event) {       
  2.         if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {       
  3.             mWebView.goBack();       
  4.                    return true;       
  5.         }       
  6.         return super.onKeyDown(keyCode, event);       
  7.     }     

 

 

下一步让我们来了解一下android中webview是如何支持javascripte自定义对象的,在w3c标准中js有 window,history,document等标准对象,同样我们可以在开发浏览器时自己定义我们的对象调用手机系统功能来处理,这样使用js就可以 为所欲为了。

  看一个实例:

 

view plaincopy to clipboardprint?
  1. public class WebViewDemo extends Activity {        
  2.     private WebView mWebView;       
  3.     private Handler mHandler = new Handler();       
  4.        
  5.     public void onCreate(Bundle icicle) {       
  6.         super.onCreate(icicle);       
  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. }   

 

 

我们看addJavascriptInterface(Object obj,String interfaceName)这个方法,该方法将一个java对象绑定到一个javascript对象中,javascript对象名就是 interfaceName(demo),作用域是Global。这样初始化webview后,在webview加载的页面中就可以直接通过 javascript:window.demo访问到绑定的java对象了。来看看在html中是怎样调用的。

 

  1. <html>       
  2.         <mce:script language="javascript"><!--     
  3.        
  4.                 function wave() {       
  5.                     document.getElementById("droid").src="android_waving.png";       
  6.                 }       
  7.              
  8. // --></mce:script>       
  9.         <body>       
  10.             <a onClick="window.demo.clickOnAndroid()">       
  11.                                 <img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br>       
  12.                                 Click me!       
  13.             </a>       
  14.         </body>       
  15. </html>      

 

 

这样在javascript中就可以调用java对象的clickOnAndroid()方法了,同样我们可以在此对象中定义很多方法(比 如发短信,调用联系人列表等手机系统功能。),这里wave()方法是java中调用javascript的例子。

这里还有几个知识点: 

1)为了让WebView从apk文件中加载assets,Android SDK提供了一个schema,前缀为"file:///android_asset/"。WebView遇到这样的schema,就去当前包中的 assets目录中找内容。如上面的"file:///android_asset/demo.html"
 
2)addJavascriptInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用 Handler的目的。


Javascript弹出框有如下三种: 

Java代码  
  1. alert();  
  2. window.confirm("Are you srue?");  
  3. window.prompt("Please input some word";,"this is text");  


WebChromeClient 中对三种dialog进行了捕捉,但不幸的是,并没有回调函数可以使用, 
或者说不能获得用户是点击“OK”还是“CANCEL”的操作结果。 
个人以为,这些方法的设置是为了对一些涉及到html操作的应用程序进行测试时使用的。 
在WebChromeClient中还有以下的方法: 
Java代码  
  1. onProgressChanged(WebView view, int newProgress);  
  2. onReceivedIcon(WebView view, Bitmap icon);  
  3. onReceivedTitle(WebView view, String title);  
  4. onRequestFocus(WebView view);  
  5. onCloseWindow(WebView window);  
  6. onProgressChanged(WebView view, int newProgress)  

这些方法的使用我会在以后的博文中讲到. 
请大家先看今天讲解的重点 
Java代码  
  1. public class WebViewDemo extends Activity {  
  2.   
  3.     private static final String LOG_TAG = "WebViewDemo";  
  4.     private WebView mWebView;  
  5.     private TextView mReusultText ;  
  6.     private Handler mHandler = new Handler();  
  7.   
  8.     @Override  
  9.     public void onCreate(Bundle icicle) {  
  10.   
  11.         super.onCreate(icicle);  
  12.         setContentView(R.layout.main);  
  13.         //获得浏览器组件  
  14.         //WebView就是一个简单的浏览器  
  15.         //android浏览器源码存在于LINUX\android\package\apps\Browser中  
  16.         //里面的所有操作都是围绕WebView来展开的  
  17.         mWebView = (WebView) findViewById(R.id.webview);  
  18.         mReusultText = (TextView) findViewById(R.id.resultText);  
  19.         //WebSettings 几乎浏览器的所有设置都在该类中进行  
  20.         WebSettings webSettings = mWebView.getSettings();  
  21.         webSettings.setSavePassword(false);  
  22.         webSettings.setSaveFormData(false);  
  23.         webSettings.setJavaScriptEnabled(true);  
  24.         webSettings.setSupportZoom(false);  
  25.         mWebView.setWebChromeClient(new MyWebChromeClient());  
  26.         /* 
  27.          * DemoJavaScriptInterface类为js调用android服务器端提供接口 
  28.          * android 作为DemoJavaScriptInterface类的客户端接口被js调用 
  29.          * 调用的具体方法在DemoJavaScriptInterface中定义: 
  30.          * 例如该实例中的clickOnAndroid 
  31.          */  
  32.         mWebView.addJavascriptInterface(new DemoJavaScriptInterface(),"androd");  
  33.         mWebView.loadUrl("file:///android_asset/page.html");  
  34.     }  
  35.   
  36.     final class DemoJavaScriptInterface {  
  37.         DemoJavaScriptInterface() {}  
  38.   
  39.         /** 
  40.          * 该方法被浏览器端调用 
  41.          */  
  42.         public void clickOnAndroid() {  
  43.             mHandler.post(new Runnable() {  
  44.                 public void run() {  
  45.                     //调用js中的onJsAndroid方法  
  46.                     mWebView.loadUrl("javascript:onJsAndroid()");  
  47.                 }  
  48.             });  
  49.         }  
  50.     }  
  51.   
  52.     /** 
  53.      * 继承WebChromeClient类 
  54.      * 对js弹出框时间进行处理 
  55.      *  
  56.      */  
  57.     final class MyWebChromeClient extends WebChromeClient {  
  58.   
  59.         /** 
  60.          * 处理alert弹出框 
  61.          */  
  62.         @Override  
  63.         public boolean onJsAlert(WebView view,String url,  
  64.                                  String message,JsResult result) {  
  65.             Log.d(LOG_TAG,"onJsAlert:"+message");  
  66.             mReusultText.setText("Alert:"+message);  
  67.             //对alert的简单封装  
  68.             new AlertDialog.Builder(WebViewDemo.this).  
  69.                 setTitle("Alert").setMessage(message).setPositiveButton("OK",  
  70.                 new DialogInterface.OnClickListener() {  
  71.                     @Override  
  72.                     public void onClick(DialogInterface arg0, int arg1) {  
  73.                        //TODO  
  74.                    }  
  75.             }).create().show();  
  76.             result.confirm();  
  77.             return true;  
  78.         }  
  79.   
  80.         /** 
  81.          * 处理confirm弹出框 
  82.          */  
  83.         @Override  
  84.         public boolean onJsConfirm(WebView view, String url, String message,  
  85.                 JsResult result) {  
  86.             Log.d(LOG_TAG, "onJsConfirm:"+message);  
  87.             mReusultText.setText("Confirm:"+message);  
  88.             result.confirm();  
  89.             return super.onJsConfirm(view, url, message, result);  
  90.         }  
  91.   
  92.         /** 
  93.          * 处理prompt弹出框 
  94.          */  
  95.         @Override  
  96.         public boolean onJsPrompt(WebView view, String url, String message,  
  97.                 String defaultValue, JsPromptResult result) {  
  98.             Log.d(LOG_TAG,"onJsPrompt:"+message);  
  99.             mReusultText.setText("Prompt input is :"+message);  
  100.             result.confirm();  
  101.             return super.onJsPrompt(view, url, message, message, result);  
  102.         }  
  103.     }  
  104. }  

推荐学习:http://www.cnblogs.com/aimeng/archive/2012/05/24/2516547.html


0 0