|
| 1 | +# A Simple note after Reading this [POST](https://blog.csdn.net/sbsujjbcy/article/details/50752595) |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +# the normal Stream of logic: |
| 6 | + |
| 7 | +## from the View of frontend |
| 8 | +```` |
| 9 | +<!DOCTYPE HTML> |
| 10 | +<html> |
| 11 | +<head> |
| 12 | + <meta charset="utf-8"> |
| 13 | + <title>JSBridge</title> |
| 14 | + <meta name="viewport" |
| 15 | + content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1, user-scalable=no"/> |
| 16 | + <script src="file:///android_asset/JSBridge.js" type="text/javascript"></script> |
| 17 | + <script type="text/javascript"> |
| 18 | +
|
| 19 | + </script> |
| 20 | + <style> |
| 21 | +
|
| 22 | + </style> |
| 23 | +</head> |
| 24 | +
|
| 25 | +<body> |
| 26 | +<div> |
| 27 | + <h3>JSBridge 测试</h3> |
| 28 | +</div> |
| 29 | +<ul class="list"> |
| 30 | + <li> |
| 31 | + <div> |
| 32 | + <button onclick="JSBridge.call('bridge','showToast',{'msg':'Hello JSBridge'},function(res){alert(JSON.stringify(res))})"> |
| 33 | + 测试showToast |
| 34 | + </button> |
| 35 | + </div> |
| 36 | + </li> |
| 37 | + <br/> |
| 38 | +</ul> |
| 39 | +</body> |
| 40 | +</html> |
| 41 | +```` |
| 42 | + |
| 43 | +When the button is pressed: the logic inside the JSBrige.js file will be triggered: |
| 44 | + |
| 45 | +```` |
| 46 | +(function (win) { |
| 47 | + var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 48 | + var JSBridge = win.JSBridge || (win.JSBridge = {}); |
| 49 | + var JSBRIDGE_PROTOCOL = 'JSBridge'; |
| 50 | + var Inner = { |
| 51 | + callbacks: {}, |
| 52 | + call: function (obj, method, params, callback) { |
| 53 | + console.log(obj+" "+method+" "+params+" "+callback); |
| 54 | + var port = Util.getPort(); |
| 55 | + console.log(port); |
| 56 | + this.callbacks[port] = callback; |
| 57 | + var uri=Util.getUri(obj,method,params,port); |
| 58 | + console.log(uri); |
| 59 | + window.prompt(uri, ""); |
| 60 | + }, |
| 61 | + onFinish: function (port, jsonObj){ |
| 62 | + var callback = this.callbacks[port]; |
| 63 | + callback && callback(jsonObj); |
| 64 | + delete this.callbacks[port]; |
| 65 | + }, |
| 66 | + }; |
| 67 | + var Util = { |
| 68 | + getPort: function () { |
| 69 | + return Math.floor(Math.random() * (1 << 30)); |
| 70 | + }, |
| 71 | + getUri:function(obj, method, params, port){ |
| 72 | + params = this.getParam(params); |
| 73 | + var uri = JSBRIDGE_PROTOCOL + '://' + obj + ':' + port + '/' + method + '?' + params; |
| 74 | + return uri; |
| 75 | + }, |
| 76 | + getParam:function(obj){ |
| 77 | + if (obj && typeof obj === 'object') { |
| 78 | + return JSON.stringify(obj); |
| 79 | + } else { |
| 80 | + return obj || ''; |
| 81 | + } |
| 82 | + } |
| 83 | + }; |
| 84 | + for (var key in Inner) { |
| 85 | + if (!hasOwnProperty.call(JSBridge, key)) { |
| 86 | + JSBridge[key] = Inner[key]; |
| 87 | + } |
| 88 | + } |
| 89 | +})(window); |
| 90 | +```` |
| 91 | +the called in the html passes in four paramerters: |
| 92 | + |
| 93 | +``JSBridge.call('bridge','showToast',{'msg':'Hello JSBridge'},function(res){alert(JSON.stringify(res))})`` |
| 94 | + |
| 95 | +the name of the related class named ``brige`` and the method of the ``bridge`` class and the json string of the value then the callback function. |
| 96 | + |
| 97 | +## from the view of Android side: |
| 98 | + |
| 99 | +- inside JSBrige.java, we ought to use reflection to get the specific class and the method inside to be flexiable. |
| 100 | + |
| 101 | +```` |
| 102 | +public class JSBridge { |
| 103 | + private static Map<String, HashMap<String, Method>> exposedMethods = new HashMap<>(); |
| 104 | +
|
| 105 | + public static void register(String exposedName, Class<? extends IBridge> clazz) { |
| 106 | + if (!exposedMethods.containsKey(exposedName)) { |
| 107 | + try { |
| 108 | + exposedMethods.put(exposedName, getAllMethod(clazz)); |
| 109 | + } catch (Exception e) { |
| 110 | + e.printStackTrace(); |
| 111 | + } |
| 112 | + } |
| 113 | + } |
| 114 | +
|
| 115 | + private static HashMap<String, Method> getAllMethod(Class injectedCls) throws Exception { |
| 116 | + HashMap<String, Method> mMethodsMap = new HashMap<>(); |
| 117 | + Method[] methods = injectedCls.getDeclaredMethods(); |
| 118 | + for (Method method : methods) { |
| 119 | + String name; |
| 120 | + if (method.getModifiers() != (Modifier.PUBLIC | Modifier.STATIC) || (name = method.getName()) == null) { |
| 121 | + continue; |
| 122 | + } |
| 123 | + Class[] parameters = method.getParameterTypes(); |
| 124 | + if (null != parameters && parameters.length == 3) { |
| 125 | + if (parameters[0] == WebView.class && parameters[1] == JSONObject.class && parameters[2] == Callback.class) { |
| 126 | + mMethodsMap.put(name, method); |
| 127 | + } |
| 128 | + } |
| 129 | + } |
| 130 | + return mMethodsMap; |
| 131 | + } |
| 132 | +
|
| 133 | +public static String callJava(WebView webView, String uriString) { |
| 134 | + String methodName = ""; |
| 135 | + String className = ""; |
| 136 | + String param = "{}"; |
| 137 | + String port = ""; |
| 138 | + if (!TextUtils.isEmpty(uriString) && uriString.startsWith("JSBridge")) { |
| 139 | + Uri uri = Uri.parse(uriString); |
| 140 | + className = uri.getHost(); |
| 141 | + param = uri.getQuery(); |
| 142 | + port = uri.getPort() + ""; |
| 143 | + String path = uri.getPath(); |
| 144 | + if (!TextUtils.isEmpty(path)) { |
| 145 | + methodName = path.replace("/", ""); |
| 146 | + } |
| 147 | + } |
| 148 | +
|
| 149 | +
|
| 150 | + if (exposedMethods.containsKey(className)) { |
| 151 | + HashMap<String, Method> methodHashMap = exposedMethods.get(className); |
| 152 | +
|
| 153 | + if (methodHashMap != null && methodHashMap.size() != 0 && methodHashMap.containsKey(methodName)) { |
| 154 | + Method method = methodHashMap.get(methodName); |
| 155 | + if (method != null) { |
| 156 | + try { |
| 157 | + method.invoke(null, webView, new JSONObject(param), new Callback(webView, port)); |
| 158 | + } catch (Exception e) { |
| 159 | + e.printStackTrace(); |
| 160 | + } |
| 161 | + } |
| 162 | + } |
| 163 | + } |
| 164 | + return null; |
| 165 | + } |
| 166 | +} |
| 167 | +
|
| 168 | +
|
| 169 | +```` |
| 170 | +- and there is one more class for callback in Javascript -- to use webview to ``loadUrl()`` the callback in JSBridge.js |
| 171 | + |
| 172 | +```` |
| 173 | +public class Callback { |
| 174 | + private static Handler mHandler = new Handler(Looper.getMainLooper()); |
| 175 | + private static final String CALLBACK_JS_FORMAT = "javascript:JSBridge.onFinish('%s', %s);"; |
| 176 | + private String mPort; |
| 177 | + private WeakReference<WebView> mWebViewRef; |
| 178 | +
|
| 179 | + public Callback(WebView view, String port) { |
| 180 | + mWebViewRef = new WeakReference<>(view); |
| 181 | + mPort = port; |
| 182 | + } |
| 183 | +
|
| 184 | +
|
| 185 | + public void apply(JSONObject jsonObject) { |
| 186 | + final String execJs = String.format(CALLBACK_JS_FORMAT, mPort, String.valueOf(jsonObject)); |
| 187 | + if (mWebViewRef != null && mWebViewRef.get() != null) { |
| 188 | + mHandler.post(new Runnable() { |
| 189 | + @Override |
| 190 | + public void run() { |
| 191 | + mWebViewRef.get().loadUrl(execJs); |
| 192 | + } |
| 193 | + }); |
| 194 | +
|
| 195 | + } |
| 196 | +
|
| 197 | + } |
| 198 | +} |
| 199 | +```` |
| 200 | + |
0 commit comments