Home  >  Article  >  Web Front-end  >  Detailed explanation of Java and JavaScript interaction in Android

Detailed explanation of Java and JavaScript interaction in Android

黄舟
黄舟Original
2017-03-15 17:30:581628browse

Android provides a very powerful WebView control for processing Web pages, and in the web page, JavaScript is also a very important script. This article will introduce how to implement mutual calls between Java code and Javascript code.

How to implement

It is very convenient to realize the interaction between Java and js. Usually only the following steps are required.

  • WebView enables JavaScript script execution

  • WebView sets the interactive interface for JavaScript calls.

  • The client and the web page write code to call each other.

This example code

For the convenience of explanation, all the code is posted first

Java code

package com.example.javajsinteractiondemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends Activity {
  private static final String LOGTAG = "MainActivity";
  @SuppressLint("JavascriptInterface")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      final WebView myWebView = (WebView) findViewById(R.id.myWebView);
      WebSettings settings = myWebView.getSettings();
      settings.setJavaScriptEnabled(true);
      myWebView.addJavascriptInterface(new JsInteration(), "control");
      myWebView.setWebChromeClient(new WebChromeClient() {});
      myWebView.setWebViewClient(new WebViewClient() {

          @Override
          public void onPageFinished(WebView view, String url) {
              super.onPageFinished(view, url);
              testMethod(myWebView);
          }

      });
      myWebView.loadUrl("file:///android_asset/js_java_interaction.html");
  }

  private void testMethod(WebView webView) {
      String call = "javascript:sayHello()";

      call = "javascript:alertMessage(\"" + "content" + "\")";

      call = "javascript:toastMessage(\"" + "content" + "\")";

      call = "javascript:sumToJava(1,2)";
      webView.loadUrl(call);

  }

  public class JsInteration {

      @JavascriptInterface
      public void toastMessage(String message) {
          Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
      }

      @JavascriptInterface
      public void onSumResult(int result) {
          Log.i(LOGTAG, "onSumResult result=" + result);
      }
  }

}

Front-end web page code

<html>
<script type="text/javascript">
    function sayHello() {
        alert("Hello")
    }

    function alertMessage(message) {
        alert(message)
    }

    function toastMessage(message) {
        window.control.toastMessage(message)
    }

    function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
    }
</script>
Java-Javascript Interaction In Android
</html>

Calling example

js calls Java

The calling format is window.jsInterfaceName.methodName(parameterValues) In this example we use control as the injection interface name.

function toastMessage(message) {
  window.control.toastMessage(message)
}

function sumToJava(number1, number2){
   window.control.onSumResult(number1 + number2)
}

Java calls JS

The basic format of webView calling js is webView.loadUrl("javascript:methodName(parameterValues)")

Calling js without parameters and no return valueFunction

String call = "javascript:sayHello()";
webView.loadUrl(call);

Call js function with parameters and no return value

Note that strings need to be escaped in double quotes as parameter values.

String call = "javascript:alertMessage(\"" + "content" + "\")";
webView.loadUrl(call);

Calling js functions with parameters and return values

Before 4.4, Android did not provide a method to directly call js functions and obtain values, so before that, the common idea was to call java js method, after the js method is executed, call the java code again to return the value.

1.Java calls js code

String call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);

2.js function processing and returns the result by calling the java method

function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
}

3.Java obtains the js function in the callback method Return value

@JavascriptInterface
public void onSumResult(int result) {
  Log.i(LOGTAG, "onSumResult result=" + result);
}

4.4 Processing

Use evaluateJavascript after Android 4.4. Here is a simple interactive example of a js method with a return value

function getGreetings() {
      return 1;
}

Use the evaluateJavascript method to call when using java code

private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

  @Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}

Output results

I/MainActivity( 1432): onReceiveValue value=1

Note

  • The above limits the return result to String. For simple types, it will be converted into a string and returned. For complex data types, it is recommended to use the string form jsonreturn.

  • evaluateJavascript method must be called on the UI thread (main thread), so onReceiveValue is also executed on the main thread.

Question Answers

Alert cannot pop up

You should not have set up WebChromeClient, follow the following code to set it up

myWebView.setWebChromeClient(new WebChromeClient() {});

Uncaught ReferenceError: functionName is not defined

The reason for the problem is that the js code of the webpage has not been loaded, so the js method is called. The solution is to call the js method after the web page is loaded.

myWebView.setWebViewClient(new WebViewClient() {

  @Override
  public void onPageFinished(WebView view, String url) {
      super.onPageFinished(view, url);
      //在这里执行你想调用的js函数
  }

});

Uncaught TypeError: Object [object Object] has no method

Security restriction issue

If the problem only occurs on machines with version 4.2 or above, then the problem is that the system is under security restrictions. The Android documentation says this

Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.

中文译为

Warning: If your program targets platform 17 or higher, you must add @JavascriptInterface annotation to the method exposed to the web page callable (this method must be public). If you don't do this, the web page will not be able to access your method on platforms 4.2 and later.

Two solutions
  • Set targetSdkVersion to 17 or higher and introduce @JavascriptInterface annotation

  • Create an annotation interface named @JavascriptInterface yourself, and then import it. Note that this interface cannot be confused.

Note, create @JavascriptInterface code

public @interface JavascriptInterface {

}

Code obfuscation problem

If the code in the unobfuscated version runs normally, the code in the obfuscated version A running error occurs and the message Uncaught TypeError: Object [object Object] has no method means that you have not done any obfuscating exception handling. Add code similar to this to the obfuscation file

-keep class com.example.javajsinteractiondemo$JsInteration {
    *;
}

All WebView methods must be called on the same thread

Filter logs have discovered this problem.

E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread &#39;JavaBridge&#39;. 
All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, 
FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546):   at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546):   at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546):   at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546):   at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546):   at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546):   at android.os.HandlerThread.run(HandlerThread.java:61)

The Java callback thread after the js call is not the main thread. If you print the log, you can verify

ThreadInfo=Thread[WebViewCoreThread,5,main]

To solve the above exception, just put the webview operation in the main thread.

webView.post(new Runnable() {
    @Override
    public void run() {
        webView.loadUrl(YOUR_URL).
    }
});


The above is the detailed content of Detailed explanation of Java and JavaScript interaction in Android. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn