Android WebView详解

在Android中可以通过WebView控件来进行Web浏览。本文将对WebView相关的知识进行一个介绍。

一、WebView介绍

WebView支持标准的浏览器特性,比如浏览历史、缩放、JavaScript。

1、可以通过WebSettings来定制WebView,通过 webview.getSettings()获取WebSettings的实例。主要有以下方法:

(1)webview.getSettings().setJavaScriptEnabled(true);传入true启用JavaScript的支持。默认是关闭的,不启用可能导致网页无法正常显示。

(2)webView.getSettings().supportMultipleWindows();传入true启用多窗口支持。

(3)webView.getSettings().setBuiltInZoomControls(true);传入true可以进行缩放。

(4)webView.getSettings().setTextZoom();设置web内容的缩放百分比。


2、WebView类的一些方法

reload()刷新或重载当前页面

goBack()在浏览历史记录中回退一步

canGoBack()检查是否有历史记录可供回退

goForward()在浏览历史记录中前进一步

canGoForward():检查是否有历史记录可供前进

clearCache():清除浏览器缓存

clearHistory():清除浏览器历史

requestFocus(): 如果不设置的话会出现不能弹出软件盘的问题

loadUrl(String url):加载路径为URL的网址

postUrl(String url, byte[] postData): 加载页面使用Post方式,postData为参数

stopLoading(): 停止加载

requestFocus(): 如果不设置的话会出现不能弹出软件盘的问题

setScrollBarStyle():设置滚动条风格,如webview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);在内容内部显示滚动条


3、WebViewClient类

webViewClient主要帮助webView处理各种通知请求事件。

如果你的网页中有网页链接,在默认情况下,android会调用默认的浏览器打开它。如果想要用自己的webView打开,则需要用到WebViewClient类。具体用法如下:

		wv.setWebViewClient(new WebViewClient() {
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				// TODO Auto-generated method stub
				if(url.contains("tel")){
					new Handler().call(url.substring(4));
					return true;
				}
		
				view.loadUrl(url);
				return false;
			}

			@Override
			public void onPageStarted(WebView view, String url, Bitmap favicon) {
				// TODO Auto-generated method stub
				super.onPageStarted(view, url, favicon);
//				if (url.contains("http")) {
//					Toast.makeText(getActivity(), "enter baidu",
//							Toast.LENGTH_LONG).show();
//				} else {
//					Toast.makeText(getActivity(), "enter your page",
//							Toast.LENGTH_LONG).show();
//				}
			}

			@Override
			public void onPageFinished(WebView view, String url) {
				// TODO Auto-generated method stub
				super.onPageFinished(view, url);
//				if (url.contains("http")) {
//					Toast.makeText(getActivity(), "baidu finish loading",
//							Toast.LENGTH_LONG).show();
//				} else {
//					Toast.makeText(getActivity(), "your page finish loading",
//							Toast.LENGTH_LONG).show();
//				}
			}

		});


shouldOverrideUrlLoading()方法的API如下:

Give the host application a chance to take over the control when a new url is about to be loaded in the current WebView. If WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the url. If WebViewClient is provided, return true means the host application handles the url, while return false means the current WebView handles the url.

翻译过来就是:在WebView中加载一个新的URL的时候给宿主程序一个机会去控制这个URL的加载。如果没有设置WebViewClient,默认情况下将通过Activity Manager去选择一个优先级高的handler,如果设置了WebViewClient,如果返回true,宿主程序处理这个URL的加载,如果返回false,当前的webView处理URL的加载。(外语水平有限,如有错误欢迎指正)。

所以,可以根据URL来判断是想要系统默认程序处理这个URL,还是想要WebView来处理。

onPageStarted()、onPageFinished() :页面开始加载/结束加载时调用;

onReceiveError():产生错误时触发


4、WebChromeClient类

主要辅助WebView处理Javascript的对话框、进度条等。由于WebView上alert,Prompt,Confirm上是无效,所以需要定制WebChromeClient处理弹出,从而获取网页中的JS,比如使用AlertDialog进行显示。

wv.setWebChromeClient(new WebChromeClient(){
				@Override
				public boolean onJsAlert(WebView view, String url,
						String message, JsResult result) {
					// TODO Auto-generated method stub
					new AlertDialog.Builder(getActivity()).setMessage(message).setNegativeButton("YES", null).show();
					return true;					
				}
			});

5、JavaScript和Android相互调用

5.1 android调用JavaScript

wv.loadUrl("javascript:showMsg('aaaa')");

代码很简单,但是一定要记得设置如下代码,否则操作无反应:

wv.getSettings().setJavaScriptEnabled(true);

5.2 JavaScript调用android

wv.addJavascriptInterface(new Object(){
			@JavascriptInterface
			public void call(String num){
				Intent intent=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+num));
				startActivity(intent);
			}
			@JavascriptInterface
			public void show(){
				Toast.makeText(getActivity(), "enter show!", Toast.LENGTH_LONG).show();
			}
		}, "handler");

html代码:

<a href="javascript:window.handler.call('456')">call 456</a>

这里特别要注意的是:在每个方法上面一定要加上:@JavascriptInterface,否则会报错误:Uncaught TypeError。


4、使用WebViewFragment类

WebViewFragment是一个包含了WebView的fragment,可以用getWebView()方法获取WebView,其他方法与上文一致。父类是 

android.app.Fragment,所以兼容性不是很好,min version is 11。当然,可以自定义一个WebViewFragment,继承android.support.v4.app.Fragment就可解决兼容性问题。


二、WebView缓存问题

当加载html页面时,会在/data/data/应用package目录下生成database与cache两个文件夹如下图如示:





请求的url记录是保存在webviewCache.db,而url的内容是保存在webviewCache文件夹下。


下面通过一个例子来说明如何生成及读取缓存:


当使用webView加载html页面时,会在/data/data/应用package目录下生成database与cache两个文件夹,请求的url记录是保存在webviewCache.db,而url的内容是保存在webviewCache文件夹下。

我们可以使用SQLiteDatabase读取数据库获取资源路径,然后根据资源路径读取缓存。当然,也可以删除这些缓存。注意:在刪除文件夹的时候要先删除文件夹下的文件,否则无法删除。




package com.dream.webviewcachedemo;

import java.io.File;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.res.Configuration;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import android.os.Build;

public class MainActivity extends ActionBarActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		if (savedInstanceState == null) {
			getSupportFragmentManager().beginTransaction()
					.add(R.id.container, new PlaceholderFragment()).commit();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class PlaceholderFragment extends Fragment implements OnClickListener{

		public PlaceholderFragment() {
		}

		View rootView ;
		Button showBtn;
		Button deleteBtn;
		WebView wv;
		String url="file:///android_asset/index.html";
		AlertDialog dialog;
		
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			rootView = inflater.inflate(R.layout.fragment_main, container,
					false);
			return rootView;
		}
		
		@SuppressLint("NewApi")
		@Override
		public void onActivityCreated(Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			super.onActivityCreated(savedInstanceState);
			
			showBtn=(Button)rootView.findViewById(R.id.btn_main_showImg);
			showBtn.setOnClickListener(this);
			deleteBtn=(Button)rootView.findViewById(R.id.btn_main_delete);
			deleteBtn.setOnClickListener(this);
			wv=(WebView)rootView.findViewById(R.id.wv_main_website);
			wv.getSettings().setJavaScriptEnabled(true);
			wv.getSettings().supportMultipleWindows();
			wv.getSettings().setSupportZoom(true);
			wv.setWebViewClient(new WebViewClient(){
				@Override
				public boolean shouldOverrideUrlLoading(WebView view, String url) {
					// TODO Auto-generated method stub
					view.loadUrl(url);
					return false;
				}
			});
			wv.loadUrl(url);
			
			initDialog();
			
		}

		private void initDialog() {
			AlertDialog.Builder builder=new AlertDialog.Builder(getActivity()).setTitle("Message").setNegativeButton("YES", null);
			dialog=builder.create();
		}

		@Override
		public void onClick(View v) {
			
			switch (v.getId()) {
			case R.id.btn_main_showImg:
				getCache();
				break;
			case R.id.btn_main_delete:
				deleteCache();
			default:
				break;
			}
		
			
		}

		private void deleteCache() {
			
			//delete the .db file
			try {
				getActivity().deleteDatabase("webviewCache.db");
				getActivity().deleteDatabase("webview.db");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			//delete cache file
			File file=new File(getActivity().getCacheDir()+"/webviewCache");
			try {
				deleteFile(file);
				dialog.setMessage("Delete Cache Success");
				dialog.show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
		}

		private void deleteFile(File file) {
			if(file.exists()){
				if(file.isFile()){
					file.delete();
					return;
				}
				if(file.isDirectory()){
					File[] childFiles=file.listFiles();
					if(childFiles==null || childFiles.length==0){
						file.delete();
						return;
					}
					
					for(File f : childFiles){
						deleteFile(f);
					}
					
					file.delete();
					
				}
				
			}
		}

		private void getCache() {
			try {
				SQLiteDatabase db=getActivity().openOrCreateDatabase("webviewCache.db",MODE_PRIVATE , null);
				
				Cursor c=db.query("cache", null, null, null, null, null, null);
				if(c!=null){
					//get the first row 
					c.moveToFirst();
					//get filepath 
					String filepath=c.getString(c.getColumnIndex("filepath"));
					Log.i("System.out", "filepath  is :"+filepath); 
					
					//find the image by filepath
					Bitmap bm=BitmapFactory.decodeFile(getActivity().getCacheDir()+"/webviewCache/"+filepath);
					if(bm==null){
						showNoCache();
						return;
					}
					ImageView iv=new ImageView(getActivity());
					iv.setImageBitmap(bm);
					new AlertDialog.Builder(getActivity()).setView(iv).setNegativeButton("YES", null).show();
					c.close();
				}				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				showNoCache();
				e.printStackTrace();
			}
		}

		private void showNoCache() {
			dialog.setMessage("No cache");
			dialog.show();
		}
	}

}



三、资料

WebView缓存 http://www.cnblogs.com/linjiqin/archive/2011/10/28/2227943.html

WebView缓存机制详解 http://blog.youkuaiyun.com/t12x3456/article/details/13745553





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值