What is thehybrid?

This is the H5 page embedded in the client, also known as the WebView. It’s not much different from HTML pages in a browser. Because it’s mostly rendered by the WebKit rendering engine.

The WebKit rendering engine consists of the following parts

  1. jsEngine threads
  2. GUIThe render thread
  3. Timer thread
  4. asynchronoushttpthread
  5. Event trigger thread

Asynchronous Event processing is done through the Event Loop, so there is no difference between a WebView and a browser page for front-end developers. But webView runs on Android and IOS. How do they communicate with each other? I’ll use Android as an example to explore how they communicate

First set up the environment

The first step

Create a simple project in Android

The second step

Create a simple HTML page as follows and place it in the SRC /main/ Assets directory of your Android project

<! DOCTYPE html> <html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>shop</title>
</head>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"> </script> <body> <div> I'm webView </div> <div id="cs"JavascriptInterface</div> </body> <script>let i = 0;
    $("#cs").on("click".function(){
        android.showToast("I'm popover.");
    })
</script>
</html>
Copy the code

The third step

Load the webview

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); // Start webView debugging modeif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        WebView.setWebContentsDebuggingEnabled(true);
    }
    WebView webView = (WebView)findViewById(R.id.shop);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.loadUrl("file:///android_asset/shop.html");
}
Copy the code

The page comes up

hybridwithAndroidCommunication mode

The first kind ofJavascriptInterface

Inject a JavascriptInterface into the javascript context. Suppose this JavascriptInterface is named AndroidIn. So you can call Android directly from the WebView

The android code

WebView webView = (WebView)findViewById(R.id.shop);
webView.getSettings().setJavaScriptEnabled(true);
 class JsInterface {
    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
    }
}
webView.addJavascriptInterface(new JsInterface(), "AndroidIn");
Copy the code

The HTML code

<div> I'm webView </div> <div id="cs"JavascriptInterface</div> </body> <script>let i = 0;
    $("#cs").on("click".function(){
        AndroidIn.showToast("I'm popover.");
    })
</script>
Copy the code

I’m popover after I click on it

The second,onJsAlert.onJsConfirm.onJsPrompt

Android can block JS call warning boxes, input boxes, and confirmation boxes

androidcode

WebView webView = (WebView)findViewById(R.id.shop);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient(){
    @Override
    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
        new AlertDialog.Builder(MainActivity.this)
                .setTitle("JsAlert")
                .setMessage(message)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        result.confirm();
                    }
                })
                .setCancelable(false)
                .show();
        return true; }});Copy the code

htmlcode

<div> I'm webView </div> <div id="cs"JavascriptInterface</div> </body> <script>let i = 0;
    $("#cs").on("click".function(){
        alert("I'm popover.");
    })
</script>
Copy the code

When you click on it, the popover has been replaced with the original popover

The third URL parameter

Android adds some parameters to the address when loading the H5 file

 webView.loadUrl("file:///android_asset/shop.html? a=12&b=12");
Copy the code

The h5 page gets the a and B values via the href link

A fourthloadUrl

Android can execute js method H5 code directly via loadUrl

window.Bridge = {
    callJS(){
      alert("I am callJS")}}Copy the code

androidcode

webView.loadUrl("javascript:Bridge.callJS()");
Copy the code

The fifthevaluateJavascript

Similar to the above, except for Android 4.4 and above

webView.evaluateJavascript("javascript:Bridge.callJS()", new ValueCallback<String>() {@override public void onReceiveValue(String value) {// Bridge.callJS returns the result}});Copy the code

6 kinds ofJsBridge

What is a Jsbridge? JsBridge is not an API that comes directly from Android or H5. It is a two-way communication bridge implemented through the above five communication modes (following a protocol). Let’s implement a simple JsBridge

  1. A corresponding is generated each time a native method is calledcallBackThe onlyid. The client callback tells to return the correspondingidTo execute the correspondingcallback
  2. callNativeisH5callThe Android nativeThe way is throughJavascriptInterfaceInto anativeBridgeTo achieve.
  3. receiveNativeisThe Android nativecallH5The way is throughwebView.loadUrl("javascript:window.Bridge.receiveNative("")To implement.

You can call me, I can call you, and then through some protocol (ID). A duplex communication is achieved

H5The following code

<body> <div> I'm webView </div> <div id="cs"JavascriptInterface</div> </body> <script>let cid = 0;
    letcallbacks = {}; Window.bridge = {// Get user login information getUserInfo(data = {}){window.bridge."getUserInfo"GetNetInfo (data = {}){window.bridge.callnative (data = {});"getNetInfo", data)
        },
        callNative: function(bridgeName, data) {
            cid++;
            if (data.onSuccess) {
                callbacks[cid] = data.onSuccess;
            }
            nativeBridge.postMessage(JSON.stringify({
                cid,
                bridgeName: bridgeName,
                data: data.params || {}
            }));
         },
        receiveNative: function(msg) {
            callbacks[msg.cid] && callbacks[msg.cid](msg);
            if(msg.bridgeName ! ="getNetInfo") {
                Reflect.deleteProperty(callbacks, msg.cid);
            }
        }
    }
    document.getElementById("cs").onclick = function(){
        window.Bridge.getUserInfo({
            params:{},
            onSuccess(res){
                alert(res.name)
            }
        })
    }
</script>
Copy the code

AndroidThe following code

final WebView webView = (WebView)findViewById(R.id.h5_shop);
final Handler handler = new Handler(){
    public void handleMessage(Message msg) {
        if (msg.what == 1) {
            webView.loadUrl("javascript:window.Bridge.receiveNative("+resObj.toString()+")"); }}}; webView.getSettings().setJavaScriptEnabled(true);
class JsInterface {
    @JavascriptInterface
    public void postMessage(String a) throws JSONException{
        JSONObject jsonObj = new JSONObject(a);
        String bridgeName = jsonObj.getString("bridgeName");
        if ( bridgeName.equals("getUserInfo") ){
            resObj.put("cid", jsonObj.get("cid"));
            resObj.put("name"."leiwuyi");
            Message msg = new Message();
            msg.what = 1;
            handler.sendMessage(msg);
        } 

    }
}
webView.addJavascriptInterface(new JsInterface(), "nativeBridge");
webView.loadUrl("file:///android_asset/shop.html");
Copy the code

Click and it will look like this

The demo address is github