方法 | 说明 |
---|---|
setAllowFileAccess | 启用或禁用WebView访问文件数据 |
setBlockNetworkImage | 是否显示网络图像 |
setBuiltInZoomControls | 设置是否支持缩放 |
setCacheMode | 设置缓冲的模式 |
setDefaultFontSize | 设置默认的字体大小 |
setDefaultTextEncodingName | 设置在解码时时候用的默认编码 |
setFixedFontFamily | 设置固定使用的字体 |
setJavaScriptEnabled | 设置是否支持JavaScript |
setLayoutAlgorithm | 设置布局方式 |
setLightTouchEnabled | 设置用鼠标激活被选项 |
setSupportZoom | 设置是否支持变焦 |
方法 | 说明 |
---|---|
doUpdateVisitedHistory | 更新历史记录 |
onFormResubmission | 应用程序重新请求网页数据 |
onLoadResource | 加载指定地址提供的资源 |
onPageFinished | 网页加载完毕 |
onPageStarted | 网页开始加载 |
onReceivedError | 报告错误信息 |
onScaleChanged | WebView发生改变 |
shouldOverrideUrlLoading | 控制新的连接在当前WebView中打开 |
方法 | 说明 |
---|---|
onCloseWindow | 关闭WebView |
onCreateWindow | 创建WebView |
onJsAlert | 处理Javascript中的Alert对话框 |
onJsConfirm | 处理Javascript中的Confirm对话框 |
onJsPrompt | 处理Javascript中的Prompt对话框 |
onProgressChanged | 加载进度条改变 |
onReceivedlcon | 网页图标更改 |
onReceivedTitle | 网页Title更改 |
onRequestFocus WebView | 显示焦点 |
shouldOverrideUrlLoading()
)。setJavaScriptEnabled(boolean arg)
方式启用JavaScript。addJavascriptInterface(Object,String)
方法注射到WebView。 这方法允许您将Java对象注入到一个页面的JavaScript上下文,这样他们可以通过JavaScript访问的页面。可以有自己的缓存和cookie存储;
该方法可以让web页面调用Android,所以这是危险的。也就是传说中的webview的注入bug。
当用户单击在WebView上的链接时,默认行为是启动一个处理URL的Android应用。通常默认网页浏览器打开和装在目的URL。但是你可以为WebView覆盖这个行为,以便在你的WebView上打开链接。然后,您可以允许用户前后浏览通过的由您的WebView保留的网页历史记录。
要打开用户点击链接,只是提供一个WebViewClient为您的WebView,使用setWebViewClient()。
mWebView.setWebViewClient(new WebViewClient());
可以越过同源策略,获得任意网页的Cookie等信息,Android4.4以下都有此问题。
通过反射机制,js可以直接获取Runtime,从而执行命令。Android4.2以上,可以通过声明 @JavascriptInterface
保证安全性,4.2以下不能调用addJavascriptInterface()
方法,需要另谋他法。
除了 web 页面自身的 URL 请求,还会有 web 页面外部引用的JS、CSS、字体、图片等等都是个独立的 http 请求。这些请求都是串行的,这些请求加上浏览器的解析、渲染时间就会导致 WebView 整体加载时间变长,消耗的流量也对应的真多。
缓存机制 | 优势 | 适用场景 |
---|---|---|
浏览器缓存机制 | HTTP协议层支持 | 静态文件的缓存 |
Dom Storage | 较大存储空间 | 临时、简单数据的缓存,Cookies的扩展 |
Web SQL Database | 存储、管理复杂结构数据 | 用IndexedDB替代,不推荐使用 |
APPCache | 方便构建离线APP | 离线APP、静态文件缓存,不推荐使用 |
IndexedDB | 存储任何类型数据、简单、支持索引 | 结构关系复杂的数据存储 Web SQL DataBase的替代 |
File System API | 支持文件系统的操作 | 数据适合以文件进行管理的场景,Android系统还不支持 |
* 浏览器缓存机制
主要前端负责,Android 端不需要进行特别的配置。
Cache-Control用户控制文件在本地缓存有效时长。Cache-Control:max-age=600
表示文件在本地缓存600秒,从发出请求算起,如果有请求该资源,浏览器不会发送HTTP请求,直接使用本地缓存文件。
Last=Modified是标识文件在服务器上的最新更改时间。下次请求时,如果文件缓存过期,浏览器通过 If-Modified-Since 字段带上这个时间,发送给服务器,由服务器比较时间戳来判断文件是否有修改。如果没有则返回 304 告诉浏览器使用缓存;如果有修改,则返回200,同时返回最新的文件。
Cache-Control和Last=Modified配合使用。
Cache-Control 还有一个同功能的字段:Expires。Expires 的值一个绝对的时间点,如:Expires: Thu, 10 Nov 2015 08:45:11 GMT,表示在这个时间点之前,缓存都是有效的。Expires 是 HTTP1.0 标准中的字段,Cache-Control 是 HTTP1.1 标准中新加的字段,功能一样,都是控制缓存的有效时间。当这两个字段同时出现时,Cache-Control 是高优化级的。
Etag也是和 Last-Modified 一样,对文件进行标识的字段。不同的是,Etag 的取值是一个对文件进行标识的特征字串。在向服务器查询文件是否有更新时,浏览器通过 If-None-Match 字段把特征字串发送给服务器,由服务器和文件最新特征字串进行匹配,来判断文件是否有更新。没有更新回包304,有更新回包200。Etag 和 Last-Modified 可根据需求使用一个或两个同时使用。两个同时使用时,只要满足基中一个条件,就认为文件没有更新。
Last-Modified是服务端文件最新修改的时间,If-Modified-Since是客户端缓存存储的文件最新修改的时间,客户端发起请求的时候,带上If-Modified-Since给服务端去验证,如果If-Modified-Since和Last-Modified相同,则表示版本相同,返回304,客户端缓存可以继续使用;不相同则返回200,刷新客户端缓存
Dom Storage(Web Storage)存储机制
配合前端使用,使用时需要打开 DomStorage 开关。
DOM 存储被设计为用来提供一个更大存储量、更安全、更便捷的存储方法,从而可以代替掉将一些不需要让服务器知道的信息存储到 cookies 里的这种传统方法。Dom Storage 机制类似 Cookies,但有一些优势。
Dom Storage 是通过存储字符串的 Key/Value 对来提供的,并提供 5MB (不同浏览器可能不同,分 HOST)的存储空间(Cookies 才 4KB)。另外 Dom Storage 存储的数据在本地,不像 Cookies,每次请求一次页面,Cookies 都会发送给服务器。
DOM Storage 分为 sessionStorage
和 localStorage
。localStorage 对象和 sessionStorage 对象使用方法基本相同,它们的区别在于作用的范围不同。sessionStorage 用来存储与页面相关的数据,它在页面关闭后无法使用。而 localStorage 则持久存在,在页面关闭后也可以使用。
比如:页面的操作需要跳到其他页面操作然后再跳回来,但又想保留之前用户输入的信息,就可以这样临时存储数据。
webSettings.setDomStorageEnabled(true);
在使用时,Android端只是设置一下,其他的需要Web开发去实现。
Web SQL Database 存储机制(不再推荐使用,官方停止维护)
为了兼容性,在 Android 内嵌 Webview 中,需要通过 Webview 设置接口启用 SQL Database,同时还要设置数据库文件的存储路径。
webSettings.setDatabaseEnabled(true);
final String dbPath = getApplicationContext().getDir("db",Context.MODE_PRIVATE).getPath();
webSettings.setDatabasePath(dbPath)
Application Cache 存储机制
Application Cache(简称 AppCache)似乎是为支持 Web App 离线使用而开发的缓存机制。它的缓存机制类似于浏览器的缓存(Cache-Control 和 Last-Modified)机制,都是以文件为单位进行缓存,且文件有一定更新机制。但 AppCache 是对浏览器缓存机制的补充,不是替代。
AppCache 的原理有两个关键点:manifest 属性和 manifest 文件。会在HTML头部定义一个manifest文件,里面声明了哪些需要缓存的文件。也有5MB的空间限制。
不过根据官方文档,AppCache 已经不推荐使用了,标准也不会再支持。现在主流的浏览器都是还支持 AppCache的,以后就不太确定了。同样给出 Android 端启用 AppCache 的代码。
webSettings.setAppCacheEnabled(true);
final String cachePath = getApplicationContext().getDir("cache",Context.MODE_PRIVATE).getPath();
webSettings.setAppCachePath(cachePath);
webSettings.setAppCacheMaxSize(5*1024*1024);
Indexed Database 存储机制
IndexedDB 也是一种数据库的存储机制,但不同于已经不再支持的 Web SQL Database。IndexedDB 不是传统的关系数据库,可归为 NoSQL 数据库。IndexedDB 又类似于 Dom Storage 的 key-value 的存储方式,但功能更强大,且存储空间更大。
Android 在4.4开始加入对 IndexedDB 的支持,只需打开允许 JS 执行的开关就好了。
webSettings.setJavaScriptEnabled(true);
File System API(Android 暂不支持)
File System API 是 H5 新加入的存储机制。它为 Web App 提供了一个虚拟的文件系统,就像 Native App 访问本地文件系统一样。由于安全性的考虑,这个虚拟文件系统有一定的限制。Web App 在虚拟的文件系统中,可以进行文件(夹)的创建、读、写、删除、遍历等操作。很可惜到目前,Android 系统的 WebView 还不支持 File System API。
上面介绍的都是二次启动,首次加载H5页面可以预加载资源文件,如(JS、CSS、图片等资源)
mWebView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, final String url) {
WebResourceResponse response = null;
// 检查该资源是否已经提前下载完成。我采用的策略是在应用启动时,用户在 wifi 的网络环境下 // 提前下载 H5 页面需要的资源。
boolean resDown = JSHelper.isURLDownValid(url);
if (resDown) {
jsStr = JsjjJSHelper.getResInputStream(url);
if (url.endsWith(".png")) {
response = getWebResourceResponse(url, "image/png", ".png");
} else if (url.endsWith(".gif")) {
response = getWebResourceResponse(url, "image/gif", ".gif");
} else if (url.endsWith(".jpg")) {
response = getWebResourceResponse(url, "image/jepg", ".jpg");
} else if (url.endsWith(".jepg")) {
response = getWebResourceResponse(url, "image/jepg", ".jepg");
} else if (url.endsWith(".js") && jsStr != null) {
response = getWebResourceResponse("text/javascript", "UTF-8", ".js");
} else if (url.endsWith(".css") && jsStr != null) {
response = getWebResourceResponse("text/css", "UTF-8", ".css");
} else if (url.endsWith(".html") && jsStr != null) {
response = getWebResourceResponse("text/html", "UTF-8", ".html");
}
}
// 若 response 返回为 null , WebView 会自行请求网络加载资源。
return response;
}
});
private WebResourceResponse getWebResourceResponse(String url, String mime, String style) {
WebResourceResponse response = null;
try {
response = new WebResourceResponse(mime, "UTF-8", new FileInputStream(new File(getJSPath() + TPMD5.md5String(url) + style)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return response;
}
public String getJsjjJSPath() {
String splashTargetPath = JarEnv.sApplicationContext.getFilesDir().getPath() + "/JS";
if (!TPFileSysUtil.isDirFileExist(splashTargetPath)) {
TPFileSysUtil.createDir(splashTargetPath);
}
return splashTargetPath + "/";
}
直接将常用JS脚本放在assert文件夹中,在WebView调用了onPageFinished()方法进行加载。注意:需要在JS文件中写入一个JS文件载入完毕的事件。
Android 的 OnPageFinished 事件会在 Javascript 脚本执行完成之后才会触发。如果在页面中使 用JQuery,会在处理完 DOM 对象,执行完 $(document).ready(function() {}); 事件自会后才会渲染并显示页面。而同样的页面在 iPhone 上却是载入相当的快,因为 iPhone 是显示完页面才会触发脚本的执行。所以我们这边的解决方案延迟 JS 脚本的载入,这个方面的问题是需要Web前端工程师帮忙优化的。
WebView 的兼容性是个大问题。Android4.4版本Google使用了Chromium
替代Webkit
作为WebView内核,第三方ROM对原生WebView作出修改。
可以使用第三方内核,比如腾讯浏览服务,SDK只有212KB。
Java WebView 与 JavaScript交互
loadUrl(“javascript:method('参数')”)
myWebView.addJavascriptInterface(new JsInteration(), "control”);
public class JsInteration {
@JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
@JavascriptInterface
public void onSumResult(int result) {
Log.i(LOGTAG, "onSumResult result=" + result);
}
}
调用时:window.control.toastMessage("message");
Android 原生的WebView存在内存泄漏,根治该问题的办法是:为WebView开启一个进程,通过AIDL与主进程通信,用完WebView直接销毁整个进程。缺点是:涉及到Android进程间通信。
android:process=":remote"
android:screenOrientation="unspecified" />
在关闭时:
@Override
protected void onDestroy() {
super.onDestroy();
System.exit(0);
}
还有一个办法:使用自定义的WebView,而且是在Java代码中直接new出来,传入 applicationContext 来防止activity引用被滥用。
抛弃使用高风险的WebView addJavascriptInterface方法,通过对js层调用函数及回调函数的包装,支持异步回调,方法参数支持js所有已知的类型,包括number、string、boolean、object、function。
原理:在页面加载30%时,把js文件load进来。