13 07 2021

WebView与APP交互

WebView与APP交互,即网页通过JSBrige调用APP的功能,APP也可以通过JSBrige调用网页提供的方法。最近刚好接触到这一块,记录一下前端侧的实际操作过程,这篇文章适合还没接触过这一块的同学们,这里不讲原理,直接开始实战的过程。

准备工作

与客户端同学沟通好使用的JSBrige库,我这里使用的是下面这两个库:

https://gitee.com/guome/uni-js-bridge
https://gitee.com/guome/uni-webview-bridge

uni-js-bridge(H5端)

适用于uni-app框架中webview组件和H5通信的js小工具。此JS是放在H5项目中的;还需要配合uni-app另外封装的webview组件;uni-app的webview组件会放在另一个项目中;

安装

执行以下安装命令

npm i uni-js-bridge --save

or

yarn add uni-js-bridge

使用方法

以vue项目为例子

在main.js中引入uni-js-bridge

import 'uni-js-bridge'

在publick/index.html中加入以下代码

<script type="text/javascript">
    var userAgent = navigator.userAgent;
    if (userAgent.indexOf('AlipayClient') > -1) {
        // 支付宝小程序的 JS-SDK 防止 404 需要动态加载,如果不需要兼容支付宝小程序,则无需引用此 JS 文件。
        document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');
    } else if (/QQ/i.test(userAgent) && /miniProgram/i.test(userAgent)) {
        // QQ 小程序
        document.write(
            '<script type="text/javascript" src="https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"><\/script>',
        );
    } else if (/miniProgram/i.test(userAgent) || /MicroMessenger/i.test(userAgent)) {
        // 微信小程序 JS-SDK 如果不需要兼容微信小程序,则无需引用此 JS 文件。
        document.write('<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"><\/script>');
    } else if (/toutiaomicroapp/i.test(userAgent)) {
        // 字节跳动小程序 JS-SDK 如果不需要兼容字节跳动小程序,则无需引用此 JS 文件。
        document.write(
            '<script type="text/javascript" src="https://s3.pstatp.com/toutiao/tmajssdk/jssdk-1.0.1.js"><\/script>');
    } else if (/swan/i.test(userAgent)) {
        // 百度小程序 JS-SDK 如果不需要兼容百度小程序,则无需引用此 JS 文件。
        document.write(
            '<script type="text/javascript" src="https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.18.js"><\/script>',
        );
    }
    // if (!/toutiaomicroapp/i.test(userAgent)) {
    //     document.querySelector('.post-message-section').style.visibility = 'visible';
    // }
</script>
<!-- uni 的 SDK -->
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>

使用方法说明

注意:这里使用方法是需要uni-app端那边配合的

先看看H5是如何触发uni-app的函数的

首先在uni-app端中需要先注册一个函数提供给H5调用,代码如下:

this.$refs.webViewBridge.registerHandler('nativeShow', (data, callbackFunction) => {
    // data: h5给客户端的参数
    uni.showToast({
        title: 'nativeShow' + JSON.stringify(data),
        icon: 'none'
    })

    // 调用此函数,触发H5回调,里面的参数是给H5用的
    // 注意,如果不调用callbackFunction那么H5就无法触发回调函数
    callbackFunction({
        toH5Data: '这里的参数是提供给H5的回调函数的'    // key是可以随便取的
    })
})

那么在我们H5端需要按如下方法使用:

UniJsBridge.callHandler(
    "nativeShow",    // 注意这里的名字必须和上面的对应上
    { nativeShowData: "nativeShow" },    // 这个参数是传递给uni-app的
    res => {
        // res:就是上面的callbackFunction的参数
        // 注意:如果uni-app不调用callbackFunction,那么这个回调函数是不会执行
        alert(JSON.stringify(res));
    }
);

然后看看uni-app如何触发H5的函数的

首先在H5中注册一个函数

UniJsBridge.registerHandler("test", (data, responseCallback) => {
    setTimeout(() => {
        // data: 是客户端给H5的参数
        alert(JSON.stringify(data));

        // 把参数传递给客户端,如果不执行的话,uni-app是无法执行回调的
        responseCallback('我是给uni-app的参数');
    }, 2000);
});

然后在uni-app中

this.$refs.webViewBridge.callHandler(
    'test',
    { toH5Data: '33333' },
    function(data) {
        uni.showToast({
            title: '哈哈' + data
        })
    }
);

[^整个库其实就是这个两个核心API,用这个两个API就可以完成H5和uni-app的通信了;以下提供几个可能也用的上的API]:

你也可以在uniapp中设置一个默认的处理函数,给H5调用(其实就是registerHandler,只不过省略了一个参数而已)

首先uni-app端代码

this.$refs.webViewBridge.setDefaultHandler((data, callHandler) => {
    uni.showToast({
        title: 'send' + JSON.stringify(data),
        icon: 'none'
    })

    callHandler({
        send: '给H5的'
    })
})

h5端代码

UniJsBridge.send({ sendData: "给uni-app的" }, res => {
    alert(JSON.stringify(res));
});

在H5端配置一个默认处理函数,提供给uni-app调用

h5端代码

UniJsBridge.init((data, responseCallback) => {
    alert(JSON.stringify(data));

    responseCallback({
        initData: "给uni-app使用的",
    });
});

uni-app端:可以调用多次,H5端会按队列依次处理

this.$refs.webViewBridge.send({
    fff: '1000.0'
}, function(data) {
    uni.showToast({
        title: 'send' + JSON.stringify(data),
        icon: 'none'
    })
})

处理uni-app的路由

具体文档参照:https://uniapp.dcloud.io/api/router

UniJsBridge.uni.navigateTo()
UniJsBridge.uni.redirectTo()
UniJsBridge.uni.reLaunch()
UniJsBridge.uni.switchTab()
UniJsBridge.uni.navigateBack()

获取当前环境

UniJsBridge.uni.getEnv()

uni-app的webview封装

封装了一下webview组件,再配合uni-js-bridge的npm包可以实现webview和h5双向通信;

使用

代码拉下来跑一下:看一下pages/index/index的例子,封装的组件在web-view-bridge中;

前端页面写在了hybrid/html文件夹

git clone https://gitee.com/guome/uni-webview-bridge.git

文档暂时先参考:https://gitee.com/guome/uni-js-bridge

约定

约定两端通信格式(不管是H5给uni,还是uni给h5都应该是这样的格式)

{
    code: 0,    // 状态码:0表示成功,其他的失败
    data: '返回的数据',    // 真正的返回数据
    msg: 'success'        // 提示信息
}

关于ajax请求

在uni-app项目中,即使是本地html也不会发生跨域问题;所以不需要封装ajax的转发

发表评论