'use strict' // Promise ES6 polyfill https://github.com/taylorhakes/promise-polyfill, 如果此polyfill依然无法满足需求,那么可以引入https://github.com/stefanpenner/es6-promise !(function(e) { function n() {} function t(e, n) { return function() { e.apply(n, arguments) } } function o(e) { if ('object' != typeof this) throw new TypeError('Promises must be constructed via new') if ('function' != typeof e) throw new TypeError('not a function') ;(this._state = 0), (this._handled = !1), (this._value = void 0), (this._deferreds = []), s(e, this) } function i(e, n) { for (; 3 === e._state; ) e = e._value return 0 === e._state ? void e._deferreds.push(n) : ((e._handled = !0), void o._immediateFn(function() { var t = 1 === e._state ? n.onFulfilled : n.onRejected if (null === t) return void (1 === e._state ? r : u)(n.promise, e._value) var o try { o = t(e._value) } catch (i) { return void u(n.promise, i) } r(n.promise, o) })) } function r(e, n) { try { if (n === e) throw new TypeError('A promise cannot be resolved with itself.') if (n && ('object' == typeof n || 'function' == typeof n)) { var i = n.then if (n instanceof o) return (e._state = 3), (e._value = n), void f(e) if ('function' == typeof i) return void s(t(i, n), e) } ;(e._state = 1), (e._value = n), f(e) } catch (r) { u(e, r) } } function u(e, n) { ;(e._state = 2), (e._value = n), f(e) } function f(e) { 2 === e._state && 0 === e._deferreds.length && o._immediateFn(function() { e._handled || o._unhandledRejectionFn(e._value) }) for (var n = 0, t = e._deferreds.length; n < t; n++) i(e, e._deferreds[n]) e._deferreds = null } function c(e, n, t) { ;(this.onFulfilled = 'function' == typeof e ? e : null), (this.onRejected = 'function' == typeof n ? n : null), (this.promise = t) } function s(e, n) { var t = !1 try { e( function(e) { t || ((t = !0), r(n, e)) }, function(e) { t || ((t = !0), u(n, e)) } ) } catch (o) { if (t) return ;(t = !0), u(n, o) } } var a = setTimeout ;(o.prototype['catch'] = function(e) { return this.then(null, e) }), (o.prototype.then = function(e, t) { var o = new this.constructor(n) return i(this, new c(e, t, o)), o }), (o.all = function(e) { var n = Array.prototype.slice.call(e) return new o(function(e, t) { function o(r, u) { try { if (u && ('object' == typeof u || 'function' == typeof u)) { var f = u.then if ('function' == typeof f) return void f.call( u, function(e) { o(r, e) }, t ) } ;(n[r] = u), 0 === --i && e(n) } catch (c) { t(c) } } if (0 === n.length) return e([]) for (var i = n.length, r = 0; r < n.length; r++) o(r, n[r]) }) }), (o.resolve = function(e) { return e && 'object' == typeof e && e.constructor === o ? e : new o(function(n) { n(e) }) }), (o.reject = function(e) { return new o(function(n, t) { t(e) }) }), (o.race = function(e) { return new o(function(n, t) { for (var o = 0, i = e.length; o < i; o++) e[o].then(n, t) }) }), (o._immediateFn = ('function' == typeof setImmediate && function(e) { setImmediate(e) }) || function(e) { a(e, 0) }), (o._unhandledRejectionFn = function(e) { 'undefined' != typeof console && console && console.warn('Possible Unhandled Promise Rejection:', e) }), (o._setImmediateFn = function(e) { o._immediateFn = e }), (o._setUnhandledRejectionFn = function(e) { o._unhandledRejectionFn = e }), 'undefined' != typeof module && module.exports ? (module.exports = o) : e.Promise || (e.Promise = o) })(this) function appCallBack() {} ;(function(window) { if (window.EWebBridge) { return } // 初始化App桥接环境 function setupWebViewJavascriptBridge(callback) { // Android 调用 if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady', function() { callback(WebViewJavascriptBridge) }, false ) } // iOS使用 if (navigator.userAgent.indexOf('iPhone') != -1) { // WebViewJavascriptBridge v6 if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge) } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback) } window.WVJBCallbacks = [callback] var WVJBIframe = document.createElement('iframe') WVJBIframe.style.display = 'none' WVJBIframe.src = 'https://__bridge_loaded__' document.documentElement.appendChild(WVJBIframe) setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) } } // App桥接调用初始化 setupWebViewJavascriptBridge(function(bridge) { bridge.registerHandler('appCallWebInJs', function(data, responseCallback) { try { data = JSON.parse(data) //业务逻辑放在这里; appCallBack(data, true) responseCallback('{"code": "0","message": "success"}') } catch (e) { appCallBack({}, false) responseCallback('{"code": "1","message": "App调用JS异常:"' + e + '"}') } }) }) // H5 & webapp 调用APP,并返回一个Promise对象 function triggerCallHandler(method, params) { return new Promise(function(resolve) { WebViewJavascriptBridge.callHandler(method, params, function(response) { resolve(response) }) }) } //解析url参数 function getQuery() { var query = window.location.href.split('?') query = query.length > 1 ? query[1].split('&') : [] var json = {} for (var i = 0, len = query.length; i < len; i++) { var key = query[i].split('=')[0], index = query[i].indexOf('='), value = query[i].substr(index + 1) json[key] = value } return json } // 初始化SDK var EWebBridge = (window.EWebBridge = { webCallAppInJs: function(method, params, debugCallback) { // params --> Mixed (json对象 {"a":"123","b":"200"} 或 null 或其他形式的参数,具体根据和app端的约定来) method = method || 'getUserToken' params = params || null var queryParam = getQuery() if (queryParam.workinapp == 1) { return triggerCallHandler(method, params) } else { debugCallback && typeof debugCallback === 'function' && debugCallback() } } }) })(window) //notation: js file can only use this kind of comments //since comments will cause error when use in webview.loadurl, //comments will be remove by java use regexp ;(function() { //If iPhone Call it, then return if (window.WebViewJavascriptBridge || navigator.userAgent.indexOf('iPhone') != -1) { return } var messagingIframe var sendMessageQueue = [] var receiveMessageQueue = [] var messageHandlers = {} var CUSTOM_PROTOCOL_SCHEME = 'yy' var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/' var responseCallbacks = {} var uniqueId = 1 function _createQueueReadyIframe(doc) { messagingIframe = doc.createElement('iframe') messagingIframe.style.display = 'none' doc.documentElement.appendChild(messagingIframe) } //set default messageHandler function init(messageHandler) { if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') } WebViewJavascriptBridge._messageHandler = messageHandler var receivedMessages = receiveMessageQueue receiveMessageQueue = null for (var i = 0; i < receivedMessages.length; i++) { _dispatchMessageFromNative(receivedMessages[i]) } } function send(data, responseCallback) { _doSend( { data: data }, responseCallback ) } function registerHandler(handlerName, handler) { messageHandlers[handlerName] = handler } function callHandler(handlerName, data, responseCallback) { _doSend( { handlerName: handlerName, data: data }, responseCallback ) } //sendMessage add message, 触发native处理 sendMessage function _doSend(message, responseCallback) { if (responseCallback) { var callbackId = 'cb_' + uniqueId++ + '_' + new Date().getTime() responseCallbacks[callbackId] = responseCallback message.callbackId = callbackId } sendMessageQueue.push(message) messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE } // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容 function _fetchQueue() { var messageQueueString = JSON.stringify(sendMessageQueue) sendMessageQueue = [] //android can't read directly the return data, so we can reload iframe src to communicate with java messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString) } //提供给native使用, function _dispatchMessageFromNative(messageJSON) { setTimeout(function() { var message = JSON.parse(messageJSON) var responseCallback //java call finished, now need to call js callback function if (message.responseId) { responseCallback = responseCallbacks[message.responseId] if (!responseCallback) { return } responseCallback(message.responseData) delete responseCallbacks[message.responseId] } else { //直接发送 if (message.callbackId) { var callbackResponseId = message.callbackId responseCallback = function(responseData) { _doSend({ responseId: callbackResponseId, responseData: responseData }) } } var handler = WebViewJavascriptBridge._messageHandler if (message.handlerName) { handler = messageHandlers[message.handlerName] } //查找指定handler try { handler(message.data, responseCallback) } catch (exception) { if (typeof console != 'undefined') { console.log('WebViewJavascriptBridge: WARNING: javascript handler threw.', message, exception) } } } }) } //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以 function _handleMessageFromNative(messageJSON) { console.log(messageJSON) if (receiveMessageQueue && receiveMessageQueue.length > 0) { receiveMessageQueue.push(messageJSON) } else { _dispatchMessageFromNative(messageJSON) } } var WebViewJavascriptBridge = (window.WebViewJavascriptBridge = { init: init, send: send, registerHandler: registerHandler, callHandler: callHandler, _fetchQueue: _fetchQueue, _handleMessageFromNative: _handleMessageFromNative }) var doc = document _createQueueReadyIframe(doc) var readyEvent = doc.createEvent('Events') readyEvent.initEvent('WebViewJavascriptBridgeReady') readyEvent.bridge = WebViewJavascriptBridge doc.dispatchEvent(readyEvent) })()