preface

At present, companies with slightly larger business will basically introduce the interactive development mode of Android and H5, or introduce Hybrid framework, or even directly adopt Js to develop into Web App, because of its advantages of lower development cost (cross-platform) and lower update risk. At present, the cold market of mobile terminal development is not only caused by too many android junior talents, but also by the rise of front-end technology, which occupies the space for native development. However, if you think carefully, in the sense of Internet, mobile terminal App actually belongs to the front-end. So adapting to technology and embracing change is what makes you invincible. Attach source code address

The interface display

The top half is the Android native interface, and the bottom half is the webView loading HTML page. As you can see, the two sides can pass parameters to each other and call each other’s code blocks. Below I put the completed code first posted, have the foundation of the students can directly copy source code and then debug their own look, no foundation of the students don’t worry, listen to me one by one analysis.

Android called Js

There are loadUrl() and evaluateJavascript() methods for calling Js methods from WebView.

Here, the HTML file in local assets is loaded for debugging

1. LoadUrl ()

JsMethod.html

<html>

    <head>
        <meta http-equiv="Content-Type" charset="UTF-8"/>

        <script type="text/javascript">
            var s = 'I'm from the Js method';
            function javatojscallback(param){
                 document.getElementById("textshow").innerHTML = (param);
                 //window.android.JsToJavaInterface(s)
            }
        </script>
    </head>

    <body>

        <h3>Js Method</h3>
        <h3 id="textshow">The results</h3>

    </body>

</html>
Copy the code

Window. The android. JsToJavaInterface call android method (s) is Js, due to the loadUrl () cannot return from Js data, can let the Js callback android back parameters.

MainActivity.java

.private void initView(a) {
        javaMethod = new JavaMethod(this);
        webView = new WebView(this);
        WebSettings settings = webView.getSettings();
        settings.setDomStorageEnabled(true);
        settings.setJavaScriptEnabled(true);
        settings.setBlockNetworkImage(false);
        frameLayout.addView(webView);
        webView.loadUrl("file:///android_asset/JsMethod.html"); }...Copy the code

Call the Js

webView.loadUrl("Javascript: javatojscallback (' I'm from Java)");
Copy the code

2, evaluateJavascript ()

<html>

    <head>
        <meta http-equiv="Content-Type" charset="UTF-8"/>

        <script type="text/javascript">
            var s = 'I'm from the Js method';
            function javatojswith(param){
                 document.getElementById("textshow").innerHTML = (param);
                 return s;
            }
        </script>
    </head>

    <body>

        <h3>Js Method</h3>
        <h3 id="textshow">The results</h3>

    </body>

</html>
Copy the code

Call the Js

    webView.evaluateJavascript("Javascript: Javatojswith (' I'm from Java')".new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String s) { textShow.setText(s); }});Copy the code

LoadUrl () : loadUrl() : loadUrl() : loadUrl() : loadUrl() : loadUrl(); EvaluateJavascript () provides this invisible reception without calling loadUrl().

It’s important to note that,evaluateJavascript()Can only be called after Android 4.4.

Js calls the Android

There are three ways for Js to call Android methods via WebView

1, the addJavascriptInterface

<html>

    <head>
        <meta http-equiv="Content-Type" charset="UTF-8"/>

        <script type="text/javascript">
        </script>
    </head>

    <body>

        <h3>Js Method</h3>
        <h3 id="textshow">The results</h3>
        
        <input type="button" value="JavascriptInterface" onclick="Window. The android. JsToJavaInterface (' I'm from Js')"/>

    </body>

</html>
Copy the code

JavaMethod.java

public class JavaMethod {
    private MainActivity mainActivity;
    private Handler uiHandler;

    public JavaMethod(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
        uiHandler = new Handler(Looper.getMainLooper());
    }

    @JavascriptInterface
    public void JsToJavaInterface(final String param) {
        uiHandler.post(new Runnable() {
            @Override
            public void run(a) {
                mainActivity.setTextShow("from JavaInterface: "+ param); }}); }}Copy the code

Here I separate the method of Js calling Java into a JavaMethod class, and then get the main thread Handler through looper.getMainLooper (), and update the interface in the form of interface.

MainActivity.java

.private void initView(a) {... settings.setJavaScriptEnabled(true);
        webView.addJavascriptInterface(javaMethod,"android");
        frameLayout.addView(webView);
        webView.loadUrl("file:///android_asset/JsMethod.html");
    }

    public void setTextShow(String str) { textShow.setText(str); }...Copy the code

Before Android 4.2, there is a serious vulnerability that Js can call other system methods after obtaining Android objects through webView. In order to avoid this vulnerability, only @javascriptInterface annotated methods can be called after 4.2.

2, shouldOverrideUrlLoading

ShouldOverrideUrlLoading in WebViewClient intercepts URL and makes a corresponding protocol.

<html>

    <head>
        <meta http-equiv="Content-Type" charset="UTF-8"/>

        <script type="text/javascript">
        </script>
    </head>

    <body>

        <h3>Js Method</h3>
        <h3 id="textshow">The results</h3>
        
        <input type="button" value="shouldOverrideUrlLoading" onclick="document.location = 'js://jstojava? Arg1 = arg1 &arg2= arg2 '"/>

    </body>

</html>
Copy the code

JavaMethod.java

.public WebViewClient getWebViewClient(a) {
        WebViewClient webViewClient = new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Uri uri = Uri.parse(url);
                // Use scheme and authority to determine the protocol name
                // url = "js://jstojava? arg1=1&arg2=2"
                if(uri.getScheme().equals("js")) {
                    if(uri.getAuthority().equals("jstojava")) {
                        final String param1 = uri.getQueryParameter("arg1");
                        final String param2 = uri.getQueryParameter("arg2");
                        uiHandler.post(new Runnable() {
                            @Override
                            public void run(a) {
                                mainActivity.setTextShow("arg1="+param1+" arg2="+param2); }}); }return true;
                }

                return super.shouldOverrideUrlLoading(view, url); }};returnwebViewClient; }...Copy the code

MainActivity.java

.private void initView(a) {
        javaMethod = new JavaMethod(this);
        webView = new WebView(this);
        WebSettings settings = webView.getSettings();
        settings.setDomStorageEnabled(true);
        settings.setJavaScriptEnabled(true);
        settings.setBlockNetworkImage(false);
        webView.setWebViewClient(javaMethod.getWebViewClient());
        webView.addJavascriptInterface(javaMethod,"android");
        frameLayout.addView(webView);
        webView.loadUrl("file:///android_asset/JsMethod.html"); }...Copy the code

There are no versionlimits or bugs, but there is no return value. If you want android to return after a Js call, you have to use loadUrl() or evaluateJavascript() to pass back the corresponding receive method. It is worth mentioning that this way is easy to use a set of protocols with IOS, simple Js side of the code.

OnJsAlert (), onJsConfirm(), onJsPrompt()

Intercept alert(), confirm(), prompt() messages in Js via onJsAlert(), onJsConfirm(), onJsPrompt() in WebChromeClient. Alert, Confirm and prompt represent the three common prompt boxes in Js. The first one has no return value, the second one returns a Boolean value, and the third one can return any value. For flexibility, we can simply implement prompt interception.

<html>

    <head>
        <meta http-equiv="Content-Type" charset="UTF-8"/>

        <script type="text/javascript">
        function jstojavaprompt(param){
             result = prompt(param);
             document.getElementById("textshow").innerHTML = (result);
        }
        
        </script>
    </head>

    <body>

        <h3>Js Method</h3>
        <h3 id="textshow">The results</h3>
        
        <input type="button" value="onJsPrompt" onclick="jstojavaprompt('js://jstojava?arg3=3号参数&arg4=4号参数')"/>

    </body>

</html>
Copy the code

JavaMethod.java

.public WebChromeClient getWebChromeClient(a) {
        WebChromeClient webChromeClient = new WebChromeClient(){
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {
                Uri uri = Uri.parse(message);
                if(uri.getScheme().equals("js")) {
                    if(uri.getAuthority().equals("jstojava")) {
                        final String param3 = uri.getQueryParameter("arg3");
                        final String param4 = uri.getQueryParameter("arg4");
                        uiHandler.post(new Runnable() {
                            @Override
                            public void run(a) {
                                mainActivity.setTextShow("arg3="+param3+" arg4="+param4);
                                result.confirm("I'm from onJsPrompt."); }}); }return true;
                }

                return super.onJsPrompt(view, url, message, defaultValue, result); }};returnwebChromeClient; }...Copy the code

MainActivity.java

.private void initView(a) {
        javaMethod = new JavaMethod(this);
        webView = new WebView(this);
        WebSettings settings = webView.getSettings();
        settings.setDomStorageEnabled(true);
        settings.setJavaScriptEnabled(true);
        settings.setBlockNetworkImage(false);
        webView.setWebChromeClient(javaMethod.getWebChromeClient());
        webView.addJavascriptInterface(javaMethod,"android");
        frameLayout.addView(webView);
        webView.loadUrl("file:///android_asset/JsMethod.html"); }...Copy the code

ShouldOverrideUrlLoading intercepts urls in the same way that result.confirm() returns the result to Js after the corresponding thread has finished processing.

conclusion

The above interaction methods have advantages and disadvantages, mainly due to the limitations of the Android version, no version limit method is a little trouble, but general, once and for all, we can consider the introduction of which way to interact with Js from the business models covered.

The source address

The source code has been integrated in the callback way, interested students can see.

Finally, I add a “chicken soup”, I hope you can always keep yourself strong, good night.

Life will not slow down for who, we can only lift the spirit, wipe tears, staggered to catch up with the pace of life.