androidasync-awaitwebviewpromiseevaluatejavascript

Handle Promise from Android WebView with evaluateJavascript


I'm working with the Android WebView and trying to handle the return of a JavaScript promise from the WebView on the Java side after calling it with evaluateJavascript.

document.java

Button buttonAnnotations = findViewById(R.id.buttonAnnotations);
buttonAnnotations.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        wv.evaluateJavascript("javascript:getAnnotations();", new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                Toast.makeText(getApplicationContext(), value, Toast.LENGTH_SHORT).show();
            }
        });
    }
});

index.html

async function getAnnotations() {
    await pdfViewer.getAnnotations().then(result => {
        return JSON.stringify(result ,null,2);
    });
}

If I change the getAnnotations() function to not be async and return a string all works fine, so I'm trying to figure out how to handle this promise in the java code to get the result.

I've seen a few similar questions but none of the answers seemed to work in this case.


Solution

  • As I mentioned in the comment, you are returning a Promise from the async function getAnnotations (which cannot be used directly in onReceiveValue).

    In order to "push" the result from getAnnotations back to Android, you have to use the JavascriptInterface:

    In your Activity you can define:

    @JavascriptInterface
    public void onAnnotations(String result) {
        Toast.makeText(WebViewActivity.this, result, Toast.LENGTH_LONG).show();
    }
    

    and register it with:

    webView.addJavascriptInterface(this, "bridge");
    

    In this case the method onAnnotations resists within the Activity which also contains the webView. Therefore I use "this" for the first Argument. The "bridge" is the namespace, where you can find the function onAnnotations on the JavaScript side.

    Now all you have to do, is to make the call from JavaScript to Android:

    function getAnnotations() {
        pdfViewer.getAnnotations().then(result => {
            bridge.onAnnotations(JSON.stringify(result ,null,2));
        });
    }