Android系统中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装为一个叫做 WebView 组件。

在开发过程中应该注意几点:

1.这是最基本的 AndroidManifest.xml 中必须添加访问网络权限。

2.如果访问的页面中有 Javascript,则 WebView 必须设置支持 Javascript。

WebView.getSettings().setJavaScriptEnabled(true);

3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 WebView的WebViewClient对象。

mWebView.setWebViewClient(newWebViewClient(){
publicbooleanshouldOverrideUrlLoading(WebViewview,Stringurl){
view.loadUrl(url);
returntrue;
}
});

4.如果不做任何处理 ,浏览网页,点击系统“Back”键,整个 Browser 会调用 finish()而结束自身,如果希望浏览的网页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该 Back 事件

publicbooleanonKeyDown(intkeyCode,KeyEventevent){
if((keyCode==KEYCODE_BACK)&&mWebView.canGoBack()){
mWebView.goBack();
returntrue;
}
returnsuper.onKeyDown(keyCode,event);
}


与js互调

既然可以显示网页,那么当然也可以让网页操作本地方法。(由于一行写不下,缩进我调整了一下)

publicclassWebViewDemoextendsActivity{
privateWebViewmWebView;
privateHandlermHandler=newHandler();

publicvoidonCreate(Bundleicicle){

setContentView(R.layout.WebViewdemo);
mWebView=(WebView)findViewById(R.id.WebView);
WebSettingswebSettings=mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(newObject(){
publicvoidclickOnAndroid(){
mHandler.post(newRunnable(){
publicvoidrun(){
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>
<scriptlanguage="javascript">
functionwave(){
document.getElementById("droid").src="android_waving.png";
}
</script>
<body>
<aonClick="window.demo.clickOnAndroid()">
<imgid="droid"src="android_normal.png"mce_src="android_normal.png"/><br>Clickme!</a>
</body>
</html>

这样在 javascript 中就可以调用 java 对象的 clickOnAndroid()方法了,同样我们可以在此对象中定义很多方法(比如发短信,调用联系人列表等手机系统功能),这里 wave()方法是 java 中调用 javascript 的例子.

需要说明一点:addJavascriptInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用 Handler 的目的.


让js调用Android代码

首先简述 WebView、WebViewClient、WebChromeClient 之间的区别:

在 WebView 的设计中,不是什么事都要 WebView类干的,有些杂事是分给其他人的,这样 WebView 专心干好 自己的解析、渲染工作就行了.WebViewClient 就是帮助 WebView 处理各种通知、请求事件等 ,WebChromeClient 是辅助 WebView 处理 Javascript 的对话框,网站图标,网站 title.


功能实现:

利用 android 中的 WebView 加载一个 html 网页,在 html 网页中定义一个按钮,点击按钮弹出一 个 toast.

实现步骤:

首先定义一个接口类,将上下文对象传进去,在接口类中定义要在 js 中实现的方法。

接着在assets资源包下定义一个 html 文件,在文件中定义一个 button.button 的点击事件定义为一个 js 函数.

之后在 xml 中定义一个 WebView 组件,在活动类中获取 WebView 并对 WebView 参数进行设置,此处特别注意要设置 WebView 支持 js 且将定义的 js 接口类添加到 WebView 中去,此后在 js 中就可以利用该接口类中定义的 函数了.即:

myWebView.getSettings().setJavaScriptEnabled(true);

myWebView.addJavascriptInterface(newJavaScriptinterface(this),”android”);

最后利用 WebView 加载本地 html 文件的方法是:

myWebView.loadData(htmlText,"text/html","utf-8");

此处的htmltext 是以字符串的方式读取 assets 报下 html中的内容.


实现利用返回键返回到上一页:

设置 WebView 的按键监听,监听到期返回键并判断网页是否能够返回 ,利用 WebView 的 goBack()返回到上一页.


WebView 缓存

在项目中如果使用到 WebView 控件,当加载 html 页面时,会在/data/data/包名目录下生成 database 与 cache 两个文件夹。

请求的 url 记录是保存在 WebViewCache.db,而 url 的内容是保存在 WebViewCache 文件夹下. 大家可以自己动手试一下,定义一个html文件,在里面显示一张图片,用WebView加载出来,然后再试着从缓存里把这张图片读取出来并显示 。


WebView 删除缓存

其实已经知道缓存保存的位置了,那么删除就很简单了,获取到这个缓存,然后删掉他就好了。

//删除保存于手机上的缓存
privateintclearCacheFolder(Filedir,longnumDays){
intdeletedFiles=0;
if(dir!=null&&dir.isDirectory()){
try{
for(Filechild:dir.listFiles()){
if(child.isDirectory()){
deletedFiles+=clearCacheFolder(child,numDays);
}
if(child.lastModified()<numDays){
if(child.delete()){
deletedFiles++;
}
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
returndeletedFiles;
}

是否启用缓存功能也是可以控制的

//优先使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//不使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

在退出应用的时候加上如下代码,可以完整的清空缓存

Filefile=CacheManager.getCacheFileBaseDir();
if(file!=null&&file.exists()&&file.isDirectory()){
for(Fileitem:file.listFiles()){
item.delete();
}
file.delete();
}
context.deleteDatabase("WebView.db");
context.deleteDatabase("WebViewCache.db");


WebView 处理 404 错误

显示网页还会遇到一个问题,就是网页有可能会找不到,WebView当然也是可以处理的

publicclassWebView_404extendsActivity{
privateHandlerhandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
if(msg.what==404){//主页不存在
//载入本地assets文件夹下面的错误提示页面404.html
web.loadUrl("file:///android_asset/404.html");
}else{
web.loadUrl(HOMEPAGE);
}
}
};
@Override
protectedvoidonCreate(BundlesavedInstanceState){
web.setWebViewClient(newWebViewClient(){
publicbooleanshouldOverrideUrl(WebViewview,Stringurl){
if(url.startsWith("http://")&&getRespStatus(url)==404){
view.stopLoading();
//载入本地assets文件夹下面的错误提示页面404.html
view.loadUrl("file:///android_asset/404.html");
}else{
view.loadUrl(url);
}
returntrue;
}
});
newThread(newRunnable(){
publicvoidrun(){
Messagemsg=newMessage();
//此处判断主页是否存在,因为主页是通过loadUrl加载的,
//此时不会执行shouldOverrideUrlLoading进行页面是否存在的判断//进入主页后,点主页里面的链接,链接到其他页面就一定会执行
shouldOverrideUrlLoading方法了
if(getRespStatus(HOMEPAGE)==404){
msg.what=404;
}
handler.sendMessage(msg);
}).start();
}
}


判断 WebView 是否已经滚动到页面底端

在View中有一个getScrollY()方法,可以返回当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离。

还有getHeight()或者 getBottom()方法都返回当前 View 这个容器的高度

在ViewView中还有getContentHeight() 方法可以返回整个 html 页面的高度,但并不等同于当前整个页面的高度 ,因为 WebView 有缩放功能。你可以通过如下代码来启动或关闭webview的缩放功能。

mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);

所以当前整个页面的高度实际上应该是原始 html 的高度再乘上缩放比例. 因此,更正后的结果 ,准确的判断方法应该是:

//如果已经处于底端
if(WebView.getContentHeight*WebView.getScale()-(webview.getHeight()+WebView.getScrollY())){
//XXX
}


WebView获取服务器中的 session 问题

接下来我们讲如下两个问题:

Android 中的 WebView 如何获取服务器页面的 jsessionid 的值

Android 的 WebView 又是如何把得到的 jsessionid 的值在 set 到服务器中,一致达到他们在同一个 jsessionid 的回话中.

其实非常非常简单,只不过是几个方法罢了:

CookieManagercm=CookieManager.getInstance();
cm.removeAllCookie();
cm.getCookie(url);
cm.setCookie(url,cookie);

另外还有个 CookieSyncManager,也许你会在一些旧的项目中看到它。从名字来理解,它实际上应该是一个异步缓存器。不过我们看到这个方法已经被标记为过时了,查看源码可以看到过时原因是现在WebView已经是自动的异步缓存了,所以这个类已经没有存在的意义了。 CookieSyncManager


WebView清除本地cookies

首先,要清除肯定要会添加,这里给大家提供一个工具方法:

/***
*如果用户已经登录,则同步本地的cookie到webview中
*/
publicvoidsynCookies(){
if(!CacheUtils.isLogin(this))return;
CookieSyncManager.createInstance(this);
CookieManagercookieManager=CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();//移除
Stringcookies=PreferenceHelper.readString(this,AppConfig.COOKIE_KEY,AppConfig.COOKIE_KEY);
KJLoger.debug(cookies);
cookieManager.setCookie(url,cookies);
CookieSyncManager.getInstance().sync();
}

在使用网页版淘宝或百度登录时,WebView会自动登录上次的帐号!(因为WebView 记录了帐号和密码的cookies) 所以,需要清除 SessionCookie也是有必要的。

那么CookieManager同样也为我们提供了清除cookie的方法

CookieManager.getInstance().removeSessionCookie();

这里顺便说一下WebView本身也是会记录html缓存的,webview本身就提供了清理缓存的方法,其中参数true是指是否包括磁盘文件也一并清除:

webview.clearCache(true);
webview.clearHistory();

更多相关文章

  1. Android 修改spinner 字体颜色 样式的方法
  2. Android 软键盘弹出时把原来布局顶上去的解决方法
  3. Android多窗口分屏(原生方法)
  4. getCacheDir()和getFilesDir()方法区别
  5. Object 开发中常用的重写方法总结toString,equals,hashCode,compare
  6. java 构造器内部的多态方法和行为
  7. Javassist生成class(生成类,方法,字段,注解)
  8. Eclipse创建的包变成文件夹的解决方法
  9. java中InputStream中的抽象方法read()为什么可以直接调用?

随机推荐

  1. android基础入门(二)――创建android工程
  2. 2010-11-4
  3. Android读写XML(上)——package说明
  4. 如何退出Android应用程序
  5. android系统更新应用的添加
  6. 17 位谷歌 Android(安卓)开发专家是如何
  7. Android(安卓)View事件分发、拦截、消费
  8. Android中的消息机制:Handler消息传递机制
  9. Android(安卓)Studio系列教程六--Gradle
  10. android Animation 动画效果介绍 续 .