Search code examples
javajavascriptandroidandroid-jsinterface

How to pass a Javascript function as an argument in Javascript Interface?


How to pass a function as a parameter in Javascript Interface, save it as a string and then call?

For example, I describe the Javascript Interface:

class JSInterface{
  String myFunction;

  //set function into myFunction attribute
  @JavascriptInterface
  public void setMyFunction(String func) {
    this.myFunction = func;
  }

  @JavascriptInterface
  public void executeMyFunction() {
    webView.loadUrl("javascript:"+this.myFunction);
  }

}

Add it:

//...

webview..addJavascriptInterface(new JSInterface, "application");

//...

In JS:

window.application.setMyFunction(function(){
        //some code here...
});

NOTE: Transfer function from JS need in this form, not as a string or json.

But in fact, in setMyFunction i get "undefined" but expect "window.application.setMyFunction(function(){ //some code here...});". Tell me please what to do, I will be very grateful!


Solution

  • To solve this problem, when function passed as null, we need to declare the function that will be send the js function into JS Interface as string.

    We also need to do this when onPageFinished.

    For example:

    @Override
    public void onPageFinished(WebView view, String url) {
        view.loadUrl("javascript: window.APPLICATION.setMyFunction = function(func){"
            + "window.APPLICATION.setMyFunctionAsString(func.toString());"
            + "};");
        super.onPageFinished(view, url);
    }
    

    ...and setMyFunctionAsString in JS Interface:

    @JavascriptInterface
    public void setMyFunctionAsString(String func) {
        this.myFunction = func;
    }
    

    Now, finnaly, when we do:

    window.APPLICATION.setMyFunction(function(){
            //some code here...
    });
    

    we will have "window.APPLICATION.setMyFunction(function(){\n//some code here...\n});" in myFunction and can easily call it like:

    @JavascriptInterface
    public void executeMyFunction() {
        webView.loadUrl("javascript:"+this.myFunction);
    }
    

    I hope that this will help someone =)