一,webkit开发注意点。
1.AndroidManifest.xml 中必须使用许可"android.permission.INTERNET",否则会出 Web page not available 错误。
2.如果访问的页面中有 Javascript,则 WebView 必须设置支持 Javascript.
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 == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
二,webview的使用
public class MainActivity extends Activity {
private WebView mWebView;
private Handler mHandler = new Handler();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
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>
<mce:script language="javascript"><!--
function wave() {
document.getElementById("droid").src="android_waving.png";
}
// --></mce: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 的例子.
下面还有几个知识点:
1)为了让WebView从apk文件中加载assets,AndroidSDK提供了一个schema, 前缀为"file:///android_asset/".WebView遇到这样的schema,就去当前包中的assets目录中找内容 . 如上面的"file:///android_asset/demo.html"
2)addJavascriptInterface 方法中要绑定的 Java 对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用 Handler 的目的.
public class MainActivity extends Activity {
WebView WebView;
final String mimeType = "text/html";
final String encoding = "utf-8";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView = (WebView) findViewById(R.id.WebView);
WebView.getSettings().setJavaScriptEnabled(true);
//
//webHtml();
//
//webImage();
//
//localHtmlZh();
//
//localHtmlBlankSpace();
//
//localHtml();
//
localImage();
//
//localHtmlImage();
}
/**
* 直接网页显示
*/
private void webHtml() {
try {
WebView.loadUrl("http://www.baidu.com");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 直接网络图片显示
*/
private void webImage() {
try {
WebView.loadUrl("http://www.gstatic.com/codesite/ph/images/code_small.png");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 中文显示
*/
private void localHtmlZh() {
try {
String data = "测试含有 中文的 Html 数据";
// utf-8 编码处理(在 SDK1.5 模拟器和真实设备上都将出现乱码,SDK1.6 上能正常显示)
//WebView.loadData(data, mimeType, encoding);
// 对数据进行编码处理(SDK1.5 版本)
WebView.loadData(URLEncoder.encode(data, encoding), mimeType,encoding);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 中文显示(空格的处理)
*/
private void localHtmlBlankSpace() {
try {
String data = " 测试含有空格的 Html 数据 ";
// 不对空格做处理
WebView.loadData(URLEncoder.encode(data, encoding), mimeType,
encoding);
//WebView.loadData(data, mimeType, encoding);
// 对空格做处理(在 SDK1.5 版本中)
WebView.loadData(URLEncoder.encode(data, encoding).replaceAll("+", " "), mimeType, encoding);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 显示本地图片文件
*/
private void localImage() {
try {
// 本地文件处理(如果文件名中有空格需要用+来替代)
WebView.loadUrl("file:///android_asset/icon.png");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 显示本地网页文件
*/
private void localHtml() {
try {
// 本地文件处理(如果文件名中有空格需要用+来替代)
WebView.loadUrl("file:///android_asset/test.html");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 显示本地图片和文字混合的 Html 内容
*/
private void localHtmlImage() {
try {
String data = "测试本地图片和文字混合显示,这是 APK 里的图片";
// SDK1.5 本地文件处理(不能显示图片)
// WebView.loadData(URLEncoder.encode(data, encoding), mimeType,
// encoding);
// SDK1.6 及以后版本
// WebView.loadData(data, mimeType, encoding);
// 本地文件处理(能显示图片)
WebView.loadDataWithBaseURL("about:blank", data, mimeType,encoding, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
三,Android WebView 深入
3.1 Android 利用 WebView 实现在 js 中调用 android 代码
1. 首先简述 WebView、WebViewClient、WebChromeClient 之间的区别:
在 WebView 的设计中,不是什么事都要 WebView 类干的,有些杂事是分给其他人的,这样 WebView 专心干好自己的解析、渲染工作就行了.
WebViewClient 就是帮助 WebView 处理各种通知、请求事件等,
WebChromeClient是辅助 WebView 处理 Javascript 的对话框,网站图标,网站 title.
WebSettings常用方法:
setAllowFileAccess 启用或禁止WebView访问文件数据
setBlockNetworkImage 是否显示网络图像
setBuiltInZoomControls 设置是否支持缩放
setCacheMode 设置缓冲的模式
setDefaultFontSize 设置默认的字体大小
setDefaultTextEncodingName 设置在解码时使用的默认编码
setFixedFontFamily 设置固定使用的字体
setJavaSciptEnabled 设置是否支持Javascript
setLayoutAlgorithm 设置布局方式
setLightTouchEnabled 设置用鼠标激活被选项
setSupportZoom 设置是否支持变焦
WebViewClient常用方法:
doUpdate VisitedHistory 更新历史记录
onFormResubmission 应用程序重新请求网页数据
onLoadResource 加载指定地址提供的资源
onPageFinished 网页加载完毕
onPageStarted 网页开始加载
onReceivedError 报告错误信息
onScaleChanged WebView发生改变
shouldOverrideUrlLoading 控制新的连接在当前WebView中打开
WebChromeClient常用方法:
onCloseWindow 关闭WebView
onCreateWindow 创建WebView
onJsAlert 处理Javascript中的Alert对话框
onJsConfirm处理Javascript中的Confirm对话框
onJsPrompt处理Javascript中的Prompt对话框
onProgressChanged 加载进度条改变
onReceivedlcon 网页图标更改
onReceivedTitle 网页Title更改
onRequestFocus WebView显示焦点
在项目中经常会使用到 WebView 控件,当加载 html 页面时,会在/data/data/应用 package 目录下生成 database与 cache 两个文件夹如下图如示:
请求的 url 记录是保存在 WebViewCache.db,而 url 的内容是保存在 WebViewCache 文件夹下.定义一个 html 文件,在里面显示一张图片,用 WebView 加载出来,然后能够从缓存里把这张图片读取出来并显示.
打开关闭使用缓存
//优先使用缓存:
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");
3.3 Android 中 WebView 跟 JAVASCRIPT 中的交互
在 android 的应用程序中,可以直接调用 WebView 中的 javascript 代码,而 WebView 中的 javascript 代码,也可以去调用 ANDROID 应用程序(也就是 JAVA 部分的代码).
(1)、JAVASCRIPT 脚本调用 android 程序要在 WebView 中,调用 addJavascriptInterface(OBJ,interfacename)其中,obj 为和 javascript 通信的应用程序,interfacename 为提供给 JAVASCRIPT 调用的名称,设置如下:
webview = (WebView) findViewById(R.id.webview);
WebSettings set = webview.getSettings();
set.setJavaScriptEnabled(true);
//将class runCameraJavaScript的对象赋给javascript中全局变量window的takephoto
//这样在javascript中可以使用window.takephoto调用类runCameraJavaScript中的函数;
webview.addJavascriptInterface(new runCameraJavaScript(), "takephoto");
final class runCameraJavaScript{
// 可以接收从JS发送过来的字符串
public void runTakePhotoJavaScript(final String str){
h.post(new Runnable(){
public void run() {
doTakePhoto();
}
});
}
}
其中 WebView 调用的 HTML 页中,JS 如下:
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd ">
<!-- saved from url=(0041)http://192.168.88.120/test/2/android.html -->
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script language="javascript" type="text/javascript">
function fasong(){
var str = '这是一个测试的JS';
window.takephoto.runTakePhotoJavaScript(str);
}
</script>
<link type="text/css" rel="stylesheet" href="chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/style.css"><script type="text/javascript" charset="utf-8" src="chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/page_context.js"></script></head>
<body screen_capture_injected="true">
<img id="preview">
<input type="button" value="WebView调用摄像头" οnclick="fasong()">
<div id="show"></div>
</body></html>
其中window.takephoto.runTakePhotoJavaScript便是调用了穿过来类的方法
(2)、要使用webview调用javascript,前面的步骤一样,将类的实例传给javascript,这样调用
mWebView.loadUrl("javascript:wave()");
例子如下
webview = (WebView) findViewById(R.id.webview);
WebSettings set = webview.getSettings();
set.setJavaScriptEnabled(true);
//将class runCameraJavaScript的对象赋给javascript中全局变量window的takephoto
//这样在javascript中可以使用window.takephoto调用类runCameraJavaScript中的函数;
webview.addJavascriptInterface(new runCameraJavaScript(), "takephoto");
final class runCameraJavaScript{
// 可以接收从JS发送过来的字符串
public void runTakePhotoJavaScript(final String str){
h.post(new Runnable(){
public void run() {
mWebView.loadUrl("javascript:fasong()");//这句就是用来调用javascript中的fasong()方法的。
}
});
}
}