WebView是一个可以浏览网页的控件,由此可以引申出android开发的两种模式:native原生开发和web混合开发。
- 如果APP仅限于前端展示,背后的逻辑都在服务端完成,那么完全可以采用web H5开发的方式,即快捷,又可以跨平台,做到一次开发多次部署的效果。纯移动H5开发的平台,则建议使用HBuilder或MUI,开发完后可以将页面打包为apk。
- 如果app的功能较复杂,比如频繁调用底层api,比如拍照、电量管理、手机优化等,那还是建议采用原生开发,或混合开发。
WebView控件则是在混合开发时必用的控件,可以实现网页加载、事件监听以及andorid代码与js代码的交互等。据说性能不佳,本文先介绍基本用法,性嫩问题后面再说。
基本使用
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);//设置webview内可执行js脚本
webView.getSettings().setDomStorageEnabled(true);//设置webview可存储dom缓存数据
webView.loadUrl("http://192.168.1.113/AngularJSTest/android.html");//为了后面测试方便,自己写个html页面,代码在后面
上面就可以加载一个网页了(记得给app设置INTERNET权限);当然也可以加载本地页面:
//加载apk包中的html页面
webView.loadUrl("file:///android_asset/test.html");
//加载手机本地的html页面
webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
下面介绍两个常用方法类:
- WebViewClient:处理各种通知、请求事件
- WebChromeClient :处理 Javascript 的对话框、加载进度、获取网站图标标题等等
具体看代码:
webView.setWebChromeClient(new WebChromeClient(){
//获取网站标题
@Override
public void onReceivedTitle(WebView view, String title) {
System.out.println("网页标题:"+title);
}
//获取加载进度
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress < 100) {
String progress = newProgress + "%";
System.out.println("加载进度:"+progress);
} else if (newProgress == 100) {
System.out.println("加载完成");
}
}
//截获页面内console.log输出的信息
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
System.out.println("from webview:"+consoleMessage.message()+"----From line" +
consoleMessage.lineNumber() + "-----sourceID:" + consoleMessage.sourceId());
return true;
}
//截获页面内alert的提示信息
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Toast.makeText(getApplicationContext(),message,Toast.LENGTH_SHORT).show();
result.cancel();//必须调用,否则出现jsalert只调用一次就页面无响应
return true;
}
});
//设置WebViewClient类
webView.setWebViewClient(new WebViewClient() {
//设置加载前的函数
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
System.out.println("开始加载了");
}
//设置结束加载函数
@Override
public void onPageFinished(WebView view, String url) {
System.out.println("结束加载,可以执行js脚本了");
}
//该方法传回了错误码,根据错误类型可以进行不同的错误分类处理
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
switch(errorCode){
case HttpStatus.SC_NOT_FOUND:
break;
}
}
});
常用方法
(1)webview状态设置,与性能调优有关
//激活WebView为活跃状态,能正常执行网页的响应
webView.onResume() ;
//当页面被失去焦点被切换到后台不可见状态,需要执行onPause
//通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
webView.onPause();
//当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
//它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
webView.pauseTimers()
//恢复pauseTimers状态
webView.resumeTimers();
//销毁Webview
//在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
//但是注意:webview调用destory时,webview仍绑定在Activity上
//这是由于自定义webview构建时传入了该Activity的context对象
//因此需要先从父容器中移除webview,然后再销毁webview:
rootLayout.removeView(webView);
webView.destroy();
(二)清除缓存数据
//清除网页访问留下的缓存
//由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
Webview.clearCache(true);
//清除当前webview访问的历史记录
//只会webview访问历史记录里的所有记录除了当前访问记录
Webview.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
Webview.clearFormData();
webveiw留下的缓存文件,可以通过studio里的DeviceFileExplorer查看:
(三)前进 / 后退网页
点击系统的“Back”键,实际上整个 Browser 会调用 finish()而结束自身activity,不能实现网页的后退效果,需要在:在当前Activity中处理并消费掉该 Back 事件
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
andorid调用js方法
需要判断设备的API是否19上下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
System.out.println("API>19");
webView.evaluateJavascript("javascript:changename()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
//此处为 js 返回的结果
System.out.println("js返回结果:" + value);
}
});
}
else {
System.out.println("API<19");
webView.loadUrl("javascript:changename()");
}
js调用android方法
在Android定义一个对象,让这个对象映射到js里面的一个对象,再让这个对象去调用方法。
//1、定义一个对象,给方法加JavascriptInterface标签
public class WebTest {
private Context context;
public WebTest(Context context){
this.context = context;
}
@JavascriptInterface
public void show(String message) {
//todo
}
}
//2、给webview添加映射“mandroid”
webView.addJavascriptInterface(new WebTest(this),"mandroid");
//3、网页中,使用js调用
function android(){
mandroid.show("js调用android中的方法");
}
最后给出本文开头的andorid.html页面,可以直接部署到iis或tomcat上。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>系统登录</title>
<script type="text/javascript">
function test(){
for(i=0;i<10;i++){
console.log(i);
}
}
function alertsth(){
alert("被修改了");
}
function android(){
mandroid.show("js调用了android中的方法");
}
</script>
</head>
<body>
<div class="container">
<header>
<h1>android开发webview测试页</h1>
</header>
</div>
<BUTTON id="tes" onClick="test()">console.log</BUTTON><p/>
<BUTTON id="btn" onClick="alertsth()">alert</BUTTON><p/>
<BUTTON id="btn" onClick="android()">调用andorid中的方法</BUTTON><p/>
</body>
</html>