muyuren 2016-04-13javascript
Android系统中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装为一个叫作 WebView 组件。html
在开发过程当中应该注意几点:java
1.这是最基本的 AndroidManifest.xml 中必须添加访问网络权限。 android
2.若是访问的页面中有 Javascript,则 WebView 必须设置支持 Javascript。web
WebView.getSettings().setJavaScriptEnabled(true);
3.若是页面中连接,若是但愿点击连接继续在当前browser中响应,而不是新开Android的系统browser中响应该连接,必须覆盖 WebView的WebViewClient对象。浏览器
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); }
与js互调服务器
既然能够显示网页,那么固然也可让网页操做本地方法。(因为一行写不下,缩进我调整了一下)cookie
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 的目的.
让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(new JavaScriptinterface(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 删除缓存
其实已经知道缓存保存的位置了,那么删除就很简单了,获取到这个缓存,而后删掉他就行了。
//删除保存于手机上的缓存 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() -(webvi ew.getHeight()+WebView.getScrollY())){ //XXX }
WebView获取服务器中的 session 问题
接下来咱们讲以下两个问题:
Android 中的 WebView 如何获取服务器页面的 jsessionid 的值
Android 的 WebView 又是如何把获得的 jsessionid 的值在 set 到服务器中,一致达到他们在同一个 jsessionid 的回话中.
其实很是很是简单,只不过是几个方法罢了:
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();