From 2957783273bbe6c14c7671ecb3a8696d1141767f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=A2=85=E7=90=A5?=
Date: Fri, 10 Apr 2020 19:13:50 +0800
Subject: [PATCH 01/14] =?UTF-8?q?=E4=BD=BF=E7=94=A8kotlin=E9=87=8D?=
=?UTF-8?q?=E6=9E=84=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
build.gradle | 2 +
.../jsbridge/example/MainActivity.java | 4 -
library/build.gradle | 6 +-
.../main/assets/WebViewJavascriptBridge.js | 133 ++++++++++
library/src/main/assets/jsbridge | 3 -
.../com/xiaomao/jsbridge/BridgeHandler.java | 7 -
.../com/xiaomao/jsbridge/BridgeHandler.kt | 5 +
.../java/com/xiaomao/jsbridge/BridgeUtil.java | 59 -----
.../java/com/xiaomao/jsbridge/BridgeUtil.kt | 12 +
.../jsbridge/BridgeWebChromeClient.java | 201 ---------------
.../com/xiaomao/jsbridge/BridgeWebView.java | 229 ------------------
.../com/xiaomao/jsbridge/BridgeWebView.kt | 36 +++
.../xiaomao/jsbridge/BridgeWebViewClient.java | 147 -----------
.../xiaomao/jsbridge/BridgeWebViewClient.kt | 185 ++++++++++++++
.../xiaomao/jsbridge/CallBackFunction.java | 7 -
.../com/xiaomao/jsbridge/DefaultHandler.java | 12 -
.../java/com/xiaomao/jsbridge/IWebView.kt | 13 +
.../java/com/xiaomao/jsbridge/JsBridge.kt | 178 ++++++++++++++
.../main/java/com/xiaomao/jsbridge/Logger.kt | 32 +++
.../main/java/com/xiaomao/jsbridge/Message.kt | 31 +++
.../xiaomao/jsbridge/OnPageLoadListener.java | 5 -
.../java/com/xiaomao/jsbridge/Request.java | 61 -----
.../java/com/xiaomao/jsbridge/Response.java | 50 ----
.../jsbridge/WebViewJavascriptBridge.java | 12 -
.../jsbridge/WebViewJavascriptBridge.js | 137 -----------
25 files changed, 630 insertions(+), 937 deletions(-)
create mode 100644 library/src/main/assets/WebViewJavascriptBridge.js
delete mode 100644 library/src/main/assets/jsbridge
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeHandler.java
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeHandler.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.java
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeWebChromeClient.java
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.java
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.java
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/CallBackFunction.java
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/DefaultHandler.java
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/IWebView.kt
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/JsBridge.kt
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/Logger.kt
create mode 100644 library/src/main/java/com/xiaomao/jsbridge/Message.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/OnPageLoadListener.java
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/Request.java
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/Response.java
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.java
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.js
diff --git a/build.gradle b/build.gradle
index 4ff022f..c60b441 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,12 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version = '1.3.70'
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
//classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/example/src/main/java/com/xiaomao/jsbridge/example/MainActivity.java b/example/src/main/java/com/xiaomao/jsbridge/example/MainActivity.java
index bb65650..3c25d11 100644
--- a/example/src/main/java/com/xiaomao/jsbridge/example/MainActivity.java
+++ b/example/src/main/java/com/xiaomao/jsbridge/example/MainActivity.java
@@ -12,11 +12,7 @@
import android.widget.Button;
import com.google.gson.Gson;
-import com.xiaomao.jsbridge.BridgeHandler;
import com.xiaomao.jsbridge.BridgeWebView;
-import com.xiaomao.jsbridge.CallBackFunction;
-import com.xiaomao.jsbridge.DefaultHandler;
-import com.xiaomao.jsbridge.OnPageLoadListener;
public class MainActivity extends Activity implements OnClickListener {
diff --git a/library/build.gradle b/library/build.gradle
index 13d47d3..fff6ed4 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -1,4 +1,5 @@
apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
//apply plugin: 'com.github.dcendents.android-maven'
version = "1.0-alpha4"
@@ -8,12 +9,11 @@ android {
buildToolsVersion "29.0.3"
defaultConfig {
- minSdkVersion 14
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName version
}
- sourceSets.main.java.exclude 'com/xiaomao/jsbridge/WebViewJavascriptBridge.js'
buildTypes {
release {
minifyEnabled false
@@ -24,6 +24,7 @@ android {
dependencies {
implementation 'com.android.support:support-annotations:28.0.0'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
// build a jar with source files
@@ -34,7 +35,6 @@ task sourcesJar(type: Jar) {
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
- exclude 'com/xiaomao/jsbridge/WebViewJavascriptBridge.js'
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
diff --git a/library/src/main/assets/WebViewJavascriptBridge.js b/library/src/main/assets/WebViewJavascriptBridge.js
new file mode 100644
index 0000000..23b1d96
--- /dev/null
+++ b/library/src/main/assets/WebViewJavascriptBridge.js
@@ -0,0 +1,133 @@
+//notation: js file can only use this kind of comments
+//since comments will cause error when use in webview.loadurl,
+//comments will be remove by java use regexp
+(function() {
+ if (window.WebViewJavascriptBridge) {
+ return;
+ }
+
+ var receiveMessageQueue = [];
+ var messageHandlers = {};
+
+ var responseCallbacks = {};
+ var uniqueId = 1;
+
+ //set default messageHandler 初始化默认的消息线程
+ function init(messageHandler) {
+ if (WebViewJavascriptBridge._messageHandler) {
+ throw new Error('WebViewJavascriptBridge.init called twice');
+ }
+ WebViewJavascriptBridge._messageHandler = messageHandler;
+ var receivedMessages = receiveMessageQueue;
+ receiveMessageQueue = null;
+ for (var i = 0; i < receivedMessages.length; i++) {
+ _dispatchMessageFromNative(receivedMessages[i]);
+ }
+ }
+
+ // 发送
+ function send(data, responseCallback) {
+ _doSend('send', data, responseCallback);
+ }
+
+ // 注册线程 往数组里面添加值
+ function registerHandler(handlerName, handler) {
+ messageHandlers[handlerName] = handler;
+ }
+ // 调用线程
+ function callHandler(handlerName, data, responseCallback) {
+ _doSend(handlerName, data, responseCallback);
+ }
+
+ //sendMessage add message, 触发native处理 sendMessage
+ function _doSend(handlerName, message, responseCallback) {
+ var callbackId;
+ if(typeof responseCallback === 'string'){
+ callbackId = responseCallback;
+ } else if (responseCallback) {
+ callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
+ responseCallbacks[callbackId] = responseCallback;
+ }else{
+ callbackId = '';
+ }
+ try {
+ var fn = eval('window.android.' + handlerName);
+ } catch(e) {
+ console.log(e);
+ }
+ if (typeof fn === 'function'){
+ var responseData = fn.call(this, JSON.stringify(message), callbackId);
+ if(responseData){
+ console.log('response message: '+ responseData);
+ responseCallback = responseCallbacks[callbackId];
+ if (!responseCallback) {
+ return;
+ }
+ responseCallback(responseData);
+ delete responseCallbacks[callbackId];
+ }
+ }
+ }
+
+ //提供给native使用,
+ function _dispatchMessageFromNative(messageJSON) {
+ setTimeout(function() {
+ var message = JSON.parse(messageJSON);
+ var responseCallback;
+ //java call finished, now need to call js callback function
+ if (message.responseId) {
+ responseCallback = responseCallbacks[message.responseId];
+ if (!responseCallback) {
+ return;
+ }
+ responseCallback(message.responseData);
+ delete responseCallbacks[message.responseId];
+ } else {
+ //直接发送
+ if (message.callbackId) {
+ var callbackResponseId = message.callbackId;
+ responseCallback = function(responseData) {
+ _doSend('response', responseData, callbackResponseId);
+ };
+ }
+
+ var handler = WebViewJavascriptBridge._messageHandler;
+ if (message.handlerName) {
+ handler = messageHandlers[message.handlerName];
+ }
+ //查找指定handler
+ try {
+ handler(message.data, responseCallback);
+ } catch (exception) {
+ if (typeof console != 'undefined') {
+ console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
+ }
+ }
+ }
+ });
+ }
+
+ //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
+ function _handleMessageFromNative(messageJSON) {
+ console.log('handle message: '+ messageJSON);
+ if (receiveMessageQueue) {
+ receiveMessageQueue.push(messageJSON);
+ }
+ _dispatchMessageFromNative(messageJSON);
+
+ }
+
+ var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
+ init: init,
+ send: send,
+ registerHandler: registerHandler,
+ callHandler: callHandler,
+ _handleMessageFromNative: _handleMessageFromNative
+ };
+
+ var doc = document;
+ var readyEvent = doc.createEvent('Events');
+ readyEvent.initEvent('WebViewJavascriptBridgeReady');
+ readyEvent.bridge = WebViewJavascriptBridge;
+ doc.dispatchEvent(readyEvent);
+})();
diff --git a/library/src/main/assets/jsbridge b/library/src/main/assets/jsbridge
deleted file mode 100644
index e705cfd..0000000
--- a/library/src/main/assets/jsbridge
+++ /dev/null
@@ -1,3 +0,0 @@
-(function(){function h(b,a){if(a){var c="cb_"+n++ +"_"+(new Date).getTime();f[c]=a;b.id=c}prompt("gl://request/"+JSON.stringify(b))}function k(b){setTimeout(function(){var a=JSON.parse(b);var c=a.id?function(b){prompt("gl://response/"+JSON.stringify({id:a.id,data:b}))}:function(a){};var d=a.handlerName?l[a.handlerName]:e._requestHandler;if(void 0==d)console.log("WebViewJavascriptBridge: WARNING:no handler for ",a.handlerName);else try{d(a.data,c)}catch(p){console.error("WebViewJavascriptBridge: WARNING: javascript handler threw.",
-p.stack)}})}if(!window.WebViewJavascriptBridge){var d=[],l={},f={},n=1;prompt("gl://pageLoaded/"+(0 Unit)
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.java b/library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.java
deleted file mode 100644
index 5fd013a..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.xiaomao.jsbridge;
-
-import android.content.Context;
-import android.webkit.WebView;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-public class BridgeUtil {
- public static final String toLoadJs = "jsbridge";
- final static String GL_SCHEMA = "gl://";
- final static String GL_RESPONSE = GL_SCHEMA + "response/";
- final static String GL_REQUEST = GL_SCHEMA + "request/";
- final static String GL_PAGE_LOADED = GL_SCHEMA + "pageLoaded/";
- final static String UNDERLINE_STR = "_";
-
- final static String CALLBACK_ID_FORMAT = "JAVA_CB_%s";
- final static String JS_HANDLE_REQUEST_FROM_JAVA = "javascript:WebViewJavascriptBridge._handleRequestFromNative('%s');";
- final static String JS_HANDLE_RESPONSE_FROM_JAVA = "javascript:WebViewJavascriptBridge._handleResponseFromNative('%s');";
-
-
- public static void webViewLoadLocalJs(WebView view, String path) {
- String jsContent = assetFile2Str(view.getContext(), path);
- view.loadUrl("javascript:" + jsContent);
- }
-
- public static String assetFile2Str(Context c, String urlStr) {
- InputStream in = null;
- try {
- in = c.getAssets().open(urlStr);
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
- String line;
- StringBuilder sb = new StringBuilder();
- do {
- line = bufferedReader.readLine();
- if (line != null && !line.matches("^\\s*//.*")) {
- sb.append(line);
- }
- } while (line != null);
-
- bufferedReader.close();
- in.close();
-
- return sb.toString();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- }
- }
- }
- return null;
- }
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.kt b/library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.kt
new file mode 100644
index 0000000..6988123
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.kt
@@ -0,0 +1,12 @@
+package com.xiaomao.jsbridge
+
+object BridgeUtil {
+ const val JAVA_SCRIPT = "WebViewJavascriptBridge.js"
+ const val CALLBACK_ID_FORMAT = "JAVA_CB_%s"
+ const val JS_HANDLE_MESSAGE_FROM_JAVA =
+ "javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');"
+ const val JAVASCRIPT_STR = "javascript:%s"
+ const val UNDERLINE_STR = "_"
+ const val WebviewJavascriptBridge =
+ "(function(){if(window.WebViewJavascriptBridge){return}var receiveMessageQueue=[];var messageHandlers={};var responseCallbacks={};var uniqueId=1;function init(messageHandler){if(WebViewJavascriptBridge._messageHandler){throw new Error('WebViewJavascriptBridge.init called twice');}WebViewJavascriptBridge._messageHandler=messageHandler;var receivedMessages=receiveMessageQueue;receiveMessageQueue=null;for(var i=0;i callback) {
- webChromeClient.getVisitedHistory(callback);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @Override
- public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
- return webChromeClient.onShowFileChooser(webView, filePathCallback, fileChooserParams);
- }
-
- @Override
- public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
- if (interceptMessage((BridgeWebView) view, message)) {
- result.confirm();
- return true;
- } else {
- return webChromeClient.onJsPrompt(view, url, message, defaultValue, result);
- }
- }
-
- private boolean interceptMessage(final BridgeWebView view, String message) {
- if (message.startsWith(BridgeUtil.GL_REQUEST)) {
- final Request request = Request.toObject(message.replace(BridgeUtil.GL_REQUEST, ""));
- if (request != null) {
- view.post(new Runnable() {
- @Override
- public void run() {
- view.handleRequest(request);
- }
- });
- }
- return true;
- } else if (message.startsWith(BridgeUtil.GL_RESPONSE)) {
- final Response response = Response.toObject(message.replace(BridgeUtil.GL_RESPONSE, ""));
- if (response != null) {
- view.post(new Runnable() {
- @Override
- public void run() {
- view.handleResponse(response);
- }
- });
- }
- return true;
- } else if (message.startsWith(BridgeUtil.GL_PAGE_LOADED)) {
- String result = message.replace(BridgeUtil.GL_PAGE_LOADED, "");
- view.onPageLoaded("ok".equals(result));
- return true;
- } else {
- return false;
- }
- }
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.java b/library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.java
deleted file mode 100644
index c71611d..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package com.xiaomao.jsbridge;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.os.Build;
-import android.os.Looper;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import androidx.annotation.RequiresApi;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@SuppressLint("SetJavaScriptEnabled")
-public class BridgeWebView extends WebView implements WebViewJavascriptBridge, OnPageLoadListener {
- private OnPageLoadListener onPageLoadListener;
- private Map responseCallbacks = new HashMap();
- private Map messageHandlers = new HashMap<>();
- private BridgeHandler defaultHandler = new DefaultHandler();
-
- private List startupRequests = new ArrayList<>();
-
- private BridgeWebViewClient bridgeWebViewClient;
- private BridgeWebChromeClient bridgeWebChromeClient;
-
- private long uniqueId = 0;
-
- public void setOnPageLoadListener(OnPageLoadListener onPageLoadListener) {
- this.onPageLoadListener = onPageLoadListener;
- }
-
- public BridgeWebView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public BridgeWebView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- public BridgeWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- @Deprecated
- public BridgeWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
- super(context, attrs, defStyleAttr, privateBrowsing);
- init();
- }
-
- public BridgeWebView(Context context) {
- super(context);
- init();
- }
-
- /**
- * @param handler default handler,handle messages send by js without assigned handler name,
- * if js message has handler name, it will be handled by named handlers registered by native
- */
- public void setDefaultHandler(BridgeHandler handler) {
- this.defaultHandler = handler;
- }
-
- private void init() {
- this.setVerticalScrollBarEnabled(false);
- this.setHorizontalScrollBarEnabled(false);
- this.getSettings().setJavaScriptEnabled(true);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- WebView.setWebContentsDebuggingEnabled(true);
- }
- bridgeWebViewClient = new BridgeWebViewClient();
- bridgeWebChromeClient = new BridgeWebChromeClient();
- super.setWebViewClient(bridgeWebViewClient);
- super.setWebChromeClient(bridgeWebChromeClient);
- }
-
- public void onPageLoaded(boolean isLoaded) {
- if (onPageLoadListener != null) {
- onPageLoadListener.onPageLoaded(isLoaded);
- }
- }
-
- @Override
- public void setWebViewClient(WebViewClient client) {
- bridgeWebViewClient.setWebViewClient(client);
- }
-
- @Override
- public void setWebChromeClient(WebChromeClient client) {
- bridgeWebChromeClient.setWebChromeClient(client);
- }
-
-
- void sendStartupRequests() {
- if (startupRequests != null) {
- for (Request request : startupRequests) {
- dispatchRequest(request);
- }
- startupRequests = null;
- }
- }
-
- @Override
- public void send(String data) {
- send(data, null);
- }
-
- @Override
- public void send(String data, CallBackFunction responseCallback) {
- doSend(null, data, responseCallback);
- }
-
- private void doSend(String handlerName, String data, CallBackFunction responseCallback) {
- Request request = new Request();
- if (!TextUtils.isEmpty(data)) {
- request.setData(data);
- }
- if (responseCallback != null) {
- String callbackStr = String.format(BridgeUtil.CALLBACK_ID_FORMAT, ++uniqueId + (BridgeUtil.UNDERLINE_STR + SystemClock.currentThreadTimeMillis()));
- responseCallbacks.put(callbackStr, responseCallback);
- request.setId(callbackStr);
- }
- if (!TextUtils.isEmpty(handlerName)) {
- request.setHandlerName(handlerName);
- }
- if (startupRequests != null) {
- startupRequests.add(request);
- } else {
- dispatchRequest(request);
- }
- }
-
- void dispatchRequest(Request request) {
- String requestJson = request.toJson();
- //escape special characters for json string
- requestJson = requestJson.replaceAll("(\\\\)([^utrn])", "\\\\\\\\$1$2");
- requestJson = requestJson.replaceAll("(?<=[^\\\\])(\")", "\\\\\"");
- String javascriptCommand = String.format(BridgeUtil.JS_HANDLE_REQUEST_FROM_JAVA, requestJson);
- if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
- this.loadUrl(javascriptCommand);
- }
- }
-
- void dispatchResponse(Response response) {
- String responseJson = response.toJson();
- //escape special characters for json string
- responseJson = responseJson.replaceAll("(\\\\)([^utrn])", "\\\\\\\\$1$2");
- responseJson = responseJson.replaceAll("(?<=[^\\\\])(\")", "\\\\\"");
- String javascriptCommand = String.format(BridgeUtil.JS_HANDLE_RESPONSE_FROM_JAVA, responseJson);
- if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
- this.loadUrl(javascriptCommand);
- }
- }
-
- void handleResponse(Response response) {
- CallBackFunction function = responseCallbacks.get(response.getId());
- if (function != null) {
- function.onCallBack(response.getData());
- responseCallbacks.remove(response.getId());
- }
- }
-
- void handleRequest(final Request request) {
- CallBackFunction responseFunction;
- // if had callbackId
- if (!TextUtils.isEmpty(request.getId())) {
- responseFunction = new CallBackFunction() {
- @Override
- public void onCallBack(String data) {
- Response response = new Response();
- response.setId(request.getId());
- response.setData(data);
- dispatchResponse(response);
- }
- };
- } else {
- responseFunction = new CallBackFunction() {
- @Override
- public void onCallBack(String data) {
- // do nothing
- }
- };
- }
- BridgeHandler handler;
- if (!TextUtils.isEmpty(request.getHandlerName())) {
- handler = messageHandlers.get(request.getHandlerName());
- } else {
- handler = defaultHandler;
- }
- if (handler != null) {
- handler.handler(request.getData(), responseFunction);
- }
- }
-
- /**
- * register handler,so that javascript can call it
- *
- * @param handlerName
- * @param handler
- */
- public void registerHandler(String handlerName, BridgeHandler handler) {
- if (handler != null) {
- messageHandlers.put(handlerName, handler);
- }
- }
-
- /**
- * call javascript registered handler
- *
- * @param handlerName
- * @param data
- * @param callBack
- */
- public void callHandler(String handlerName, String data, CallBackFunction callBack) {
- doSend(handlerName, data, callBack);
- }
-
-
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.kt b/library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.kt
new file mode 100644
index 0000000..06ba208
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/BridgeWebView.kt
@@ -0,0 +1,36 @@
+package com.xiaomao.jsbridge
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.webkit.WebView
+import android.webkit.WebViewClient
+
+@SuppressLint("SetJavaScriptEnabled")
+class BridgeWebView : WebView, IWebView {
+
+ val jsBridge: JsBridge = JsBridge(this)
+ private var bridgeWebViewClient: BridgeWebViewClient = BridgeWebViewClient(jsBridge)
+
+ constructor(context: Context?) : super(context)
+ constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
+ constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
+ context,
+ attrs,
+ defStyleAttr
+ )
+
+ init {
+ super.setWebViewClient(bridgeWebViewClient)
+ }
+
+ override fun setWebViewClient(webViewClient: WebViewClient) {
+ bridgeWebViewClient.webViewClient = webViewClient
+ }
+
+ override fun destroy() {
+ super.destroy()
+ jsBridge.clean()
+ }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.java b/library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.java
deleted file mode 100644
index 8107fab..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package com.xiaomao.jsbridge;
-
-import android.graphics.Bitmap;
-import android.net.http.SslError;
-import android.os.Build;
-import android.os.Message;
-import android.view.KeyEvent;
-import android.webkit.ClientCertRequest;
-import android.webkit.HttpAuthHandler;
-import android.webkit.RenderProcessGoneDetail;
-import android.webkit.SslErrorHandler;
-import android.webkit.WebResourceError;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebResourceResponse;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import androidx.annotation.RequiresApi;
-
-
-class BridgeWebViewClient extends WebViewClient {
- private WebViewClient webViewClient = new WebViewClient();
-
- public void setWebViewClient(WebViewClient webViewClient) {
- this.webViewClient = webViewClient;
- }
-
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- return webViewClient.shouldOverrideUrlLoading(view, url);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.N)
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
- return webViewClient.shouldOverrideUrlLoading(view, request);
- }
-
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- webViewClient.onPageStarted(view, url, favicon);
- }
-
- @Override
- public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
- return webViewClient.shouldOverrideKeyEvent(view, event);
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- BridgeUtil.webViewLoadLocalJs(view, BridgeUtil.toLoadJs);
- ((BridgeWebView) view).sendStartupRequests();
- webViewClient.onPageFinished(view, url);
- }
-
- @Override
- public void onLoadResource(WebView view, String url) {
- webViewClient.onLoadResource(view, url);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.M)
- @Override
- public void onPageCommitVisible(WebView view, String url) {
- webViewClient.onPageCommitVisible(view, url);
- }
-
- @Override
- public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
- return webViewClient.shouldInterceptRequest(view, url);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @Override
- public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
- return webViewClient.shouldInterceptRequest(view, request);
- }
-
- @Override
- public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg) {
- webViewClient.onTooManyRedirects(view, cancelMsg, continueMsg);
- }
-
- @Override
- public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
- webViewClient.onReceivedError(view, errorCode, description, failingUrl);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.M)
- @Override
- public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
- webViewClient.onReceivedError(view, request, error);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.M)
- @Override
- public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
- webViewClient.onReceivedHttpError(view, request, errorResponse);
- }
-
- @Override
- public void onFormResubmission(WebView view, Message dontResend, Message resend) {
- webViewClient.onFormResubmission(view, dontResend, resend);
- }
-
- @Override
- public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
- webViewClient.doUpdateVisitedHistory(view, url, isReload);
- }
-
- @Override
- public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
- webViewClient.onReceivedSslError(view, handler, error);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @Override
- public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
- webViewClient.onReceivedClientCertRequest(view, request);
- }
-
- @Override
- public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
- webViewClient.onReceivedHttpAuthRequest(view, handler, host, realm);
- }
-
- @Override
- public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
- webViewClient.onUnhandledKeyEvent(view, event);
- }
-
- @Override
- public void onScaleChanged(WebView view, float oldScale, float newScale) {
- webViewClient.onScaleChanged(view, oldScale, newScale);
- }
-
- @Override
- public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
- webViewClient.onReceivedLoginRequest(view, realm, account, args);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.O)
- @Override
- public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
- return webViewClient.onRenderProcessGone(view, detail);
- }
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.kt b/library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.kt
new file mode 100644
index 0000000..8b6e3d7
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/BridgeWebViewClient.kt
@@ -0,0 +1,185 @@
+package com.xiaomao.jsbridge
+
+import android.graphics.Bitmap
+import android.net.http.SslError
+import android.os.Build
+import android.os.Message
+import android.view.KeyEvent
+import android.webkit.*
+import androidx.annotation.RequiresApi
+
+/**
+ * 如果要自定义WebViewClient必须要集成此类
+ * Created by bruce on 10/28/15.
+ */
+internal class BridgeWebViewClient(private val jsBridge: JsBridge) : WebViewClient() {
+ internal var webViewClient: WebViewClient = WebViewClient()
+
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ url: String?
+ ): Boolean {
+ return webViewClient.shouldOverrideUrlLoading(view, url)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.N)
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): Boolean {
+ return webViewClient.shouldOverrideUrlLoading(view, request)
+ }
+
+ override fun onPageStarted(
+ view: WebView?,
+ url: String?,
+ favicon: Bitmap?
+ ) {
+ webViewClient.onPageStarted(view, url, favicon)
+ }
+
+ override fun shouldOverrideKeyEvent(
+ view: WebView?,
+ event: KeyEvent?
+ ): Boolean {
+ return webViewClient.shouldOverrideKeyEvent(view, event)
+ }
+
+ override fun onPageFinished(view: WebView, url: String?) {
+ webViewClient.onPageFinished(view, url)
+ jsBridge.register(view as IWebView)
+ }
+
+ override fun onLoadResource(view: WebView?, url: String?) {
+ webViewClient.onLoadResource(view, url)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.M)
+ override fun onPageCommitVisible(view: WebView?, url: String?) {
+ webViewClient.onPageCommitVisible(view, url)
+ }
+
+ override fun shouldInterceptRequest(
+ view: WebView?,
+ url: String?
+ ): WebResourceResponse? {
+ return webViewClient.shouldInterceptRequest(view, url)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ override fun shouldInterceptRequest(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): WebResourceResponse? {
+ return webViewClient.shouldInterceptRequest(view, request)
+ }
+
+ override fun onTooManyRedirects(
+ view: WebView?,
+ cancelMsg: Message?,
+ continueMsg: Message?
+ ) {
+ webViewClient.onTooManyRedirects(view, cancelMsg, continueMsg)
+ }
+
+ override fun onReceivedError(
+ view: WebView?,
+ errorCode: Int,
+ description: String?,
+ failingUrl: String?
+ ) {
+ webViewClient.onReceivedError(view, errorCode, description, failingUrl)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.M)
+ override fun onReceivedError(
+ view: WebView?,
+ request: WebResourceRequest?,
+ error: WebResourceError?
+ ) {
+ webViewClient.onReceivedError(view, request, error)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.M)
+ override fun onReceivedHttpError(
+ view: WebView?,
+ request: WebResourceRequest?,
+ errorResponse: WebResourceResponse?
+ ) {
+ webViewClient.onReceivedHttpError(view, request, errorResponse)
+ }
+
+ override fun onFormResubmission(
+ view: WebView?,
+ dontResend: Message?,
+ resend: Message?
+ ) {
+ webViewClient.onFormResubmission(view, dontResend, resend)
+ }
+
+ override fun doUpdateVisitedHistory(
+ view: WebView?,
+ url: String?,
+ isReload: Boolean
+ ) {
+ webViewClient.doUpdateVisitedHistory(view, url, isReload)
+ }
+
+ override fun onReceivedSslError(
+ view: WebView?,
+ handler: SslErrorHandler?,
+ error: SslError?
+ ) {
+ webViewClient.onReceivedSslError(view, handler, error)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ override fun onReceivedClientCertRequest(
+ view: WebView?,
+ request: ClientCertRequest?
+ ) {
+ webViewClient.onReceivedClientCertRequest(view, request)
+ }
+
+ override fun onReceivedHttpAuthRequest(
+ view: WebView?,
+ handler: HttpAuthHandler?,
+ host: String?,
+ realm: String?
+ ) {
+ webViewClient.onReceivedHttpAuthRequest(view, handler, host, realm)
+ }
+
+ override fun onUnhandledKeyEvent(
+ view: WebView?,
+ event: KeyEvent?
+ ) {
+ webViewClient.onUnhandledKeyEvent(view, event)
+ }
+
+ override fun onScaleChanged(
+ view: WebView?,
+ oldScale: Float,
+ newScale: Float
+ ) {
+ webViewClient.onScaleChanged(view, oldScale, newScale)
+ }
+
+ override fun onReceivedLoginRequest(
+ view: WebView?,
+ realm: String?,
+ account: String?,
+ args: String?
+ ) {
+ webViewClient.onReceivedLoginRequest(view, realm, account, args)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ override fun onRenderProcessGone(
+ view: WebView?,
+ detail: RenderProcessGoneDetail?
+ ): Boolean {
+ return webViewClient.onRenderProcessGone(view, detail)
+ }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/CallBackFunction.java b/library/src/main/java/com/xiaomao/jsbridge/CallBackFunction.java
deleted file mode 100644
index c01a92c..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/CallBackFunction.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.xiaomao.jsbridge;
-
-public interface CallBackFunction {
-
- void onCallBack(String data);
-
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/DefaultHandler.java b/library/src/main/java/com/xiaomao/jsbridge/DefaultHandler.java
deleted file mode 100644
index 0771aed..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/DefaultHandler.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.xiaomao.jsbridge;
-
-public class DefaultHandler implements BridgeHandler{
-
- @Override
- public void handler(String data, CallBackFunction function) {
- if(function != null){
- function.onCallBack("DefaultHandler response data.");
- }
- }
-
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/IWebView.kt b/library/src/main/java/com/xiaomao/jsbridge/IWebView.kt
new file mode 100644
index 0000000..671ba21
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/IWebView.kt
@@ -0,0 +1,13 @@
+package com.xiaomao.jsbridge
+
+import android.webkit.ValueCallback
+
+interface IWebView {
+
+ fun loadUrl(url: String?)
+
+ fun addJavascriptInterface(obj: Any?, interfaceName: String?)
+
+ fun evaluateJavascript(var1: String?, callback: ValueCallback?)
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/JsBridge.kt b/library/src/main/java/com/xiaomao/jsbridge/JsBridge.kt
new file mode 100644
index 0000000..cab3ddb
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/JsBridge.kt
@@ -0,0 +1,178 @@
+package com.xiaomao.jsbridge
+
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.util.ArrayMap
+import android.webkit.JavascriptInterface
+import java.net.URLEncoder
+import java.util.*
+import java.util.concurrent.atomic.AtomicLong
+import kotlin.collections.HashMap
+
+private val EmptyResponseCallBack: (String) -> Unit = {}
+
+
+class JsBridge(private val webView: IWebView) {
+ enum class State {
+ IDLE, RUN, DESTROY
+ }
+
+ private var state: State = State.IDLE
+
+ private val mUniqueId = AtomicLong(0)
+
+ private val mMessageHandlers: MutableMap = HashMap()
+
+ private val mCallbacks: MutableMap Unit> = ArrayMap()
+
+ private var mRequests: MutableList = ArrayList()
+
+ private val mainHandler = Handler(Looper.getMainLooper())
+
+ private fun checkState() {
+ require(state < State.DESTROY) { "JsBridge is destroyed." }
+ }
+
+ /**
+ * register handler,so that javascript can call it
+ * 注册处理程序,以便javascript调用它
+ *
+ * @param handlerName handlerName
+ * @param handler BridgeHandler
+ */
+ @Synchronized
+ fun registerHandler(handlerName: String, handler: BridgeHandler) {
+ checkState()
+ // 添加至 Map
+ mMessageHandlers[handlerName] = handler
+ }
+
+
+ /**
+ * register handler,so that javascript can call it
+ * 注册处理程序,以便javascript调用它
+ *
+ * @param handlers handlerName
+ */
+ @Synchronized
+ fun registerHandler(handlers: Map) {
+ checkState()
+ mMessageHandlers.putAll(handlers)
+ }
+
+
+ /**
+ * unregister handler
+ *
+ * @param handlerName
+ */
+ @Synchronized
+ fun unregisterHandler(handlerName: String) {
+ checkState()
+ mMessageHandlers.remove(handlerName)
+ }
+
+
+ @JavascriptInterface
+ @Synchronized
+ fun request(seqNo: String, handlerName: String, data: String) {
+ mMessageHandlers[handlerName]?.handle(data) {
+ dispatchMessage(JSResponse(seqNo, data))
+ }
+ }
+
+ @JavascriptInterface
+ @Synchronized
+ fun response(data: String, seqNo: String) {
+ Logger.d(
+ javaClass.simpleName,
+ "response->$data, seqNo: $seqNo ${Thread.currentThread().name}"
+ )
+ mCallbacks.remove(seqNo)?.invoke(data)
+ }
+
+ @Synchronized
+ fun register(view: IWebView) {
+ require(state == State.IDLE) { "JsBridge is registered." }
+ state = State.RUN
+ view.addJavascriptInterface(this, "jsbridge")
+ view.loadUrl(
+ String.format(
+ BridgeUtil.JAVASCRIPT_STR,
+ BridgeUtil.WebviewJavascriptBridge
+ )
+ )
+ for (request in mRequests) {
+ dispatchMessage(request)
+ }
+ }
+
+ /**
+ * free memory
+ */
+ @Synchronized
+ fun clean() {
+ state = State.DESTROY
+ mCallbacks.clear()
+ mMessageHandlers.clear()
+ mRequests.clear()
+ }
+
+ /**
+ * 分发message 必须在主线程才分发成功
+ *
+ * @param message Message
+ */
+ private fun dispatchMessage(message: Message) {
+ var messageJson = message.toJson()
+ //escape special characters for json string 为json字符串转义特殊字符
+ messageJson = messageJson.replace("(\\\\)([^utrn])".toRegex(), "\\\\\\\\$1$2")
+ messageJson = messageJson.replace("(?<=[^\\\\])(\")".toRegex(), "\\\\\"")
+ messageJson = messageJson.replace("(?<=[^\\\\])(\')".toRegex(), "\\\\\'")
+ messageJson = messageJson.replace("%7B".toRegex(), URLEncoder.encode("%7B"))
+ messageJson = messageJson.replace("%7D".toRegex(), URLEncoder.encode("%7D"))
+ messageJson = messageJson.replace("%22".toRegex(), URLEncoder.encode("%22"))
+ val javascriptCommand =
+ String.format(BridgeUtil.JS_HANDLE_MESSAGE_FROM_JAVA, messageJson)
+ Logger.d(javaClass.simpleName, "javascriptCommand->$javascriptCommand")
+
+ // 必须要找主线程才会将数据传递出去 --- 划重点
+ if (Thread.currentThread() === Looper.getMainLooper().thread) {
+ webView.evaluateJavascript(javascriptCommand, null)
+ } else {
+ mainHandler.post { webView.evaluateJavascript(javascriptCommand, null) }
+ }
+ }
+
+
+ /**
+ * 保存message到消息队列
+ *
+ * @param handlerName handlerName
+ * @param data data
+ * @param responseCallback OnBridgeCallback
+ */
+ @Synchronized
+ fun callHandler(
+ handlerName: String,
+ data: String,
+ responseCallback: (String) -> Unit = EmptyResponseCallBack
+ ) {
+ checkState()
+ require(handlerName.isNotEmpty()) { "Empty handler name." }
+ val sequenceId: String = String.format(
+ BridgeUtil.CALLBACK_ID_FORMAT,
+ "${mUniqueId.incrementAndGet()}" + BridgeUtil.UNDERLINE_STR + "${SystemClock.currentThreadTimeMillis()}"
+ )
+ mCallbacks[sequenceId] = responseCallback
+ val request = JSRequest(sequenceId, handlerName, data)
+ //等待状态添加到消息集合否则分发消息
+ if (state == State.IDLE) {
+ mRequests.add(request)
+ } else {
+ dispatchMessage(request)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/Logger.kt b/library/src/main/java/com/xiaomao/jsbridge/Logger.kt
new file mode 100644
index 0000000..e6b2cc3
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/Logger.kt
@@ -0,0 +1,32 @@
+package com.xiaomao.jsbridge
+
+import android.util.Log
+
+object Logger {
+ var debug: Boolean = false
+
+ fun d(tag: String, message: String) {
+ if (debug) {
+ Log.d(tag, message)
+ }
+ }
+
+ fun i(tag: String, message: String) {
+ if (debug) {
+ Log.i(tag, message)
+ }
+ }
+
+ fun w(tag: String, message: String) {
+ if (debug) {
+ Log.w(tag, message)
+ }
+ }
+
+
+ fun e(tag: String, message: String) {
+ if (debug) {
+ Log.e(tag, message)
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/Message.kt b/library/src/main/java/com/xiaomao/jsbridge/Message.kt
new file mode 100644
index 0000000..51b7ad2
--- /dev/null
+++ b/library/src/main/java/com/xiaomao/jsbridge/Message.kt
@@ -0,0 +1,31 @@
+package com.xiaomao.jsbridge
+
+import org.json.JSONObject
+
+interface Message {
+ fun toJson(): String
+}
+
+data class JSRequest(
+ val seqNo: String,
+ val handlerName: String,
+ val data: String
+) : Message {
+ override fun toJson(): String {
+ val jsonObject = JSONObject()
+ jsonObject.put("seqNo", seqNo)
+ jsonObject.put("handlerName", handlerName)
+ jsonObject.put("data", data)
+ return jsonObject.toString()
+ }
+}
+
+
+data class JSResponse(val seqNo: String, val data: String) : Message {
+ override fun toJson(): String {
+ val jsonObject = JSONObject()
+ jsonObject.put("seqNo", seqNo)
+ jsonObject.put("data", data)
+ return jsonObject.toString()
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/xiaomao/jsbridge/OnPageLoadListener.java b/library/src/main/java/com/xiaomao/jsbridge/OnPageLoadListener.java
deleted file mode 100644
index 0d142e7..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/OnPageLoadListener.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.xiaomao.jsbridge;
-
-public interface OnPageLoadListener {
- void onPageLoaded(boolean isLoaded);
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/Request.java b/library/src/main/java/com/xiaomao/jsbridge/Request.java
deleted file mode 100644
index 8ce965c..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/Request.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.xiaomao.jsbridge;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class Request {
- private String id;
- private String handlerName;
- private String data;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getHandlerName() {
- return handlerName;
- }
-
- public void setHandlerName(String handlerName) {
- this.handlerName = handlerName;
- }
-
- public String getData() {
- return data;
- }
-
- public void setData(String data) {
- this.data = data;
- }
-
- public String toJson() {
- try {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("id", id);
- jsonObject.put("handlerName", handlerName);
- jsonObject.put("data", data);
- return jsonObject.toString();
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static Request toObject(String jsonStr) {
- try {
- Request request = new Request();
- JSONObject jsonObject = new JSONObject(jsonStr);
- request.setId(jsonObject.has("id") ? jsonObject.getString("id") : "");
- request.setHandlerName(jsonObject.has("handlerName") ? jsonObject.getString("handlerName") : "");
- request.setData(jsonObject.has("data") ? jsonObject.getString("data") : "");
- return request;
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/Response.java b/library/src/main/java/com/xiaomao/jsbridge/Response.java
deleted file mode 100644
index 23daf69..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/Response.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.xiaomao.jsbridge;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class Response {
- private String id;
- private String data;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getData() {
- return data;
- }
-
- public void setData(String data) {
- this.data = data;
- }
-
- public String toJson() {
- try {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("id", id);
- jsonObject.put("data", data);
- return jsonObject.toString();
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static Response toObject(String jsonStr) {
- try {
- Response response = new Response();
- JSONObject jsonObject = new JSONObject(jsonStr);
- response.setId(jsonObject.has("id") ? jsonObject.getString("id") : "");
- response.setData(jsonObject.has("data") ? jsonObject.getString("data") : "");
- return response;
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.java b/library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.java
deleted file mode 100644
index b3b52af..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.xiaomao.jsbridge;
-
-
-public interface WebViewJavascriptBridge {
- void send(String data);
-
- void send(String data, CallBackFunction responseCallback);
-
- void registerHandler(String handlerName, BridgeHandler handler);
-
- void callHandler(String handlerName, String data, CallBackFunction callBack);
-}
diff --git a/library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.js b/library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.js
deleted file mode 100644
index 7ed0fa7..0000000
--- a/library/src/main/java/com/xiaomao/jsbridge/WebViewJavascriptBridge.js
+++ /dev/null
@@ -1,137 +0,0 @@
-//use http://closure-compiler.appspot.com/home to generate jsbridge file
-//notation: js file can only use this kind of comments
-//since comments will cause error when use in webview.loadurl,
-//comments will be remove by java use regexp
-(function () {
- if (window.WebViewJavascriptBridge) {
- return;
- }
-
- var receiveRequestQueue = [];
- var requestHandlers = {};
-
- var CUSTOM_PROTOCOL_SCHEME = 'gl://';
- var GL_REQUEST = CUSTOM_PROTOCOL_SCHEME + 'request/';
- var GL_RESPONSE = CUSTOM_PROTOCOL_SCHEME + 'response/';
-
- var responseCallbacks = {};
- var uniqueId = 1;
-
- var state = window.location.host.length > 0 ? "ok" : "error";
- prompt(CUSTOM_PROTOCOL_SCHEME + 'pageLoaded/' + state);
-
- //set default requestHandler
- function init(requestHandler) {
- if (WebViewJavascriptBridge._requestHandler) {
- throw new Error('WebViewJavascriptBridge.init called twice');
- }
- WebViewJavascriptBridge._requestHandler = requestHandler;
- var receivedRequests = receiveRequestQueue;
- receiveRequestQueue = null;
- for (var i = 0; i < receivedRequests.length; i++) {
- _dispatchRequestFromNative(receivedRequests[i]);
- }
- }
-
- function send(data, responseCallback) {
- _doSend({
- data: data
- }, responseCallback);
- }
-
- function registerHandler(handlerName, handler) {
- requestHandlers[handlerName] = handler;
- }
-
- function callHandler(handlerName, data, responseCallback) {
- _doSend({
- handlerName: handlerName,
- data: data
- }, responseCallback);
- }
-
- //sendRequest
- function _doSend(request, responseCallback) {
- if (responseCallback) {
- var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
- responseCallbacks[callbackId] = responseCallback;
- request.id = callbackId;
- }
- prompt(GL_REQUEST + JSON.stringify(request));
- }
-
- function _handleResponseFromNative(responseJson) {
- setTimeout(function () {
- var response = JSON.parse(responseJson);
- var responseCallback = responseCallbacks[response.id];
- if (!responseCallback) {
- return;
- }
- responseCallback(response.data);
- delete responseCallbacks[response.id];
- });
- }
-
- //提供给native使用,
- function _dispatchRequestFromNative(requestJSON) {
- setTimeout(function () {
- var request = JSON.parse(requestJSON);
- var responseCallback;
- if (request.id) {
- responseCallback = function (responseData) {
- var response = {
- id: request.id,
- data: responseData
- };
- prompt(GL_RESPONSE + JSON.stringify(response));
- }
- } else {
- responseCallback = function (responseData) {
-
- }
- }
- //查找指定handler
- var handler;
- if (request.handlerName) {
- handler = requestHandlers[request.handlerName];
- } else {
- handler = WebViewJavascriptBridge._requestHandler;
- }
- if (handler == undefined) {
- console.log("WebViewJavascriptBridge: WARNING:no handler for ", request.handlerName);
- } else {
- try {
- handler(request.data, responseCallback);
- } catch (exception) {
- console.error('WebViewJavascriptBridge: WARNING: javascript handler threw.', exception.stack);
- }
- }
- });
- }
-
- //提供给native调用,receiveRequestQueue 在会在页面加载完后赋值为null,所以
- function _handleRequestFromNative(requestJSON) {
- //console.log(requestJSON);
- if (receiveRequestQueue) {
- receiveRequestQueue.push(requestJSON);
- } else {
- _dispatchRequestFromNative(requestJSON);
- }
- }
-
- var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
- init: init,
- send: send,
- registerHandler: registerHandler,
- callHandler: callHandler,
- _handleRequestFromNative: _handleRequestFromNative,
- _handleResponseFromNative: _handleResponseFromNative
- };
-
- var doc = document;
- var readyEvent = doc.createEvent('Events');
- readyEvent.initEvent('WebViewJavascriptBridgeReady');
- readyEvent.bridge = WebViewJavascriptBridge;
- doc.dispatchEvent(readyEvent);
-
-})();
From 7ee825327ff452836359a511c7d729804d9de395 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=A2=85=E7=90=A5?=
Date: Mon, 13 Apr 2020 18:46:09 +0800
Subject: [PATCH 02/14] =?UTF-8?q?=E4=BD=BF=E7=94=A8kotlin=E9=87=8D?=
=?UTF-8?q?=E6=9E=84=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
build.gradle | 7 +
example/build.gradle | 6 +-
example/src/main/AndroidManifest.xml | 13 +-
example/src/main/assets/demo.html | 5 +-
.../jsbridge/example/MainActivity.kt | 61 +++++
.../jsbridge/example/MainActivity.java | 139 -----------
example/src/main/res/layout/activity_main.xml | 4 +-
library/bintray.gradle | 91 +++++++
library/build.gradle | 26 +-
library/src/main/AndroidManifest.xml | 2 +-
.../main/assets/WebViewJavascriptBridge.js | 138 +++++------
.../com/orientsec/jsbridge/BridgeHandler.kt | 7 +
.../java/com/orientsec/jsbridge/BridgeUtil.kt | 11 +
.../jsbridge/BridgeWebView.kt | 7 +-
.../jsbridge/BridgeWebViewClient.kt | 2 +-
.../jsbridge/IWebView.kt | 4 +-
.../java/com/orientsec/jsbridge/JsBridge.kt | 232 ++++++++++++++++++
.../{xiaomao => orientsec}/jsbridge/Logger.kt | 2 +-
.../java/com/orientsec/jsbridge/Message.kt | 7 +
.../orientsec/jsbridge/OnPageLoadListener.kt | 5 +
.../com/xiaomao/jsbridge/BridgeHandler.kt | 5 -
.../java/com/xiaomao/jsbridge/BridgeUtil.kt | 12 -
.../java/com/xiaomao/jsbridge/JsBridge.kt | 178 --------------
.../main/java/com/xiaomao/jsbridge/Message.kt | 31 ---
peoject.properties | 18 ++
25 files changed, 532 insertions(+), 481 deletions(-)
create mode 100644 example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt
delete mode 100644 example/src/main/java/com/xiaomao/jsbridge/example/MainActivity.java
create mode 100644 library/bintray.gradle
create mode 100644 library/src/main/java/com/orientsec/jsbridge/BridgeHandler.kt
create mode 100644 library/src/main/java/com/orientsec/jsbridge/BridgeUtil.kt
rename library/src/main/java/com/{xiaomao => orientsec}/jsbridge/BridgeWebView.kt (83%)
rename library/src/main/java/com/{xiaomao => orientsec}/jsbridge/BridgeWebViewClient.kt (99%)
rename library/src/main/java/com/{xiaomao => orientsec}/jsbridge/IWebView.kt (71%)
create mode 100644 library/src/main/java/com/orientsec/jsbridge/JsBridge.kt
rename library/src/main/java/com/{xiaomao => orientsec}/jsbridge/Logger.kt (94%)
create mode 100644 library/src/main/java/com/orientsec/jsbridge/Message.kt
create mode 100644 library/src/main/java/com/orientsec/jsbridge/OnPageLoadListener.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeHandler.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/BridgeUtil.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/JsBridge.kt
delete mode 100644 library/src/main/java/com/xiaomao/jsbridge/Message.kt
create mode 100644 peoject.properties
diff --git a/build.gradle b/build.gradle
index c60b441..fae62e9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,11 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
+Properties props = new Properties()
+new File(rootDir, 'peoject.properties').withInputStream { props.load(it) }
+props.each {
+ project.ext.set(it.key, it.value)
+}
+
buildscript {
ext.kotlin_version = '1.3.70'
repositories {
@@ -21,3 +27,4 @@ allprojects {
google()
}
}
+
diff --git a/example/build.gradle b/example/build.gradle
index ceb34f3..e71b375 100644
--- a/example/build.gradle
+++ b/example/build.gradle
@@ -1,12 +1,13 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
- applicationId "com.xiaomao.jsbridge.example"
- minSdkVersion 14
+ applicationId "com.orientsec.jsbridge.example"
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
@@ -24,4 +25,5 @@ dependencies {
implementation project(':library')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.code.gson:gson:2.8.2'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
diff --git a/example/src/main/AndroidManifest.xml b/example/src/main/AndroidManifest.xml
index 05a481e..6576e35 100644
--- a/example/src/main/AndroidManifest.xml
+++ b/example/src/main/AndroidManifest.xml
@@ -1,15 +1,16 @@
+ package="com.orientsec.jsbridge.example">
-
+
+ android:label="@string/app_name">
diff --git a/example/src/main/assets/demo.html b/example/src/main/assets/demo.html
index c1dd3d1..64264c0 100644
--- a/example/src/main/assets/demo.html
+++ b/example/src/main/assets/demo.html
@@ -5,7 +5,7 @@
js调用java
-
+
@@ -103,7 +103,8 @@
var responseData = "Javascript Says Right back aka!";
responseCallback(responseData);
});
- })
+ });
+
\ No newline at end of file
diff --git a/example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt b/example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt
new file mode 100644
index 0000000..556f9d1
--- /dev/null
+++ b/example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt
@@ -0,0 +1,61 @@
+package com.orientsec.jsbridge.example
+
+import android.app.Activity
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import android.widget.Button
+import android.widget.Toast
+import com.google.gson.Gson
+import com.orientsec.jsbridge.BridgeHandler
+import com.orientsec.jsbridge.BridgeWebView
+import com.orientsec.jsbridge.Logger
+
+class MainActivity : Activity(), View.OnClickListener {
+ private lateinit var webView: BridgeWebView
+
+ data class Location(
+ val address: String
+ )
+
+ data class User(
+ val name: String,
+ val location: Location,
+ val testStr: String
+ )
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ Logger.debug = true
+ webView = findViewById(R.id.webView)
+ val settings = webView.settings
+ settings.javaScriptEnabled = true
+ val button = findViewById
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt b/example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt
deleted file mode 100644
index 40914bc..0000000
--- a/example/src/main/java/com/orientsec/jsbridge/example/MainActivity.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.orientsec.jsbridge.example
-
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.os.Bundle
-import android.util.Log
-import android.view.View
-import android.widget.Button
-import android.widget.Toast
-import com.google.gson.Gson
-import com.orientsec.jsbridge.BridgeHandler
-import com.orientsec.jsbridge.BridgeWebView
-import com.orientsec.jsbridge.JsBridge
-
-class MainActivity : Activity(), View.OnClickListener {
- private lateinit var webView: BridgeWebView
-
- data class Location(
- val address: String
- )
-
- data class User(
- val name: String,
- val location: Location,
- val testStr: String
- )
-
- @SuppressLint("SetJavaScriptEnabled")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- JsBridge.debug = true
- webView = findViewById(R.id.webView)
- val settings = webView.settings
- settings.javaScriptEnabled = true
- val button = findViewById(R.id.button)
- button.setOnClickListener(this)
- webView.loadUrl("file:///android_asset/demo.html")
- webView.registerHandler("submitFromWeb", object : BridgeHandler {
- override fun handle(data: String, callback: (String) -> Unit) {
- Log.i("MainActivity", "handler = submitFromWeb, data from web = $data")
- callback("submitFromWeb exe, response data 中文 from Java")
- }
- })
- val location =
- Location("SDU")
- val user = User("大头鬼", location, "")
-
- webView.callHandler("functionInJs", Gson().toJson(user)) {}
-
- }
-
- override fun onClick(v: View) {
- if (R.id.button == v.id) {
- webView.callHandler(
- "functionInJs",
- "data from Java"
- ) {
- Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
- }
- }
- }
-}
\ No newline at end of file
diff --git a/javascrpit/demo/.eslintignore b/javascrpit/demo/.eslintignore
new file mode 100644
index 0000000..e17404d
--- /dev/null
+++ b/javascrpit/demo/.eslintignore
@@ -0,0 +1,5 @@
+*.*
+/dist
+/node_modules
+/resources
+/.vscode
\ No newline at end of file
diff --git a/javascrpit/demo/.eslintrc.js b/javascrpit/demo/.eslintrc.js
new file mode 100644
index 0000000..d6226e2
--- /dev/null
+++ b/javascrpit/demo/.eslintrc.js
@@ -0,0 +1,41 @@
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es2021': true
+ },
+ 'extends': [
+ 'airbnb-typescript/base'
+ ],
+ 'parser': '@typescript-eslint/parser',
+ 'parserOptions': {
+ 'ecmaVersion': 'latest',
+ 'sourceType': 'module',
+ 'parser': '@typescript-eslint/parser',
+ 'project': './tsconfig.json',
+ 'tsconfigRootDir': __dirname
+ },
+ 'plugins': [
+ '@typescript-eslint',
+ 'import'
+ ],
+ 'rules': {
+ '@typescript-eslint/indent': ['error', 4],
+ '@typescript-eslint/semi': ['error', 'never'],
+ '@typescript-eslint/comma-dangle': 'off',
+ 'linebreak-style': ['error', 'windows'],
+ 'quotes': ['error', 'single'],
+ 'semi': ['error', 'never'],
+ 'max-classes-per-file': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'error',
+ 'import/extensions': [
+ 'error',
+ 'ignorePackages',
+ {
+ 'js': 'never',
+ 'jsx': 'never',
+ 'ts': 'never',
+ 'tsx': 'never'
+ }
+ ]
+ }
+}
diff --git a/javascrpit/demo/.gitingore b/javascrpit/demo/.gitingore
new file mode 100644
index 0000000..246d599
--- /dev/null
+++ b/javascrpit/demo/.gitingore
@@ -0,0 +1,2 @@
+/dist
+/node_modules
\ No newline at end of file
diff --git a/javascrpit/demo/.vscode/launch.json b/javascrpit/demo/.vscode/launch.json
new file mode 100644
index 0000000..578abae
--- /dev/null
+++ b/javascrpit/demo/.vscode/launch.json
@@ -0,0 +1,16 @@
+{
+ // 使用 IntelliSense 了解相关属性。
+ // 悬停以查看现有属性的描述。
+ // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "Launch Chrome against localhost",
+ "url": "http://localhost:8080",
+ "webRoot": "${workspaceFolder}",
+ "preLaunchTask": "debug"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/javascrpit/demo/.vscode/settings.json b/javascrpit/demo/.vscode/settings.json
new file mode 100644
index 0000000..d0cb57b
--- /dev/null
+++ b/javascrpit/demo/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "eslint.workingDirectories": [
+ "src"
+ ]
+}
\ No newline at end of file
diff --git a/javascrpit/demo/.vscode/tasks.json b/javascrpit/demo/.vscode/tasks.json
new file mode 100644
index 0000000..5823654
--- /dev/null
+++ b/javascrpit/demo/.vscode/tasks.json
@@ -0,0 +1,13 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "debug",
+ "type": "npm",
+ "isBackground": true,
+ "script": "debug",
+ "group": "build",
+ "detail": "开发调试"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/javascrpit/demo/dist/index.html b/javascrpit/demo/dist/index.html
new file mode 100644
index 0000000..a89d822
--- /dev/null
+++ b/javascrpit/demo/dist/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ jsdemo
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/javascrpit/demo/dist/index.js b/javascrpit/demo/dist/index.js
new file mode 100644
index 0000000..dc8934a
--- /dev/null
+++ b/javascrpit/demo/dist/index.js
@@ -0,0 +1,200 @@
+/*
+ * ATTENTION: An "eval-source-map" devtool has been used.
+ * This devtool is neither made for production nor for readable output files.
+ * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
+ * or disable the default devtool with "devtool: false".
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
+ */
+/******/ (() => { // webpackBootstrap
+/******/ "use strict";
+/******/ var __webpack_modules__ = ({
+
+/***/ "./node_modules/react-dom/cjs/react-dom.development.js":
+/*!*************************************************************!*\
+ !*** ./node_modules/react-dom/cjs/react-dom.development.js ***!
+ \*************************************************************/
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+eval("/**\n * @license React\n * react-dom.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n\nif (true) {\n (function() {\n\n 'use strict';\n\n/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\nif (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===\n 'function'\n) {\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());\n}\n var React = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\nvar Scheduler = __webpack_require__(/*! scheduler */ \"./node_modules/scheduler/index.js\");\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nvar suppressWarning = false;\nfunction setSuppressWarning(newSuppressWarning) {\n {\n suppressWarning = newSuppressWarning;\n }\n} // In DEV, calls to console.warn and console.error get replaced\n// by calls to these methods by a Babel plugin.\n//\n// In PROD (or in packages without access to React internals),\n// they are left as they are instead.\n\nfunction warn(format) {\n {\n if (!suppressWarning) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n printWarning('warn', format, args);\n }\n }\n}\nfunction error(format) {\n {\n if (!suppressWarning) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n printWarning('error', format, args);\n }\n }\n}\n\nfunction printWarning(level, format, args) {\n // When changing this logic, you might want to also\n // update consoleWithStackDev.www.js as well.\n {\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n if (stack !== '') {\n format += '%s';\n args = args.concat([stack]);\n } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n var argsWithFormat = args.map(function (item) {\n return String(item);\n }); // Careful: RN currently depends on this prefix\n\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n // breaks IE9: https://github.com/facebook/react/issues/13610\n // eslint-disable-next-line react-internal/no-production-logging\n\n Function.prototype.apply.call(console[level], console, argsWithFormat);\n }\n}\n\nvar FunctionComponent = 0;\nvar ClassComponent = 1;\nvar IndeterminateComponent = 2; // Before we know whether it is function or class\n\nvar HostRoot = 3; // Root of a host tree. Could be nested inside another node.\n\nvar HostPortal = 4; // A subtree. Could be an entry point to a different renderer.\n\nvar HostComponent = 5;\nvar HostText = 6;\nvar Fragment = 7;\nvar Mode = 8;\nvar ContextConsumer = 9;\nvar ContextProvider = 10;\nvar ForwardRef = 11;\nvar Profiler = 12;\nvar SuspenseComponent = 13;\nvar MemoComponent = 14;\nvar SimpleMemoComponent = 15;\nvar LazyComponent = 16;\nvar IncompleteClassComponent = 17;\nvar DehydratedFragment = 18;\nvar SuspenseListComponent = 19;\nvar ScopeComponent = 21;\nvar OffscreenComponent = 22;\nvar LegacyHiddenComponent = 23;\nvar CacheComponent = 24;\nvar TracingMarkerComponent = 25;\n\n// -----------------------------------------------------------------------------\n\nvar enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing\n// the react-reconciler package.\n\nvar enableNewReconciler = false; // Support legacy Primer support on internal FB www\n\nvar enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics.\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n\nvar enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz\n// React DOM Chopping Block\n//\n// Similar to main Chopping Block but only flags related to React DOM. These are\n// grouped because we will likely batch all of them into a single major release.\n// -----------------------------------------------------------------------------\n// Disable support for comment nodes as React DOM containers. Already disabled\n// in open source, but www codebase still relies on it. Need to remove.\n\nvar disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection.\n// and client rendering, mostly to allow JSX attributes to apply to the custom\n// element's object properties instead of only HTML attributes.\n// https://github.com/facebook/react/issues/11347\n\nvar enableCustomElementPropertySupport = false; // Disables children for