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="Say hello"
onClick="showAndroidToast('Hello Android!')" />
</body>
</html>
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://img04.taobaocdn.com/imgextra/i4/608825099/T2nGXBXXpaXXXXXXXX_!!608825099.jpg_310x310.jpg"/>
</body>
</html></span>
第三步:修改 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>