Android调用js代码:
webview.loadUrl("javascript:fun()")
js调用java代码:
getSettings().setJavaScriptEnabled(true);
addJavascriptInterface(new JsHandel(), "jsApi");
public class JsHandel {
@JavascriptInterface
public void call(String dataObj) {
}
}
?????不过这种只能简单的相互调用而已,如果需要回调(例如:js调用android方法并从android端返回数据)还需要做一定的封装处理才可以,大概实现步骤: ?????1. 在android代码中向H5页面注入js对象 ?????2. js端创建一个存储callback回调函数唯一id、callback回调函数的map键值对对象,当js调用android代码时,生成一个callback回调函数唯一id,把该callback回调函数的唯一id和callback回调函数存放到map对象中,并把callback回调函数唯一id传递给android端 ????? 3. android端执行js调用并获取到callback回调函数唯一id,调用js代码将执行结果数据和callback回调函数唯一id传递给js端 ?????4. js端遍历map对象并根据回调函数唯一id找到对应的callback回调函数,通过callback.call(null, data)执行该js回到函数
?????至此js调用android代码并完成回调,具体代码如下:
- 在android代码中向H5页面注入js对象
@Override
public void initView() {
binding.webview.registHandel("gjsbridgeApi", new JsHandel() {
@Override
public void jscall(String funName, String funData, JsFunctionCallBack jsFunction) {
if("getVolumn".equals(funName)){
VolumnApi volumnApi = new VolumnApi();
jsFunction.callback(volumnApi.getVolumn(MainActivity.this));
return;
}else if("showToast".equals(funName) && funData!=null && !funData.isEmpty()){
Toast.makeText(MainActivity.this, funData, Toast.LENGTH_LONG).show();
return;
}
jsFunction.callback("from native");
}
});
binding.webview.loadUrl("http://pojul.gitee.io/web/testjsbridge/");
}
public void registHandel(String handelName, JsHandel jsHandel){
if(jsHandel==null){
return;
}
jsHandel.init(this);
getSettings().setJavaScriptEnabled(true);
addJavascriptInterface(jsHandel, handelName);
}
public abstract class JsHandel {
private static final String TAG = "JsHandel";
private GjsbridgeWebview gjsbridgeWebview;
public void init(GjsbridgeWebview gjsbridgeWebview){
this.gjsbridgeWebview = gjsbridgeWebview;
}
@JavascriptInterface
public void call(String dataObj) {
JsFun jsFun = new Gson().fromJson(dataObj, JsFun.class);
if(jsFun.funName==null||jsFun.funName.isEmpty()){
return;
}
JsFunctionCallBack jsFunction = new JsFunctionCallBack(jsFun.funId) {
@Override
public void callback(String respData) {
if(gjsbridgeWebview==null){
Log.e(TAG, "gjsbridgeWebview has not init");
return;
}
if(funId==null||funId.isEmpty()){
return;
}
gjsbridgeWebview.post(() -> {
gjsbridgeWebview.loadUrl("javascript:gjsbridgeApiCallBack('"+funId+"', '"+respData+"')");
});
}
};
jscall(jsFun.funName, jsFun.funData, jsFunction);
}
public abstract void jscall(String funName, String funData, JsFunctionCallBack jsFunction);
}
public class JsFun {
public String funId;
public String funName;
public String funData;
}
- js端创建map并执行callback.call(null, data)代码
class Api{
constructor(){
}
showToast(msg){
call("showToast", msg, null);
}
getVolumn(fun){
call("getVolumn", null, fun);
}
}
var api = new Api();
var funMap = new Map();
function gjsbridgeApiCallBack(funId, data){
console.log("H5 gjsbridgeApiCallBack funId: " + funId + "; data: " + data);
let fun = funMap.get(funId);
if(fun!=null){
fun.call(null, data);
}
funMap.delete(funId);
console.log("funMap size: " + funMap.size)
}
function call(name, data, fun){
if(window.gjsbridgeApi==null){
console.log(name + "; H5 window.gjsbridgeApi: null");
}else{
console.log(name + "; H5 window.gjsbridgeApi: " + window.gjsbridgeApi);
let dataObj = {
funName: name,
funData: data
}
if(fun!=null && typeof fun === "function"){
let funId = Date.now()+"";
funMap.set(funId, fun);
dataObj.funId = funId;
}
window.gjsbridgeApi.call(JSON.stringify(dataObj));
}
}
- H5直接调用
<body>
<div class="toast-div" id="show" onclick="showToast()">toast</div>
<div class="toast-div" id="volumn" onclick="getVolumn()">volumn: unknow</div>
</body>
<script type="text/javascript">
function showToast(){
api.showToast("toast-div click");
}
function getVolumn(){
api.getVolumn(function(data){
console.log("getVolumn: " + data);
document.getElementById("volumn").innerHTML = data;
});
}
</script>
demo地址: https://github.com/pojul/gjsbridge: gjsbridge集成:implementation ‘io.github.pojul:gjsbridge:1.0.1’
|