- The original address: segmentfault.com/a/119000002…
JavaScript is run in a separate JS Context (for example: JSBridge is a communication method of JS and Native in Hybrid development. In brief, JSBridge is a communication method of JS and Native in Hybrid development. JSBridge is to define the communication between Native and JS. Native only calls JS through a fixed bridge object, and JS only calls Native through a fixed bridge object.
jsBridge
Two ways to interactInto the API
,url schema
,Override the H5 global method
Injection API form
Android operating method
-
Call native js
Before Android 4.4, you can't get the return value // mWebView = new WebView(this); // The current WebView object mWebView.loadUrl("Javascript: method name (' parameter, need to be converted to string ')") // Android 4.4 and later // webView.evaluateJavascript("javascript:if(window.callJS){window.callJS('" + str + "');}", new ValueCallback<String>() { mWebView.evaluateJavascript("Javascript: method name, parameter needs to be converted to string".new ValueCallback() { @Override public void onReceiveValue(String value) { // Where value is the return value of the corresponding JS method}})// js declares a function on the global window for Android to call window.callAndroid = function() { console.log('Method from h5 for native call') return "Return value from H5" } Conclusion: / * * 1. 4.4 Before, Native used loadUrl to call JS methods, so only one JS method could be executed, but the return value of this method could not be obtained. And get the return value in onReceive 3. 4. The mWebView. LoadUrl ("javascript: method name ") function needs to be run in the UI thread because mWebView is a UI control and blocks the UI thread */ Copy the code
-
JS call Native
// Android environment configuration WebSettings webSettings = mWebView.getSettings(); // The Android container allows JAVASCRIPT, which is mandatory webSettings.setJavaScriptEnabled(true); // The Android container sets the connection object mWebView.addJavascriptInterface(getJSBridge(), "JSBridge"); // JSBridge business code for Android private Object getJSBridge(a) { Object insterObj = new Object() { @JavascriptInterface public String foo(a) { // The business code for foo Bridge is executed here return "foo" / / the return value } @JavascriptInterface public String foo2(final String param) { // Execute the business code for the foo2 method bridge here return "foo2"+ param; }}return inserObj; } // js calls native code // JSBridge has been injected into the Window object via addJavascriptInterface window.JSBridge.foo(); / / return a 'foo' window.JSBridge.foo2(); / / return 'foo2: test' // note: before android 4.2, addJavascriptInterface is a risk,hacker can decompilate Native registered Js objects, and then reflect Java's built-in static classes on the page to get sensitive information and damage Copy the code
Ios Operating Methods
- Js call native
// Note: before ios7, javascript could not call native methods. After ios7, JavaScriptCore libraries provided by third parties can be introduced / * summary: 2. Js can call exposed apis and get corresponding return values. 3. Ios Native itself cannot be called by JS. However, by introducing officially provided third-party "JavaScriptCore", you can develop API to JS call */ // WKWebview comes out after ios8, js calls native methods https://zhuanlan.zhihu.com/p/32899522 / code/ios configuration / / js calls window.webkit.messageHandlers.{name}.postMessage(msgObj); /* * Advantages and disadvantages Ios development comes with two kinds of WebView control UIWebview (ios8 earlier version, recommended deprecation) version is older, can use JavaScriptCore to inject global custom objects occupy a large memory, Slow loading Speed WKWebview version is faster than the new loading speed, small memory */ Copy the code
- Call native js
// UIWebview [webView stringByEvaluatingJavaScriptFromString:@"Method name (parameter);"]; // WKWebview [_customWebView evaluateJavaScript:[@"Method name (parameter)"] completionHandler:nil]; -------------------- // js calls native UIWebview = UIWebview = UIWebview = UIWebview #import <JavaScriptCore/JavaScriptCore.h> // Set up some js interfaces after the webView is loaded- (void)webViewDidFinishLoad:(UIWebView *)webView{ [self hideProgress]; [self setJSInterface]; } - (void)setJSInterface{ JSContext *context =[_wv valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // Register an API method named foo context[@"foo"] = ^ () {// Get parameters NSArray *args = [JSContext currentArguments]; NSString *title = [NSString stringWithFormat:@"% @",[args objectAtIndex:0]].// Do some logic of your own and return a value of 'foo:'+title return [NSString stringWithFormat:@"foo:%@", title]; }; } window.foo('test'); / / return a 'foo: test' Copy the code
The url scheme is introduced
-
Url scheme is a link similar to URL, which is designed to facilitate apps to call each other directly: You can use the OpenURI of the system to open links similar to URL (parameters that can be spelt), and then the system will judge. If it is the system URL Scheme, open the system application; otherwise, check whether there is any scheme registered in app, open the corresponding app. This scheme takes effect only after the native APP is registered. For example, weixin:// is used in wechat
-
Call the process (such as iframe.src), and then native uses some method to capture the corresponding URL triggering event, and then get the current triggering URL, according to the established protocol (Scheme ://method/? Params = XXX), and native intercepts the request to analyze which method is currently triggered, and then implements it according to the definition
-
The client captures the URL
- Android capture URL scheme:
shouldoverrideurlloading
Capture the URL for analysis - Ios:
UIWebView WKWebview
All network requests initiated in the native layer can be notified through the delegate functionshouldStartLoadWithRequest
Catch the trigger in the WebViewurl scheme
- Android capture URL scheme:
-
General process: H5 –> trigger a URL in some way –> Native captures the URL for analysis –> native does the processing –> Call H5 JSBridge object to pass the callback if it needs to be called
-
Disadvantages: The speed may be slightly slower, the URL length will be limited, the need to define the URL structure is complicated
-
The API form has the following advantages over injection:
- The addJavaScriptInterface method has a security hole
- Js cannot call Native under ios7
- Url Scheme interaction is a set of existing mature scheme, compatible with various versions
Override native methods such as prompt/alert
- Native will hijack webView
OnJsAlert, onJsConfirm, onConsoleMessage, onJsPrompt
And rewrite it, as if the higher version of ios had restricted it
The design implements a JSBridge
- Design a native interaction with JS
Global bridge object
- How does JS call Native
- How does Native call JS
- H5 API methods
send
/register
// Name: a property that JSBridge hangs on the window
window.JSBridge = {
/ /... Other attributes, such as version and basic APP information
// A collection of callback functions
_cbMap: {},
// js register method, native initiate the call
register(method, callback) {
const callbackId = method
this._cbMap[callbackId] = callback
},
// h5 calls the native method, which stores the callback ID into the local variable cbList
send(method, data, callback) {
let callbackId
if (callback) {
callbackId = `${method}_The ${Date.now()}`
this._cbMap[callbackId] = callback
}
const params = {
method, // The method field is the bridge name
callback: callbackId,
data: {} // Business parameters
}
// Call native to pass parameters in ==> Communication mode above three can be selected arbitrarily
callNative(JSON.Stringify(params))
},
// Native callback js method obj: {callback id, callback data}
// Native only calls this method with a json string
handler(obj) {
const { callbackId, data } = JSON.parse(obj)
// Execute the corresponding callback function (send callback). If you want to return a value, send another callback
this._cbMap[callbackId] && this._cbMap[callbackId].(data)
}
}
// Call an example
// Take the initiative to send messages
JSBridge.send('ui.callNative', {}, (data) = > data)
// Register locally and passively accept client calls
JSBridge.register("ui.datatabupdate".(data) = > data);
Copy the code
JSBridge.send
The inside of thecallNative
Concrete implementation of
- Url schema way
// Url schema implementation
// becomes a string and encodes it
var url = scheme://ecape(JSON.stringify(param))
// Use an internally created iframe to trigger scheme (location.href = may cause jump problems)
var iframe = document.createElment('iframe');
iframe.src = url;
document.head.appendChild(iframe);
setTimeout(() = > document.head.removeChild('iframe'), 200)
Copy the code
- API injection mode
// ios
window.webkit.messageHandlers.{name}.postMessage(JSON.stringify(params))
/ / android
window.{name}.{name}(JSON.stringify(params))
Copy the code
The resources
- www.cnblogs.com/dailc/p/593…
- Zhuanlan.zhihu.com/p/32899522, JSBridgeDemo
- Github.com/chemdemo/ch…
- Android interacts with JS
- ZOO TTEAM JSBridge