Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Interface Cannot Find Function

I have a JavaScriptInterface class that has a single function. The function is annotated with @JavascriptInterface and I believe I have set it up correctly.

public class JavaScriptInterface {

    ...

    @JavascriptInterface
    public void processBody(String uri, String body) {
        Log.d(TAG, "Process body");
        ...
    }
}

Then I set JavaScriptEnabled on the WebView and attempt to call the function:

final WebView webView = new WebView(this);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(), "java");

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        Log.d(TAG, "Page finished");
        callJavaScript();
    }
});

The page finishes loading, then I have tried a variety of methods to call the JavaScript function from my JavaScriptInterface. Using one of these two methods:

view.evaluateJavascript(javascript);

view.loadUrl("javascript:" + javascript);

And one of these javascript strings:

"(function() { window.java.processBody('" + url + "', document.body.innerHTML); })()"

"(function() { processBody('" + url + "', document.body.innerHTML); })()"

"window.java.processBody('" + url + "', document.body.innerHTML);"

"processBody('" + url + "', document.body.innerHTML);"

Every time I get the error message:

I/chromium: [INFO:CONSOLE(1)] "Uncaught TypeError: processBody is not a function", source: (1)

Though on older devices (pre KitKat) the error message never shows up, the function just never gets called.

This method also had been working previously, and I do not believe I have changed any of the code for this activity. I was just made aware of the bug this morning.

like image 696
Bryan Avatar asked Jan 29 '16 15:01

Bryan


1 Answers

As we have figured out with Bryan, the problem was due to ProGuard stripping out functions that are not called from Java. A quick and simple test is to add some code in Java that calls the JS interface function, and see whether it helps.

For information on how to configure ProGuard not to strip out methods of injected Java objects, see How to configure proguard for javascript interface?

like image 86
Mikhail Naganov Avatar answered Oct 28 '22 16:10

Mikhail Naganov