安卓中webview的使用以及与js的相互调用

之前就使用了webview写了公司的安卓客户端 那时因为时间仓促赶着上线 没很多时间学习安卓 复杂的界面只能用html写了 而且这种混合的应用方式貌似还很流行啊 html5的很多跨平台应用大概都是这样的吧 在应用里面嵌入一个webview之类的 然后加载网页 不过对于我这样原本就是web前端的来说 是不是写这种混合式的应用有种先天的优势的 不需要像其他那些需要各种其他html整合工具和类库 开发工具类似hybird xdk 这种 或者是web前端框架 native.js nativeScript这样的

我就整理一下我所知道的要注意的点吧

一、 webview的使用

首先 webview 有几个属性很重要

1. wv_main.getSettings().setJavaScriptEnabled(true);

这个设置webview可以执行js

2. wv_main.addJavascriptInterface(new MyJsInterface(MianActivity.this),"myapp");

这个是定义js与java接口, 在js中可以使用 windows.app 调用这个new出来的对象 , 调用里面的方法 , 而且貌似只能是方法,调用不了属性,等下再具体讲这个js如何调用这个类的。

3. wv_main.setWebViewClient(new WebViewClient());

这个WebViewClient是和webview的数据加载相关的,可以重载好几个方法,比如可以这样用:

1
2
3
4
5
6
7
8
9
10
11
12
wv_main.setWebViewClient(new WebViewClient() {
//发起网络请求前,如果返回值为true表示页面在当前webview打开,否则调用系统默认浏览器打开页面。。。。
public boolean shouldOverrideUrlLoading(WebView view, String url) {}
//已经发起网络请求,开始加载页面
public void onPageStarted(WebView view, String url, Bitmap favicon) {}
//页面加载结束
public void onPageFinished(WebView view, String url) {}
//访问失败
public void onReceivedError(WebView view, int errorCode, String description, String url){}
//https请求错误 handler.proceed(); 接受所有网站的证书  一般和https请求相关
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){}
});

具体的用法可以查一下,还有其他很多方法

4. wv_main.setWebChromeClient(new WebChromeClient());

这个WebChromeClient是和我自己感觉是应该称做为交互相关的,主要处理js的各种弹框,页面加载进度,图标favicon,title,新建窗体,关闭窗体,这样的

1
2
3
4
5
6
7
8
9
10
11
12
wv_main.setWebChromeClient(new WebChromeClient(){
//返回值表示js 调用alert的时候,是否会运行这一段,一般如果不重写这个方法,alert出来的框的标题会是 : 网址为"http://xxxx"的网站提示 。 然后下面的内容才是alert的内容, 居然这个标题不是网站的title。。。。想不通。。。所以一般这里都是直接return true; 然后在里面手动写一个AlertDialog.Builder,自定义标题样式什么的,然后show出来,不过最后操作完了之后要执行result.confirm(); 否则的话js里面alert运行了之后就就卡住了,无法继续运行。。。开始的时候被这个坑惨了
public boolean onJsAlert(WebView view, String url, String message,final JsResult result) {}
//这个基本和onJsAlert类似,处理confirm的,最后有result.confirm(); 和 result.cancel(); 两种方法分别表示确定和取消
public boolean onJsConfirm(WebView view, String url, String message,final JsResult result) {}

//prompt这个方法在web里面js用的少,但是我觉得在客户端这里会用到很多吧, 可以result.confirm(text); 向js返回数据,或者result.cancel(); 取消
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {}

//用来展示网站加载进度的, progress貌似是百分比的值,tv_progress.setText("已经加载"+progress+"%"); 这样
public void onProgressChanged(WebView view, int progress) {}
});

其他的方法应该用不多 就不列举了

webview主要就这几个重要的方法,其他的一些都不是很重要的就不讲了。

二、 js与anroid相互调用接口

1. js调用android

说不清楚 直接上代码 以wv_main.addJavascriptInterface(new MyJsInterface(),"myapp");为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MyJsInterface{
int index=0;

@JavascriptInterface //这个必须要有,表示是js接口,如果没有js那边是无法调用到这个函数的 除了这个标记外,这个类与其他普通的类完全一样,构造函数 private public 什么乱七八糟的都可以用
public int getIndex(){ // 返回int 可以支持基础的数据类型 比如 string int boolean 其他的复杂的应该也不支持吧没试过
index++;
return index;
}

@JavascriptInterface
public void setIndex(int n){ //参数可以为 string int boolean 其他复杂的 也没过 应该也不支持吧,好在js弱类型语言,转换什么的比较方便,字符串能解决所有
index=n;
}

@JavascriptInterface
public void exit(){}
}

这个差不多就这样
然后在js里面是这样调用的 坑超级多。。

1
2
var i = window.myapp.getIndex();
window.myapp.setIndex(100);

这几个接口函数基本和普通js函数差不多 但是还是有区别!! 之前被坑掉了

1
2
setTimeout(window.myapp.exit,1000); // 这个是无法执行的!!尼玛!!
setTimeout(window.myapp.exit(),1000);// 这个才是能执行的!! js三观已毁。。。。

所以为了安全起见,不知道还会发生什么意料之外的东西,最好还是下面这样写吧

1
setTimeout(function(){window.myapp.exit();},1000);

2. android调用js

在api19 及之后 webview提供了evaluateJavascript方法 第一个参数是需要执行的js的字符串,第二个参数是回调 用来获取这个js执行完成后返回的值
api19以下 android没有直接调用js的方法,没办法,只能这样了

js:

1
function myFunc(){ }

android:

1
2
3
4
5
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.JELLY_BEAN_MR2){
webview.evaluateJavascript("myFunc()",null);
}else {
wv_main.loadUrl("javascript:myFunc();");
}

很明显 这样如果运行很长的东西还是有点奇怪的。。。 因此里面不会包含很长大语句,一般就一句函数吧。

嗯嗯 差不多就这样吧