Android WebView小结
基础篇
在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的简单例子。在看下面这些总结知识之前,大家请看示例代码中MainActivtiy的代码,运行整个程序后,第一个页面显示的就是MainActivity的运行效果。上面的Button按钮是点击到第二个Activity进行测试用的。
在开发过程中应该注意几点:
1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。
2.如果访问的页面中有Javascript,则webview必须设置支持Javascript。webview.getSettings().setJavaScriptEnabled(true);
3. 在要Activity中生成一个WebView组件:WebView webView = new WebView(this);
4. 设置WebView基本信息:
如果访问的页面中有Javascript,则webview必须设置支持Javascript。
webview.getSettings().setJavaScriptEnabled(true);
触摸焦点起作用 requestFocus();
取消滚动条 this.setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY)
5. 设置WevView要显示的网页:
互联网用:webView.loadUrl("http://www.google.com");
本地文件用:webView.loadUrl(file:///android_asset/xx.html);固定格式
本地文件存放在:assets文件中
6. 如果希望点击链接由自己处理,而不是新开Android的系统browser中响应该链接。
给WebView添加一个事件监听对象(WebViewClient)
并重写其中的一些方法
shouldOverrideUrlLoading:对网页中超链接按钮的响应。当按下某个连接时WebViewClient会调用这个方法,并传递参数:按下的url
onLoadResource:加载资源时响应
onPageStart:在加载页面时响应
onPageFinish:在加载页面结束时响应
onReceiveError:在加载出错时响应
onReceivedHttpAuthRequest:
7.如果页面中链接,如果希望点击链接继续在当前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. });
8.如果不做任何处理,浏览网页,点击系统“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. }
9. @Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, android.net.http.SslError error) { // 重写此方法可以让webview处理https请求
handler.proceed();
}
});
提高篇(一)
下一步让我们来了解一下android中webview是如何支持javascripte自定义对象的,在w3c标准中js有 window,history,document等标准对象,同样我们可以在开发浏览器时自己定义我们的对象调用手机系统功能来处理,这样使用js就可以为所欲为了。
看一个实例:
public class WebViewDemo extends Activity {
private WebView mWebView;
private Handler mHandler = new Handler();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.webviewdemo);
mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new Object() {
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
mWebView.loadUrl("javascript:wave()");
}
});
}
}, "demo");
mWebView.loadUrl("file:///android_asset/demo.html");
}
}
我们看addJavascriptInterface(Object obj,String interfaceName)这个方法,该方法将一个java对象绑定到一个javascript对象中,javascript对象名就是 interfaceName(demo),作用域是Global。这样初始化webview后,在webview加载的页面中就可以直接通过 javascript:window.demo访问到绑定的java对象了。来看看在html中是怎样调用的。
<html>
<mce:script language="javascript"><!--
function wave() {
document.getElementById("droid").src="android_waving.png";
}
// --></mce:script>
<body>
<a onClick="window.demo.clickOnAndroid()">
<img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br>
Click me!
</a>
</body>
</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的目的。
提高篇(二)
Android中使用WebView, WebChromeClient和WebViewClient加载网页
在android应用中,有时要加载一个网页,如果能配上一个进度条就更好了,而android中提供了其很好的支持,运行示例程序后点击Button,跳转到WebPageLoader中,就可以看到进度条的效果了。
要注意的是,其中的webView的一系列用法,比如 webView.getSettings().setJavaScriptEnabled(true);设置可以使用javscript;
webView.getSettings().setJavaScriptEnabled(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
webView.setHorizontalScrollBarEnabled(false);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.setInitialScale(70);
webView.setHorizontalScrollbarOverlay(true);
等等,具体参考API
而进度条的使用是在new出一个setWebChromeClient后,可以在内部类中写
onProgressChanged事件
在WebView的设计中,不是什么事都要WebView类干的,有些杂事是分给其他人的,这样WebView专心干好自己的解析、渲染工作就行了。WebViewClient就是帮助WebView处理各种通知、请求事件的,具体来说包括:
onLoadResource
onPageStart
onPageFinish
onReceiveError
onReceivedHttpAuthRequest
WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等
onCloseWindow(关闭WebView)
onCreateWindow()
onJsAlert (WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出)
onJsPrompt
onJsConfirm
onProgressChanged
onReceivedIcon
onReceivedTitle
[img]
[/img]
[img]
[/img]
[img]
[/img]
MainActivity.java
package com.parabola.main;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.KeyEvent;import android.view.View;import android.view.View.OnClickListener;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.Button;public class MainActivity extends Activity {/** Called when the activity is first created. */private WebView webview;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) this.findViewById(R.id.button1);webview = (WebView) findViewById(R.id.webview);// 设置WebView属性,能够执行JavaScript脚本webview.getSettings().setJavaScriptEnabled(true);// 加载URL内容webview.loadUrl("http://www.baidu.com");// 设置web视图客户端webview.setWebViewClient(new MyWebViewClient());button.setOnClickListener(new OnClickListener() {public void onClick(View v) {Intent intent = new Intent(MainActivity.this, WebPageLoader.class);startActivity(intent);}});}// 设置回退public boolean onKeyDown(int keyCode, KeyEvent event) {if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {webview.goBack();return true;}return super.onKeyDown(keyCode, event);}// web视图客户端public class MyWebViewClient extends WebViewClient {public boolean shouldOverviewUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}}}
package com.parabola.main;import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.webkit.WebChromeClient;import android.webkit.WebView;import android.webkit.WebViewClient;public class WebPageLoader extends Activity {final Activity activity = this;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.getWindow().requestFeature(Window.FEATURE_PROGRESS);setContentView(R.layout.webview);WebView webView = (WebView) findViewById(R.id.webView);webView.getSettings().setJavaScriptEnabled(true);webView.getSettings().setSupportZoom(true);webView.setWebChromeClient(new WebChromeClient() {public void onProgressChanged(WebView view, int progress) {activity.setTitle("Loading...");activity.setProgress(progress * 100);if (progress == 100)activity.setTitle(R.string.app_name);}});webView.setWebViewClient(new WebViewClient() {public void onReceivedError(WebView view, int errorCode,String description, String failingUrl) { // Handle the error}public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});webView.loadUrl("http://www.sohu.com");}}