Android调用Js
- loadUrl()
通过WebView的loadUrl()方法调用Js方法。
mWebView.loadUrl("javascript:callJsDefault()");
//在android调用js有参的函数的时候参数要加单引号
String param = "\'来自Android的参数\'";
mWebView.loadUrl(String.format("javascript:callJsWithParams(%s)", param));
- evaluateJavascript()
通过WebView的evaluateJavascript()方法调用Js方法,此方法可以获得Js方法执行后的返回值。
mWebView.evaluateJavascript("javascript:callJsWithReturn(2,3)",
value -> Toast.makeText(MainActivity.this, "Js的计算结果为:" + value, Toast.LENGTH_SHORT).show());
Js调用Android
- addJavascriptInterface()
创建一个类通过WebView的addJavascriptInterface()方法提供给Js使用,Js通过它调用我们在Android中写好的方法。
public class JsCallAndroid {
private Context mContext;
public JsCallAndroid(Context context) {
mContext = context;
}
//供Js调用的方法要加JavascriptInterface注解
@JavascriptInterface
public void hello(String msg){
Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show();
}
/*...*/
}
//"android"为Js中调用对象的名称
mWebView.addJavascriptInterface(new JsCallAndroid(this), "android");
Js中调用
function callAndroid(){
// 由于对象映射,所以调用android对象等于调用Android映射的对象
android.hello("js调用了android中的hello方法!!!");
}
- alert()、confirm()、prompt()
通过重写WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法响应Js的alert()、confirm()、prompt()调用。
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Alert")
.setMessage(message)
.setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm())
.setNegativeButton(android.R.string.cancel, (dialog, which) -> result.cancel())
.setCancelable(false)
.create()
.show();
return true;
}
});
Js代码
function callAndroidAlert(){
alert("来自Js的提示");
}
-
shouldOverrideUrlLoading
Js与Android定义一组特殊的URL,然后重写WebViewClient的shouldOverrideUrlLoading()方法,拦截url,解析url包含的数据,针对不同数据做不同操作。
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("protocol://webview?")) {
Map<String, String> dataMap = getUrlDataMap(url);
if (dataMap != null) {
switch (dataMap.get("operate")) {
case "toast":
Toast.makeText(MainActivity.this, dataMap.get("msg"), Toast.LENGTH_LONG).show();
break;
case "startActivity":
/*...*/
break;
default:
break;
}
}
} else
view.loadUrl(url);
return true;
}
});
/**
* 获取URl所包含的数据
* @param url
* @return 数据的map集合
*/
private Map<String, String> getUrlDataMap(String url) {
Map<String, String> map = null;
try {
url = URLDecoder.decode(url, "utf-8");
String substring = url.substring(url.indexOf("?") + 1);
String[] split = substring.split("&");
map = new HashMap<>();
String[] entry;
for (String s : split) {
entry = s.split("=");
map.put(entry[0], entry[1]);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return map;
}
Js代码
//这里用一个a标签做示例
<a href="protocol://webview?operate=toast&msg=Js通过url控制Android执行方法">通过url执行方法</a>
扩展方式
Js和Android的交互还可以通过JsBridge来完成,JsBridge是一个开源的第三方库,其作用和名字一样,可以作为Js和Android之间的桥梁进行沟通。使用方法在Github上都有介绍,网上也有挺多博客的,有兴趣的自己搜一下,我就不写了。
本次示例Html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p id="content"></p>
<p><button type="button" id="button1" onclick="callAndroid()">点击按钮则调用callAndroid函数</button></p>
<a href="protocol://webview?operate=toast&msg=Js通过url控制Android执行方法">通过url执行方法</a>
<script type="text/javascript">
var content = document.getElementById("content");
function callAndroid(){
// 由于对象映射,所以调用android对象等于调用Android映射的对象
android.hello("js调用了android中的hello方法!!!");
}
function callAndroidAlert(){
alert("来自Js的提示");
}
// Android需要调用的方法
function callJsDefault(){
content.innerHTML='Android调用了Js的默认方法';
}
function callJsWithParams(params){
content.innerHTML = "Android调用了Js的带参方法:" + params;
}
function callJsWithReturn(a,b){
return a+b;
}
</script>
</body>
</html>
总结
以上所有的Js和Android的交互方法,各有各的特点,其中Js调用Android的方法中,使用拦截Url的方式比较多,因为考虑到要兼顾ios的通用性,拦截Url是两个端实现成本最低的一种,如果不需要考虑ios端,那么随便哪一种都可以。