混合开发 客户端与webview交互类
逻辑
- 一般客户端可以主动访问webview挂载到window上的方法,webview可以访问客户端注入到window上的桥接类
- 如果将客户端看作服务器的话,那么webview就是浏览器端,客户端服务器和webview浏览器端是可以双向交互,可以看作一个半双工的交互协议
- 而在实际开发过程中 多是webview端主动请求客户端 而客户端进行回复 因此可以设计一个协议如下:
{
actionId: '',
callbackName: '',
content: {
...
}
}
{
status: 1,
message: ''
data: {
...
}
}
- 一般在webview端 应该首先确认客户端注入的桥接类是否加载完成(测试基本是秒加载) 之后才能进行其他的交互操作
代码
export function useHybirdInit(isIosWebkit: Boolean, bridgeClassName: string, callfunctionName: string) : {
BridgeCall : Function,
GetBridge : Function
} {
const MAX_TRY_TIME : number = 50
const TRY_INTERVAL: number = 20
let tryTimes = 0
let hasLoaded = false
const GetBridge = (callback : Function,finalCallback: Function|undefined = undefined) => {
if (tryTimes > MAX_TRY_TIME) {
if (finalCallback !== undefined) {
finalCallback()
}
return
}
hasLoaded =
isIosWebkit == true
? (window as any).webkit !== undefined
: (window as any)[bridgeClassName] !== undefined
if (hasLoaded == false) {
tryTimes += 1
setTimeout(() => {
GetBridge(callback)
}, TRY_INTERVAL)
} else {
if (isIosWebkit == true && (window as any)[bridgeClassName] == undefined) {
(window as any)[bridgeClassName] = Object.create(null)
(window as any)[bridgeClassName][callfunctionName] = function (args: string) {
(window as any).webkit.messageHandlers[bridgeClassName].postMessage(args)
}
}
callback()
}
}
const BridgeCall = (action : string | number, data : any , callbackName: string, callback: Function | undefined) => {
if(callback !== undefined) {
(window as any)[callbackName] = function(responseJson: string) {
callback(JSON.parse(responseJson))
}
}
(window as any)?.[bridgeClassName]?.[callfunctionName](
JSON.stringify({
actionId: action,
callbackName,
content: JSON.stringify(data)
})
)
}
return {
GetBridge,
BridgeCall
}
}
调用
import { useHybirdInit } from 'hybird.ts'
const {GetBridge, BridgeCall} = useHybirdInit(true, 'OCJSBridge', 'jsToOc')
GetBridge(()=>{
BridgeCall(
1,
{
userid: '123'
},
'getUserInfo',
(userinfo) => {console.log('userinfo is',userinfo)}
)
})
BridgeCall(
2,
{
mediaId: 'xxxx'
},
'getMediaSrc',
(src) => {console.log('media src is',src)}
)