现在开发的app中有很多是用网页加载的,所以android中的webview控件也就诞生了。简单的整理了一下关于webview我们常用的一些方法和javascript之间的交互。 Android系统中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装了一个叫做 WebView 组件。
在开发过程中应该注意几点:
1.这是最基本的 AndroidManifest.xml 中必须添加访问网络权限。
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
2.如果访问的页面中有 Javascript,则 WebView 必须设置支持 Javascript.
WebView.getSettings().setJavaScriptEnabled(true);
3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 WebView的WebViewClient对象。这里的WebViewClient就是帮助WebView处理各种通知、请求
mWebView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url){
view.loadUrl(url);
return true;
}
});
4.如果不做任何处理 ,浏览网页,点击系统“Back”键,整个 Browser 会调用 finish()而结束自身,如果希望浏览的网页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该 Back 事件
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
5.如果我们要在网页上处理
处理Javascript的对话框,网站图标,网站title,加载进度等 :
onCloseWindow(关闭WebView)
onCreateWindow()
onJsAlert (WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出)
onJsPrompt
onJsConfirm
onProgressChanged
onReceivedIcon
onReceivedTitle
与js互调的原理
既然可以显示网页,那么当然也可以让网页操作本地方法。
public class WebViewDemo extends Activity {
private WebView mWebView;
private Handler mHandler = new Handler();
public void onCreate(Bundle icicle) {
setContentView(R.layout.WebViewdemo);
mWebView = (WebView) findViewById(R.id.WebView);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new Object() {
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
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>
<script language="javascript">
function wave() {
document.getElementById("droid").src="android_waving.png";
}
</script>
<body>
<a onClick="window.demo.clickOnAndroid()">
<img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br> Click me! </a>
</body>
</html>
这样在 javascript 中就可以调用 java 对象的 clickOnAndroid()方法了,同样我们可以在此对象中定义很多方法(比如发短信,调用联系人列表等手机系统功能),这里 wave()方法是 java 中调用 javascript 的例子.
需要说明一点:addJavascriptInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用 Handler 的目的。
WebView 缓存
在项目中如果使用到 WebView 控件,当加载 html 页面时,会在/data/data/包名目录下生成 database 与 cache 两个文件夹。请求的 url 记录是保存在 WebViewCache.db,而 url 的内容是保存在 WebViewCache 文件夹下. 大家可以自己动手试一下,定义一个html文件,在里面显示一张图片,用WebView加载出来,然后再试着从缓存里把这张图片读取出来并显示 。
WebView 删除缓存
//删除保存于手机上的缓存
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");
WebView 处理 404 错误
显示网页还会遇到一个问题,就是网页有可能会找不到,WebView当然也是可以处理的,这也是我们经常遇到的问题,为了解决用户的良好体验,我们需加一个方法。
public class WebView_404 extends Activity {
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what==404) {//主页不存在
//载入本地 assets 文件夹下面的错误提示页面 404.html
web.loadUrl("file:///android_asset/404.html");
}else{
web.loadUrl(HOMEPAGE);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
web.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrl(WebView view,String url) {
if(url.startsWith("http://") && getRespStatus(url)==404) {
view.stopLoading();
//载入本地 assets 文件夹下面的错误提示页面 404.html
view.loadUrl("file:///android_asset/404.html");
}else{
view.loadUrl(url);
}
return true;
}
});
new Thread(new Runnable() {
public void run() {
Message msg = new Message();
//此处判断主页是否存在,因为主页是通过 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 问题
CookieManager cm = CookieManager.getInstance();
cm.removeAllCookie();
cm.getCookie(url);
cm.setCookie(url, cookie);
另外还有个 CookieSyncManager,也许你会在一些旧的项目中看到它。从名字来理解,它实际上应该是一个异步缓存器。不过我们看到这个方法已经被标记为过时了,查看源码可以看到过时原因是现在WebView已经是自动的异步缓存了,所以这个类已经没有存在的意义了。 CookieSyncManager。
WebView清除本地cookies
首先,要清除肯定要会添加,这里给大家提供一个工具方法:
/***
* 如果用户已经登录,则同步本地的cookie到webview中
*/
public void synCookies() {
if (!CacheUtils.isLogin(this)) return;
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();//移除
String cookies = 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();
本文来自http://www.36nu.com/post/154.html,非常感谢
muyuren,在他的基础上我增加了自己的一些方法,望大家能更加的了解关于webview这个组件,过后会很流行这方面的网页加载。