简体   繁体   中英

JavaScriptInterface not added on API 18

I am using a WebView to execute some JS code in my app. This works fine so far on my KitKat (targetSdk) device, and also on a 2.2 (minSdk) emulator.
On a 4.3 Nexus 7 I encountered an error though. It seems as the JS object doesn't get injected.

Uncaught ReferenceError: android is not defined at null:1

Following a stripped down version of my code:

public void getData(Context ctx) {
    WebView webView = new WebView(ctx);
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webView.addJavascriptInterface(new AndroidInterface(), "android");
    webView.loadUrl("javascript:console.log(android.getInput());");
}

public class AndroidInterface {
    @JavascriptInterface
    public String getInput() {
        return "FOO";
    }
}  

The JS itself gets executed fine, so doing console.log('FOO'); prints FOO just as expected. But as soon as I try to access the interface I get the ReferenceError . Any ideas?
Thanks in advance!

Could be a number of things. You can try the following to narrow it down:

  • insert a sleep (1sec is more than enough) between the add and the loadUrl. It's unlikely that the API is racey but it's easy to check.
  • load a page before calling loadUrl("javascript:..."). Call something like loadUrl("about:blank") or loadData("<p>foo</p>", ...); and sleep for a bit.

Calling loadUrl("javascript:...") internally evaluates the JavaScript in the current page, it doesn't perform a 'real' navigation. It might be that the interface that you're adding is not being picked up by the context in which your loadUrl("javascript:...") call is executed (especially that the 'starting' page the WebView loads after being constructed is a bit special) and that performing a navigation makes the WebView "pick up" the newly added interface.

Found a workaround, would still be interesting to know why it doesn't work on 4.3.

So instead of using loadUrl , I surrounded the JS by a piece of HTML and used loadData .

webView.loadData("<!DOCTYPE html><html><head><script type=\"text/javascript\">function go(){console.log(android.getInput());}</script></head><body onload=\"javascript:go()\"></body></html", "text/html", "UTF-8");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM