├── .gitignore ├── LICENSE ├── ZJsBridge-JsHandlerImpl-Image ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hcanyz │ │ └── zjsbridge │ │ └── jshandlerimpl │ │ └── image │ │ └── ImageJsHandler.kt │ └── res │ └── xml │ └── provider_paths.xml ├── ZJsBridge ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── jsapi │ │ └── zfjs.js │ └── java │ └── com │ └── hcanyz │ └── zjsbridge │ ├── ZJsBridge.kt │ ├── bridge │ ├── ZBridgeMessage.kt │ ├── ZJavascriptInterface.kt │ ├── ZJsCallBacker.kt │ └── ZJsEventer.kt │ ├── cotainer │ ├── IZWebView.kt │ ├── IZWebViewContainer.kt │ └── ZWebHelper.kt │ ├── handler │ ├── IZJsApiHandler.kt │ ├── ZBaseJsApiHandler.kt │ └── ZCommonJsHandler.kt │ └── util │ └── ZUtils.kt ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── css │ │ └── app.00e3d0b7.css │ ├── favicon.ico │ ├── index.html │ └── js │ │ ├── app.a2ee3b8d.js │ │ ├── app.a2ee3b8d.js.map │ │ ├── chunk-689084fa.19f2e525.js │ │ ├── chunk-689084fa.19f2e525.js.map │ │ ├── chunk-b1b79330.528aee60.js │ │ ├── chunk-b1b79330.528aee60.js.map │ │ ├── chunk-vendors.6616e6fe.js │ │ └── chunk-vendors.6616e6fe.js.map │ ├── java │ └── com │ │ └── hcanyz │ │ └── zjsbridge │ │ └── test │ │ ├── MainActivity.kt │ │ ├── chromium │ │ ├── ChromiumWebViewJava.java │ │ └── TestWebViewActivity.kt │ │ ├── fragment │ │ ├── ChromiumWebView.kt │ │ ├── TestInFragmentActivity.kt │ │ └── TestWebViewFragment.kt │ │ ├── test │ │ └── TestJsHandler.kt │ │ └── x5 │ │ ├── TestX5WebViewActivity.kt │ │ └── X5WebView.kt │ └── res │ ├── layout │ ├── activity_main.xml │ ├── activity_test_in_fragment.xml │ ├── activity_test_web_view.xml │ ├── activity_test_x5_web_view.xml │ └── fragmenttest_web_view.xml │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── network_security_config.xml ├── build.gradle ├── dependencies.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── readme-jssdk-api.md ├── readme-nativeResourceUrl.md ├── readme-protocol.md ├── readme.md └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea 6 | .DS_Store 7 | /build 8 | /build/generated 9 | /build/intermediates 10 | /build/outputs 11 | /build/ 12 | /captures 13 | .externalNativeBuild 14 | /install.md 15 | /z_rawfile/assemble_back/pre_release 16 | /z_rawfile/assemble_back/debug 17 | /z_rawfile/assemble_back/quarytest 18 | /z_rawfile/assemble_back/highcopytest 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 hcanyz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ZJsBridge-JsHandlerImpl-Image/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ZJsBridge-JsHandlerImpl-Image/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android deps.gradleConfig.simpleAndroid(project) 8 | 9 | dependencies { 10 | implementation fileTree(dir: 'libs', include: ['*.jar']) 11 | 12 | implementation project(':ZJsBridge') 13 | 14 | compileOnly deps.android.appcompat 15 | } 16 | -------------------------------------------------------------------------------- /ZJsBridge-JsHandlerImpl-Image/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | #PictureSelector 2.0 24 | -keep class com.luck.picture.lib.** { *; } 25 | 26 | -dontwarn com.yalantis.ucrop** 27 | -keep class com.yalantis.ucrop** { *; } 28 | -keep interface com.yalantis.ucrop** { *; } -------------------------------------------------------------------------------- /ZJsBridge-JsHandlerImpl-Image/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ZJsBridge-JsHandlerImpl-Image/src/main/java/com/hcanyz/zjsbridge/jshandlerimpl/image/ImageJsHandler.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.jshandlerimpl.image 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.provider.MediaStore 7 | import android.webkit.MimeTypeMap 8 | import com.hcanyz.zjsbridge.bridge.ZJsCallBacker 9 | import com.hcanyz.zjsbridge.handler.ZBaseJsApiHandler 10 | import org.json.JSONArray 11 | import org.json.JSONObject 12 | 13 | 14 | class ImageJsHandler : ZBaseJsApiHandler() { 15 | 16 | companion object { 17 | const val REQUEST_ALBUM = 10000 18 | } 19 | 20 | override fun handleApi(apiName: String, params: String, jsCallBacker: ZJsCallBacker): Boolean { 21 | when (apiName) { 22 | "choosePhotos" -> { 23 | val activity = getActivity() ?: return true 24 | val fragment = getFragment() 25 | val albumIntent = Intent(Intent.ACTION_PICK) 26 | albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*") 27 | if (fragment != null) { 28 | fragment.startActivityForResult(albumIntent, REQUEST_ALBUM) 29 | } else { 30 | activity.startActivityForResult(albumIntent, REQUEST_ALBUM) 31 | } 32 | saveJsCallBacker("choosePhotos_$REQUEST_ALBUM", jsCallBacker) 33 | return true 34 | } 35 | "previewPhotos" -> { 36 | try { 37 | val activity = getActivity() ?: return true 38 | 39 | val jsonObject = JSONObject(params) 40 | val urls = jsonObject.optJSONArray("urls") 41 | val index = jsonObject.optInt("index", 0) 42 | 43 | val intent = Intent(Intent.ACTION_VIEW) 44 | 45 | val filePath = urls.getString(index) 46 | 47 | val uri = Uri.parse(filePath) 48 | intent.setDataAndType(uri, MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(filePath))) 49 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) 50 | activity.startActivity(intent) 51 | } catch (e: Exception) { 52 | jsCallBacker.fail(ZJsCallBacker.CODE_ERR_FAIL, e.toString()) 53 | } 54 | return true 55 | } 56 | "uploadPhotos" -> { 57 | } 58 | } 59 | return false 60 | } 61 | 62 | override fun onContainerResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { 63 | when (requestCode) { 64 | REQUEST_ALBUM -> { 65 | when (resultCode) { 66 | Activity.RESULT_OK -> { 67 | val get7RemoveJsCallBacker = get7RemoveJsCallBacker("choosePhotos_$REQUEST_ALBUM") 68 | ?: return true 69 | val result = JSONArray() 70 | 71 | val item = JSONObject() 72 | item.put("nativeResourceUrl", data?.dataString ?: "") 73 | result.put(item) 74 | 75 | get7RemoveJsCallBacker.success(jsonArray = result) 76 | } 77 | } 78 | return true 79 | } 80 | } 81 | return super.onContainerResult(requestCode, resultCode, data) 82 | } 83 | } -------------------------------------------------------------------------------- /ZJsBridge-JsHandlerImpl-Image/src/main/res/xml/provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ZJsBridge/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ZJsBridge/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | group = 'com.github.hcanyz' 5 | 6 | apply plugin: 'kotlin-android' 7 | 8 | apply plugin: 'kotlin-android-extensions' 9 | 10 | android deps.gradleConfig.simpleAndroid(project) 11 | 12 | android { 13 | defaultConfig { 14 | minSdkVersion 19 15 | } 16 | } 17 | 18 | dependencies { 19 | implementation fileTree(dir: 'libs', include: ['*.jar']) 20 | 21 | compileOnly deps.android.appcompat 22 | } 23 | -------------------------------------------------------------------------------- /ZJsBridge/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | 24 | -keep class com.hcanyz.zjsbridge.bridge.ZBridgeMessage.** {*;} 25 | -keep class com.hcanyz.zjsbridge.bridge.ZJavascriptInterface.** {*;} 26 | -------------------------------------------------------------------------------- /ZJsBridge/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ZJsBridge/src/main/assets/jsapi/zfjs.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | //--- util 3 | 4 | var __DL = 0, __IL = 1, __EL = 2, __LogLvl = parseInt("${_debugLevel}") || __DL 5 | var __LogArr = ["start"] 6 | function __Log(lvl) { 7 | __LogArr.push(arguments) 8 | if (lvl >= __LogLvl) { 9 | window.console && window.console.log.apply(console, Array.prototype.slice.call(arguments, 1)) 10 | } 11 | } 12 | 13 | var CryptoJS = CryptoJS || function (e, m) { 14 | var p = {}, 15 | j = p.lib = {}, 16 | l = function () { }, 17 | f = j.Base = { 18 | extend: function (a) { 19 | l.prototype = this 20 | var c = new l 21 | a && c.mixIn(a) 22 | c.hasOwnProperty("init") || (c.init = function () { 23 | c.$super.init.apply(this, arguments) 24 | }) 25 | c.init.prototype = c 26 | c.$super = this 27 | return c 28 | }, 29 | create: function () { 30 | var a = this.extend() 31 | a.init.apply(a, arguments) 32 | return a 33 | }, 34 | init: function () { }, 35 | mixIn: function (a) { 36 | for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]) 37 | a.hasOwnProperty("toString") && (this.toString = a.toString) 38 | }, 39 | clone: function () { 40 | return this.init.prototype.extend(this) 41 | } 42 | }, 43 | n = j.WordArray = f.extend({ 44 | init: function (a, c) { 45 | a = this.words = a || [] 46 | this.sigBytes = c != m ? c : 4 * a.length 47 | }, 48 | toString: function (a) { 49 | return (a || h).stringify(this) 50 | }, 51 | concat: function (a) { 52 | var c = this.words, 53 | q = a.words, 54 | d = this.sigBytes 55 | a = a.sigBytes 56 | this.clamp() 57 | if (d % 4) 58 | for (var b = 0; b < a; b++) c[d + b >>> 2] |= (q[b >>> 2] >>> 24 - 8 * (b % 4) & 255) << 24 - 8 * ((d + b) % 4) 59 | else if (65535 < q.length) 60 | for (b = 0; b < a; b += 4) c[d + b >>> 2] = q[b >>> 2] 61 | else c.push.apply(c, q) 62 | this.sigBytes += a 63 | return this 64 | }, 65 | clamp: function () { 66 | var a = this.words, 67 | c = this.sigBytes 68 | a[c >>> 2] &= 4294967295 << 32 - 8 * (c % 4) 69 | a.length = e.ceil(c / 4) 70 | }, 71 | clone: function () { 72 | var a = f.clone.call(this) 73 | a.words = this.words.slice(0) 74 | return a 75 | }, 76 | random: function (a) { 77 | for (var c = [], b = 0; b < a; b += 4) c.push(4294967296 * e.random() | 0) 78 | return new n.init(c, a) 79 | } 80 | }), 81 | b = p.enc = {}, 82 | h = b.Hex = { 83 | stringify: function (a) { 84 | var c = a.words 85 | a = a.sigBytes 86 | for (var b = [], d = 0; d < a; d++) { 87 | var f = c[d >>> 2] >>> 24 - 8 * (d % 4) & 255 88 | b.push((f >>> 4).toString(16)) 89 | b.push((f & 15).toString(16)) 90 | } 91 | return b.join("") 92 | }, 93 | parse: function (a) { 94 | for (var c = a.length, 95 | b = [], d = 0; d < c; d += 2) b[d >>> 3] |= parseInt(a.substr(d, 2), 16) << 24 - 4 * (d % 8) 96 | return new n.init(b, c / 2) 97 | } 98 | }, 99 | g = b.Latin1 = { 100 | stringify: function (a) { 101 | var c = a.words 102 | a = a.sigBytes 103 | for (var b = [], d = 0; d < a; d++) b.push(String.fromCharCode(c[d >>> 2] >>> 24 - 8 * (d % 4) & 255)) 104 | return b.join("") 105 | }, 106 | parse: function (a) { 107 | for (var c = a.length, 108 | b = [], d = 0; d < c; d++) b[d >>> 2] |= (a.charCodeAt(d) & 255) << 24 - 8 * (d % 4) 109 | return new n.init(b, c) 110 | } 111 | }, 112 | r = b.Utf8 = { 113 | stringify: function (a) { 114 | try { 115 | return decodeURIComponent(escape(g.stringify(a))) 116 | } catch (c) { 117 | throw Error("Malformed UTF-8 data") 118 | } 119 | }, 120 | parse: function (a) { 121 | return g.parse(unescape(encodeURIComponent(a))) 122 | } 123 | }, 124 | k = j.BufferedBlockAlgorithm = f.extend({ 125 | reset: function () { 126 | this._data = new n.init 127 | this._nDataBytes = 0 128 | }, 129 | _append: function (a) { 130 | "string" == typeof a && (a = r.parse(a)) 131 | this._data.concat(a) 132 | this._nDataBytes += a.sigBytes 133 | }, 134 | _process: function (a) { 135 | var c = this._data, 136 | b = c.words, 137 | d = c.sigBytes, 138 | f = this.blockSize, 139 | ht = d / (4 * f), 140 | h = a ? e.ceil(ht) : e.max((ht | 0) - this._minBufferSize, 0) 141 | a = h * f 142 | d = e.min(4 * a, d) 143 | if (a) { 144 | for (var g = 0; g < a; g += f) this._doProcessBlock(b, g) 145 | g = b.splice(0, a) 146 | c.sigBytes -= d 147 | } 148 | return new n.init(g, d) 149 | }, 150 | clone: function () { 151 | var a = f.clone.call(this) 152 | a._data = this._data.clone() 153 | return a 154 | }, 155 | _minBufferSize: 0 156 | }) 157 | j.Hasher = k.extend({ 158 | cfg: f.extend(), 159 | init: function (a) { 160 | this.cfg = this.cfg.extend(a) 161 | this.reset() 162 | }, 163 | reset: function () { 164 | k.reset.call(this) 165 | this._doReset() 166 | }, 167 | update: function (a) { 168 | this._append(a) 169 | this._process() 170 | return this 171 | }, 172 | finalize: function (a) { 173 | a && this._append(a) 174 | return this._doFinalize() 175 | }, 176 | blockSize: 16, 177 | _createHelper: function (a) { 178 | return function (c, b) { 179 | return (new a.init(b)).finalize(c) 180 | } 181 | }, 182 | _createHmacHelper: function (a) { 183 | return function (b, f) { 184 | return (new s.HMAC.init(a, f)).finalize(b) 185 | } 186 | } 187 | }) 188 | var s = p.algo = {} 189 | return p 190 | }(Math); 191 | 192 | (function () { 193 | var e = CryptoJS, 194 | mt = e.lib, 195 | p = mt.WordArray, 196 | j = mt.Hasher, 197 | l = [], 198 | m = e.algo.SHA1 = j.extend({ 199 | _doReset: function () { 200 | this._hash = new p.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) 201 | }, 202 | _doProcessBlock: function (f, n) { 203 | for (var b = this._hash.words, 204 | h = b[0], g = b[1], e = b[2], k = b[3], j = b[4], a = 0; 80 > a; a++) { 205 | if (16 > a) l[a] = f[n + a] | 0 206 | else { 207 | var c = l[a - 3] ^ l[a - 8] ^ l[a - 14] ^ l[a - 16] 208 | l[a] = c << 1 | c >>> 31 209 | } 210 | c = (h << 5 | h >>> 27) + j + l[a] 211 | c = 20 > a ? c + ((g & e | ~g & k) + 1518500249) : 40 > a ? c + ((g ^ e ^ k) + 1859775393) : 60 > a ? c + ((g & e | g & k | e & k) - 1894007588) : c + ((g ^ e ^ k) - 899497514) 212 | j = k 213 | k = e 214 | e = g << 30 | g >>> 2 215 | g = h 216 | h = c 217 | } 218 | b[0] = b[0] + h | 0 219 | b[1] = b[1] + g | 0 220 | b[2] = b[2] + e | 0 221 | b[3] = b[3] + k | 0 222 | b[4] = b[4] + j | 0 223 | }, 224 | _doFinalize: function () { 225 | var f = this._data, 226 | e = f.words, 227 | b = 8 * this._nDataBytes, 228 | h = 8 * f.sigBytes 229 | e[h >>> 5] |= 128 << 24 - h % 32 230 | e[(h + 64 >>> 9 << 4) + 14] = Math.floor(b / 4294967296) 231 | e[(h + 64 >>> 9 << 4) + 15] = b 232 | f.sigBytes = 4 * e.length 233 | this._process() 234 | return this._hash 235 | }, 236 | clone: function () { 237 | var e = j.clone.call(this) 238 | e._hash = this._hash.clone() 239 | return e 240 | } 241 | }) 242 | e.SHA1 = j._createHelper(m) 243 | e.HmacSHA1 = j._createHmacHelper(m) 244 | })() 245 | 246 | var zfHelper = { 247 | isIOS: function () { 248 | let reg = /iphone|ipad|ipod/i 249 | if (reg.test(window.navigator.userAgent)) { return true } else { return false } 250 | }, 251 | b64DecodeUnicode: function (str) { 252 | // Going backwards: from bytestream, to percent-encoding, to original string. 253 | return decodeURIComponent(atob(str).split('').map(function(c) { 254 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 255 | }).join('')); 256 | } 257 | } 258 | 259 | //--- core 260 | 261 | var __zf 262 | if (zfHelper.isIOS()) { 263 | if (window.webkit && window.webkit.messageHandlers) { 264 | __zf = window.webkit.messageHandlers 265 | } 266 | if (!__zf) return "inject err: __zf not found" 267 | delete window.webkit.messageHandlers 268 | } else { 269 | __zf = window.__zf 270 | if (!__zf) return "inject err: __zf not found" 271 | delete window.__zf 272 | } 273 | 274 | if (__DL >= __LogLvl) 275 | __Log(__DL, "inject start") 276 | 277 | var injectStartTime = Date.now() 278 | 279 | var _callback_count = 1000, 280 | _callback_map = {}, 281 | _MESSAGE_TYPE = 'msgType', 282 | _CALLBACK_ID = 'callbackId', 283 | 284 | _EVENT_NAME = 'eventName', 285 | _event_map = {} 286 | 287 | //客户端注入时替换 288 | var _dgtVerifyRandomStr = "${_dgtVerifyRandomStr}" 289 | 290 | var _JSON_MESSAGE = 'jsonMessage', 291 | _SHA_KEY = 'shaKey', 292 | _xxyy = _dgtVerifyRandomStr 293 | 294 | if (__DL >= __LogLvl) 295 | __Log(__DL, "__zf inject VerifyRandomStr:" + _xxyy) 296 | 297 | //防止方法被替换 298 | var _handleMessageIdentifier = _handleMessageFromZF; 299 | var _callIdentifier = _call; 300 | 301 | /** 302 | * H5调用Native方法 303 | */ 304 | function _sendMessage(msg) { 305 | var msgStr = JSON.stringify(msg) 306 | 307 | var arr = new Array 308 | arr[0] = msgStr 309 | arr[1] = _xxyy 310 | var str = arr.join("") 311 | var msgSha = '' 312 | 313 | var shaObj = CryptoJS.SHA1(str) 314 | msgSha = shaObj.toString() 315 | 316 | var retMap = {} 317 | retMap[_JSON_MESSAGE] = msgStr 318 | retMap[_SHA_KEY] = msgSha 319 | msgStr = JSON.stringify(retMap) 320 | 321 | _doSendMessage(msgStr) 322 | } 323 | 324 | function _doSendMessage(msgStr) { 325 | if (__DL >= __LogLvl) 326 | __Log(__DL, "_doSendMessage , msgStr : " + msgStr) 327 | 328 | if (zfHelper.isIOS()) { 329 | __zf._sendMessage.postMessage(msgStr) 330 | } else { 331 | __zf._sendMessage(msgStr) 332 | } 333 | } 334 | 335 | /** 336 | * Native调用 337 | */ 338 | function _handleMessageFromZF(msgStr) { 339 | var curFuncIdentifier = ___zfJSBridge._handleMessageFromZF 340 | if (curFuncIdentifier !== _handleMessageIdentifier) { 341 | return '{}' 342 | } 343 | 344 | var msg = JSON.parse(msgStr) 345 | 346 | var msgWrapStr = zfHelper.b64DecodeUnicode(msg[_JSON_MESSAGE]) 347 | var msgWrap = JSON.parse(msgWrapStr) 348 | var shaStr = msg[_SHA_KEY] 349 | var arr = new Array 350 | arr[0] = msg[_JSON_MESSAGE] 351 | arr[1] = _xxyy 352 | var str = arr.join("") 353 | var msgSha = '' 354 | var shaObj = CryptoJS.SHA1(str) 355 | msgSha = shaObj.toString() 356 | 357 | if (__DL >= __LogLvl) 358 | __Log(__DL, '_handleMessageFromZF , msgWrapStr : ' + msgWrapStr) 359 | 360 | if (msgSha !== shaStr) { 361 | if (__DL >= __LogLvl) 362 | __Log(__DL, '_handleMessageFromZF shaStr not match, shaStr : ' + shaStr + ' , str : ' + str + ' , msgSha : ' + msgSha) 363 | return '{}' 364 | } 365 | 366 | switch (msgWrap[_MESSAGE_TYPE]) { 367 | case 'callback': { 368 | if (typeof msgWrap[_CALLBACK_ID] === 'string' && typeof _callback_map[msgWrap[_CALLBACK_ID]] === 'function') { 369 | var callBackRet = _callback_map[msgWrap[_CALLBACK_ID]](msgWrap['params']) 370 | delete _callback_map[msgWrap[_CALLBACK_ID]]; 371 | 372 | var hasRet = callBackRet != undefined 373 | callBackRet = callBackRet || {} 374 | callBackRet['errCode'] = callBackRet['errCode'] || 0 375 | 376 | var callBackRetStr = JSON.stringify(callBackRet) 377 | 378 | if (__DL >= __LogLvl && hasRet) 379 | __Log(__DL, "_handleMessageFromZF , callBackRetStr : " + callBackRetStr) 380 | return callBackRetStr 381 | } 382 | return JSON.stringify({ 383 | 'errCode': '404' 384 | }) 385 | } 386 | case 'event': { 387 | if (typeof _event_map[msgWrap[_EVENT_NAME]] === 'function') { 388 | var eventRet = _event_map[msgWrap[_EVENT_NAME]](msgWrap['params']) 389 | 390 | var hasRet = callBackRet != undefined 391 | eventRet = eventRet || {} 392 | eventRet['errCode'] = eventRet['errCode'] || 0 393 | 394 | var eventRetStr = JSON.stringify(eventRet) 395 | 396 | if (__DL >= __LogLvl && hasRet) 397 | __Log(__DL, "_handleMessageFromZF , eventRetStr : " + eventRetStr) 398 | return eventRetStr 399 | } 400 | 401 | return JSON.stringify({ 402 | 'errCode': '404' 403 | }) 404 | } 405 | } 406 | 407 | return JSON.stringify({ 408 | 'errCode': '404' 409 | }) 410 | } 411 | 412 | /** 413 | * js-sdk调用bridge方法 414 | * @param {String} apiName 415 | * @param {Any} params 416 | * @param {(result)->Unit?} callBack 417 | */ 418 | function _call(apiName, params, callback) { 419 | var curFuncIdentifier = ___zfJSBridge.call 420 | if (curFuncIdentifier !== _callIdentifier) { 421 | return 422 | } 423 | 424 | if (!apiName || typeof apiName !== 'string') { 425 | return 426 | } 427 | if (typeof params !== 'object') { 428 | params = {} 429 | } 430 | 431 | var callbackID = (_callback_count++).toString() 432 | 433 | if (typeof callback === 'function') { 434 | _callback_map[callbackID] = callback 435 | } 436 | 437 | var msgObj = { 438 | 'apiName': apiName, 439 | 'params': params 440 | } 441 | msgObj[_MESSAGE_TYPE] = 'call' 442 | msgObj[_CALLBACK_ID] = callbackID 443 | 444 | try { 445 | _sendMessage(msgObj) 446 | } catch (e) { 447 | __Log(__EL, "_call error", e) 448 | } 449 | } 450 | 451 | function _on(eventName, callback) { 452 | if (__DL >= __LogLvl) 453 | __Log(__DL, "_on event ,eventName : " + eventName + " callback : " + callback) 454 | 455 | if (!eventName || typeof eventName !== 'string') { 456 | return 457 | } 458 | 459 | if (typeof callback !== 'function') { 460 | return 461 | } 462 | 463 | _event_map[eventName] = callback 464 | } 465 | 466 | var ___zfJSBridge = { 467 | // public 468 | call: _call, 469 | on: _on, 470 | // log: _log, 471 | // private 472 | _hasInit: false 473 | } 474 | 475 | try { 476 | Object.defineProperty(___zfJSBridge, '_handleMessageFromZF', { 477 | value: _handleMessageFromZF, 478 | writable: false, 479 | configurable: false 480 | }); 481 | } catch (e) { 482 | __Log(__EL, "define _handleMessageFromZF", e) 483 | return "zfJSBridge init err:" + e.message 484 | } 485 | 486 | try { 487 | Object.defineProperty(window, 'zfJSBridge', { 488 | value: ___zfJSBridge, 489 | writable: false, 490 | configurable: false 491 | }) 492 | } catch (e) { 493 | __Log(__EL, "define zfJSBridge", e) 494 | return "inject err:" + e.message 495 | } 496 | 497 | if (__DL >= __LogLvl) 498 | __Log(__IL, 'inject exec time', (Date.now() - injectStartTime)) 499 | 500 | return "inject success" 501 | }()) -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/ZJsBridge.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge 2 | 3 | import android.util.Log 4 | 5 | class ZJsBridge { 6 | companion object { 7 | var ZJS_DEBUG = false 8 | var logFun: ((msg: String?) -> Unit)? = null 9 | 10 | fun init(debug: Boolean, log: ((msg: String?) -> Unit)? = null) { 11 | ZJS_DEBUG = debug 12 | logFun = log 13 | } 14 | 15 | fun log(msg: String?) { 16 | if (ZJS_DEBUG) { 17 | val logFun = logFun 18 | if (logFun != null) { 19 | logFun(msg) 20 | return 21 | } 22 | Log.d("ZJsBridge", msg) 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/bridge/ZBridgeMessage.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.bridge 2 | 3 | import com.hcanyz.zjsbridge.ZJsBridge 4 | import com.hcanyz.zjsbridge.util.ZUtils 5 | import org.json.JSONObject 6 | 7 | data class ZBridgeMessage( 8 | var apiName: String, 9 | var params: String, 10 | var callbackId: String, 11 | var msgType: String 12 | ) { 13 | companion object { 14 | /** 15 | * 解析zfjs层请求过来的数据 16 | * 保证必要数据都是符合要求的,数据结构详见 [readme-protocol.md] 17 | * @param msg String 请求元数据 18 | * @param dgtVerifyRandomStr String 加密密钥 19 | * @return BridgeMessage 20 | */ 21 | fun parse7Check(msg: String, dgtVerifyRandomStr: String): ZBridgeMessage { 22 | try { 23 | val msgJson = JSONObject(msg) 24 | val jsonMessage = msgJson.optString("jsonMessage") 25 | // sha1(jsonMessage+_dgtVerifyRandomStr) 26 | val shaKey = msgJson.optString("shaKey") 27 | 28 | //检验数据签名不一致 29 | require(ZUtils.signatureSHA1("${jsonMessage}$dgtVerifyRandomStr") == shaKey) { "JsSendMessage parse7Check error shaKey" } 30 | 31 | val jsonMessageJson = JSONObject(jsonMessage) 32 | 33 | //require,请求的api name 34 | val apiName = jsonMessageJson.optString("apiName") 35 | requireNotNull(apiName) { "error apiName" } 36 | 37 | //require,当前请求zfjs层回调id,用于执行完成后回调 38 | val callbackId = jsonMessageJson.optString("callbackId") 39 | requireNotNull(callbackId) { "error callbackId" } 40 | 41 | //可能是 "",当前api请求携带数据 42 | val params = jsonMessageJson.optString("params", "") 43 | requireNotNull(params) { "error params" } 44 | 45 | //请求类型,预置扩展。目前一直是 "call" 46 | val msgType = jsonMessageJson.optString("msgType", "call") 47 | requireNotNull(msgType) { "error msgType" } 48 | 49 | return ZBridgeMessage(apiName, params, callbackId, msgType) 50 | } catch (e: Exception) { 51 | if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("JsSendMessage parse7Check null $msg \ndgtVerifyRandomStr: $dgtVerifyRandomStr \n e:$e") 52 | throw e 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/bridge/ZJavascriptInterface.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.bridge 2 | 3 | import android.webkit.JavascriptInterface 4 | import com.hcanyz.zjsbridge.ZJsBridge 5 | import com.hcanyz.zjsbridge.cotainer.IZWebView 6 | import java.lang.ref.WeakReference 7 | 8 | class ZJavascriptInterface(private val qWebView: IZWebView) { 9 | 10 | companion object { 11 | const val INTERFACE_NAME = "__zf" 12 | } 13 | 14 | //bridge层请求native api 参考readme-protocol.md 15 | @JavascriptInterface 16 | fun _sendMessage(msg: String?) { 17 | if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("bridge _sendMessage:$msg") 18 | 19 | if (msg != null) { 20 | try { 21 | //参考readme-protocol.md数据接口,解析成BridgeMessage对象 22 | val bridgeMessage = ZBridgeMessage.parse7Check(msg, qWebView.getCurZWebHelper().dgtVerifyRandomStr) 23 | 24 | val handler = ZJsCallBacker(bridgeMessage, izWebView = WeakReference(qWebView)) 25 | 26 | qWebView.getCurZWebHelper().dispatchExeApi(bridgeMessage.apiName, bridgeMessage.params, handler) 27 | } catch (e: Exception) { 28 | if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("_sendMessage e:$e") 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/bridge/ZJsCallBacker.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.bridge 2 | 3 | import com.hcanyz.zjsbridge.ZJsBridge 4 | import com.hcanyz.zjsbridge.cotainer.IZWebView 5 | import com.hcanyz.zjsbridge.util.ZUtils 6 | import org.json.JSONArray 7 | import org.json.JSONObject 8 | import java.lang.ref.WeakReference 9 | 10 | 11 | class ZJsCallBacker(private val bridgeMessage: ZBridgeMessage, private val izWebView: WeakReference) { 12 | 13 | companion object { 14 | const val CODE_SUCCESS = 0 //成功 15 | const val CODE_ERR_CANCEL = 1 //取消操作 16 | const val CODE_ERR_FAIL = 3 //未知错误 17 | const val CODE_ERR_INVALID = 400 //无效的请求参数 18 | const val CODE_ERR_FORBIDDEN = 403 //没有该方法的调用权限 19 | const val CODE_ERR_404 = 404 //请求的方法或者事件名没有找到 20 | } 21 | 22 | fun cancel() { 23 | val jsonObject = JSONObject() 24 | jsonObject.put("errCode", CODE_ERR_CANCEL) 25 | doHandle(jsonObject) 26 | } 27 | 28 | fun fail(errCode: Int = CODE_ERR_FAIL, errMsg: String = "") { 29 | val jsonObject = JSONObject() 30 | jsonObject.put("errCode", errCode) 31 | jsonObject.put("errMsg", errMsg) 32 | doHandle(resultObj = jsonObject) 33 | } 34 | 35 | fun success(jsonObject: JSONObject = JSONObject()) { 36 | jsonObject.put("errCode", CODE_SUCCESS) 37 | doHandle(resultObj = jsonObject) 38 | } 39 | 40 | fun success(key: String = "result", jsonArray: JSONArray) { 41 | val jsonObject = JSONObject() 42 | jsonObject.put("errCode", CODE_SUCCESS) 43 | jsonObject.put(key, jsonArray) 44 | doHandle(resultObj = jsonObject) 45 | } 46 | 47 | private fun doHandle(resultObj: JSONObject) { 48 | izWebView.get()?.let { izWebView -> 49 | try { 50 | val jsonMessage = JSONObject() 51 | 52 | jsonMessage.put("msgType", "callback") 53 | jsonMessage.put("callbackId", bridgeMessage.callbackId) 54 | jsonMessage.put("params", resultObj) 55 | 56 | val jsonMessageBase64 = ZUtils.base64Encode(jsonMessage.toString()) 57 | 58 | val shaKey = ZUtils.signatureSHA1("$jsonMessageBase64${izWebView.getCurZWebHelper().dgtVerifyRandomStr}") 59 | 60 | val toBridgeRet = JSONObject() 61 | toBridgeRet.put("jsonMessage", jsonMessageBase64) 62 | toBridgeRet.put("shaKey", shaKey) 63 | 64 | izWebView.execJs("zfJSBridge._handleMessageFromZF", toBridgeRet.toString(), null) 65 | } catch (e: Exception) { 66 | e.printStackTrace() 67 | } 68 | } ?: if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("$bridgeMessage izWebView recycle") 69 | } 70 | 71 | @Deprecated("use content://") 72 | fun createNativeResourceVirtualKey(nativeResource: String): String? { 73 | return izWebView.get()?.getCurZWebHelper()?.createNativeResourceVirtualKey(nativeResource) 74 | } 75 | 76 | @Deprecated("use content://") 77 | fun getVirtualKeyRealPath(virtualKey: String): String? { 78 | return izWebView.get()?.getCurZWebHelper()?.findVirtualKeyRealPath(virtualKey) 79 | } 80 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/bridge/ZJsEventer.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.bridge 2 | 3 | import android.webkit.ValueCallback 4 | import com.hcanyz.zjsbridge.cotainer.IZWebView 5 | import com.hcanyz.zjsbridge.util.ZUtils 6 | import org.json.JSONArray 7 | import org.json.JSONObject 8 | 9 | class ZJsEventer(private val izWebView: IZWebView) { 10 | 11 | fun event(eventName: String, jsonObject: JSONObject = JSONObject(), valueCallback: ValueCallback? = null) { 12 | doHandle(eventName, jsonObject, valueCallback) 13 | } 14 | 15 | fun event(eventName: String, key: String = "result", jsonArray: JSONArray = JSONArray(), valueCallback: ValueCallback? = null) { 16 | val jsonObject = JSONObject() 17 | jsonObject.put(key, jsonArray) 18 | 19 | doHandle(eventName, jsonObject, valueCallback) 20 | } 21 | 22 | private fun doHandle(eventName: String, jsonObject: JSONObject, valueCallback: ValueCallback? = null) { 23 | val jsonMessage = JSONObject() 24 | jsonMessage.put("eventName", eventName) 25 | jsonMessage.put("msgType", "event") 26 | jsonMessage.put("params", jsonObject) 27 | 28 | val jsonMessageBase64 = ZUtils.base64Encode(jsonMessage.toString()) 29 | 30 | val shaKey = ZUtils.signatureSHA1("$jsonMessageBase64${izWebView.getCurZWebHelper().dgtVerifyRandomStr}") 31 | 32 | val toBridgeRet = JSONObject() 33 | toBridgeRet.put("jsonMessage", jsonMessageBase64) 34 | toBridgeRet.put("shaKey", shaKey) 35 | 36 | izWebView.execJs("zfJSBridge._handleMessageFromZF", toBridgeRet.toString(), valueCallback) 37 | } 38 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/cotainer/IZWebView.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.cotainer 2 | 3 | import android.content.Context 4 | import android.webkit.ValueCallback 5 | 6 | 7 | interface IZWebView { 8 | 9 | fun execJs(methodName: String, params: String? = null, valueCallback: ValueCallback? = null) 10 | 11 | fun execJs(sourceJs: String, valueCallback: ValueCallback? = null) 12 | 13 | fun runOnMainThread(runnable: Runnable) 14 | 15 | fun getCurUrl(): String 16 | 17 | fun getCurContext(): Context 18 | 19 | fun getCurZWebHelper(): ZWebHelper 20 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/cotainer/IZWebViewContainer.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.cotainer 2 | 3 | interface IZWebViewContainer { 4 | fun closeWindow() 5 | 6 | fun updateTitle(title: String) 7 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/cotainer/ZWebHelper.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.cotainer 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.webkit.MimeTypeMap 6 | import android.webkit.ValueCallback 7 | import androidx.fragment.app.Fragment 8 | import androidx.fragment.app.FragmentActivity 9 | import com.hcanyz.zjsbridge.ZJsBridge 10 | import com.hcanyz.zjsbridge.bridge.ZJsCallBacker 11 | import com.hcanyz.zjsbridge.bridge.ZJsEventer 12 | import com.hcanyz.zjsbridge.handler.IZJsApiHandler 13 | import com.hcanyz.zjsbridge.util.ZUtils 14 | import java.io.File 15 | import java.io.FileInputStream 16 | import java.io.InputStream 17 | import java.io.InputStreamReader 18 | import java.util.* 19 | 20 | /** 21 | * 处理一些预置行为 22 | * 例如注入zfjs.js到当前页面,此过程会协商加密密钥 23 | * 24 | * @property izWebView IZWebView 25 | * @property dgtVerifyRandomStr String 与bridge约定的加密密钥 26 | * @property apiHandlers MutableSet 处理web的api请求对象,由容器初始化 27 | * @property nativeResourceVirtualKeyMap MutableMap 虚拟路径映射表 28 | * @constructor 29 | */ 30 | class ZWebHelper(private val izWebView: IZWebView) { 31 | 32 | val dgtVerifyRandomStr: String by lazy { UUID.randomUUID().toString() } 33 | 34 | // 加载js处理 35 | private val injectCoreJsStr: String by lazy { 36 | val readLines = InputStreamReader(izWebView.getCurContext().assets.open("jsapi/zfjs.js")).readLines() 37 | val js = StringBuilder() 38 | readLines.fold(js, { acc, s -> 39 | acc.append(s.replace("\${_dgtVerifyRandomStr}", dgtVerifyRandomStr) 40 | .replace("\${_debugLevel}", if (ZJsBridge.ZJS_DEBUG) "0" else "2")).append("\n") 41 | }) 42 | js.toString() 43 | } 44 | 45 | fun injectCoreJs() { 46 | izWebView.execJs(injectCoreJsStr, 47 | ValueCallback { 48 | if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("url: ${izWebView.getCurUrl()}\ninject result: $it") 49 | }) 50 | } 51 | 52 | private val apiHandlers: MutableSet by lazy { hashSetOf() } 53 | 54 | fun dispatchExeApi(apiName: String, params: String, zJsCallBacker: ZJsCallBacker) { 55 | izWebView.runOnMainThread(Runnable { 56 | try { 57 | for (handler in apiHandlers) { 58 | if (handler.handleApi(apiName, params, zJsCallBacker)) { 59 | return@Runnable 60 | } 61 | } 62 | } catch (e: Exception) { 63 | zJsCallBacker.fail(ZJsCallBacker.CODE_ERR_FAIL, e.toString()) 64 | return@Runnable 65 | } 66 | zJsCallBacker.fail(ZJsCallBacker.CODE_ERR_404, "") 67 | }) 68 | } 69 | 70 | fun dispatchContainerResult(requestCode: Int, resultCode: Int, data: Intent?) { 71 | for (handler in apiHandlers) { 72 | if (handler.onContainerResult(requestCode, resultCode, data)) { 73 | return 74 | } 75 | } 76 | } 77 | 78 | fun dispatchContainerDestroy() { 79 | for (handler in apiHandlers) { 80 | handler.onContainerDestroy() 81 | } 82 | } 83 | 84 | fun registeredJsApiHandler(fragment: Fragment, clazz: Class) { 85 | val jsApiHandler = clazz.newInstance() 86 | jsApiHandler.onAttachContainer(fragment) 87 | apiHandlers.add(jsApiHandler) 88 | } 89 | 90 | fun registeredJsApiHandler(fragment: Fragment, jsApiHandler: IZJsApiHandler) { 91 | jsApiHandler.onAttachContainer(fragment) 92 | apiHandlers.add(jsApiHandler) 93 | } 94 | 95 | fun registeredJsApiHandler(fragmentActivity: FragmentActivity, clazz: Class) { 96 | val jsApiHandler = clazz.newInstance() 97 | jsApiHandler.onAttachContainer(fragmentActivity) 98 | apiHandlers.add(jsApiHandler) 99 | } 100 | 101 | fun registeredJsApiHandler(fragmentActivity: FragmentActivity, jsApiHandler: IZJsApiHandler) { 102 | jsApiHandler.onAttachContainer(fragmentActivity) 103 | apiHandlers.add(jsApiHandler) 104 | } 105 | 106 | /** 107 | * 用于存储一个真实地址与虚拟路径的映射关系 108 | */ 109 | @Deprecated("use content://") 110 | private val nativeResourceVirtualKeyMap by lazy { mutableMapOf() } 111 | 112 | @Deprecated("use content://") 113 | fun createNativeResourceVirtualKey(nativeResource: String): String { 114 | val file = File(nativeResource) 115 | if (!file.exists() || !file.isFile) { 116 | ZJsBridge.log("createNativeResourceVirtualKey file does not exists or not a file") 117 | } 118 | 119 | val virtualKey = "zf://nativeResourceMap?key=${ZUtils.signatureSHA1(nativeResource)}.${MimeTypeMap.getFileExtensionFromUrl(nativeResource)}" 120 | 121 | nativeResourceVirtualKeyMap[virtualKey] = nativeResource 122 | 123 | return virtualKey 124 | } 125 | 126 | @Deprecated("use content://") 127 | fun findVirtualKeyRealPath(virtualKey: String): String? { 128 | return nativeResourceVirtualKeyMap[virtualKey] 129 | } 130 | 131 | @Deprecated("use content://") 132 | fun hookNativeResourceWithWebViewRequest(url: Uri): ZWebResourceResponse? { 133 | if (url.scheme == "zf" && url.host == "nativeResourceMap") { 134 | val nativeResource = nativeResourceVirtualKeyMap[url.toString()] ?: return null 135 | val file = File(nativeResource) 136 | if (!file.exists() || !file.isFile) { 137 | ZJsBridge.log("hookNativeResourceWithWebViewRequest file does not exists or not a file") 138 | return null 139 | } 140 | val mimeType = MimeTypeMap.getSingleton() 141 | .getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url.getQueryParameter("key"))) 142 | ?: "" 143 | return ZWebResourceResponse(mimeType, FileInputStream(file)) 144 | } 145 | return null 146 | } 147 | 148 | @Deprecated("use content://") 149 | data class ZWebResourceResponse(val mimeType: String?, val data: InputStream) 150 | 151 | val jsEventer: ZJsEventer by lazy { ZJsEventer(izWebView) } 152 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/handler/IZJsApiHandler.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.handler 2 | 3 | import android.content.Intent 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.FragmentActivity 6 | import com.hcanyz.zjsbridge.bridge.ZJsCallBacker 7 | 8 | 9 | interface IZJsApiHandler { 10 | 11 | fun handleApi(apiName: String, params: String, jsCallBacker: ZJsCallBacker): Boolean 12 | 13 | fun onAttachContainer(activity: FragmentActivity) 14 | 15 | fun onAttachContainer(fragment: Fragment) 16 | 17 | fun onContainerResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { 18 | return false 19 | } 20 | 21 | fun onContainerDestroy() 22 | } 23 | -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/handler/ZBaseJsApiHandler.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.handler 2 | 3 | import androidx.annotation.CallSuper 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.FragmentActivity 6 | import com.hcanyz.zjsbridge.bridge.ZJsCallBacker 7 | import com.hcanyz.zjsbridge.cotainer.IZWebViewContainer 8 | import java.lang.ref.WeakReference 9 | 10 | abstract class ZBaseJsApiHandler : IZJsApiHandler { 11 | 12 | private var activityWR: WeakReference? = null 13 | private var fragmentWR: WeakReference? = null 14 | private var containerWR: WeakReference? = null 15 | 16 | override fun onAttachContainer(activity: FragmentActivity) { 17 | activityWR = WeakReference(activity) 18 | check(activity is IZWebViewContainer) { "activity Must implement IZWebViewContainer" } 19 | containerWR = WeakReference(activity) 20 | } 21 | 22 | override fun onAttachContainer(fragment: Fragment) { 23 | activityWR = WeakReference(fragment.requireActivity()) 24 | fragmentWR = WeakReference(fragment) 25 | check(fragment is IZWebViewContainer) { "fragment Must implement IZWebViewContainer" } 26 | containerWR = WeakReference(fragment) 27 | } 28 | 29 | fun getActivity(): FragmentActivity? { 30 | return activityWR?.get() 31 | } 32 | 33 | fun getFragment(): Fragment? { 34 | return fragmentWR?.get() 35 | } 36 | 37 | fun getContainerOp(): T? { 38 | @Suppress("UNCHECKED_CAST") 39 | return containerWR?.get() as T? 40 | } 41 | 42 | private val zJsCallBackerMap: MutableMap by lazy { 43 | mutableMapOf() 44 | } 45 | 46 | fun saveJsCallBacker(key: String, ZJsCallBacker: ZJsCallBacker) { 47 | zJsCallBackerMap[key] = ZJsCallBacker 48 | } 49 | 50 | fun get7RemoveJsCallBacker(key: String): ZJsCallBacker? { 51 | return zJsCallBackerMap.remove(key) 52 | } 53 | 54 | @CallSuper 55 | override fun onContainerDestroy() { 56 | zJsCallBackerMap.clear() 57 | } 58 | 59 | override fun equals(other: Any?): Boolean { 60 | if (this === other) return true 61 | if (javaClass != other?.javaClass) return false 62 | return true 63 | } 64 | 65 | override fun hashCode(): Int { 66 | return javaClass.hashCode() 67 | } 68 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/handler/ZCommonJsHandler.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.handler 2 | 3 | import com.hcanyz.zjsbridge.bridge.ZJsCallBacker 4 | import com.hcanyz.zjsbridge.cotainer.IZWebViewContainer 5 | 6 | class ZCommonJsHandler : ZBaseJsApiHandler() { 7 | 8 | override fun handleApi(apiName: String, params: String, jsCallBacker: ZJsCallBacker): Boolean { 9 | when (apiName) { 10 | "closeWindow" -> { 11 | getContainerOp()?.closeWindow() 12 | return true 13 | } 14 | "setTitle" -> { 15 | getContainerOp()?.updateTitle(params) 16 | return true 17 | } 18 | } 19 | return false 20 | } 21 | } -------------------------------------------------------------------------------- /ZJsBridge/src/main/java/com/hcanyz/zjsbridge/util/ZUtils.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.util 2 | 3 | import android.util.Base64 4 | import java.security.MessageDigest 5 | 6 | class ZUtils { 7 | companion object { 8 | 9 | private val HEX_DIGITS = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f') 10 | 11 | fun signatureSHA1(paramsStr: String): String { 12 | return try { 13 | val digest = MessageDigest.getInstance("SHA-1") 14 | digest.update(paramsStr.toByteArray()) 15 | toHexString(digest.digest()) 16 | } catch (e: Exception) { 17 | "" 18 | } 19 | } 20 | 21 | private fun toHexString(bData: ByteArray): String { 22 | val sb = StringBuilder(bData.size * 2) 23 | for (i in bData.indices) { 24 | sb.append(HEX_DIGITS[(bData[i].toInt() shr 4) and 0x0f]) 25 | sb.append(HEX_DIGITS[bData[i].toInt() and 0x0f]) 26 | } 27 | return sb.toString() 28 | } 29 | 30 | fun base64Encode(str: String): String { 31 | return Base64.encodeToString(str.toByteArray(), Base64.NO_WRAP) 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | apply plugin: 'kotlin-kapt' 8 | 9 | android deps.gradleConfig.simpleAndroid(project) 10 | 11 | android { 12 | compileOptions { 13 | sourceCompatibility 1.8 14 | targetCompatibility 1.8 15 | } 16 | } 17 | 18 | dependencies { 19 | implementation fileTree(dir: 'libs', include: ['*.jar']) 20 | 21 | implementation project(':ZJsBridge') 22 | 23 | implementation project(':ZJsBridge-JsHandlerImpl-Image') 24 | 25 | implementation deps.android.recyclerview 26 | implementation deps.android.appcompat 27 | implementation deps.android.constraintLayout 28 | implementation deps.android.lifecycleextensions 29 | 30 | implementation deps.third.x5webview 31 | 32 | implementation deps.kotlin.stdLib 33 | implementation deps.kotlin.reflect 34 | } 35 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses ChromiumWebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/assets/css/app.00e3d0b7.css: -------------------------------------------------------------------------------- 1 | .box[data-v-03b12d62]:before{content:attr(name);width:100%;display:block;font-size:20px;margin-bottom:5px;text-align:left;margin-left:10px;font-weight:700}.box[data-v-03b12d62]{border-top:1px solid #5f9ea0;padding:10px 0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;justify-items:flex-start;-ms-flex-wrap:wrap;flex-wrap:wrap}.button[data-v-03b12d62]{display:block;padding:5px;margin:5px 10px;border:1px solid #5f9ea0} -------------------------------------------------------------------------------- /app/src/main/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcanyz/ZJsBridge/3c476ebd5a59287014e3c34cabf13af8350ff554/app/src/main/assets/favicon.ico -------------------------------------------------------------------------------- /app/src/main/assets/index.html: -------------------------------------------------------------------------------- 1 | zfjs-test
-------------------------------------------------------------------------------- /app/src/main/assets/js/app.a2ee3b8d.js: -------------------------------------------------------------------------------- 1 | (function(e){function o(o){for(var n,s,a=o[0],l=o[1],u=o[2],r=0,d=[];rUnit)?,\r\n * fail:((res:String)->Unit)?)?\r\n * cancel:((res:String)->Unit)?)?\r\n * complete:((res:String)->Unit)?)? 操作完成后一定会调用\r\n * } callBack res对象包括 errCode errMsg\r\n */\r\n function call(apiName, params, callBack) {\r\n windowz.zfJSBridge ? windowz.zfJSBridge.call(apiName, checkParams(params), function (ret) {\r\n callBack._complete && callBack._complete(ret) || delete callBack._complete\r\n\r\n var errCode = ret && ret['errCode']\r\n switch (errCode) {\r\n case 0:\r\n callBack.success && callBack.success(ret)\r\n break\r\n case 1:\r\n callBack.cancel && callBack.cancel(ret)\r\n break\r\n default:\r\n callBack.fail && callBack.fail(ret)\r\n break\r\n }\r\n callBack.complete && callBack.complete(ret)\r\n }) : defCall(apiName, callBack)\r\n }\r\n\r\n function checkParams(params) {\r\n return params || {}\r\n }\r\n\r\n function defCall(apiName, callBack) {\r\n callBack.complete && callBack.complete()\r\n console.log(\"zfJSBridge not found ,\" + apiName)\r\n }\r\n\r\n function on(eventName, callBack) {\r\n windowz.zfJSBridge ? windowz.zfJSBridge.on(eventName, function (ret) {\r\n callBack(ret)\r\n }) : defOn(eventName, callBack)\r\n }\r\n\r\n function defOn(eventName, callBack) {\r\n callBack.complete && callBack.complete()\r\n console.log(\"zfJSBridge not found ,\" + eventName)\r\n }\r\n\r\n var api = {\r\n config: function (e) {\r\n call(\"config\", {}, (e._complete = function () {\r\n console.log(\"_complete config\")\r\n }, e))\r\n }, setTitle: function (e) {\r\n call(\"setTitle\", {\r\n title: e.title || \"\"\r\n }, e)\r\n }, backCloseWindow: function (e) {\r\n call(\"backCloseWindow\", {\r\n }, e)\r\n }, closeWindow: function (e) {\r\n call(\"closeWindow\", {\r\n }, e)\r\n }, putLocalStorageKV: function (e) {\r\n call(\"putLocalStorageKV\", {\r\n key: e.key || \"\",\r\n value: e.value || \"\"\r\n }, e)\r\n }, getLocalStorageKV: function (e) {\r\n call(\"getLocalStorageKV\", {\r\n key: e.key || \"\"\r\n }, e)\r\n },\r\n\r\n choosePhotos: function (e) {\r\n call(\"choosePhotos\", {\r\n enableCount: e.enableCount || (e.enableCount == undefined ? 0 : e.enableCount)\r\n }, e)\r\n },\r\n uploadPhotos: function (e) {\r\n call(\"uploadPhotos\", {\r\n nativeResourceUrls: e.nativeResourceUrls || []\r\n }, e)\r\n },\r\n previewPhotos: function (e) {\r\n call(\"previewPhotos\", {\r\n urls: e.urls || [],\r\n index: e.index || (e.index == undefined ? 0 : e.index)\r\n }, e)\r\n },\r\n\r\n chooseVideos: function (e) {\r\n call(\"chooseVideos\", {\r\n enableCount: e.enableCount || (e.enableCount == undefined ? 0 : e.enableCount)\r\n }, e)\r\n },\r\n uploadVideos: function (e) {\r\n call(\"uploadVideos\", {\r\n nativeResourceUrls: e.nativeResourceUrls || []\r\n }, e)\r\n },\r\n previewVideo: function (e) {\r\n call(\"previewVideo\", {\r\n url: e.url || \"\"\r\n }, e)\r\n },\r\n\r\n chooseFile: function (e) {\r\n call(\"chooseFile\", {\r\n enableCount: e.enableCount || (e.enableCount == undefined ? 0 : e.enableCount),\r\n maxSize: e.maxSize || (e.maxSize == undefined ? 0 : e.maxSize),\r\n isMultiSelect: e.isMultiSelect || (e.isMultiSelect == undefined ? true : e.isMultiSelect)\r\n }, e)\r\n },\r\n uploadFile: function (e) {\r\n call(\"uploadFile\", {\r\n nativeResourceUrls: e.nativeResourceUrls || []\r\n }, e)\r\n },\r\n previewFile: function (e) {\r\n call(\"previewFile\", {\r\n url: e.url || \"\"\r\n }, e)\r\n },\r\n\r\n chooseLocation: function (e) {\r\n call(\"chooseLocation\", {\r\n }, e)\r\n },\r\n getLocation: function (e) {\r\n call(\"getLocation\", {\r\n }, e)\r\n },\r\n previewLocation: function (e) {\r\n call(\"previewLocation\", {\r\n }, e)\r\n },\r\n onContainerResume: function (e) {\r\n on(\"onContainerResume\", e)\r\n },\r\n onContainerPause: function (e) {\r\n on(\"onContainerPause\", e)\r\n }\r\n }\r\n return open && (windowz.zfApi = api), api\r\n})","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{\"id\":\"app\"}},[_c('HelloWorld')],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"hello\"},[_c('img',{attrs:{\"src\":this.selectNativeResourceUrl,\"width\":\"50\",\"height\":\"50\"}}),_c('div',{staticClass:\"box\",attrs:{\"name\":\"base\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm.config}},[_vm._v(\"config\")])]),_c('div',{staticClass:\"box\",attrs:{\"name\":\"test\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm._test_unicode_params_and_result}},[_vm._v(\"_test_unicode_params_and_result\")])]),_c('div',{staticClass:\"box\",attrs:{\"name\":\"utils\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm.setTitle}},[_vm._v(\"setTitle\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.backCloseWindow}},[_vm._v(\"backCloseWindow\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.closeWindow}},[_vm._v(\"closeWindow\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.putLocalStorageKV}},[_vm._v(\"putLocalStorageKV\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.getLocalStorageKV}},[_vm._v(\"getLocalStorageKV\")])]),_c('div',{staticClass:\"box\",attrs:{\"name\":\"photos\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm.choosePhotos}},[_vm._v(\"choosePhotos\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.uploadPhotos}},[_vm._v(\"uploadPhotos\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.previewPhotos}},[_vm._v(\"previewPhotos\")])]),_c('div',{staticClass:\"box\",attrs:{\"name\":\"videos\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm.chooseVideos}},[_vm._v(\"chooseVideos\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.uploadVideos}},[_vm._v(\"uploadVideos\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.previewVideo}},[_vm._v(\"previewVideo\")])]),_c('div',{staticClass:\"box\",attrs:{\"name\":\"files\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm.chooseFile}},[_vm._v(\"chooseFile\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.uploadFile}},[_vm._v(\"uploadFile\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.previewFile}},[_vm._v(\"previewFile\")])]),_c('div',{staticClass:\"box\",attrs:{\"name\":\"location\"}},[_c('div',{staticClass:\"button\",on:{\"click\":_vm.chooseLocation}},[_vm._v(\"chooseLocation\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.getLocation}},[_vm._v(\"getLocation\")]),_c('div',{staticClass:\"button\",on:{\"click\":_vm.previewLocation}},[_vm._v(\"previewLocation\")])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n\r\n\r\n\r\n\r\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HelloWorld.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HelloWorld.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./HelloWorld.vue?vue&type=template&id=03b12d62&scoped=true&\"\nimport script from \"./HelloWorld.vue?vue&type=script&lang=js&\"\nexport * from \"./HelloWorld.vue?vue&type=script&lang=js&\"\nimport style0 from \"./HelloWorld.vue?vue&type=style&index=0&id=03b12d62&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"03b12d62\",\n null\n \n)\n\nexport default component.exports","\r\n\r\n\r\n\r\n\r\n","import mod from \"-!../node_modules/cache-loader/dist/cjs.js??ref--13-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/cache-loader/dist/cjs.js??ref--1-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../node_modules/cache-loader/dist/cjs.js??ref--13-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/cache-loader/dist/cjs.js??ref--1-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./App.vue?vue&type=template&id=3100d2ba&\"\nimport script from \"./App.vue?vue&type=script&lang=js&\"\nexport * from \"./App.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","import Vue from 'vue'\r\nimport App from './App.vue'\r\nimport VConsole from 'vconsole'\r\n\r\nif (navigator.platform == \"Win32\") {\r\n import('@/mock/zfjs-mock-pc.js')\r\n import('@/mock/zfjs.js')\r\n} else {\r\n new VConsole();\r\n}\r\n\r\nimport '@/vendor/zfjs-sdk.js'\r\nimport '@/vendor/zfjs-test-sdk'\r\n\r\nVue.config.productionTip = false\r\n\r\nnew Vue({\r\n render: h => h(App),\r\n}).$mount('#app')\r\n","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HelloWorld.vue?vue&type=style&index=0&id=03b12d62&scoped=true&lang=css&\"","! function (windowz, n) {\r\n n(windowz, !0)\r\n}(window, function (windowz, open) {\r\n /**\r\n * 调用zfJSBridge执行api\r\n * @param {String} apiName \r\n * @param {Any} params \r\n * @param {\r\n * success:((res:String)->Unit)?,\r\n * fail:((res:String)->Unit)?)?\r\n * cancel:((res:String)->Unit)?)?\r\n * complete:((res:String)->Unit)?)? 操作完成后一定会调用\r\n * } callBack res对象包括 errCode errMsg\r\n */\r\n function call(apiName, params, callBack) {\r\n windowz.zfJSBridge ? windowz.zfJSBridge.call(apiName, checkParams(params), function (ret) {\r\n callBack._complete && callBack._complete(ret) || delete callBack._complete\r\n\r\n var errCode = ret && ret['errCode']\r\n switch (errCode) {\r\n case 0:\r\n callBack.success && callBack.success(ret)\r\n break\r\n case 1:\r\n callBack.cancel && callBack.cancel(ret)\r\n break\r\n default:\r\n callBack.fail && callBack.fail(ret)\r\n break\r\n }\r\n callBack.complete && callBack.complete(ret)\r\n }) : defCall(apiName, callBack)\r\n }\r\n\r\n function checkParams(params) {\r\n return params || {}\r\n }\r\n\r\n function defCall(apiName, callBack) {\r\n callBack.complete && callBack.complete()\r\n console.log(\"zfJSBridge not found ,\" + apiName)\r\n }\r\n\r\n function on(eventName, callBack) {\r\n windowz.zfJSBridge ? windowz.zfJSBridge.on(eventName, function (ret) {\r\n callBack(ret)\r\n }) : defOn(eventName, callBack)\r\n }\r\n\r\n function defOn(eventName, callBack) {\r\n callBack.complete && callBack.complete()\r\n console.log(\"zfJSBridge not found ,\" + eventName)\r\n }\r\n\r\n var api = {\r\n _test_unicode_params_and_result: function (e) {\r\n call(\"_test_unicode_params_and_result\", {\r\n unicodeParams: e.unicodeParams || \"\"\r\n }, e)\r\n }\r\n }\r\n return open && (windowz.zfTestApi = api), api\r\n})"],"sourceRoot":""} -------------------------------------------------------------------------------- /app/src/main/assets/js/chunk-689084fa.19f2e525.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-689084fa"],{"00d8":function(r,t){(function(){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",e={rotl:function(r,t){return r<>>32-t},rotr:function(r,t){return r<<32-t|r>>>t},endian:function(r){if(r.constructor==Number)return 16711935&e.rotl(r,8)|4278255360&e.rotl(r,24);for(var t=0;t0;r--)t.push(Math.floor(256*Math.random()));return t},bytesToWords:function(r){for(var t=[],e=0,n=0;e>>5]|=r[e]<<24-n%32;return t},wordsToBytes:function(r){for(var t=[],e=0;e<32*r.length;e+=8)t.push(r[e>>>5]>>>24-e%32&255);return t},bytesToHex:function(r){for(var t=[],e=0;e>>4).toString(16)),t.push((15&r[e]).toString(16));return t.join("")},hexToBytes:function(r){for(var t=[],e=0;e>>6*(3-i)&63)):e.push("=");return e.join("")},base64ToBytes:function(r){r=r.replace(/[^A-Z0-9+\/]/gi,"");for(var e=[],n=0,o=0;n>>6-2*o);return e}};r.exports=e})()},"0eb6":function(r,t,e){"use strict";var n=e("23e7"),o=e("7c37"),i=e("d066"),s=e("d039"),a=e("7c73"),u=e("5c6c"),f=e("9bf2").f,c=e("37e8").f,h=e("6eeb"),l=e("1a2d"),p=e("19aa"),g=e("825a"),d=e("aa1f"),y=e("e391"),v=e("cf98"),w=e("c770"),E=e("69f3"),m=e("83ab"),R=e("c430"),b="DOMException",A="DATA_CLONE_ERR",_=i("Error"),T=i(b)||function(){try{var r=i("MessageChannel")||o("worker_threads").MessageChannel;(new r).port1.postMessage(new WeakMap)}catch(t){if(t.name==A&&25==t.code)return t.constructor}}(),S=T&&T.prototype,C=_.prototype,U=E.set,I=E.getterFor(b),B="stack"in _(b),P=function(r){return l(v,r)&&v[r].m?v[r].c:0},O=function(){p(this,M);var r=arguments.length,t=y(r<1?void 0:arguments[0]),e=y(r<2?void 0:arguments[1],"Error"),n=P(e);if(U(this,{type:b,name:e,message:t,code:n}),m||(this.name=e,this.message=t,this.code=n),B){var o=_(t);o.name=b,f(this,"stack",u(1,w(o.stack,1)))}},M=O.prototype=a(C),k=function(r){return{enumerable:!0,configurable:!0,get:r}},D=function(r){return k((function(){return I(this)[r]}))};m&&c(M,{name:D("name"),message:D("message"),code:D("code")}),f(M,"constructor",u(1,O));var N=s((function(){return!(new T instanceof _)})),L=N||s((function(){return C.toString!==d||"2: 1"!==String(new T(1,2))})),Y=N||s((function(){return 25!==new T(1,"DataCloneError").code})),x=N||25!==T[A]||25!==S[A],z=R?L||Y||x:N;n({global:!0,forced:z},{DOMException:z?O:T});var F=i(b),V=F.prototype;for(var j in L&&(R||T===F)&&h(V,"toString",d),Y&&m&&T===F&&f(V,"code",k((function(){return P(g(this).name)}))),v)if(l(v,j)){var J=v[j],W=J.s,H=u(6,J.c);l(F,W)||f(F,W,H),l(V,W)||f(V,W,H)}},"1fb5":function(r,t,e){"use strict";t.byteLength=c,t.toByteArray=l,t.fromByteArray=d;for(var n=[],o=[],i="undefined"!==typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var e=r.indexOf("=");-1===e&&(e=t);var n=e===t?0:4-e%4;return[e,n]}function c(r){var t=f(r),e=t[0],n=t[1];return 3*(e+n)/4-n}function h(r,t,e){return 3*(t+e)/4-e}function l(r){var t,e,n=f(r),s=n[0],a=n[1],u=new i(h(r,s,a)),c=0,l=a>0?s-4:s;for(e=0;e>16&255,u[c++]=t>>8&255,u[c++]=255&t;return 2===a&&(t=o[r.charCodeAt(e)]<<2|o[r.charCodeAt(e+1)]>>4,u[c++]=255&t),1===a&&(t=o[r.charCodeAt(e)]<<10|o[r.charCodeAt(e+1)]<<4|o[r.charCodeAt(e+2)]>>2,u[c++]=t>>8&255,u[c++]=255&t),u}function p(r){return n[r>>18&63]+n[r>>12&63]+n[r>>6&63]+n[63&r]}function g(r,t,e){for(var n,o=[],i=t;iu?u:a+s));return 1===o?(t=r[e-1],i.push(n[t>>2]+n[t<<4&63]+"==")):2===o&&(t=(r[e-2]<<8)+r[e-1],i.push(n[t>>10]+n[t>>4&63]+n[t<<2&63]+"=")),i.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},"25f0":function(r,t,e){"use strict";var n=e("e330"),o=e("5e77").PROPER,i=e("6eeb"),s=e("825a"),a=e("3a9b"),u=e("577e"),f=e("d039"),c=e("ad6d"),h="toString",l=RegExp.prototype,p=l[h],g=n(c),d=f((function(){return"/a/b"!=p.call({source:"a",flags:"b"})})),y=o&&p.name!=h;(d||y)&&i(RegExp.prototype,h,(function(){var r=s(this),t=u(r.source),e=r.flags,n=u(void 0===e&&a(l,r)&&!("flags"in l)?g(r):e);return"/"+t+"/"+n}),{unsafe:!0})},"558f":function(r,t,e){"use strict";e.r(t);e("0eb6"),e("b7ef"),e("8bd4"),e("e9c4"),e("d3b7"),e("25f0");var n=e("58b7"),o=e.n(n),i="${_dgtVerifyRandomStr}";window.__zf=window.__zf||function(){var r=function(r,t){var e={msgType:"event",eventName:r,params:t},n=window.btoa(JSON.stringify(e));window.zfJSBridge._handleMessageFromZF(JSON.stringify({jsonMessage:n,shaKey:o()(n+i).toString()}))};return document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&r("onContainerPause",{test:"test onContainerPause data"}),"visible"===document.visibilityState&&r("onContainerResume",{test:"test onContainerResume data"})})),{_sendMessage:function(r){var t=JSON.parse(r),e=JSON.parse(t.jsonMessage),n={msgType:"callback",callbackId:e.callbackId};if(o()(t.jsonMessage+i).toString()!=t.shaKey)n.params={errCode:"99999999"};else switch(e.apiName){case"config":n.params={errCode:0};break;case"setTitle":document.title=e.params.title,n.params={errCode:0};break;case"backCloseWindow":history.back(),n.params={errCode:0};break;case"closeWindow":window.close(),n.params={errCode:0};break;case"putLocalStorageKV":localStorage.setItem(e.params.key,e.params.value),n.params={errCode:0};break;case"getLocalStorageKV":n.params={errCode:0,value:localStorage.getItem(e.params.key)};break;case"choosePhotos":if(e.params.enableCount>0){n.params={errCode:0,result:[]};for(var s=0;s<5;s++)n.params.result.push({nativeResourceUrl:"assets/logo.png",name:"logo.png",size:"123"})}else n.params={errCode:1};break;case"uploadPhotos":for(var a in n.params={errCode:0,result:[]},e.params.nativeResourceUrls)n.params.result.push({nativeResourceUrl:e.params.nativeResourceUrls[a],serverResourceUrl:e.params.nativeResourceUrls[a]});break;case"previewPhotos":n.params={errCode:0};break;case"chooseVideos":if(e.params.enableCount>0){n.params={errCode:0,result:[]};for(var u=0;u<5;u++)n.params.result.push({nativeResourceUrl:"assets/logo.png",name:"logo.png",size:123,videoTime:123})}else n.params={errCode:1};break;case"uploadVideos":for(var f in n.params={errCode:0,result:[]},e.params.nativeResourceUrls)n.params.result.push({nativeResourceUrl:e.params.nativeResourceUrls[f],serverResourceUrl:e.params.nativeResourceUrls[f]});break;case"previewVideo":n.params={errCode:0};break;case"chooseFile":if(e.params.enableCount>0){n.params={errCode:0,result:[]};for(var c=0;c<5;c++)n.params.result.push({nativeResourceUrl:"assets/logo.png",name:"logo.png",size:"123"})}else n.params={errCode:1};break;case"uploadFile":for(var h in n.params={errCode:0,result:[]},e.params.nativeResourceUrls)n.params.result.push({nativeResourceUrl:e.params.nativeResourceUrls[h],serverResourceUrl:e.params.nativeResourceUrls[h]});break;case"previewFile":n.params={errCode:0};break;case"chooseLocation":n.params={errCode:0,address:"深圳",latitude:0,longitude:0};break;case"getLocation":n.params={errCode:0,address:"深圳",latitude:0,longitude:0};break;case"previewLocation":n.params={errCode:0};break}var l=window.btoa(JSON.stringify(n));window.zfJSBridge._handleMessageFromZF(JSON.stringify({jsonMessage:l,shaKey:o()(l+i).toString()}))}}}()},"58b7":function(r,t,e){(function(t){(function(){var n=e("00d8"),o=e("9a63").utf8,i=e("9a63").bin,s=function(r){r.constructor==String?r=o.stringToBytes(r):"undefined"!==typeof t&&"function"==typeof t.isBuffer&&t.isBuffer(r)?r=Array.prototype.slice.call(r,0):Array.isArray(r)||(r=r.toString());var e=n.bytesToWords(r),i=8*r.length,s=[],a=1732584193,u=-271733879,f=-1732584194,c=271733878,h=-1009589776;e[i>>5]|=128<<24-i%32,e[15+(i+64>>>9<<4)]=i;for(var l=0;l>>31}var m=(a<<5|a>>>27)+h+(s[w]>>>0)+(w<20?1518500249+(u&f|~u&c):w<40?1859775393+(u^f^c):w<60?(u&f|u&c|f&c)-1894007588:(u^f^c)-899497514);h=c,c=f,f=u<<30|u>>>2,u=a,a=m}a+=p,u+=g,f+=d,c+=y,h+=v}return[a,u,f,c,h]},a=function(r,t){var e=n.wordsToBytes(s(r));return t&&t.asBytes?e:t&&t.asString?i.bytesToString(e):n.bytesToHex(e)};a._blocksize=16,a._digestsize=20,r.exports=a})()}).call(this,e("b639").Buffer)},7156:function(r,t,e){var n=e("1626"),o=e("861d"),i=e("d2bb");r.exports=function(r,t,e){var s,a;return i&&n(s=t.constructor)&&s!==e&&o(a=s.prototype)&&a!==e.prototype&&i(r,a),r}},"7c37":function(r,t,e){var n=e("605d");r.exports=function(r){try{if(n)return Function('return require("'+r+'")')()}catch(t){}}},"8bd4":function(r,t,e){var n=e("d066"),o=e("d44e"),i="DOMException";o(n(i),i)},9152:function(r,t){ 2 | /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ 3 | t.read=function(r,t,e,n,o){var i,s,a=8*o-n-1,u=(1<>1,c=-7,h=e?o-1:0,l=e?-1:1,p=r[t+h];for(h+=l,i=p&(1<<-c)-1,p>>=-c,c+=a;c>0;i=256*i+r[t+h],h+=l,c-=8);for(s=i&(1<<-c)-1,i>>=-c,c+=n;c>0;s=256*s+r[t+h],h+=l,c-=8);if(0===i)i=1-f;else{if(i===u)return s?NaN:1/0*(p?-1:1);s+=Math.pow(2,n),i-=f}return(p?-1:1)*s*Math.pow(2,i-n)},t.write=function(r,t,e,n,o,i){var s,a,u,f=8*i-o-1,c=(1<>1,l=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:i-1,g=n?1:-1,d=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=c):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),t+=s+h>=1?l/u:l*Math.pow(2,1-h),t*u>=2&&(s++,u/=2),s+h>=c?(a=0,s=c):s+h>=1?(a=(t*u-1)*Math.pow(2,o),s+=h):(a=t*Math.pow(2,h-1)*Math.pow(2,o),s=0));o>=8;r[e+p]=255&a,p+=g,a/=256,o-=8);for(s=s<0;r[e+p]=255&s,p+=g,s/=256,f-=8);r[e+p-g]|=128*d}},"9a63":function(r,t){var e={utf8:{stringToBytes:function(r){return e.bin.stringToBytes(unescape(encodeURIComponent(r)))},bytesToString:function(r){return decodeURIComponent(escape(e.bin.bytesToString(r)))}},bin:{stringToBytes:function(r){for(var t=[],e=0;e 8 | * @license MIT 9 | */ 10 | var n=e("1fb5"),o=e("9152"),i=e("e3db");function s(){try{var r=new Uint8Array(1);return r.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===r.foo()&&"function"===typeof r.subarray&&0===r.subarray(1,1).byteLength}catch(t){return!1}}function a(){return f.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function u(r,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|r}function E(r){return+r!=r&&(r=0),f.alloc(+r)}function m(r,t){if(f.isBuffer(r))return r.length;if("undefined"!==typeof ArrayBuffer&&"function"===typeof ArrayBuffer.isView&&(ArrayBuffer.isView(r)||r instanceof ArrayBuffer))return r.byteLength;"string"!==typeof r&&(r=""+r);var e=r.length;if(0===e)return 0;for(var n=!1;;)switch(t){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":case void 0:return q(r).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*e;case"hex":return e>>>1;case"base64":return $(r).length;default:if(n)return q(r).length;t=(""+t).toLowerCase(),n=!0}}function R(r,t,e){var n=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if(e>>>=0,t>>>=0,e<=t)return"";r||(r="utf8");while(1)switch(r){case"hex":return L(this,t,e);case"utf8":case"utf-8":return O(this,t,e);case"ascii":return D(this,t,e);case"latin1":case"binary":return N(this,t,e);case"base64":return P(this,t,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Y(this,t,e);default:if(n)throw new TypeError("Unknown encoding: "+r);r=(r+"").toLowerCase(),n=!0}}function b(r,t,e){var n=r[t];r[t]=r[e],r[e]=n}function A(r,t,e,n,o){if(0===r.length)return-1;if("string"===typeof e?(n=e,e=0):e>2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,isNaN(e)&&(e=o?0:r.length-1),e<0&&(e=r.length+e),e>=r.length){if(o)return-1;e=r.length-1}else if(e<0){if(!o)return-1;e=0}if("string"===typeof t&&(t=f.from(t,n)),f.isBuffer(t))return 0===t.length?-1:_(r,t,e,n,o);if("number"===typeof t)return t&=255,f.TYPED_ARRAY_SUPPORT&&"function"===typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(r,t,e):Uint8Array.prototype.lastIndexOf.call(r,t,e):_(r,[t],e,n,o);throw new TypeError("val must be string, number or Buffer")}function _(r,t,e,n,o){var i,s=1,a=r.length,u=t.length;if(void 0!==n&&(n=String(n).toLowerCase(),"ucs2"===n||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(r.length<2||t.length<2)return-1;s=2,a/=2,u/=2,e/=2}function f(r,t){return 1===s?r[t]:r.readUInt16BE(t*s)}if(o){var c=-1;for(i=e;ia&&(e=a-u),i=e;i>=0;i--){for(var h=!0,l=0;lo&&(n=o)):n=o;var i=t.length;if(i%2!==0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var s=0;s239?4:f>223?3:f>191?2:1;if(o+h<=e)switch(h){case 1:f<128&&(c=f);break;case 2:i=r[o+1],128===(192&i)&&(u=(31&f)<<6|63&i,u>127&&(c=u));break;case 3:i=r[o+1],s=r[o+2],128===(192&i)&&128===(192&s)&&(u=(15&f)<<12|(63&i)<<6|63&s,u>2047&&(u<55296||u>57343)&&(c=u));break;case 4:i=r[o+1],s=r[o+2],a=r[o+3],128===(192&i)&&128===(192&s)&&128===(192&a)&&(u=(15&f)<<18|(63&i)<<12|(63&s)<<6|63&a,u>65535&&u<1114112&&(c=u))}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return k(n)}t.Buffer=f,t.SlowBuffer=E,t.INSPECT_MAX_BYTES=50,f.TYPED_ARRAY_SUPPORT=void 0!==r.TYPED_ARRAY_SUPPORT?r.TYPED_ARRAY_SUPPORT:s(),t.kMaxLength=a(),f.poolSize=8192,f._augment=function(r){return r.__proto__=f.prototype,r},f.from=function(r,t,e){return c(null,r,t,e)},f.TYPED_ARRAY_SUPPORT&&(f.prototype.__proto__=Uint8Array.prototype,f.__proto__=Uint8Array,"undefined"!==typeof Symbol&&Symbol.species&&f[Symbol.species]===f&&Object.defineProperty(f,Symbol.species,{value:null,configurable:!0})),f.alloc=function(r,t,e){return l(null,r,t,e)},f.allocUnsafe=function(r){return p(null,r)},f.allocUnsafeSlow=function(r){return p(null,r)},f.isBuffer=function(r){return!(null==r||!r._isBuffer)},f.compare=function(r,t){if(!f.isBuffer(r)||!f.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(r===t)return 0;for(var e=r.length,n=t.length,o=0,i=Math.min(e,n);o0&&(r=this.toString("hex",0,e).match(/.{2}/g).join(" "),this.length>e&&(r+=" ... ")),""},f.prototype.compare=function(r,t,e,n,o){if(!f.isBuffer(r))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===e&&(e=r?r.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),t<0||e>r.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&t>=e)return 0;if(n>=o)return-1;if(t>=e)return 1;if(t>>>=0,e>>>=0,n>>>=0,o>>>=0,this===r)return 0;for(var i=o-n,s=e-t,a=Math.min(i,s),u=this.slice(n,o),c=r.slice(t,e),h=0;ho)&&(e=o),r.length>0&&(e<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return T(this,r,t,e);case"utf8":case"utf-8":return S(this,r,t,e);case"ascii":return C(this,r,t,e);case"latin1":case"binary":return U(this,r,t,e);case"base64":return I(this,r,t,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return B(this,r,t,e);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},f.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var M=4096;function k(r){var t=r.length;if(t<=M)return String.fromCharCode.apply(String,r);var e="",n=0;while(nn)&&(e=n);for(var o="",i=t;ie)throw new RangeError("Trying to access beyond buffer length")}function z(r,t,e,n,o,i){if(!f.isBuffer(r))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||tr.length)throw new RangeError("Index out of range")}function F(r,t,e,n){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(r.length-e,2);o>>8*(n?o:1-o)}function V(r,t,e,n){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(r.length-e,4);o>>8*(n?o:3-o)&255}function j(r,t,e,n,o,i){if(e+n>r.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function J(r,t,e,n,i){return i||j(r,t,e,4,34028234663852886e22,-34028234663852886e22),o.write(r,t,e,n,23,4),e+4}function W(r,t,e,n,i){return i||j(r,t,e,8,17976931348623157e292,-17976931348623157e292),o.write(r,t,e,n,52,8),e+8}f.prototype.slice=function(r,t){var e,n=this.length;if(r=~~r,t=void 0===t?n:~~t,r<0?(r+=n,r<0&&(r=0)):r>n&&(r=n),t<0?(t+=n,t<0&&(t=0)):t>n&&(t=n),t0&&(o*=256))n+=this[r+--t]*o;return n},f.prototype.readUInt8=function(r,t){return t||x(r,1,this.length),this[r]},f.prototype.readUInt16LE=function(r,t){return t||x(r,2,this.length),this[r]|this[r+1]<<8},f.prototype.readUInt16BE=function(r,t){return t||x(r,2,this.length),this[r]<<8|this[r+1]},f.prototype.readUInt32LE=function(r,t){return t||x(r,4,this.length),(this[r]|this[r+1]<<8|this[r+2]<<16)+16777216*this[r+3]},f.prototype.readUInt32BE=function(r,t){return t||x(r,4,this.length),16777216*this[r]+(this[r+1]<<16|this[r+2]<<8|this[r+3])},f.prototype.readIntLE=function(r,t,e){r|=0,t|=0,e||x(r,t,this.length);var n=this[r],o=1,i=0;while(++i=o&&(n-=Math.pow(2,8*t)),n},f.prototype.readIntBE=function(r,t,e){r|=0,t|=0,e||x(r,t,this.length);var n=t,o=1,i=this[r+--n];while(n>0&&(o*=256))i+=this[r+--n]*o;return o*=128,i>=o&&(i-=Math.pow(2,8*t)),i},f.prototype.readInt8=function(r,t){return t||x(r,1,this.length),128&this[r]?-1*(255-this[r]+1):this[r]},f.prototype.readInt16LE=function(r,t){t||x(r,2,this.length);var e=this[r]|this[r+1]<<8;return 32768&e?4294901760|e:e},f.prototype.readInt16BE=function(r,t){t||x(r,2,this.length);var e=this[r+1]|this[r]<<8;return 32768&e?4294901760|e:e},f.prototype.readInt32LE=function(r,t){return t||x(r,4,this.length),this[r]|this[r+1]<<8|this[r+2]<<16|this[r+3]<<24},f.prototype.readInt32BE=function(r,t){return t||x(r,4,this.length),this[r]<<24|this[r+1]<<16|this[r+2]<<8|this[r+3]},f.prototype.readFloatLE=function(r,t){return t||x(r,4,this.length),o.read(this,r,!0,23,4)},f.prototype.readFloatBE=function(r,t){return t||x(r,4,this.length),o.read(this,r,!1,23,4)},f.prototype.readDoubleLE=function(r,t){return t||x(r,8,this.length),o.read(this,r,!0,52,8)},f.prototype.readDoubleBE=function(r,t){return t||x(r,8,this.length),o.read(this,r,!1,52,8)},f.prototype.writeUIntLE=function(r,t,e,n){if(r=+r,t|=0,e|=0,!n){var o=Math.pow(2,8*e)-1;z(this,r,t,e,o,0)}var i=1,s=0;this[t]=255&r;while(++s=0&&(s*=256))this[t+i]=r/s&255;return t+e},f.prototype.writeUInt8=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,1,255,0),f.TYPED_ARRAY_SUPPORT||(r=Math.floor(r)),this[t]=255&r,t+1},f.prototype.writeUInt16LE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,2,65535,0),f.TYPED_ARRAY_SUPPORT?(this[t]=255&r,this[t+1]=r>>>8):F(this,r,t,!0),t+2},f.prototype.writeUInt16BE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,2,65535,0),f.TYPED_ARRAY_SUPPORT?(this[t]=r>>>8,this[t+1]=255&r):F(this,r,t,!1),t+2},f.prototype.writeUInt32LE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,4,4294967295,0),f.TYPED_ARRAY_SUPPORT?(this[t+3]=r>>>24,this[t+2]=r>>>16,this[t+1]=r>>>8,this[t]=255&r):V(this,r,t,!0),t+4},f.prototype.writeUInt32BE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,4,4294967295,0),f.TYPED_ARRAY_SUPPORT?(this[t]=r>>>24,this[t+1]=r>>>16,this[t+2]=r>>>8,this[t+3]=255&r):V(this,r,t,!1),t+4},f.prototype.writeIntLE=function(r,t,e,n){if(r=+r,t|=0,!n){var o=Math.pow(2,8*e-1);z(this,r,t,e,o-1,-o)}var i=0,s=1,a=0;this[t]=255&r;while(++i>0)-a&255;return t+e},f.prototype.writeIntBE=function(r,t,e,n){if(r=+r,t|=0,!n){var o=Math.pow(2,8*e-1);z(this,r,t,e,o-1,-o)}var i=e-1,s=1,a=0;this[t+i]=255&r;while(--i>=0&&(s*=256))r<0&&0===a&&0!==this[t+i+1]&&(a=1),this[t+i]=(r/s>>0)-a&255;return t+e},f.prototype.writeInt8=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,1,127,-128),f.TYPED_ARRAY_SUPPORT||(r=Math.floor(r)),r<0&&(r=255+r+1),this[t]=255&r,t+1},f.prototype.writeInt16LE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,2,32767,-32768),f.TYPED_ARRAY_SUPPORT?(this[t]=255&r,this[t+1]=r>>>8):F(this,r,t,!0),t+2},f.prototype.writeInt16BE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,2,32767,-32768),f.TYPED_ARRAY_SUPPORT?(this[t]=r>>>8,this[t+1]=255&r):F(this,r,t,!1),t+2},f.prototype.writeInt32LE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,4,2147483647,-2147483648),f.TYPED_ARRAY_SUPPORT?(this[t]=255&r,this[t+1]=r>>>8,this[t+2]=r>>>16,this[t+3]=r>>>24):V(this,r,t,!0),t+4},f.prototype.writeInt32BE=function(r,t,e){return r=+r,t|=0,e||z(this,r,t,4,2147483647,-2147483648),r<0&&(r=4294967295+r+1),f.TYPED_ARRAY_SUPPORT?(this[t]=r>>>24,this[t+1]=r>>>16,this[t+2]=r>>>8,this[t+3]=255&r):V(this,r,t,!1),t+4},f.prototype.writeFloatLE=function(r,t,e){return J(this,r,t,!0,e)},f.prototype.writeFloatBE=function(r,t,e){return J(this,r,t,!1,e)},f.prototype.writeDoubleLE=function(r,t,e){return W(this,r,t,!0,e)},f.prototype.writeDoubleBE=function(r,t,e){return W(this,r,t,!1,e)},f.prototype.copy=function(r,t,e,n){if(e||(e=0),n||0===n||(n=this.length),t>=r.length&&(t=r.length),t||(t=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),r.length-t=0;--o)r[o+t]=this[o+e];else if(i<1e3||!f.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,e=void 0===e?this.length:e>>>0,r||(r=0),"number"===typeof r)for(i=t;i55295&&e<57344){if(!o){if(e>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(s+1===n){(t-=3)>-1&&i.push(239,191,189);continue}o=e;continue}if(e<56320){(t-=3)>-1&&i.push(239,191,189),o=e;continue}e=65536+(o-55296<<10|e-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,e<128){if((t-=1)<0)break;i.push(e)}else if(e<2048){if((t-=2)<0)break;i.push(e>>6|192,63&e|128)}else if(e<65536){if((t-=3)<0)break;i.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return i}function Q(r){for(var t=[],e=0;e>8,o=e%256,i.push(o),i.push(n)}return i}function $(r){return n.toByteArray(K(r))}function rr(r,t,e,n){for(var o=0;o=t.length||o>=r.length)break;t[o+e]=r[o]}return o}function tr(r){return r!==r}}).call(this,e("c8ba"))},b7ef:function(r,t,e){"use strict";var n=e("23e7"),o=e("d066"),i=e("5c6c"),s=e("9bf2").f,a=e("1a2d"),u=e("19aa"),f=e("7156"),c=e("e391"),h=e("cf98"),l=e("c770"),p=e("c430"),g="DOMException",d=o("Error"),y=o(g),v=function(){u(this,w);var r=arguments.length,t=c(r<1?void 0:arguments[0]),e=c(r<2?void 0:arguments[1],"Error"),n=new y(t,e),o=d(t);return o.name=g,s(n,"stack",i(1,l(o.stack,1))),f(n,this,v),n},w=v.prototype=y.prototype,E="stack"in d(g),m="stack"in new y(1,2),R=E&&!m;n({global:!0,forced:p||R},{DOMException:R?v:y});var b=o(g),A=b.prototype;if(A.constructor!==b)for(var _ in p||s(A,"constructor",i(1,b)),h)if(a(h,_)){var T=h[_],S=T.s;a(b,S)||s(b,S,i(6,T.c))}},c770:function(r,t,e){var n=e("e330"),o=n("".replace),i=function(r){return String(Error(r).stack)}("zxcasd"),s=/\n\s*at [^:]*:[^\n]*/,a=s.test(i);r.exports=function(r,t){if(a&&"string"==typeof r)while(t--)r=o(r,s,"");return r}},cf98:function(r,t){r.exports={IndexSizeError:{s:"INDEX_SIZE_ERR",c:1,m:1},DOMStringSizeError:{s:"DOMSTRING_SIZE_ERR",c:2,m:0},HierarchyRequestError:{s:"HIERARCHY_REQUEST_ERR",c:3,m:1},WrongDocumentError:{s:"WRONG_DOCUMENT_ERR",c:4,m:1},InvalidCharacterError:{s:"INVALID_CHARACTER_ERR",c:5,m:1},NoDataAllowedError:{s:"NO_DATA_ALLOWED_ERR",c:6,m:0},NoModificationAllowedError:{s:"NO_MODIFICATION_ALLOWED_ERR",c:7,m:1},NotFoundError:{s:"NOT_FOUND_ERR",c:8,m:1},NotSupportedError:{s:"NOT_SUPPORTED_ERR",c:9,m:1},InUseAttributeError:{s:"INUSE_ATTRIBUTE_ERR",c:10,m:1},InvalidStateError:{s:"INVALID_STATE_ERR",c:11,m:1},SyntaxError:{s:"SYNTAX_ERR",c:12,m:1},InvalidModificationError:{s:"INVALID_MODIFICATION_ERR",c:13,m:1},NamespaceError:{s:"NAMESPACE_ERR",c:14,m:1},InvalidAccessError:{s:"INVALID_ACCESS_ERR",c:15,m:1},ValidationError:{s:"VALIDATION_ERR",c:16,m:0},TypeMismatchError:{s:"TYPE_MISMATCH_ERR",c:17,m:1},SecurityError:{s:"SECURITY_ERR",c:18,m:1},NetworkError:{s:"NETWORK_ERR",c:19,m:1},AbortError:{s:"ABORT_ERR",c:20,m:1},URLMismatchError:{s:"URL_MISMATCH_ERR",c:21,m:1},QuotaExceededError:{s:"QUOTA_EXCEEDED_ERR",c:22,m:1},TimeoutError:{s:"TIMEOUT_ERR",c:23,m:1},InvalidNodeTypeError:{s:"INVALID_NODE_TYPE_ERR",c:24,m:1},DataCloneError:{s:"DATA_CLONE_ERR",c:25,m:1}}},e391:function(r,t,e){var n=e("577e");r.exports=function(r,t){return void 0===r?arguments.length<2?"":t:n(r)}},e3db:function(r,t){var e={}.toString;r.exports=Array.isArray||function(r){return"[object Array]"==e.call(r)}}}]); 11 | //# sourceMappingURL=chunk-689084fa.19f2e525.js.map -------------------------------------------------------------------------------- /app/src/main/assets/js/chunk-b1b79330.528aee60.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-b1b79330"],{"00b4":function(t,r,e){"use strict";e("ac1f");var n=e("23e7"),o=e("da84"),i=e("c65b"),a=e("e330"),c=e("1626"),s=e("861d"),u=function(){var t=!1,r=/[ac]/;return r.exec=function(){return t=!0,/./.exec.apply(this,arguments)},!0===r.test("abc")&&t}(),f=o.Error,d=a(/./.test);n({target:"RegExp",proto:!0,forced:!u},{test:function(t){var r=this.exec;if(!c(r))return d(this,t);var e=i(r,this,t);if(null!==e&&!s(e))throw new f("RegExp exec method returned something other than an Object or null");return!!e}})},"057f":function(t,r,e){var n=e("c6b6"),o=e("fc6a"),i=e("241c").f,a=e("4dae"),c="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(t){try{return i(t)}catch(r){return a(c)}};t.exports.f=function(t){return c&&"Window"==n(t)?s(t):i(o(t))}},"0eb6":function(t,r,e){"use strict";var n=e("23e7"),o=e("7c37"),i=e("d066"),a=e("d039"),c=e("7c73"),s=e("5c6c"),u=e("9bf2").f,f=e("37e8").f,d=e("6eeb"),l=e("1a2d"),p=e("19aa"),h=e("825a"),g=e("aa1f"),v=e("e391"),b=e("cf98"),y=e("c770"),m=e("69f3"),E=e("83ab"),x=e("c430"),_="DOMException",w="DATA_CLONE_ERR",S=i("Error"),R=i(_)||function(){try{var t=i("MessageChannel")||o("worker_threads").MessageChannel;(new t).port1.postMessage(new WeakMap)}catch(r){if(r.name==w&&25==r.code)return r.constructor}}(),O=R&&R.prototype,I=S.prototype,A=m.set,N=m.getterFor(_),M="stack"in S(_),C=function(t){return l(b,t)&&b[t].m?b[t].c:0},T=function(){p(this,D);var t=arguments.length,r=v(t<1?void 0:arguments[0]),e=v(t<2?void 0:arguments[1],"Error"),n=C(e);if(A(this,{type:_,name:e,message:r,code:n}),E||(this.name=e,this.message=r,this.code=n),M){var o=S(r);o.name=_,u(this,"stack",s(1,y(o.stack,1)))}},D=T.prototype=c(I),k=function(t){return{enumerable:!0,configurable:!0,get:t}},j=function(t){return k((function(){return N(this)[t]}))};E&&f(D,{name:j("name"),message:j("message"),code:j("code")}),u(D,"constructor",s(1,T));var B=a((function(){return!(new R instanceof S)})),P=B||a((function(){return I.toString!==g||"2: 1"!==String(new R(1,2))})),F=B||a((function(){return 25!==new R(1,"DataCloneError").code})),H=B||25!==R[w]||25!==O[w],U=x?P||F||H:B;n({global:!0,forced:U},{DOMException:U?T:R});var z=i(_),L=z.prototype;for(var J in P&&(x||R===z)&&d(L,"toString",g),F&&E&&R===z&&u(L,"code",k((function(){return C(h(this).name)}))),b)if(l(b,J)){var W=b[J],V=W.s,Z=s(6,W.c);l(z,V)||u(z,V,Z),l(L,V)||u(L,V,Z)}},"107c":function(t,r,e){var n=e("d039"),o=e("da84"),i=o.RegExp;t.exports=n((function(){var t=i("(?b)","g");return"b"!==t.exec("b").groups.a||"bc"!=="b".replace(t,"$c")}))},1276:function(t,r,e){"use strict";var n=e("2ba4"),o=e("c65b"),i=e("e330"),a=e("d784"),c=e("44e7"),s=e("825a"),u=e("1d80"),f=e("4840"),d=e("8aa5"),l=e("50c4"),p=e("577e"),h=e("dc4a"),g=e("4dae"),v=e("14c3"),b=e("9263"),y=e("9f7f"),m=e("d039"),E=y.UNSUPPORTED_Y,x=4294967295,_=Math.min,w=[].push,S=i(/./.exec),R=i(w),O=i("".slice),I=!m((function(){var t=/(?:)/,r=t.exec;t.exec=function(){return r.apply(this,arguments)};var e="ab".split(t);return 2!==e.length||"a"!==e[0]||"b"!==e[1]}));a("split",(function(t,r,e){var i;return i="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,e){var i=p(u(this)),a=void 0===e?x:e>>>0;if(0===a)return[];if(void 0===t)return[i];if(!c(t))return o(r,i,t,a);var s,f,d,l=[],h=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),v=0,y=new RegExp(t.source,h+"g");while(s=o(b,y,i)){if(f=y.lastIndex,f>v&&(R(l,O(i,v,s.index)),s.length>1&&s.index=a))break;y.lastIndex===s.index&&y.lastIndex++}return v===i.length?!d&&S(y,"")||R(l,""):R(l,O(i,v)),l.length>a?g(l,0,a):l}:"0".split(void 0,0).length?function(t,e){return void 0===t&&0===e?[]:o(r,this,t,e)}:r,[function(r,e){var n=u(this),a=void 0==r?void 0:h(r,t);return a?o(a,r,n,e):o(i,p(n),r,e)},function(t,n){var o=s(this),a=p(t),c=e(i,o,a,n,i!==r);if(c.done)return c.value;var u=f(o,RegExp),h=o.unicode,g=(o.ignoreCase?"i":"")+(o.multiline?"m":"")+(o.unicode?"u":"")+(E?"g":"y"),b=new u(E?"^(?:"+o.source+")":o,g),y=void 0===n?x:n>>>0;if(0===y)return[];if(0===a.length)return null===v(b,a)?[a]:[];var m=0,w=0,S=[];while(w=51||!n((function(){var r=[],e=r.constructor={};return e[a]=function(){return{foo:1}},1!==r[t](Boolean).foo}))}},"25f0":function(t,r,e){"use strict";var n=e("e330"),o=e("5e77").PROPER,i=e("6eeb"),a=e("825a"),c=e("3a9b"),s=e("577e"),u=e("d039"),f=e("ad6d"),d="toString",l=RegExp.prototype,p=l[d],h=n(f),g=u((function(){return"/a/b"!=p.call({source:"a",flags:"b"})})),v=o&&p.name!=d;(g||v)&&i(RegExp.prototype,d,(function(){var t=a(this),r=s(t.source),e=t.flags,n=s(void 0===e&&c(l,t)&&!("flags"in l)?h(t):e);return"/"+r+"/"+n}),{unsafe:!0})},"428f":function(t,r,e){var n=e("da84");t.exports=n},"44e7":function(t,r,e){var n=e("861d"),o=e("c6b6"),i=e("b622"),a=i("match");t.exports=function(t){var r;return n(t)&&(void 0!==(r=t[a])?!!r:"RegExp"==o(t))}},"4dae":function(t,r,e){var n=e("da84"),o=e("23cb"),i=e("07fa"),a=e("8418"),c=n.Array,s=Math.max;t.exports=function(t,r,e){for(var n=i(t),u=o(r,n),f=o(void 0===e?n:e,n),d=c(s(f-u,0)),l=0;u>(-2*m&6))));return i}})},8418:function(t,r,e){"use strict";var n=e("a04b"),o=e("9bf2"),i=e("5c6c");t.exports=function(t,r,e){var a=n(r);a in t?o.f(t,a,i(0,e)):t[a]=e}},"8aa5":function(t,r,e){"use strict";var n=e("6547").charAt;t.exports=function(t,r,e){return r+(e?n(t,r).length:1)}},"8bd4":function(t,r,e){var n=e("d066"),o=e("d44e"),i="DOMException";o(n(i),i)},9263:function(t,r,e){"use strict";var n=e("c65b"),o=e("e330"),i=e("577e"),a=e("ad6d"),c=e("9f7f"),s=e("5692"),u=e("7c73"),f=e("69f3").get,d=e("fce3"),l=e("107c"),p=s("native-string-replace",String.prototype.replace),h=RegExp.prototype.exec,g=h,v=o("".charAt),b=o("".indexOf),y=o("".replace),m=o("".slice),E=function(){var t=/a/,r=/b*/g;return n(h,t,"a"),n(h,r,"a"),0!==t.lastIndex||0!==r.lastIndex}(),x=c.BROKEN_CARET,_=void 0!==/()??/.exec("")[1],w=E||_||x||d||l;w&&(g=function(t){var r,e,o,c,s,d,l,w=this,S=f(w),R=i(t),O=S.raw;if(O)return O.lastIndex=w.lastIndex,r=n(g,O,R),w.lastIndex=O.lastIndex,r;var I=S.groups,A=x&&w.sticky,N=n(a,w),M=w.source,C=0,T=R;if(A&&(N=y(N,"y",""),-1===b(N,"g")&&(N+="g"),T=m(R,w.lastIndex),w.lastIndex>0&&(!w.multiline||w.multiline&&"\n"!==v(R,w.lastIndex-1))&&(M="(?: "+M+")",T=" "+T,C++),e=new RegExp("^(?:"+M+")",N)),_&&(e=new RegExp("^"+M+"$(?!\\s)",N)),E&&(o=w.lastIndex),c=n(h,A?e:w,T),A?c?(c.input=m(c.input,C),c[0]=m(c[0],C),c.index=w.lastIndex,w.lastIndex+=c[0].length):w.lastIndex=0:E&&c&&(w.lastIndex=w.global?c.index+c[0].length:o),_&&c&&c.length>1&&n(p,c[0],e,(function(){for(s=1;s=51||!i((function(){var t=[];return t[g]=!1,t.concat()[0]!==t})),E=l("concat"),x=function(t){if(!c(t))return!1;var r=t[g];return void 0!==r?!!r:a(t)},_=!m||!E;n({target:"Array",proto:!0,forced:_},{concat:function(t){var r,e,n,o,i,a=s(this),c=d(a,0),l=0;for(r=-1,n=arguments.length;rv)throw y(b);for(e=0;e=v)throw y(b);f(c,l++,i)}return c.length=l,c}})},"9f7f":function(t,r,e){var n=e("d039"),o=e("da84"),i=o.RegExp,a=n((function(){var t=i("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),c=a||n((function(){return!i("a","y").sticky})),s=a||n((function(){var t=i("^r","gy");return t.lastIndex=2,null!=t.exec("str")}));t.exports={BROKEN_CARET:s,MISSED_STICKY:c,UNSUPPORTED_Y:a}},a15b:function(t,r,e){"use strict";var n=e("23e7"),o=e("e330"),i=e("44ad"),a=e("fc6a"),c=e("a640"),s=o([].join),u=i!=Object,f=c("join",",");n({target:"Array",proto:!0,forced:u||!f},{join:function(t){return s(a(this),void 0===t?",":t)}})},a434:function(t,r,e){"use strict";var n=e("23e7"),o=e("da84"),i=e("23cb"),a=e("5926"),c=e("07fa"),s=e("7b0b"),u=e("65f0"),f=e("8418"),d=e("1dde"),l=d("splice"),p=o.TypeError,h=Math.max,g=Math.min,v=9007199254740991,b="Maximum allowed length exceeded";n({target:"Array",proto:!0,forced:!l},{splice:function(t,r){var e,n,o,d,l,y,m=s(this),E=c(m),x=i(t,E),_=arguments.length;if(0===_?e=n=0:1===_?(e=0,n=E-x):(e=_-2,n=g(h(a(r),0),E-x)),E+e-n>v)throw p(b);for(o=u(m,n),d=0;dE-n+e;d--)delete m[d-1]}else if(e>n)for(d=E-n;d>x;d--)l=d+n-1,y=d+e-1,l in m?m[y]=m[l]:delete m[y];for(d=0;d=o&&window.console&&window.console.log.apply(console,Array.prototype.slice.call(arguments,1))}var c=c||function(t,r){var e={},n=e.lib={},o=function(){},i=n.Base={extend:function(t){o.prototype=this;var r=new o;return t&&r.mixIn(t),r.hasOwnProperty("init")||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},a=n.WordArray=i.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=e!=r?e:4*t.length},toString:function(t){return(t||s).stringify(this)},concat:function(t){var r=this.words,e=t.words,n=this.sigBytes;if(t=t.sigBytes,this.clamp(),n%4)for(var o=0;o>>2]|=(e[o>>>2]>>>24-o%4*8&255)<<24-(n+o)%4*8;else if(65535>>2]=e[o>>>2];else r.push.apply(r,e);return this.sigBytes+=t,this},clamp:function(){var r=this.words,e=this.sigBytes;r[e>>>2]&=4294967295<<32-e%4*8,r.length=t.ceil(e/4)},clone:function(){var t=i.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){for(var e=[],n=0;n>>2]>>>24-n%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,e=[],n=0;n>>3]|=parseInt(t.substr(n,2),16)<<24-n%8*4;return new a.init(e,r/2)}},u=c.Latin1={stringify:function(t){var r=t.words;t=t.sigBytes;for(var e=[],n=0;n>>2]>>>24-n%4*8&255));return e.join("")},parse:function(t){for(var r=t.length,e=[],n=0;n>>2]|=(255&t.charCodeAt(n))<<24-n%4*8;return new a.init(e,r)}},f=c.Utf8={stringify:function(t){try{return decodeURIComponent(escape(u.stringify(t)))}catch(r){throw Error("Malformed UTF-8 data")}},parse:function(t){return u.parse(unescape(encodeURIComponent(t)))}},d=n.BufferedBlockAlgorithm=i.extend({reset:function(){this._data=new a.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=f.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var e=this._data,n=e.words,o=e.sigBytes,i=this.blockSize,c=o/(4*i),s=r?t.ceil(c):t.max((0|c)-this._minBufferSize,0);if(r=s*i,o=t.min(4*r,o),r){for(var u=0;uu;u++){if(16>u)o[u]=0|t[r+u];else{var f=o[u-3]^o[u-8]^o[u-14]^o[u-16];o[u]=f<<1|f>>>31}f=(n<<5|n>>>27)+s+o[u],f=20>u?f+(1518500249+(i&a|~i&c)):40>u?f+(1859775393+(i^a^c)):60>u?f+((i&a|i&c|a&c)-1894007588):f+((i^a^c)-899497514),s=c,c=a,a=i<<30|i>>>2,i=n,n=f}e[0]=e[0]+n|0,e[1]=e[1]+i|0,e[2]=e[2]+a|0,e[3]=e[3]+c|0,e[4]=e[4]+s|0},_doFinalize:function(){var t=this._data,r=t.words,e=8*this._nDataBytes,n=8*t.sigBytes;return r[n>>>5]|=128<<24-n%32,r[14+(n+64>>>9<<4)]=Math.floor(e/4294967296),r[15+(n+64>>>9<<4)]=e,t.sigBytes=4*r.length,this._process(),this._hash},clone:function(){var t=n.clone.call(this);return t._hash=this._hash.clone(),t}});t.SHA1=n._createHelper(i),t.HmacSHA1=n._createHmacHelper(i)})();var s,u={isIOS:function(){var t=/iphone|ipad|ipod/i;return!!t.test(window.navigator.userAgent)},b64DecodeUnicode:function(t){return decodeURIComponent(atob(t).split("").map((function(t){return"%"+("00"+t.charCodeAt(0).toString(16)).slice(-2)})).join(""))}};if(u.isIOS()){if(window.webkit&&window.webkit.messageHandlers&&(s=window.webkit.messageHandlers),!s)return"inject err: __zf not found";delete window.webkit.messageHandlers}else{if(s=window.__zf,!s)return"inject err: __zf not found";delete window.__zf}t>=o&&a(t,"inject start");var f=Date.now(),d=1e3,l={},p="msgType",h="callbackId",g="eventName",v={},b="${_dgtVerifyRandomStr}",y="jsonMessage",m="shaKey",E=b;t>=o&&a(t,"__zf inject VerifyRandomStr:"+E);var x=R,_=O;function w(t){var r=JSON.stringify(t),e=new Array;e[0]=r,e[1]=E;var n=e.join(""),o="",i=c.SHA1(n);o=i.toString();var a={};a[y]=r,a[m]=o,r=JSON.stringify(a),S(r)}function S(r){t>=o&&a(t,"_doSendMessage , msgStr : "+r),u.isIOS()?s._sendMessage.postMessage(r):s._sendMessage(r)}function R(r){var e=A._handleMessageFromZF;if(e!==x)return"{}";var n=JSON.parse(r),i=u.b64DecodeUnicode(n[y]),s=JSON.parse(i),f=n[m],d=new Array;d[0]=n[y],d[1]=E;var b=d.join(""),_="",w=c.SHA1(b);if(_=w.toString(),t>=o&&a(t,"_handleMessageFromZF , msgWrapStr : "+i),_!==f)return t>=o&&a(t,"_handleMessageFromZF shaStr not match, shaStr : "+f+" , str : "+b+" , msgSha : "+_),"{}";switch(s[p]){case"callback":if("string"===typeof s[h]&&"function"===typeof l[s[h]]){var S=l[s[h]](s["params"]);delete l[s[h]];var R=void 0!=S;S=S||{},S["errCode"]=S["errCode"]||0;var O=JSON.stringify(S);return t>=o&&R&&a(t,"_handleMessageFromZF , callBackRetStr : "+O),O}return JSON.stringify({errCode:"404"});case"event":if("function"===typeof v[s[g]]){var I=v[s[g]](s["params"]);R=void 0!=S;I=I||{},I["errCode"]=I["errCode"]||0;var N=JSON.stringify(I);return t>=o&&R&&a(t,"_handleMessageFromZF , eventRetStr : "+N),N}return JSON.stringify({errCode:"404"})}return JSON.stringify({errCode:"404"})}function O(t,r,o){var i=A.call;if(i===_&&t&&"string"===typeof t){"object"!==n(r)&&(r={});var c=(d++).toString();"function"===typeof o&&(l[c]=o);var s={apiName:t,params:r};s[p]="call",s[h]=c;try{w(s)}catch(u){a(e,"_call error",u)}}}function I(r,e){t>=o&&a(t,"_on event ,eventName : "+r+" callback : "+e),r&&"string"===typeof r&&"function"===typeof e&&(v[r]=e)}var A={call:O,on:I,_hasInit:!1};try{Object.defineProperty(A,"_handleMessageFromZF",{value:R,writable:!1,configurable:!1})}catch(N){return a(e,"define _handleMessageFromZF",N),"zfJSBridge init err:"+N.message}try{Object.defineProperty(window,"zfJSBridge",{value:A,writable:!1,configurable:!1})}catch(N){return a(e,"define zfJSBridge",N),"inject err:"+N.message}t>=o&&a(r,"inject exec time",Date.now()-f)}()},aa1f:function(t,r,e){"use strict";var n=e("83ab"),o=e("d039"),i=e("825a"),a=e("7c73"),c=e("e391"),s=Error.prototype.toString,u=o((function(){if(n){var t=a(Object.defineProperty({},"name",{get:function(){return this===t}}));if("true"!==s.call(t))return!0}return"2: 1"!==s.call({message:1,name:2})||"Error"!==s.call({})}));t.exports=u?function(){var t=i(this),r=c(t.name,"Error"),e=c(t.message);return r?e?r+": "+e:r:e}:s},ab36:function(t,r,e){var n=e("861d"),o=e("9112");t.exports=function(t,r){n(r)&&"cause"in r&&o(t,"cause",r.cause)}},ac1f:function(t,r,e){"use strict";var n=e("23e7"),o=e("9263");n({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},ad6d:function(t,r,e){"use strict";var n=e("825a");t.exports=function(){var t=n(this),r="";return t.global&&(r+="g"),t.ignoreCase&&(r+="i"),t.multiline&&(r+="m"),t.dotAll&&(r+="s"),t.unicode&&(r+="u"),t.sticky&&(r+="y"),r}},b7ef:function(t,r,e){"use strict";var n=e("23e7"),o=e("d066"),i=e("5c6c"),a=e("9bf2").f,c=e("1a2d"),s=e("19aa"),u=e("7156"),f=e("e391"),d=e("cf98"),l=e("c770"),p=e("c430"),h="DOMException",g=o("Error"),v=o(h),b=function(){s(this,y);var t=arguments.length,r=f(t<1?void 0:arguments[0]),e=f(t<2?void 0:arguments[1],"Error"),n=new v(r,e),o=g(r);return o.name=h,a(n,"stack",i(1,l(o.stack,1))),u(n,this,b),n},y=b.prototype=v.prototype,m="stack"in g(h),E="stack"in new v(1,2),x=m&&!E;n({global:!0,forced:p||x},{DOMException:x?b:v});var _=o(h),w=_.prototype;if(w.constructor!==_)for(var S in p||a(w,"constructor",i(1,_)),d)if(c(d,S)){var R=d[S],O=R.s;c(_,O)||a(_,O,i(6,R.c))}},b917:function(t,r){for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",n={},o=0;o<66;o++)n[e.charAt(o)]=o;t.exports={itoc:e,ctoi:n}},b980:function(t,r,e){var n=e("d039"),o=e("5c6c");t.exports=!n((function(){var t=Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",o(1,7)),7!==t.stack)}))},c770:function(t,r,e){var n=e("e330"),o=n("".replace),i=function(t){return String(Error(t).stack)}("zxcasd"),a=/\n\s*at [^:]*:[^\n]*/,c=a.test(i);t.exports=function(t,r){if(c&&"string"==typeof t)while(r--)t=o(t,a,"");return t}},cf98:function(t,r){t.exports={IndexSizeError:{s:"INDEX_SIZE_ERR",c:1,m:1},DOMStringSizeError:{s:"DOMSTRING_SIZE_ERR",c:2,m:0},HierarchyRequestError:{s:"HIERARCHY_REQUEST_ERR",c:3,m:1},WrongDocumentError:{s:"WRONG_DOCUMENT_ERR",c:4,m:1},InvalidCharacterError:{s:"INVALID_CHARACTER_ERR",c:5,m:1},NoDataAllowedError:{s:"NO_DATA_ALLOWED_ERR",c:6,m:0},NoModificationAllowedError:{s:"NO_MODIFICATION_ALLOWED_ERR",c:7,m:1},NotFoundError:{s:"NOT_FOUND_ERR",c:8,m:1},NotSupportedError:{s:"NOT_SUPPORTED_ERR",c:9,m:1},InUseAttributeError:{s:"INUSE_ATTRIBUTE_ERR",c:10,m:1},InvalidStateError:{s:"INVALID_STATE_ERR",c:11,m:1},SyntaxError:{s:"SYNTAX_ERR",c:12,m:1},InvalidModificationError:{s:"INVALID_MODIFICATION_ERR",c:13,m:1},NamespaceError:{s:"NAMESPACE_ERR",c:14,m:1},InvalidAccessError:{s:"INVALID_ACCESS_ERR",c:15,m:1},ValidationError:{s:"VALIDATION_ERR",c:16,m:0},TypeMismatchError:{s:"TYPE_MISMATCH_ERR",c:17,m:1},SecurityError:{s:"SECURITY_ERR",c:18,m:1},NetworkError:{s:"NETWORK_ERR",c:19,m:1},AbortError:{s:"ABORT_ERR",c:20,m:1},URLMismatchError:{s:"URL_MISMATCH_ERR",c:21,m:1},QuotaExceededError:{s:"QUOTA_EXCEEDED_ERR",c:22,m:1},TimeoutError:{s:"TIMEOUT_ERR",c:23,m:1},InvalidNodeTypeError:{s:"INVALID_NODE_TYPE_ERR",c:24,m:1},DataCloneError:{s:"DATA_CLONE_ERR",c:25,m:1}}},d28b:function(t,r,e){var n=e("746f");n("iterator")},d784:function(t,r,e){"use strict";e("ac1f");var n=e("e330"),o=e("6eeb"),i=e("9263"),a=e("d039"),c=e("b622"),s=e("9112"),u=c("species"),f=RegExp.prototype;t.exports=function(t,r,e,d){var l=c(t),p=!a((function(){var r={};return r[l]=function(){return 7},7!=""[t](r)})),h=p&&!a((function(){var r=!1,e=/a/;return"split"===t&&(e={},e.constructor={},e.constructor[u]=function(){return e},e.flags="",e[l]=/./[l]),e.exec=function(){return r=!0,null},e[l](""),!r}));if(!p||!h||e){var g=n(/./[l]),v=r(l,""[t],(function(t,r,e,o,a){var c=n(t),s=r.exec;return s===i||s===f.exec?p&&!a?{done:!0,value:g(r,e,o)}:{done:!0,value:c(e,r,o)}:{done:!1}}));o(String.prototype,t,v[0]),o(f,l,v[1])}d&&s(f[l],"sham",!0)}},d81d:function(t,r,e){"use strict";var n=e("23e7"),o=e("b727").map,i=e("1dde"),a=i("map");n({target:"Array",proto:!0,forced:!a},{map:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},d9e2:function(t,r,e){var n=e("23e7"),o=e("da84"),i=e("2ba4"),a=e("e5cb"),c="WebAssembly",s=o[c],u=7!==Error("e",{cause:7}).cause,f=function(t,r){var e={};e[t]=a(t,r,u),n({global:!0,forced:u},e)},d=function(t,r){if(s&&s[t]){var e={};e[t]=a(c+"."+t,r,u),n({target:c,stat:!0,forced:u},e)}};f("Error",(function(t){return function(r){return i(t,this,arguments)}})),f("EvalError",(function(t){return function(r){return i(t,this,arguments)}})),f("RangeError",(function(t){return function(r){return i(t,this,arguments)}})),f("ReferenceError",(function(t){return function(r){return i(t,this,arguments)}})),f("SyntaxError",(function(t){return function(r){return i(t,this,arguments)}})),f("TypeError",(function(t){return function(r){return i(t,this,arguments)}})),f("URIError",(function(t){return function(r){return i(t,this,arguments)}})),d("CompileError",(function(t){return function(r){return i(t,this,arguments)}})),d("LinkError",(function(t){return function(r){return i(t,this,arguments)}})),d("RuntimeError",(function(t){return function(r){return i(t,this,arguments)}}))},e01a:function(t,r,e){"use strict";var n=e("23e7"),o=e("83ab"),i=e("da84"),a=e("e330"),c=e("1a2d"),s=e("1626"),u=e("3a9b"),f=e("577e"),d=e("9bf2").f,l=e("e893"),p=i.Symbol,h=p&&p.prototype;if(o&&s(p)&&(!("description"in h)||void 0!==p().description)){var g={},v=function(){var t=arguments.length<1||void 0===arguments[0]?void 0:f(arguments[0]),r=u(h,this)?new p(t):void 0===t?p():p(t);return""===t&&(g[r]=!0),r};l(v,p),v.prototype=h,h.constructor=v;var b="Symbol(test)"==String(p("test")),y=a(h.toString),m=a(h.valueOf),E=/^Symbol\((.*)\)[^)]+$/,x=a("".replace),_=a("".slice);d(h,"description",{configurable:!0,get:function(){var t=m(this),r=y(t);if(c(g,t))return"";var e=b?_(r,7,-1):x(r,E,"$1");return""===e?void 0:e}}),n({global:!0,forced:!0},{Symbol:v})}},e391:function(t,r,e){var n=e("577e");t.exports=function(t,r){return void 0===t?arguments.length<2?"":r:n(t)}},e538:function(t,r,e){var n=e("b622");r.f=n},e5cb:function(t,r,e){"use strict";var n=e("d066"),o=e("1a2d"),i=e("9112"),a=e("3a9b"),c=e("d2bb"),s=e("e893"),u=e("7156"),f=e("e391"),d=e("ab36"),l=e("c770"),p=e("b980"),h=e("c430");t.exports=function(t,r,e,g){var v=g?2:1,b=t.split("."),y=b[b.length-1],m=n.apply(null,b);if(m){var E=m.prototype;if(!h&&o(E,"cause")&&delete E.cause,!e)return m;var x=n("Error"),_=r((function(t,r){var e=f(g?r:t,void 0),n=g?new m(t):new m;return void 0!==e&&i(n,"message",e),p&&i(n,"stack",l(n.stack,2)),this&&a(E,this)&&u(n,this,_),arguments.length>v&&d(n,arguments[v]),n}));if(_.prototype=E,"Error"!==y&&(c?c(_,x):s(_,x,{name:!0})),s(_,m),!h)try{E.name!==y&&i(E,"name",y),E.constructor=_}catch(w){}return _}}},fb6a:function(t,r,e){"use strict";var n=e("23e7"),o=e("da84"),i=e("e8b5"),a=e("68ee"),c=e("861d"),s=e("23cb"),u=e("07fa"),f=e("fc6a"),d=e("8418"),l=e("b622"),p=e("1dde"),h=e("f36a"),g=p("slice"),v=l("species"),b=o.Array,y=Math.max;n({target:"Array",proto:!0,forced:!g},{slice:function(t,r){var e,n,o,l=f(this),p=u(l),g=s(t,p),m=s(void 0===r?p:r,p);if(i(l)&&(e=l.constructor,a(e)&&(e===b||i(e.prototype))?e=void 0:c(e)&&(e=e[v],null===e&&(e=void 0)),e===b||void 0===e))return h(l,g,m);for(n=new(void 0===e?b:e)(y(m-g,0)),o=0;g valueCallback) { 54 | String js; 55 | if (TextUtils.isEmpty(params)) { 56 | js = String.format("%s()", methodName); 57 | } else { 58 | js = String.format("%s('%s')", methodName, params); 59 | } 60 | execJs(js, valueCallback); 61 | } 62 | 63 | @Override 64 | public void execJs(@NotNull final String sourceJs, @Nullable final ValueCallback valueCallback) { 65 | runOnMainThread(() -> evaluateJavascript(sourceJs, valueCallback)); 66 | } 67 | 68 | @Override 69 | public void runOnMainThread(@NotNull Runnable runnable) { 70 | if (Looper.getMainLooper() == Looper.myLooper()) { 71 | runnable.run(); 72 | return; 73 | } 74 | post(runnable); 75 | } 76 | 77 | @NotNull 78 | @Override 79 | public String getCurUrl() { 80 | return getUrl(); 81 | } 82 | 83 | @NotNull 84 | @Override 85 | public Context getCurContext() { 86 | return getContext(); 87 | } 88 | 89 | @NotNull 90 | @Override 91 | public ZWebHelper getCurZWebHelper() { 92 | return zWebHelper; 93 | } 94 | 95 | private class InnerCustomWebViewClient extends WebViewClient { 96 | @Override 97 | public void onPageFinished(WebView view, String url) { 98 | super.onPageFinished(view, url); 99 | zWebHelper.injectCoreJs(); 100 | } 101 | 102 | @Override 103 | public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { 104 | super.doUpdateVisitedHistory(view, url, isReload); 105 | zWebHelper.injectCoreJs(); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/chromium/TestWebViewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.chromium 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import androidx.appcompat.app.AppCompatActivity 6 | import com.hcanyz.zjsbridge.cotainer.IZWebViewContainer 7 | import com.hcanyz.zjsbridge.handler.ZCommonJsHandler 8 | import com.hcanyz.zjsbridge.jshandlerimpl.image.ImageJsHandler 9 | import com.hcanyz.zjsbridge.test.R 10 | import com.hcanyz.zjsbridge.test.test.TestJsHandler 11 | import kotlinx.android.synthetic.main.activity_test_web_view.* 12 | 13 | class TestWebViewActivity : AppCompatActivity(), IZWebViewContainer { 14 | 15 | override fun onCreate(savedInstanceState: Bundle?) { 16 | super.onCreate(savedInstanceState) 17 | 18 | setContentView(R.layout.activity_test_web_view) 19 | 20 | web_test.loadUrl("file:///android_asset/index.html") 21 | 22 | web_test.getCurZWebHelper().registeredJsApiHandler(this, ZCommonJsHandler::class.java) 23 | web_test.getCurZWebHelper().registeredJsApiHandler(this, ImageJsHandler::class.java) 24 | web_test.getCurZWebHelper().registeredJsApiHandler(this, TestJsHandler::class.java) 25 | } 26 | 27 | override fun closeWindow() { 28 | finish() 29 | } 30 | 31 | override fun updateTitle(title: String) { 32 | tv_test_tile.text = title 33 | } 34 | 35 | override fun onResume() { 36 | super.onResume() 37 | web_test.getCurZWebHelper().jsEventer.event("onContainerResume") 38 | } 39 | 40 | override fun onPause() { 41 | super.onPause() 42 | web_test.getCurZWebHelper().jsEventer.event("onContainerPause") 43 | } 44 | 45 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 46 | super.onActivityResult(requestCode, resultCode, data) 47 | web_test.getCurZWebHelper().dispatchContainerResult(requestCode, resultCode, data) 48 | } 49 | 50 | override fun onDetachedFromWindow() { 51 | super.onDetachedFromWindow() 52 | web_test.getCurZWebHelper().dispatchContainerDestroy() 53 | } 54 | 55 | override fun onBackPressed() { 56 | if (web_test.canGoBack()) { 57 | web_test.goBack() 58 | } else { 59 | super.onBackPressed() 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/fragment/ChromiumWebView.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.fragment 2 | 3 | import android.content.Context 4 | import android.os.Looper 5 | import android.util.AttributeSet 6 | import android.webkit.ValueCallback 7 | import android.webkit.WebView 8 | import android.webkit.WebViewClient 9 | import com.hcanyz.zjsbridge.ZJsBridge 10 | import com.hcanyz.zjsbridge.bridge.ZJavascriptInterface 11 | import com.hcanyz.zjsbridge.cotainer.IZWebView 12 | import com.hcanyz.zjsbridge.cotainer.ZWebHelper 13 | 14 | 15 | class ChromiumWebView : WebView, IZWebView { 16 | 17 | constructor(p0: Context?) : super(p0) 18 | constructor(p0: Context?, p1: AttributeSet?) : super(p0, p1) 19 | constructor(p0: Context?, p1: AttributeSet?, p2: Int) : super(p0, p1, p2) 20 | 21 | private val zWebHelper: ZWebHelper by lazy { ZWebHelper(this) } 22 | 23 | init { 24 | val settings = settings 25 | @Suppress("SetJavaScriptEnabled") 26 | settings.javaScriptEnabled = true 27 | 28 | settings.userAgentString = settings.userAgentString + " zfjs/1.0.0" 29 | 30 | //提供js-bridge层注入 31 | webViewClient = InnerCustomWebViewClient() 32 | 33 | //注册bridge事件处理对象 34 | addJavascriptInterface(ZJavascriptInterface(this), ZJavascriptInterface.INTERFACE_NAME) 35 | } 36 | 37 | override fun getCurUrl(): String { 38 | return url 39 | } 40 | 41 | override fun getCurContext(): Context { 42 | return context 43 | } 44 | 45 | override fun getCurZWebHelper(): ZWebHelper { 46 | return zWebHelper 47 | } 48 | 49 | override fun execJs(methodName: String, params: String?, valueCallback: ValueCallback?) { 50 | val js: String = if (params.isNullOrBlank()) { 51 | String.format("%s()", methodName) 52 | } else { 53 | String.format("%s('%s')", methodName, params) 54 | } 55 | execJs(js, valueCallback) 56 | } 57 | 58 | override fun execJs(sourceJs: String, valueCallback: ValueCallback?) { 59 | if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("evaluateJavascript:javascript:$sourceJs") 60 | runOnMainThread(Runnable { 61 | evaluateJavascript("javascript:$sourceJs", valueCallback) 62 | }) 63 | } 64 | 65 | override fun runOnMainThread(runnable: Runnable) { 66 | if (Looper.getMainLooper() == Looper.myLooper()) { 67 | runnable.run() 68 | return 69 | } 70 | post(runnable) 71 | } 72 | 73 | private inner class InnerCustomWebViewClient : WebViewClient() { 74 | override fun onPageFinished(webView: WebView?, s: String?) { 75 | super.onPageFinished(webView, s) 76 | //注入js-bridge,可以多次调用,js-bridge有幂等处理 77 | zWebHelper.injectCoreJs() 78 | } 79 | 80 | override fun doUpdateVisitedHistory(p0: WebView?, p1: String?, p2: Boolean) { 81 | super.doUpdateVisitedHistory(p0, p1, p2) 82 | //注入js-bridge,可以多次调用,js-bridge有幂等处理 83 | zWebHelper.injectCoreJs() 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/fragment/TestInFragmentActivity.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.fragment 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.hcanyz.zjsbridge.test.R 6 | 7 | class TestInFragmentActivity : AppCompatActivity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.activity_test_in_fragment) 12 | 13 | val fragment = supportFragmentManager.findFragmentByTag("TestWebViewFragment") 14 | ?: TestWebViewFragment() 15 | supportFragmentManager.beginTransaction().add(R.id.fl_container, fragment, "TestWebViewFragment").commit() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/fragment/TestWebViewFragment.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.fragment 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.activity.OnBackPressedCallback 9 | import androidx.fragment.app.Fragment 10 | import com.hcanyz.zjsbridge.cotainer.IZWebViewContainer 11 | import com.hcanyz.zjsbridge.handler.ZCommonJsHandler 12 | import com.hcanyz.zjsbridge.jshandlerimpl.image.ImageJsHandler 13 | import com.hcanyz.zjsbridge.test.R 14 | import com.hcanyz.zjsbridge.test.test.TestJsHandler 15 | import kotlinx.android.synthetic.main.fragmenttest_web_view.* 16 | 17 | class TestWebViewFragment : Fragment(), IZWebViewContainer { 18 | 19 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 20 | return inflater.inflate(R.layout.fragmenttest_web_view, container, false) 21 | } 22 | 23 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 24 | super.onViewCreated(view, savedInstanceState) 25 | 26 | web_test.loadUrl("file:///android_asset/index.html") 27 | 28 | web_test.getCurZWebHelper().registeredJsApiHandler(this, ZCommonJsHandler::class.java) 29 | web_test.getCurZWebHelper().registeredJsApiHandler(this, ImageJsHandler::class.java) 30 | web_test.getCurZWebHelper().registeredJsApiHandler(this, TestJsHandler::class.java) 31 | 32 | requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { 33 | override fun handleOnBackPressed() { 34 | if (web_test.canGoBack()) { 35 | web_test.goBack() 36 | } else { 37 | requireActivity().finish() 38 | } 39 | } 40 | }) 41 | } 42 | 43 | override fun onResume() { 44 | super.onResume() 45 | web_test.getCurZWebHelper().jsEventer.event("onContainerResume") 46 | } 47 | 48 | override fun onPause() { 49 | super.onPause() 50 | web_test.getCurZWebHelper().jsEventer.event("onContainerPause") 51 | } 52 | 53 | override fun closeWindow() { 54 | requireActivity().finish() 55 | } 56 | 57 | override fun updateTitle(title: String) { 58 | tv_test_tile.text = title 59 | } 60 | 61 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 62 | super.onActivityResult(requestCode, resultCode, data) 63 | web_test.getCurZWebHelper().dispatchContainerResult(requestCode, resultCode, data) 64 | } 65 | 66 | override fun onDestroyView() { 67 | super.onDestroyView() 68 | web_test.getCurZWebHelper().dispatchContainerDestroy() 69 | } 70 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/test/TestJsHandler.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.test 2 | 3 | import android.widget.Toast 4 | import com.hcanyz.zjsbridge.bridge.ZJsCallBacker 5 | import com.hcanyz.zjsbridge.handler.ZBaseJsApiHandler 6 | import org.json.JSONObject 7 | 8 | class TestJsHandler : ZBaseJsApiHandler() { 9 | 10 | override fun handleApi(apiName: String, params: String, jsCallBacker: ZJsCallBacker): Boolean { 11 | when (apiName) { 12 | "_test_unicode_params_and_result" -> { 13 | val activity = getActivity() ?: return true 14 | 15 | Toast.makeText(activity, params, Toast.LENGTH_LONG).show() 16 | 17 | val result = JSONObject() 18 | result.put("unicodeResult", "中文 Emoji 😂🤣") 19 | jsCallBacker.success(result) 20 | return true 21 | } 22 | } 23 | return false 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/x5/TestX5WebViewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.x5 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.view.View 6 | import androidx.appcompat.app.AppCompatActivity 7 | import com.hcanyz.zjsbridge.cotainer.IZWebViewContainer 8 | import com.hcanyz.zjsbridge.handler.ZCommonJsHandler 9 | import com.hcanyz.zjsbridge.jshandlerimpl.image.ImageJsHandler 10 | import com.hcanyz.zjsbridge.test.R 11 | import com.hcanyz.zjsbridge.test.test.TestJsHandler 12 | import kotlinx.android.synthetic.main.activity_test_x5_web_view.* 13 | 14 | class TestX5WebViewActivity : AppCompatActivity(), IZWebViewContainer { 15 | 16 | override fun onCreate(savedInstanceState: Bundle?) { 17 | super.onCreate(savedInstanceState) 18 | 19 | setContentView(R.layout.activity_test_x5_web_view) 20 | 21 | x5web_test.loadUrl("file:///android_asset/index.html") 22 | 23 | x5web_test.getCurZWebHelper().registeredJsApiHandler(this, ZCommonJsHandler::class.java) 24 | x5web_test.getCurZWebHelper().registeredJsApiHandler(this, ImageJsHandler::class.java) 25 | x5web_test.getCurZWebHelper().registeredJsApiHandler(this, TestJsHandler::class.java) 26 | } 27 | 28 | override fun onResume() { 29 | super.onResume() 30 | x5web_test.getCurZWebHelper().jsEventer.event("onContainerResume") 31 | } 32 | 33 | override fun onPause() { 34 | super.onPause() 35 | x5web_test.getCurZWebHelper().jsEventer.event("onContainerPause") 36 | } 37 | 38 | override fun closeWindow() { 39 | finish() 40 | } 41 | 42 | override fun updateTitle(title: String) { 43 | tv_test_tile.text = title 44 | } 45 | 46 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 47 | super.onActivityResult(requestCode, resultCode, data) 48 | x5web_test.getCurZWebHelper().dispatchContainerResult(requestCode, resultCode, data) 49 | } 50 | 51 | override fun onDetachedFromWindow() { 52 | super.onDetachedFromWindow() 53 | x5web_test.getCurZWebHelper().dispatchContainerDestroy() 54 | } 55 | 56 | override fun onBackPressed() { 57 | if (x5web_test.visibility == View.VISIBLE && x5web_test.canGoBack()) { 58 | x5web_test.goBack() 59 | } else { 60 | super.onBackPressed() 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/hcanyz/zjsbridge/test/x5/X5WebView.kt: -------------------------------------------------------------------------------- 1 | package com.hcanyz.zjsbridge.test.x5 2 | 3 | import android.content.Context 4 | import android.os.Looper 5 | import android.util.AttributeSet 6 | import android.webkit.ValueCallback 7 | import com.hcanyz.zjsbridge.ZJsBridge 8 | import com.hcanyz.zjsbridge.bridge.ZJavascriptInterface 9 | import com.hcanyz.zjsbridge.cotainer.IZWebView 10 | import com.hcanyz.zjsbridge.cotainer.ZWebHelper 11 | import com.tencent.smtt.sdk.WebView 12 | import com.tencent.smtt.sdk.WebViewClient 13 | 14 | 15 | class X5WebView : WebView, IZWebView { 16 | 17 | constructor(p0: Context?) : super(p0) 18 | constructor(p0: Context?, p1: AttributeSet?) : super(p0, p1) 19 | constructor(p0: Context?, p1: AttributeSet?, p2: Int) : super(p0, p1, p2) 20 | constructor(p0: Context?, p1: AttributeSet?, p2: Int, p3: Boolean) : super(p0, p1, p2, p3) 21 | constructor(p0: Context?, p1: AttributeSet?, p2: Int, p3: MutableMap?, p4: Boolean) : super(p0, p1, p2, p3, p4) 22 | 23 | private val zWebHelper: ZWebHelper by lazy { ZWebHelper(this) } 24 | 25 | init { 26 | val settings = settings 27 | @Suppress("DEPRECATION") 28 | settings.javaScriptEnabled = true 29 | 30 | webViewClient = InnerCustomWebViewClient() 31 | 32 | settings.userAgentString = settings.userAgentString + " zfjs/1.0.0" 33 | 34 | addJavascriptInterface(ZJavascriptInterface(this), ZJavascriptInterface.INTERFACE_NAME) 35 | } 36 | 37 | override fun getCurUrl(): String { 38 | return url 39 | } 40 | 41 | override fun getCurContext(): Context { 42 | return context 43 | } 44 | 45 | override fun getCurZWebHelper(): ZWebHelper { 46 | return zWebHelper 47 | } 48 | 49 | override fun execJs(methodName: String, params: String?, valueCallback: ValueCallback?) { 50 | val js: String = if (params.isNullOrBlank()) { 51 | String.format("%s()", methodName) 52 | } else { 53 | String.format("%s('%s')", methodName, params) 54 | } 55 | execJs(js, valueCallback) 56 | } 57 | 58 | override fun execJs(sourceJs: String, valueCallback: ValueCallback?) { 59 | if (ZJsBridge.ZJS_DEBUG) ZJsBridge.log("evaluateJavascript:javascript:$sourceJs") 60 | runOnMainThread(Runnable { 61 | evaluateJavascript("javascript:$sourceJs") { valueCallback?.onReceiveValue(it) } 62 | }) 63 | } 64 | 65 | override fun runOnMainThread(runnable: Runnable) { 66 | if (Looper.getMainLooper() == Looper.myLooper()) { 67 | runnable.run() 68 | return 69 | } 70 | post(runnable) 71 | } 72 | 73 | private inner class InnerCustomWebViewClient : WebViewClient() { 74 | override fun onPageFinished(webView: WebView?, s: String?) { 75 | super.onPageFinished(webView, s) 76 | zWebHelper.injectCoreJs() 77 | } 78 | 79 | override fun doUpdateVisitedHistory(p0: WebView?, p1: String?, p2: Boolean) { 80 | super.doUpdateVisitedHistory(p0, p1, p2) 81 | zWebHelper.injectCoreJs() 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |