Android javascript mixed development

1. Using JavaScript in WebView

Android provides a very powerful WebView control to process web pages, and JavaScript is a very important script in web pages. Therefore, the interaction between Android code and JavaScript code is often involved when using WebView.

Realizing the interaction between Java and js usually only requires the following steps:

①WebView starts JavaScript script execution.

WebView myWebView = (WebView) findViewById(R.id.webview);

WebSettings webSettings = myWebView.getSettings();

webSettings.setJavaScriptEnabled(true);

②WebView sets the interactive interface for JavaScript calls.

③The client and the webpage write the code to call each other.

 

2. JavaScript calls methods in Android

For example, you can use JavaScript code to call a method in Android code to display a dialog box instead of using the alert() method in JS.

To bind a new interface between JS and Android code, you need to call the addJavascriptInterface() method. The method parameter passes in a Java object instance and a string, the string is a name (interface name, note that this interface is not the commonly used interface for implementation, but the object passed in in JS Alias), use this name to call the method of the Java object in the JS code.

The addJavascriptInterface() method allows JS code to control the host program. This is a very powerful feature, but there are also some security issues, because further JS code can access the public domain of the injected object through reflection. Attackers may include threatening code in HTML and JavaScript. So starting from Android 4.1 and API 17, only the public methods identified by the JavascriptInterface annotation can be accessed by JS code.

In addition, because JS code and Java objects interact in the background thread private to this WebView, you also need to pay attention to thread safety issues.

Note that the Java object bound to the JS code runs in a different thread than the thread that created it. And the field of this Java object is not accessible.

//The bridge class between custom Android code and JavaScript code

public class WebAppInterface {

    Context mContext;

    WebAppInterface(Context c) {

        mContext = c;

    }

    // If target>=API 17, you need to add the following annotation

   @JavascriptInterface

    public void showToast(String toast) {

        Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show();

    }

}

Then bind this class to the JS code in WebView:

WebView webView = (WebView) findViewById(R.id.webview);

webView.addJavascriptInterface(new WebAppInterface(this), "Android"); //The alias name for this object is "Android"

In this way, an interface name is created, called "Android", and the JS code running in WebView can call the showToast() method in the WebAppInterface class through this name:

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">

    function showAndroidToast(toast) {

        Android.showToast(toast);

    }

</script>

 

3. Android calls JavaScript code

This is relatively simple, and only one line of code is needed when calling:

myWebView.loadUrl("javascript:myFunction()");

where myFunction() is a JS function.

Note: If the JavaScript function has parameters, special care should be taken when calling it.

For example, the following JS function adds a line to the original content:

function writeLine(string) {

    console.log("Write a new Line");

    document.getElementById("content").innerHTML += string + "<br />";//Add a new line to the content tag paragraph

}

Among them, content is a custom label, and there is a paragraph in html: <p id="content"></p>

Then when calling this writeLine() function in Android code, you need to pass in a string parameter, for example, if you want to pass in a String called name:

myWebView.loadUrl("javascript:writeLine('"+name+"')");//JS code with parameters

Note: The function name in double quotes must not be wrong.

 

4. Example of use

① Android code:

public class MainActivity extends Activity {

  @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(this, 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>

③JS calls Java

The calling format is window.jsInterfaceName.methodName(parameterValues). In this example, control is used 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)”)

1) Call the js function with no parameters and no return value:

String call = "javascript:sayHello()";

webView.loadUrl(call);

2) Call the js function with parameters and no return value:

String call = "javascript:alertMessage(\"" + "content" + "\")"; //Note that double quotes need to be escaped for strings as parameter values.

webView.loadUrl(call);

3) Call js function with parameters and return value

Before 4.4, Android did not provide a method to directly call the js function and get the value, so before that, the common idea is that java calls the js method, and after the js method is executed, the java code is called again to return the value.

Step 1: Java calls js code:

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

webView.loadUrl(call);

The second step: js function processing, and the result is returned by calling the java method

function sumToJava(number1, number2){

   window.control.onSumResult(number1 + number2)

}

Step 3: Java obtains the js function return value in the callback method

@JavascriptInterface

public void onSumResult(int result) {

  Log.i(LOGTAG, "onSumResult result=" + result);

}

Use evaluateJavascript after Android 4.4. A simple interactive example is shown here.

First provide a js method with a return value:

function getGreetings() {

      return 1;

}

In the java code, use the evaluateJavascript method to call:

private void testEvaluateJavascript(WebView webView) {

  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

      @Override

      public void onReceiveValue(String value) {

          Log.i(LOGTAG, "onReceiveValue value=" + value);

      }

   });

}

Output result:

I/MainActivity( 1432): onReceiveValue value=1

Notice:

①The above limits the result to be returned as a String. For simple types, it will try to convert it into a string and return it. For complex data types, it is recommended to return it in the form of json in the form of a string.

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

Guess you like

Origin blog.csdn.net/zenmela2011/article/details/130970132