为什么要学习Android与H5互调?
微信,QQ空间等大量软件都内嵌了H5,不得不说是一种趋势。Android与H5互调可以让我们的实现混合开发,至于混合开发就是在一个App中内嵌一个轻量级的浏览器,一部分原生的功能改为Html 5来开发。
优势:使用H5实现的功能能够在不升级App的情况下动态更新,而且可以在Android或iOS的App上同时运行,节约了成本,提高了开发效率。
原理:其实就是Java代码和JavaScript之间的调用。
WebView简介
要实现Android与H5互调,WebView是一个很重要的控件,WebView可以很好地帮助我们展示html页面,所以有必要先了解一下WebView。
一丶WebView常用方法
(1)loadUrl
加载界面,其次还有LoadData和LoadDataWithBase方法
//加载assets目录下的test.html文件
webView.loadUrl("file:///android_asset/test.html");
//加载网络资源(注意要加上网络权限)
setWebViewClient(如果用户设置了WebViewClient,则在点击新的链接以后就不会跳转到系统浏览器了,而是在本WebView中显示。注意:并不需要覆盖 shouldOverrideUrlLoading 方法,同样可以实现所有的链接都在 WebView 中打开。)
WebViewClient主要用来辅助WebView处理各种通知、请求等事件,通过setWebViewClient方法设置。以下是它的几种常见用法:
实现对网页中超链接的拦截(比如如果是极客导航的主页,则直接拦截转到百度主页):
当点击页面中的链接后,会在WebView加载URL前回调shouldOverrideUrlLoading(WebView view, String url)方法,一般点击一个链接此方法调用一次。
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if("http://www.jikedaohang.com/".equals(url)) {
view.loadUrl("https://www.baidu.com/");
}
return true;
}
});
(2)加载网页时替换某个资源(比如在加载一个网页时,需要加载一个logo图片,而我们想要替换这个logo图片,用我们assets目录下的一张图片替代)
我们知道我们在加载一个网页的同时也会加载js,css,图片等资源,所以会多次调用shouldInterceptRequest方法,我们可以在shouldInterceptRequest中进行图片替换。
注意:shouldInterceptRequest有两个重载:
①public WebResourceResponse shouldInterceptRequest (WebView view, String url) 【已过时】
②public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request)
这两种方法主要是第二个参数的不同,WebResourceRequest 将能够获取更多的信息,提供了getUrl(),getMethod,getRequestHeaders等方法。这里主要是为了展示效果,使用了第一种回调方法。实现方法如下:
mWebView.setWebViewClient(new WebViewClient(){
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
WebResourceResponse response = null;
if (url.contains("logo")) {
try {
InputStream logo = getAssets().open("logo.png");
response = new WebResourceResponse("image/png", "UTF-8", logo);
} catch (IOException e) {
e.printStackTrace();
}
}
return response;
}
});
(3)设置开始加载网页、加载完成、加载错误时处理
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
// 开始加载网页时处理 如:显示"加载提示" 的加载对话框
...
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// 网页加载完成时处理 如:让 加载对话框 消失
...
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
// 加载网页失败时处理 如:提示失败,或显示新的界面
...
}
});
(4)处理https请求,为WebView处理ssl证书设置WebView默认是不处理https请求的,需要在WebViewClient子类中重写父类的onReceivedSslError函数
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed(); // 接受信任所有网站的证书
// handler.cancel(); // 默认操作 不处理
// handler.handleMessage(null); // 可做其他处理
}
});
setWebChromeClient
WebChromeClient主要用来辅助WebView处理Javascript的对话框、网站图标、网站标题以及网页加载进度等。通过WebView的setWebChromeClient()方法设置。
(1)显示页面加载进度在WebChromeClient子类中重写父类的onProgressChanged函数,progress表示当前页面加载的进度,为1至100的整数
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
setTitle("页面加载中,请稍候..." + progress + "%");
setProgress(progress * 100);
if (progress == 100) {
//...
}
}
});
(2)加快HTML网页加载完成速度(默认情况html代码下载到WebView后,webkit开始解析网页各个节点,发现有外部样式文件或者外部脚本文件时,会异步发起网络请求下载文件,但如果在这之前也有解析到image节点,那势必也会发起网络请求下载相应的图片。在网络情况较差的情况下,过多的网络请求就会造成带宽紧张,影响到css或js文件加载完成的时间,造成页面空白loading过久。解决的方法就是告诉WebView先不要自动加载图片,等页面finish后再发起图片加载。)
//1.首先在WebView初始化时添加如下代码
if(Build.VERSION.SDK_INT >= 19) {
/*对系统API在19以上的版本作了兼容。因为4.4以上系统在onPageFinished时再恢复图片加载时,如果存在多张图片引用的是相同的src时,会只有一个image标签得到加载,因而对于这样的系统我们就先直接加载。*/ webView.getSettings().setLoadsImagesAutomatically(true);
} else {
webView.getSettings().setLoadsImagesAutomatically(false);
}
//2.在WebView的WebViewClient子类中重写onPageFinished()方法添加如下代码:
@Override
public void onPageFinished(WebView view, String url) {
if(!webView.getSettings().getLoadsImagesAutomatically()) {
webView.getSettings().setLoadsImagesAutomatically(true);
}
}
setDownloadListener
通常webview渲染的界面中含有可以下载文件的链接,点击该链接后,应该开始执行下载的操作并保存文件到本地中。
创建DownloadListener
class MyDownLoadListener implements DownloadListener{
@Override
public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype, long contentLength) {
//下载任务...,主要有两种方式
//(1)自定义下载任务
//(2)调用系统的download的模块
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
给webview加入监听
webview.setDownloadListener(new MyDownLoadListener());
(3)goBack()
返回上一浏览页面,通过重写onKeyDown方法实现点击返回键返回上一浏览页面而非退出程序
public boolean onKeyDown(int keyCode, KeyEvent event) {
//其中webView.canGoBack()在webView含有一个可后退的浏览记录时返回true
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
二丶WebSettings配置
- 获取WebSettings对象
WebSettings webSettings = webView.getSettings();
- 常用设置方法
(1)支持jssettings.setJavaScriptEnabled(true);
(2)设置缓存方式,主要有以下几种:
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据。
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式。
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据。
LOAD_CACHE_ELSE_NETWORK:只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
(3)开启DOM storage API功能(HTML5 提供的一种标准的接口,主要将键值对存储在本地,在页面加载完毕后可以通过 JavaScript 来操作这些数据。)settings.setDomStorageEnabled(true);
(4)设置数据库缓存路径settings.setDatabasePath(cacheDirPath);
(5)设置Application Caches缓存目录settings.setAppCachePath(cacheDirPath);
(6)设置默认编码settings.setDefaultTextEncodingName(“utf-8”);
(7)将图片调整到适合webview的大小settings.setUseWideViewPort(false);
(8)支持缩放settings.setSupportZoom(true);
(9)支持内容重新布局settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
(10)多窗口settings.supportMultipleWindows();
(11)设置可以访问文件settings.setAllowFileAccess(true);
(12)当webview调用requestFocus时为webview设置节点settings.setNeedInitialFocus(true);
(13)设置支持缩放settings.setBuiltInZoomControls(true);
(14)支持通过JS打开新窗口settings.setJavaScriptCanOpenWindowsAutomatically(true);
(15)缩放至屏幕的大小settings.setLoadWithOverviewMode(true);
(16)支持自动加载图片settings.setLoadsImagesAutomatically(true);
三丶WebViewClient 的回调方法列表