首页 > 代码库 > (二) Android Webview 深入 (上)

(二) Android Webview 深入 (上)

1 Android 利用 WebView 实现在 js 中调用 android 代码

     在 java 或 android 中,接口占有很大比重,做程序员当然要对接口了解了,哈哈! android 和 js 看似牛马不相及,但是由于 WebView 的连接在 js 中就能够调用 android 写的代码实现 android 的功能! android 和 js 就像 java 和c/c++靠 jni 连接似的,二者也是靠接口连接.不废话了,下面就以一个简单的案例讲述一下在 js 中调用 android 代码

实现 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 文件的方法是:myWebView.loadData(htmlText, "text/html", "utf-8");此处的htmltext 是以字符串的方式读取 assets 报下 html 中的内容.具体代码见源码!哈哈.
4. 实现利用返回键返回到上一页:
设置 WebView 的按键监听,监听到期返回键并判断网页是否能够返回,利用 WebView 的 goBack()返回到上一页.

废话不多说,上代码:

xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <WebView
        android:id="@+id/myWebView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="false"
        android:focusableInTouchMode="false" />

</LinearLayout>
       java代码:
package com.sihuaTech.webview;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {
	/** Called when the activity is first created. */
	private WebView myWebView;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		myWebView = (WebView) findViewById(R.id.myWebView);
		myWebView.getSettings().setJavaScriptEnabled(true);
		myWebView.addJavascriptInterface(new JavaScriptinterface(this),
				"android");
		String htmlText = getFromAssets("test.html");
		myWebView.loadData(htmlText, "text/html", "utf-8");
		myWebView.setWebViewClient(new myWebViewClient());

	}

	// 此按键监听的是返回键,能够返回到上一个网页(通过网页的hostlistery)
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
			myWebView.goBack();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	public String getFromAssets(String fileName) {
		try {
			InputStreamReader inputReader = new InputStreamReader(
					getResources().getAssets().open(fileName));

			BufferedReader bufReader = new BufferedReader(inputReader);

			String line = "";
			String Result = "";

			while ((line = bufReader.readLine()) != null)
				Result += line;
			if (bufReader != null)
				bufReader.close();
			if (inputReader != null)
				inputReader.close();
			return Result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	class myWebViewClient extends WebViewClient {

		@Override
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
			// TODO Auto-generated method stub
			view.loadUrl(url);
			return true;
		}

	}
}

package com.sihuaTech.webview;

import android.content.Context;
import android.widget.Toast;

public class JavaScriptinterface {

	private Context mContext;

	/** Instantiate the interface and set the context */
	public JavaScriptinterface(Context c) {
		mContext = c;
	}

	/** Show a toast from the web page */
	public void showToast(String toast) {
		Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
	}
}
html代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<script type="text/javascript">   
function showAndroidToast(toast) {       
	android.showToast(toast);   
	 }
</script>

</head>
<body>
<input type="button" value=http://www.mamicode.com/"Say hello">
2.Android WebView缓存

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


请求的 url 记录是保存在 WebViewCache.db,而 url 的内容是保存在 WebViewCache 文件夹下.为了便于理解,接下来模拟一个案例,定义一个 html 文件,在里面显示一张图片,用 WebView 加载出来,然后再试着从缓存里把这张图片读取出来并显示.
第一步:新建一个 Android 工程命名为 WebViewCache.目录结构如下:

    

第二步:在 assets 目录下新建一个 html 文件,命名为 index.html

<span style="font-size:14px;"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>WebViewCacheDemo</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<img
src=http://www.mamicode.com/"http://img04.taobaocdn.com/imgextra/i4/608825099/T2nGXBXXpaXXXXXXXX_!!608825099.jpg_310x310.jpg"/>>第三步:修改 main.xml 布局文件,一个 WebView 控件一个 Button(点击加载缓存图片用),代码如下:
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<WebView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/WebView"/>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="从缓存读取图片"
android:id="@+id/button"/></LinearLayout></span>
第四步:修改主核心程序 WebViewCacheDemo.java,这里我只加载了 index.html 文件,按钮事件暂时没写,代码如下:
<span style="font-size:14px;">public class WebViewActivity extends Activity {
private WebView WebView;
private static final String url="file:///android_asset/index.html";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView=(WebView)findViewById(R.id. WebView);
WebView.loadUrl(url);
}
}</span>
第五步:在 AndroidMainifest.xml 文件中加访问网络的权限:

<uses-permission android:name="android.permission.INTERNET" />
运行效果如下:


此时我们在 WebViewCache.db 里的 cache.table 里多了一条记录如下图所示:


在 cache/WebViewCache/目录下多了一个 10d8d5cd 文件,刚好和 cache.table 里的 filepath,我们可以断定这个
文件就是我们从网上拽下来的图片:
为了验证猜想,我给 Button 增加事件响应,就是弹出 Dialog,里面加载缓存的图片,完整代码如下:

<span style="font-size:14px;">public class WebViewActivity extends Activity {
private WebView WebView;
private static final String url="file:///android_asset/index.html";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView=(WebView)findViewById(R.id. WebView);
WebView.loadUrl(url);
//点击按钮时弹出对话框
Button button=(Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ImageView imageView=new ImageView(WebViewActivity.this);
imageView.setImageBitmap(getPictureFromCache());
Builder builder=new android.app.AlertDialog.Builder(WebViewActivity.this);
//设置对话框的图标
builder.setTitle("从缓存查看图片");
builder.setView(imageView);
//退出按钮
builder.setPositiveButton("退 出", new OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
//关闭 alert 对话框架
dialog.cancel();
}
});
builder.create().show();
}
});
}
/**
* 从缓存获取图片
*
* @return
*/
private Bitmap getPictureFromCache(){
Bitmap bitmap=null;
try {
//这里写死,在实际开发项目中要灵活使用
File file=new File(getCacheDir()+"/WebViewCache/10d8d5cd");
FileInputStream inStream=new FileInputStream(file);
bitmap=BitmapFactory.decodeStream(inStream);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}</span>
第六步:再次运行工程,点击 button 按钮,效果如下图所示:

3.Android WebView 删除缓存

<span style="font-size:14px;">删除保存于手机上的缓存:
// clear the cache before time numDays
private int clearCacheFolder(File dir, long numDays) {
int deletedFiles = 0;
if (dir!= null && dir.isDirectory()) {
try {
for (File child:dir.listFiles()) {
if (child.isDirectory()) {
deletedFiles += clearCacheFolder(child, numDays);
}
if (child.lastModified() < numDays) {
if (child.delete()) {
deletedFiles++;
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
return deletedFiles;
}
打开关闭使用缓存
//优先使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//不使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
在退出应用的时候加上如下代码
File file = CacheManager.getCacheFileBaseDir();
if (file != null && file.exists() && file.isDirectory()) {
for (File item : file.listFiles()) {
item.delete();
}
file.delete();
}
context.deleteDatabase("WebView.db");
context.deleteDatabase("WebViewCache.db");</span><span style="font-size:24px;">
</span>

(二) Android Webview 深入 (上)