WebView interacts with native controls
1. Call Webview natively
Prepare before use
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> Android调用 JavaScript</title>
</head>
<body>
<h1>这是H1</h1>
<script>
// Android需要调用的方法
function callJS() {
alert("Android调用了JS的callJS方法");
}
</script>
</body>
</html>
1.1 Method 1: loadUrl
Method
webView.loadUrl("javascript:callJS()");
1.2 Method 2: evaluateJavascript
Method
webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
//此处为 js 返回的结果
}
});
2. Webview calls native controls
2.1 Method 1: addJavascriptInterface
Method
Step 1: Define Entity Classes
public class AndroidtoJs {
// 定义JS需要调用的方法
// 被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
public void hello(String msg) {
Log.i("AndroidtoJs","msg:"+msg);
}
}
Step 2: Add html code
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebView Study</title>
<script>
function callAndroid() {
test.hello("js调用了android中的hello方法");
}
</script>
</head>
<body>
<button type="button" id="button1" onclick="callAndroid()">callAndroid</button>
</body>
</html>
Step 3: java calling code
//AndroidtoJS类对象映射到js的test对象
webView.addJavascriptInterface(new AndroidtoJs(), "test");
2.2 Method 2: shouldOverrideUrlLoading method
Step 1: Add html code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>lucashu</title>
<script>
function callAndroid(){
document.location = "js://webview?arg1=111&arg2=222";
}
</script>
</head>
<body>
<button type="button" id="button1" onclick="callAndroid()">callAndroid</button>
</body>
</html>
Step 2:
Override the WebViewClient
methodshouldOverrideUrlLoading
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("MainActivity", "shouldOverrideUrlLoading:"+url);
return true;
}
2.3 Method 3: onJsAlert
, onJsConfirm
, onJsPrompt
method
Step 1: Add html code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>lucashu</title>
<script>
function callAndroid(){
prompt("js://webview?arg1=111&arg2=222");
}
</script>
</head>
<body>
<button type="button" id="button1" onclick="callAndroid()">callAndroid</button>
</body>
</html>
overridden method WebChromeClient
_onJsPrompt
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
Log.d("MainActivity","onJsPrompt:"+ message);
return true;
}
3. The third-party framework jsbridge
Official website : https://github.com/lzyzsd/JsBridge
3.1 How to use
repositories {
// ...
maven {
url "https://jitpack.io" }
}
dependencies {
compile 'com.github.lzyzsd:jsbridge:1.0.4'
}
3.2 js calls native general method with callback
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>lucashu</title>
<script>
//h5直接通过send向Native发送消息,在MyHandlerCallBack的Handler里接收,并可通过onCallBack方法回传
function sendClick() {
var name = document.getElementById("uname").value;
var pwd = document.getElementById("psw").value;
var data = "name = " + name + ", password = " + pwd;
window.WebViewJavascriptBridge.send(
data,
function(responseData) {
document.getElementById("show").innerHTML = responseData
}
);
}
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function () {
callback(WebViewJavascriptBridge)
},
false
);
}
}
// 第一连接时初始化bridage
connectWebViewJavascriptBridge(function (bridge) {
//也注册默认的Handler,用来接收java调用的send(string,CallBackFunction)方法
bridge.init(function (message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': '测试中文!'
};
console.log('JS responding with', data);
responseCallback(data);
});
//注册handler等待java代码调用
//初始化时获取数据是调用此处代码
//参数:标识,要传递到JAVA的数据,回调方法。
//JAVA代码响应的方法:mBridgeWebview.callHandler("functionInJs", new Gson().toJson(实体类对象), new CallBackFunction(){onCallBack(String data)}
bridge.registerHandler("functionInJs", function (data, responseCallback) {
document.getElementById("show").innerHTML = ("data from Java: = " + data);
var responseData = "I am javascript, Data reception success!";
responseCallback(responseData);
});
})
</script>
</head>
<body>
<p>
<input type="text" id="uname" value="用户名" />
</p>
<p>
<input type="text" id="psw" value="密码" />
</p>
<button type="button" id="button1" onclick="sendClick()">发给Native</button>
<p>
<div id="show">Native将要回传回来的数据展示</div>
</p>
</body>
</html>
java side code
webView.loadUrl("file:///android_asset/test.html");
WebSettings webSettings = webView.getSettings();
webView.clearCache(true);
webSettings.setJavaScriptEnabled(true);
webView.setDefaultHandler(new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
Log.i(TAG, "handler web data = " + data);
function.onCallBack("从java端传回的数据");
}
});
3.3 JS calls native with a callback and sends it to a specific method
html code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>lucashu</title>
<script>
function clickAlert() {
var name = document.getElementById("uname").value;
var pwd = document.getElementById("psw").value;
var data = "name = " + name + ", password = " + pwd;
WebViewJavascriptBridge.callHandler(
'submitFromWeb', {
'param': data
},
function (responseData) {
document.getElementById("show").innerHTML = responseData;
}
);
}
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function () {
callback(WebViewJavascriptBridge)
},
false
);
}
}
// 第一连接时初始化bridage
connectWebViewJavascriptBridge(function (bridge) {
//也注册默认的Handler,用来接收java调用的send(string,CallBackFunction)方法
bridge.init(function (message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': '测试中文!'
};
console.log('JS responding with', data);
responseCallback(data);
});
//注册handler等待java代码调用
//初始化时获取数据是调用此处代码
//参数:标识,要传递到JAVA的数据,回调方法。
//JAVA代码响应的方法:mBridgeWebview.callHandler("functionInJs", new Gson().toJson(实体类对象), new CallBackFunction(){onCallBack(String data)}
bridge.registerHandler("functionInJs", function (data, responseCallback) {
document.getElementById("show").innerHTML = ("data from Java: = " + data);
var responseData = "I am javascript, Data reception success!";
responseCallback(responseData);
});
})
</script>
</head>
<body>
<p>
<input type="text" id="uname" value="用户名" />
</p>
<p>
<input type="text" id="psw" value="密码" />
</p>
<button type="button" id="button1" onclick="clickAlert()">获取用户名和密码</button>
<p>
<div id="show">Native将要回传回来的数据展示</div>
</p>
</body>
</html>
java code
webView.loadUrl("file:///android_asset/test.html");
WebSettings webSettings = webView.getSettings();
webView.clearCache(true);
webSettings.setJavaScriptEnabled(true);
webView.registerHandler("submitFromWeb", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
Log.i(TAG, "handler web data = " + data);
function.onCallBack("从java端传回的数据");
}
});
3.4 Native sends data to js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>lucashu</title>
<script>
//Native方法直接调用,示例代码:mBridgeWebview.loadUrl("javascript:nativeFunction('" + data + "')");
function nativeFunction(data) {
document.getElementById("show").innerHTML = data;
}
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function () {
callback(WebViewJavascriptBridge)
},
false
);
}
}
// 第一连接时初始化bridage
connectWebViewJavascriptBridge(function (bridge) {
//也注册默认的Handler,用来接收java调用的send(string,CallBackFunction)方法
bridge.init(function (message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': '测试中文!'
};
console.log('JS responding with', data);
responseCallback(data);
});
//注册handler等待java代码调用
//初始化时获取数据是调用此处代码
//参数:标识,要传递到JAVA的数据,回调方法。
//JAVA代码响应的方法:mBridgeWebview.callHandler("functionInJs", new Gson().toJson(实体类对象), new CallBackFunction(){onCallBack(String data)}
bridge.registerHandler("functionInJs", function (data, responseCallback) {
document.getElementById("show").innerHTML = ("data from Java: = " + data);
var responseData = "I am javascript, Data reception success!";
responseCallback(responseData);
});
})
</script>
</head>
<body>
<div id="show">Native将要回传回来的数据展示</div>
</p>
</body>
</html>
java side
webView.loadUrl("file:///android_asset/test.html");
WebSettings webSettings = webView.getSettings();
webView.clearCache(true);
webSettings.setJavaScriptEnabled(true);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.loadUrl("javascript:nativeFunction('data')");
}
});
3.5 Other methods
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>lucashu</title>
<script>
//Native方法直接调用,示例代码:mBridgeWebview.loadUrl("javascript:nativeFunction('" + data + "')");
function nativeFunction(data) {
document.getElementById("show").innerHTML = data;
}
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function () {
callback(WebViewJavascriptBridge)
},
false
);
}
}
// 第一连接时初始化bridage
connectWebViewJavascriptBridge(function (bridge) {
//也注册默认的Handler,用来接收java调用的send(string,CallBackFunction)方法
bridge.init(function (message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': '测试中文!'
};
console.log('JS responding with', data);
responseCallback(data);
});
//注册handler等待java代码调用
//初始化时获取数据是调用此处代码
//参数:标识,要传递到JAVA的数据,回调方法。
//JAVA代码响应的方法:mBridgeWebview.callHandler("functionInJs", new Gson().toJson(实体类对象), new CallBackFunction(){onCallBack(String data)}
bridge.registerHandler("functionInJs", function (data, responseCallback) {
document.getElementById("show").innerHTML = ("data from Java: = " + data);
var responseData = "I am javascript, Data reception success!";
responseCallback(responseData);
});
})
</script>
</head>
<body>
<p>
<input type="text" id="uname" value="用户名" />
</p>
<p>
<input type="text" id="psw" value="密码" />
</p>
<button type="button" id="button1" onclick="sendClick()">发给Native</button>
<p>
<div id="show">Native将要回传回来的数据展示</div>
</p>
</body>
</html>
java
webView.loadUrl("file:///android_asset/test.html");
WebSettings webSettings = webView.getSettings();
webView.clearCache(true);
webSettings.setJavaScriptEnabled(true);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//应用启动后初始化数据调用,js处理方法connectWebViewJavascriptBridge(function(bridge)
webView.callHandler("functionInJs", "username passwod", new CallBackFunction() {
@Override
public void onCallBack(String data) {
Toast.makeText(MainActivity.this, "向h5发送初始化数据成功,接收h5返回值为:" + data, Toast.LENGTH_SHORT).show();;
}
});
}
});
//对应js中的bridge.init处理,此处需加CallBackFunction,如果只使用mBridgeWebview.send("");会导致js中只收到通知,接收不到值
webView.send("来自java的发送消息!!!", new CallBackFunction() {
@Override
public void onCallBack(String data) {
Toast.makeText(MainActivity.this, "bridge.init初始化数据成功" + data, Toast.LENGTH_SHORT).show();
}
});