Javascript Callback function pass to Android

The WebView allows you to directly execute some JavaScript in the window context. So you don't need to pass JavaScript via resource URL .

This is an approved way to pass data back to the html page

/**
 * This is an approved way to pass data back to the html page
 */
 webView.evaluateJavascript("alert('pass here some ...')", new ValueCallback<String>() {
       @Override
       public void onReceiveValue(String s) {

        }
    });

Details from official documentation

Asynchronously evaluates JavaScript in the context of the currently displayed page. If non-null, |resultCallback| will be invoked with any result returned from that execution. This method must be called on the UI thread and the callback will be made on the UI thread.

Compatibility note. Applications targeting N or later, JavaScript state from an empty WebView is no longer persisted across navigations like loadUrl(String). For example, global variables and functions defined before calling loadUrl(String) will not exist in the loaded page. Applications should use addJavascriptInterface(Object, String) instead to persist JavaScript objects across navigations.

Link to the official WebView documentation


I had a similar problem: From within a web app, I'd like to use a native Android confirmation dialog. That implies that I have to call back from Android into the Javascript part with the result of the confirmation dialog.

I solved this as follows:

function foo() {
    // user confirmation needed
    var dataString = <encode data into string>;
    MyClient.showConfirmationDialog('myCallBackFunction', dataString, 'A title', 'A message');
}

The code above calls the Android javascript interface (see below). The javascript provides the callback method myCallbackFunction(), the name of which is passed to Android as parameter (along with a data string, a title and a message). The callback function looks as follows:

function myCallbackFunction(dataString, result) {
    var data = <decode data from dataString>;
    if (result) {
        // user has confirmed
    } else {
        // user has denied
    }
}

On the Android side, I first activate the Javascript interface in the Activity's onCreate() method:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    WebView webView = new WebView(this);
    setContentView(webView);
    WebSettings settings = webView.getSettings();
    settings.setJavaScriptEnabled(true);
    webView.addJavascriptInterface(new MyJavascriptInterface(webView), "MyClient");
}

The implementation of MyJavascriptInterface then creates the according Android dialog and passes the result back to javascript:

    WebView webView;

    public MyJavascriptInterface(WebView w) {
         this.webView = w;
    }

    @JavascriptInterface
    public void showConfirmationDialog(final String callbackFunction, final String data, String title,
            String message) {

        Dialog.OnClickListener positiveListener = new Dialog.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                webView.loadUrl("javascript:" + callbackFunction + "('" + data + "', true)");
            }
        };
        Dialog.OnClickListener negativeListener = new Dialog.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                webView.loadUrl("javascript:" + callbackFunction + "('" + data + "', false)");
            }
        };

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle(title).setMessage(message).setPositiveButton("Ok", positiveListener)
                .setNegativeButton("Cancel", negativeListener).setCancelable(false);
        builder.create().show();
    }

Passing the callback function's name to Android allows to use several calls to confirmation dialogs, each of which is equipped with an own function do the actual action. The data string will carry all data needed to perform the action (and can even contain Json-encoded objects).


You won't be able to pass the function in how you have it specified. You pass a function to Android.myData, but Android.myData takes a string. Instead, you probably want

var myCallback = console.log;
Android.myFunction("myCallback");

You still have a problem in that you aren't passing any data to the callback. While that's not directly related to your question, it will become an issue since you'll have the same cast to/from string issue (solvable via JSON... but it would be nice if Android handled that part for you).

Finally, you can probably shorten the javascript: string to

String js = "javascript:" + callback + "();";

But, of course, test first ;)