原生代码和JS交互说明
原生代码和JS交互说明 简介
- 接口不要定义返回值,JS有获取数据需求的情况通过回调函数的方式实现
- 尽量保证iOS和Android端一致,简化JS端的使用
- 通过在WebView注入JS实现Web端和客户端的交互
- 定义一个公共的kf对象,在WebView初始化时注入
- 定义js文件,记录公共方法
- 尽可能统一方法名
//method 方法名
//params 参数
//callback 回调
window.webkit.messageHandlers.kf.postMessage(JSON.stringify({method:'showMessage',params:'Please call me Steven',callback:''}));
iOS端 WKWebView交互
JS调用OC接口WKWebView提供了postMessage的机制来让JS调用OC接口:
window.webkit.messageHandlers[namespace].postMessage(JSON.stringify(wrap));
OC回调JS函数
[self.webView evaluateJavaScript:@"getShareLink('网页该分享了');
" completionHandler:^(id _Nullable jsShareUrl, NSError * _Nullable error) {
HKLog(@"分享链接%@",jsShareUrl);
}];
JS调用OC
//JS Call OC
function showMessage(){// ??????window.webkit.messageHandlers.方法名.postMessage(参数);
// 注意:参数不能为空,有且只有一个参数,如不传参数写postMessage(null)
//kf 为我们注入JS的对象
/*
// 传null
window.webkit.messageHandlers.kf.postMessage(null);
// 传字典
window.webkit.messageHandlers.kf.postMessage({name:'小明',gender:'男'});
// 传字符串
window.webkit.messageHandlers.kf.postMessage('hello');
// 传数组
window.webkit.messageHandlers.kf.postMessage(['小明','小华','小亮']);
*/
//method 方法名
//params 参数
//callback 回调
window.webkit.messageHandlers.kf.postMessage(JSON.stringify({method:'showMessage',params:'Please call me Steven',callback:''}));
}
bridge.js为方便JS端调用,在注册了OC方法后,需要再bridge.js中定义好JS函数,例如
kf.getResourceInfo = function (callBackName) {
calliOSFunction("kf","getResourceInfo","",callBackName);
};
bridge.js 在webview加载页面时会自动注入到页面中,JS端可直接调用这里声明的函数
案例代码
测试页面 - 锐客网
此处展示OC传过来的内容(点击右上角分享按钮即可)
效果图
文章图片
WkWebView和OC交互.gif Android端 JS调用Java接口
Android端只要调用:
webview.addJavascriptInterface(obj, "kf");
方法即可将obj对象中被
@JavascriptInterface
注解的方法提供给JS端调Java调用JS
【原生代码和JS交互说明】webview.loadUrl("javascript:" + function + "("" + data + "")"); 通过此方法可以调用JS中的函数,该函数必须在window对象下。
带回调函数的接口为方便JS端调用,目前要求所有带回调函数的方法,允许传入function对象,如:
kf.getResourceInfo = function (callback){ };
在调用时,调用方式如下:
kf.getResourceInfo(function(data){
console.log(data)
})
因为Java端并不能直接使用JS中函数对象,Java提供的接口只能接收String类型的回调函数名,所以为了支持在前端这样调用,需要做如下的处理
bridge.js和iOS端一样,带回调的JS接口需要再bridge.js中重新声明, 在assets下的android_bridge.js中:
kf.getResourceInfo = function(callback){
win.kf._getResourceInfo(wrapCallback("getResourceInfo", callback));
};
和iOS端不同的时,Android端仅需要重新声明带回调函数的方法,无返回值的不需要重新声明
@CallbackFunction注解
请注意上面bridge.js中出现的 _getResourceInfo 方法调用,该方法在Java的接口中并不存在,它是在编译的时候自动生成的,实际的Java方法声明如下:
public class DetailJsFunction extends BaseJsFunction {
@CallbackFunction
public void getResourceInfo(final String callback) {
webView.callJsFunction(callback, resourceInfo);
}
}
所有被@CallbackFunction注解的方法,在编译时,会自动生成一个新的代理类,该代理类中会自动追加一个 "_" + 原方法名的方法,所以在JS中可以直接以:
win.kf._getResourceInfo(wrapCallback("getResourceInfo", callback));
的方式调用
使用JsFunctionProxy为了使上述方式生效,需要通过JsFunctionProxy来创建要注入给JS的对象, 如下:
detailJsFunction = JsFunctionProxy.inject(DetailJsFunction.class, this, webView);
webView.injectJsObject(detailJsFunction, "kf");
这里的DetailJsFunction不能是内部类了,必须是public的独立类,所以有些情况可能会略有不便
推荐阅读
- 急于表达——往往欲速则不达
- CVE-2020-16898|CVE-2020-16898 TCP/IP远程代码执行漏洞
- 第三节|第三节 快乐和幸福(12)
- 20170612时间和注意力开销记录
- 2.6|2.6 Photoshop操作步骤的撤消和重做 [Ps教程]
- 对称加密和非对称加密的区别
- 眼光要放高远
- 樱花雨
- 前任
- 2020-04-07vue中Axios的封装和API接口的管理