Js and native interaction is divided into two cases: JS calls native methods, native calls JS methods.

This article will explain the two cases respectively, H5 end with VUE implementation.

I. Preliminary Preparation (Vue project preparation)

The H5 side of this article is implemented using Vue, so get the Vue project environment ready before you start.

After the project is written, run the NPM run serve command to start the project.

http://localhost:8080/ and http://10.0.0.188:8080/

10.0.0.188 is the IP address of my machine. Everyone’s IP address is different.

Either is fine if you want to access it from your computer’s browser, but use a second one with an IP address if you want to access it from your phone or emulator, and make sure your phone is connected to the same wifi or network segment as your computer.

Note: vuE-cli 3.0 is used here, running the command is different from vue-cli 2.X. Please consult the official documentation for details.

After successful startup, you can configure http://10.0.0.188:8080/ address to WebView in the Android project

Intent intent = new Intent(getActivity(), ProgressWebviewActivity.class);
intent.putExtra("url"."http://10.0.0.188:8080/");
startActivity(intent);
Copy the code

At this point, you can access the Vue project from your phone.

2, Android native call JS methods

Android calls JS in two ways, both via WebView methods:

  1. webview.loadUrl()
  2. webview.evaluateJavascript()

Differences between the two:

  1. LoadUrl () refreshes the page, but evaluateJavascript() does not, so evaluateJavascript() is more efficient

  2. LoadUrl () does not get the js return, evaluateJavascript() does

  3. EvaluateJavascript () is available after Android 4.4

Effects to be achieved:

As shown in the picture below, there is a line of text “haha” on the page. When the WebView page is loaded, the line should be changed to “I changed the text through the native method” + the parameter passed by Android, and a string “JS call successful” should be returned to Android.

2.1 the Vue code

How to write the code in Vue first

mounted() {
    // The method to be called native will be mounted on the window
    window.callJsFunction = this.callJsFunction
},
data() {
    return {
    	msg: "Ha ha"}},methods: {
    callJsFunction(str) {
        this.msg = "I changed the text by native means." + str
        return "Js call successful"}}Copy the code

In methods, define a method called callJsFunction(STR) for Android to call, which takes an argument STR and changes the text on the page.

If you just define a method in methods, the native call will not find the method. So mount the method on the window when the page loads so that the WebView can get hold of it. Notice, this step is very important to write!

Note one detail: this. CallJsFunction should not be followed by parentheses (). Parentheses are equivalent to calling directly.

To sum up, there are two steps to do in Vue:

  1. inmethodsMethod defined in
  2. inmountedMount the method inwindow

2.2 Code in Android

You need to wait until the page is loaded to write the call logic in the onPageFinished method of the WebView, otherwise it will not execute.

2.2.1 loadUrl()implementation

tbsWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url, headerMap);
                return true;
            }

            @Override
            public void onPageFinished(WebView webView, String s) {
                super.onPageFinished(webView, s);
                // Android calls the js method. Note that it needs to be called in the onPageFinished callback
                tbsWebView.post(new Runnable() {
                    @Override
                    public void run(a) {
                        tbsWebView.loadUrl("javascript:callJsFunction('soloname')"); }}); }}); }});Copy the code

If no parameter is not required, remove the parameters can be tbsWebView. LoadUrl (” javascript: callJsFunction () “);

2.2.2 evaluateJavascript()implementation

Other places with the loadUrl (), just put tbsWebView. LoadUrl (” javascript: callJsFunction (‘ soloname ‘) “); replace

@Override
public void onPageFinished(WebView webView, String s) {
    super.onPageFinished(webView, s);
    // Android calls the js method. Note that it needs to be called in the onPageFinished callback
    tbsWebView.post(new Runnable() {
        @Override
        public void run(a) {
            tbsWebView.evaluateJavascript("javascript:callJsFunction('soloname')".new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String s) {
                    Logger.d("Js returns result:"+ s); }}); }}); }Copy the code

You can see that the page is updated, and the second method gets the result returned.

JS calls Android native methods

There are three ways to call Android code with JS:

  1. throughWebViewaddJavascriptInterface()Object mapping
  2. throughWebViewClientshouldOverrideUrlLoading()Method callback intercepts url
  3. throughWebChromeClientonJsAlert(),onJsConfirm(),onJsPrompt()Method callback intercepts the JS dialog boxalert(),confirm(),prompt()The message

Comparison: The first is the simplest, but has bugs below Android 4.2; The second and third are complex to use, but do not have bug problems.

Because the current device system version is basically above 4.2, so the first kind can be used, simple and quick. Time is limited in this article only to achieve the first, the second and the third will not be implemented, want to know can refer to this article.

3.1 Effect Display

The effect is to click the button on the H5 page to pop up the Android native Toast

3.2 the Vue code

methods: {
  showAndroidToast() {
    $App.showToast("Ha ha, I'm calling from JS.")}}Copy the code

Define the method showAndroidToast() in methods and call it when you click the button “Call Android native Toast” on the page.

3.3 the Android code

A new kind of JsJavaBridge

public class JsJavaBridge {

    private Activity activity;
    private WebView webView;

    public JsJavaBridge(Activity activity, WebView webView) {
        this.activity = activity;
        this.webView = webView;
    }

    @JavascriptInterface
    public void onFinishActivity(a) {
        activity.finish();
    }

    @JavascriptInterface
    public void showToast(String msg) { ToastUtils.show(msg); }}Copy the code

Then set up the mapping between Android class and JS code through WebView

tbsWebView.addJavascriptInterface(new JsJavaBridge(this, tbsWebView), "$App");
Copy the code

Here the JsJavaBridge class is mapped to $App in JS, so in Vue you can call $app.showtoast like this (” ha ha, I am called by JS “).

This is how Android and JS call each other.