android、ios通过webview与JavaScript交互实践
持续更新...
# 前言
在移动开发过程中,总会碰上 webview 与 app 交互的时候,JavaScript 和 android webview 交互,JavaScript 和 ios 交互也是很常见的。app 端不管使用哪种语言开发,与 JavaScript 交互的时候是两种方式:
- app 通过 webview 传参给 JavaScript
- JavaScript 通过 webview 传参给 app
下面总结一下在开发的实战经验,给自己留一份碎片记忆。
ios 端以 OC 为例。 OC->Objective-C。
# 传参数据
在实际开发中,app 通过 webview 与 JavaScript 相互传递参数时,可以通过向 webview 的 window 对象 注入成员属性或者函数来实现数据交互。双方的数据传输协定根据 app 实际的开发语言有所区别。
从属性与函数的功能性作分类:
- 属性: app 向 window 注入变量,主要用于获得标识参考。
- 函数:
- app 向 window 的回调函数注入回调参数,主要用于让 window 动态获取 app 传递的参数(需要提前向 window 注入全局函数)。
- window 向 app 传递参数,接收方式因终端语言而异。
谈完数据传输方式后接下来聊一下传输的数据结构。
一般来讲传输的数据结构可以是字符串、数字、JSON 字符串,需要注意的是 JSON 这块。
JSON 字符串传输对象(指数组和对象等符合数据结构)数据:
- 在 window 传递数据给 APP 时需要使用 JSON.stringify(params)将对象传化为 JSON 字符串才能顺利传输数据
- 在 window 调回 APP 的回调函数时,回调参数需要使用 JSON.parse(params)将对象传化为传输前的数据形式。
- 目前暂时不能给 window 注入属性?(2020/10/13)
# ios 端
# OC 传参给 Javascript
当 oc 需要传参给 window 时,开发者需要在 window 定义好属性和函数,这里以 vuejs 为例。
先使用 JavaScript 定义好方法
export default {
data() {
return {
id: -1,
record: null,
};
},
methods: {
/**
* @param {Number} id
* @return {Object} params -> {"name": "JyLie", "age": 18}
*/
getRecord(id, params) {
this.id = id;
this.record = JSON.parse(params);
},
},
beforeMounted() {
window.getRecord = this.getRecord;
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
接着 ios 端就可以定义接受数据
// 页面加载完成之后调用在iOS里面调用js方法:
(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSString *jsStr = @"getRecord('{"name": "JyLie", "age": 18}')";
NSLog(@"%@",jsStr);
[webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable d, NSError * _Nullable error) {
NSLog(@"%@",d);
NSLog(@"%@",error);
}];
}
2
3
4
5
6
7
8
9
可见 ios 端在加载 webview 时会监听页面都是否存在需要传递参数的函数,如果检查到函数存在则输出参数(这里以 JSON 为例)
# Javascript 传参给 OC
基本数据结构可以直接传输数据,复合对象则需要通过 JSON.stringify()将数据转化为 JSON 字符串。
webview 只需提前定义好需要交互的实践和传输数据的函数,ios 端会监听页面根据实际情况接收函数参数即可完成数据交互。
export default {
data() {
return {
awakeIOSFnMap: {
pc: 'gotoWebGame',
h5: 'gotoWebGame',
wap: 'gotoMobileGame',
server: 'gotoService',
},
};
},
methods: {
awakedIOSAPP(url, type) {
const fun = this.awakeIOSFnMap[type];
if (!fun) return;
window.webkit.messageHandlers[fun].postMessage(url);
},
},
beforeMounted() {
this.awakedIOSAPP('http://www.xxx.com/', 'h5');
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# android 端
android 端直接调用数据注入即可,实际跟 ios 端方式相似只是对应的方法不一样而已~
# JavaScript 与 android 交互
android 端像 window 注入一个包含 checkApp 方法的对象 callApp,Javascript 可以直接通过 window 对象调用即可
export default {
data() {
return {
type: 'app',
};
},
methods: {},
beforeMounted() {
// 向webview注入属性
window.appType = this.type;
// 在webview注入方法reportDevice,页面加载后 android向reportDevice 注入设备配置后调用,reportDevice则上传设备数据后后台
window.reportDevice = function reportDevice(info) {
userApi.postReportdevice({ ...info });
};
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
本文为一次项目实践所得,希望让更多的人看到少踩点坑。如有纰漏欢迎指正~