首页 > 代码库 > (二) 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 深入 (上)