【uni-app】App与webview双向实时通信
在 Uniapp 中,App 与 里面嵌入的 webview 进行双向的实时通信
vue2 , 模拟器
主要分为两部分
- webview 向 app 发送信息
- app 向 webview 发送信息
以下是实现方式,用一个例子来说明
(文章最后我会放这个例子的github地址)
webview 向 app 发送信息
示例: webview 里面向 app 发送 图片的 base64 , app 保存图片到系统相册;
此处分为, app 和 webview 部分:
- app 注册事件
- webview 触发 app 的事件
app部分
- 保存到系统相册功能(功能具体细节不重要)
// utils/appMessageHandler.js// 这里代码都在app下执行functionappSaveImgFile(params){const{ base64, downloadName }= params const bitmap =newplus.nativeObj.Bitmap("test"); bitmap.loadBase64Data( base64,function(){const url ="_doc/"+ downloadName +".png";// url为时间戳命名方式 bitmap.save( url,{overwrite:true,// 是否覆盖// quality: 'quality' // 图片清晰度},(i)=>{ plus.gallery.save( i.target,function(){ uni.showToast({title:"APP图片保存至相册",icon:"none",}); bitmap.clear();},function(e){ uni.showToast({title:"APP图片保存至相册失败:"+JSON.stringify(e),icon:"none",}); bitmap.clear();});},(e)=>{ uni.showToast({title:"图片保存失败1:"+JSON.stringify(e),icon:"none",}); bitmap.clear();});},(e)=>{ uni.showToast({title:"图片保存失败2:"+JSON.stringify(e),icon:"none",}); bitmap.clear();});}export{ appSaveImgFile,}
- 在App.vue中注册事件;将 appMessageHandle.js 里面所有导出的事件进行注册;注意需要条件编译
// App.vue<script>import*as appPlusMessageHandler from"./utils/appMessageHandler";exportdefault{data(){return{appRegisterMap:undefined,};},onLaunch:function(){ console.log("App Launch");// #ifdef APP-PLUS// 注册事件 plus.globalEvent.addEventListener("plusMessage",this.plusMessageHandler);// #endif},methods:{/** * 将所有导出的 app 事件 * 用 map 建立 函数名 - 函数 的联系 * 返回 map */registerAppPlusMap(){if(this.appRegisterMap){returnthis.appRegisterMap;}let map =newMap(); Object.keys(appPlusMessageHandler).forEach((item)=>{ map.set(item, appPlusMessageHandler[item]);});this.appRegisterMap = map;return map;},/** * 用 action 获取的函数名 * 通过 map 获取到函数,调用执行 */plusMessageHandler(msg){let map =this.registerAppPlusMap();if(msg.data.args.data.arg?.action){let handler = map.get(msg.data.args.data.arg?.action);let params = msg.data.args.data.arg?.params; handler &&handler(params);}},},};</script>
webview 部分
通过使用 uni.webview.js (文末附录放源码,我做了些许修改,逻辑没改,是一些变量调整了下) 的功能 postMessage , 向 app 发送图片生成的 base64;
- main.js 中挂载 uWeb (uni.webview.js)
// main.js// 全局添加uWeb// #ifdef H5import uWeb from"@/utils/uni.webview.js";// #endif// #ifdef H5Vue.prototype.$uWeb = uWeb;// #endif
- 生成的图片base64,通过以下方式发送给 app此处 action 与 上面 plusMessageHandler方法的 action 是对应的****appSaveImgFile 与 appMessageHandler.js 里的函数名是对应的
// 某个页面或者jsthis.$uWeb.postMessage({data:{action:"appSaveImgFile",params:{base64: imgBase64, downloadName,},},});
至此,webview 能随时向 app 发送消息了
App 向 webview 发送消息
使用 evalJS
分两步:
- webview 在 window 注册事件
- app 使用 evalJs 触发 webview 的事件
注意: 确保webview 先注册好事件之后,app发送的事件才能被 webview 接收到
具体实现,utils下新建appToWebview.js; appSendMessage 是给 App 用的;webviewGetMessage 是给 webview 注册用的
// appToWebview.js// 发送信息之前,先要有 webviewGetMessagefunctionappSendMessage(_this, action, params){const self = _this;
self.currentWebview = self.$scope?.$getAppWebview()?.children()[0];//传递大量数据
self.currentWebview?.evalJS(`${action}(${JSON.stringify(params)})`);}functionwebviewGetMessage(action, callback){// #ifdef H5
window[action]=(data)=>{let params =JSON.parse(JSON.stringify(data));callback(params);};// #endif}export{ appSendMessage, webviewGetMessage };
webview 部分
用 webviewGetMessage 注册一个 msgFromApp 名字的事件,给 App 调用;
// 某个 webview 页面,created(){webviewGetMessage("msgFromApp",(params)=>{
console.log("getAppParams", params);this.appMsg = params;});},
App
用 appSendMessage 发送一个信息给 webview
// 某个有 webview 的 app 页面,mounted(){setTimeout(()=>{appSendMessage(this,"msgFromApp",{msgFromApp:233});},5000);},
至此,完成了 app 向 webview 发送信息
GitHub 地址
GitHub - adcGG/uniapp-app-webview: Communication between app and webview
这里 uniapp 项目,app 和 用到的 h5 地址是同一个项目下的
app/index 用到的 webview 的 url 为 webviewUrl: “http://192.168.1.16:8080/#/pages/h5/index”,
附录
uni.webview.js
!(function(e, n){"object"==typeof exports &&"undefined"!=typeof module
?(module.exports =n()):"function"==typeof define && define.amd
?define(n):((e = e || self).webUni =n());})(this,function(){"use strict";try{var e ={};
Object.defineProperty(e,"passive",{get:function(){!0;},}),
window.addEventListener("test-passive",null, e);}catch(e){}var n =Object.prototype.hasOwnProperty;functiont(e, t){returnn.call(e, t);}var i =[],a=function(e, n){var t ={options:{timestamp:+newDate(),},name: e,arg: n,};if(window.__dcloud_weex_postMessage || window.__dcloud_weex_){if("postMessage"=== e){var a ={data:[n],};return window.__dcloud_weex_postMessage
? window.__dcloud_weex_postMessage(a): window.__dcloud_weex_.postMessage(JSON.stringify(a));}var o ={type:"WEB_INVOKE_APPSERVICE",args:{data: t,webviewIds: i,},};
window.__dcloud_weex_postMessage
? window.__dcloud_weex_postMessageToService(o): window.__dcloud_weex_.postMessageToService(JSON.stringify(o));}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data: t,pageId:"",},"*");if(0=== i.length){var r = plus.webview.currentWebview();if(!r)thrownewError("plus.webview.currentWebview() is undefined");var d = r.parent(),
s ="";(s = d ? d.id : r.id), i.push(s);}if(plus.webview.getWebviewById("__uniapp__service"))
plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data: t,webviewIds: i,},},"__uniapp__service");else{var w =JSON.stringify(t);
plus.webview
.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"));}},
o ={navigateTo:function(){var e =
arguments.length >0&&void0!== arguments[0]? arguments[0]:{},
n = e.url;a("navigateTo",{url:encodeURI(n),});},navigateBack:function(){var e =
arguments.length >0&&void0!== arguments[0]? arguments[0]:{},
n = e.delta;a("navigateBack",{delta:parseInt(n)||1,});},switchTab:function(){var e =
arguments.length >0&&void0!== arguments[0]? arguments[0]:{},
n = e.url;a("switchTab",{url:encodeURI(n),});},reLaunch:function(){var e =
arguments.length >0&&void0!== arguments[0]? arguments[0]:{},
n = e.url;a("reLaunch",{url:encodeURI(n),});},redirectTo:function(){var e =
arguments.length >0&&void0!== arguments[0]? arguments[0]:{},
n = e.url;a("redirectTo",{url:encodeURI(n),});},getEnv:function(e){
window.plus
?e({plus:!0,}):e({h5:!0,});},postMessage:function(){var e =
arguments.length >0&&void0!== arguments[0]? arguments[0]:{};a("postMessage", e.data ||{});},},
r =/uni-app/i.test(navigator.userAgent),
d =/Html5Plus/i.test(navigator.userAgent),
s =/complete|loaded|interactive/;var w = window.my && navigator.userAgent.indexOf("AlipayClient")>-1;var u =
window.swan && window.swan.webView &&/swan/i.test(navigator.userAgent);var c =
window.qq &&
window.qq.miniProgram &&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g =
window.tt &&
window.tt.miniProgram &&/toutiaomicroapp/i.test(navigator.userAgent);var v =
window.wx &&
window.wx.miniProgram &&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p = window.qa &&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){(window.UniAppJSBridge =!0),
document.dispatchEvent(newCustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0,}));},
f =[function(e){if(r || d)return(
window.__dcloud_weex_postMessage || window.__dcloud_weex_
? document.addEventListener("DOMContentLoaded", e): window.plus && s.test(document.readyState)?setTimeout(e,0): document.addEventListener("plusready", e),
o
);},function(e){if(v)return(
window.WeixinJSBridge && window.WeixinJSBridge.invoke
?setTimeout(e,0): document.addEventListener("WeixinJSBridgeReady", e),
window.wx.miniProgram
);},function(e){if(c)return(
window.QQJSBridge && window.QQJSBridge.invoke
?setTimeout(e,0): document.addEventListener("QQJSBridgeReady", e),
window.qq.miniProgram
);},function(e){if(w){
document.addEventListener("DOMContentLoaded", e);var n = window.my;return{navigateTo: n.navigateTo,navigateBack: n.navigateBack,switchTab: n.switchTab,reLaunch: n.reLaunch,redirectTo: n.redirectTo,postMessage: n.postMessage,getEnv: n.getEnv,};}},function(e){if(u)return(
document.addEventListener("DOMContentLoaded", e),
window.swan.webView
);},function(e){if(g)return(
document.addEventListener("DOMContentLoaded", e),
window.tt.miniProgram
);},function(e){if(p){
window.QaJSBridge && window.QaJSBridge.invoke
?setTimeout(e,0): document.addEventListener("QaJSBridgeReady", e);var n = window.qa;return{navigateTo: n.navigateTo,navigateBack: n.navigateBack,switchTab: n.switchTab,reLaunch: n.reLaunch,redirectTo: n.redirectTo,postMessage: n.postMessage,getEnv: n.getEnv,};}},function(e){return document.addEventListener("DOMContentLoaded", e), o;},],
m =0;
m < f.length &&!(l = f[m](_));
m++);
l ||(l ={});varE="undefined"!=typeof webUni ? webUni :{};if(!E.navigateTo)for(var b in l)t(l, b)&&(E[b]= l[b]);return(E.webView = l),E;});
版权归原作者 智能คิดถึง 所有, 如有侵权,请联系我们删除。