This article detailed how to use JSBridge to interact with H5 and native Android and IOS. OC and Swift are available on IOS, and Java and Kotlin are available on Android.

First, write first

This article mainly describes how to use JSBridge to communicate between H5 and native through code. The article contains H5, IOS, Android three parts of the code. OC and Swift were used to implement the code respectively in IOS. Android using Java and Kotlin code implementation respectively.

Demo address: jsbridge-example

  • JSBridgeH5:H5End code implementation
  • JSBridgeIOSOC: nativeIOSOCCode implementation
  • JSBridgeIOSSwift: nativeIOSSwiftCode implementation
  • JSBridgeAndroidJava: nativeAndroidJavaCode implementation
  • JSBridgeAndroidKotlin: nativeIOSKotlinCode implementation

This article does not explain the principle of the part, just detailed use of the code to introduce the use of JSBridge. For those who want to know more about the principles, you can search a separate blog about the principles.


Ii. H5 end code

  • Initialize theWebViewJavascriptBridge, the mode code is as follows
  • Register event functions for native invocation:window.setupWebViewJavascriptBridge(bridge => bridge.registerHandler('fnName', function) )
  • Call the native event function:window.setupWebViewJavascriptBridge(bridge => bridge.callHandler('fnName', data, callback) )

1. InitializationWebViewJavascriptBridge

In the project entry file or root js file, add the following code:


// Use the mobile terminal's native userAgent to determine whether it is Android or ios
const u = navigator.userAgent;
/ / Android terminal
const isAndroid = u.indexOf('Android') > - 1 || u.indexOf('Adr') > - 1;
/ / IOS terminal
constisIOS = !! u.match(/\(i[^;] +; ( U;) ? CPU.+Mac OS X/); 

/** * Init method used with IOS */
const iosFunction = (callback) = > {
    if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) }
    if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback) }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function(){
         document.documentElement.removeChild(WVJBIframe);
    }, 0);
}

/** * The initialization method for Android */
const androidFunction = (callback) = > {
    if (window.WebViewJavascriptBridge) {
        callback(window.WebViewJavascriptBridge);
    } else {
        document.addEventListener('WebViewJavascriptBridgeReady'.function () {
            callback(window.WebViewJavascriptBridge);
        }, false)}}window.setupWebViewJavascriptBridge = isAndroid ? androidFunction : iosFunction;

isAndroid && window.setupWebViewJavascriptBridge(function (bridge) {
    // Register the default receiving function of H5 interface (when interacting with Android, android can send data directly without calling the function name, and can receive data here)
    bridge.init(function (msg, responseCallback) {
        console.log(msg);
        responseCallback("JS returns to native message content"); })});Copy the code

Register event functions that interact with the native

/ * window. SetupWebViewJavascriptBridge (bridge = > {bridge. RegisterHandler (' event function name, fun executive function); }) * /
window.setupWebViewJavascriptBridge(bridge= > {
    /** * data: native data * fn: native callback */
    bridge.registerHandler("H5Function", (data, fn) => {
        console.log(data);
        fn && fn();
    });
});
Copy the code

3. Call the natively registered event function

The native registered time function is called with the following code:

/ * window. SetupWebViewJavascriptBridge (bridge = > {bridge. CallHandler (' AnZhuoDuan function name, "data" to the native, the callback callback function); }) * /
window.setupWebViewJavascriptBridge(bridge= > {
    bridge.callHandler('changeData', data, (result) => {
        console.log(result);
    });
})
Copy the code

Iii. IOS code

  • Initialize WebViewJavascriptBridge:

    + (instancetype)bridgeForWebView:(id)webView;
    + (instancetype)bridge:(id)webView;
    Copy the code
  • – (void)registerHandler:(NSString*)handlerName Handler:(WVJBHandler) Handler;

  • Call the h5-side event function:

    - (void)callHandler:(NSString*)handlerName;
    - (void)callHandler:(NSString*)handlerName data:(id)data;
    - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
    Copy the code

1. Introduce WebViewJavascriptBridge

Direct use mode

  • Download WebViewJavascriptBridge

  • Find the WebViewJavascriptBridge folder and drag it directly into the XCode project. In the pop-up window prompted, select Copy items if needed and Create groups, as shown below:

  • The ViewController. H header file into # import “WebViewJavascriptBridge. H

Cocopad usage mode

If you must use this method, Google it yourself.

2. Initialize the WebViewJavascriptBridge

// Enable WebViewJavascriptBridge Log
[WebViewJavascriptBridge enableLogging];

Initialize the WKWebViewConfiguration object
self.webConfig = [[WKWebViewConfiguration alloc] init];
// Set preferences
_webConfig.preferences = [[WKPreferences alloc] init];
// Default is 0
_webConfig.preferences.minimumFontSize = 10;
// The default is YES
_webConfig.preferences.javaScriptEnabled = YES;
// On iOS, the default value is NO, indicating that the window cannot be opened automatically
_webConfig.preferences.javaScriptCanOpenWindowsAutomatically = NO;

// TODO:Replace with the url of the page
NSString *URLSTR = @"http://xxx.xxx.xxx.xx:xxxx";
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:_webConfig];
// Set the UserAgent suffix
_webView.customUserAgent = [NSString stringWithFormat:self.webView.customUserAgent, @"app"];
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
NSURL *url = [NSURL URLWithString:URLSTR];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[_webView loadRequest:urlRequest];
[self.view addSubview:_webView];

self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[_bridge setWebViewDelegate:self];
Copy the code

3. Register event functions that interact with H5

// Example: Register the changeUser function that changes the User name
[self.bridge registerHandler:@"changeUser" handler:^(id data, WVJBResponseCallback responseCallback) {
    // Handle the logic here
    NSLog(@"Data from JS %@", data);
    if (responseCallback) {
        // Execute the callback function
        responseCallback(@"Data returned to JS"); }}];Copy the code

4. Call the h5-side event function

[self.bridge callHandler:@"changeName" data:name responseCallback:^(id responseData) {self.bridge callHandler:@"changeName" data:name responseCallback:^(id responseData) { NSLog(responseData);}];Copy the code

Iv. Android code

  • Registration andH5Interactive event functions:
    public void registerHandler(String handlerName, BridgeHandler handler) {
        if(handler ! =null) { messageHandlers.put(handlerName, handler); }}Copy the code
  • callH5End event function
    public void callHandler(String handlerName, String data, CallBackFunction callBack) {
        doSend(handlerName, data, callBack);
    }
    Copy the code
  • Registration andH5The default event for the interaction, i.eH5End does not call the function name, directly usesendFunction to pass data, and Android can also receive data in this event
    // Set the default receiver function
    public void setDefaultHandler(BridgeHandler handler) {
        this.defaultHandler = handler;
    }
    Copy the code
  • Call the default event function registered on the H5 side
    @Override
    public void send(String data, CallBackFunction responseCallback) {
        doSend(null, data, responseCallback);
    }
    Copy the code

1. Introduce BridgeWebView

  • Add the following code to your project’s build.gradle file:
    buildTypes {
        // ...
        repositories {
            // ...
            maven { url "https://jitpack.io"}}}Copy the code
  • Add dependencies:Implementation 'com. Making. Lzyzsd: jsbridge: 1.0.4'

2. Initialize BridgeWebView

inactivity_main.xmlAdd layout to file

<com.github.lzyzsd.jsbridge.BridgeWebView
    android:id="@+id/main_wv"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</com.github.lzyzsd.jsbridge.BridgeWebView>
Copy the code

Initialize the BridgeWebView in MainActivity

mWebView = findViewById(R.id.main_wv);

mWebView.getSettings().setAllowFileAccess(true);
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.getSettings().setDatabaseEnabled(true);
/ / open localStorage
mWebView.getSettings().setDomStorageEnabled(true);
// Set javascript support
mWebView.getSettings().setJavaScriptEnabled(true);
// Zoom
mWebView.getSettings().setBuiltInZoomControls(true);
/ / set the UserAgent
mWebView.getSettings().setUserAgentString(mWebView.getSettings().getUserAgentString() + "app");
// Set it to display directly in the current WebView without opening in the system browser
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebViewClient(new MyWebViewClient(mWebView));

mWebView.loadUrl(URL);
Copy the code

3. Register event functions that interact with H5

// The default event function
mWebView.setDefaultHandler(new BridgeHandler() {
    @Override
    public void handler(String data, CallBackFunction function) {
        Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show();
        function.onCallBack("Message content returned by Android to JS"); }});// A normal event function
mWebView.registerHandler("reloadUrl".new BridgeHandler() {

    @Override
    public void handler(String data, CallBackFunction function) {
        mWebView.reload();
        Toast.makeText(MainActivity.this."Refresh successful ~", Toast.LENGTH_SHORT).show();
        function.onCallBack(""); }});Copy the code

4. Call the h5-side event function

// Call the h5-side default event function
mWebView.send("Android message to JS".new CallBackFunction() {
    @Override
    public void onCallBack(String data) {
        Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show(); }});// Call the h5-side normal event function
mWebView.callHandler("changeName", mEditName.getText().toString(), new CallBackFunction() {
    @Override
    public void onCallBack(String data) {
        Toast.makeText(MainActivity.this."Name changed successfully", Toast.LENGTH_SHORT).show();
        mEditName.setText(""); }});Copy the code

5. Add network permissions

Now, this step is required, otherwise, the WebView does not load, and the phone screen says Webpage not available.

  • In the androidmanifest.xml manifest file add:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    Copy the code
  • Add the permissions, web pages load may be not to come out, may be because the mistrust of unencrypted traffic, in AndroidManifest. An attribute is added to the application of XML: android: usesCleartextTraffic = “true”. As follows:

    <?xml version="1.0" encoding="utf-8"? >
    <manifest .>
        <application 
            .
            android:usesCleartextTraffic="true">.</application>
    </manifest>
    Copy the code

Five, the Tips

1. Use WebViewJavascriptBridge in Swift

Just like in OC, drag the downloaded WebViewJavascriptBridge folder directly into the Swift project. However, it cannot be used directly at this point because WebViewJavascriptBridge is written using OC. So you need to create a Header file called: project-name-bridge-header. h to import the OC Header files you need to use. Instead of creating it manually, LET XCode do it for you. Create an OC file in Swift project:

XCode will then automatically prompt you to create the Bridging Header:

Introducing WebViewJavascriptBridge created, in the folder. H header file:

Finally, you can use the methods written in OC normally in Swift code:

Unknown Class ViewController in Interface Builder file Unknown Class ViewController in Interface Builder file

The solution: Open the main. storyboard file and use the following image to find the ViewController in the input box indicated by the arrow, delete it, and then type again. Find a new ViewController and fill it in:


6. Reference links

  • JsBridge
  • WebViewJavascriptBridge
  • IOS developer -WKWebView sets cookies
  • OC/C method is used in SWIFT project
  • IOS is similar to toast on Android

7. Demo address

jsbridge-example

If it helps, welcome Star!