7

I'm trying to add a javascript interface to a WebView I've found. I followed all the standard tutorial and still getting struggled with the task. When adding the javascript interface, I don't get any exceptions or errors, but when explicitly calling the bridge from JS, I get the following error:

I/chromium: [INFO:CONSOLE(1)] "Uncaught ReferenceError: JSNativeBridge is not defined", source:  (1)

Adding the javascript interface:

new Handler(context.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        WebView webView = webViews[0];
        if (Constants.DEBUG_MODE) {
            webView.setWebChromeClient(new WebChromeClient());
            webView.getSettings().setJavaScriptEnabled(true);
        }
        ImpressionSyncJsInterface impressionSyncJsInterface = new ImpressionSyncJsInterface(context);
        webView.addJavascriptInterface(impressionSyncJsInterface, JS_BRIDGE_NAME);
        didAddInterfaceToWebView = true;
    }
});

My interface:

public class ImpressionSyncJsInterface {
    private final Context context;

    public ImpressionSyncJsInterface(Context context) {
        this.context = context;
    }

    @JavascriptInterface
    public void foo() {
        Log.e("TEST", "test");
    }
}

The Javascript execution:

final String javascriptInjectionTest = "javascript: " + JS_BRIDGE_NAME + ".foo();";

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        webView.loadUrl(javascriptInjectionTest);
    }
});
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
Daniel
  • 935
  • 2
  • 6
  • 11
  • 1
    Please put the javascript code, from where you are calling java class. – Ashish Rawat Jan 25 '16 at 03:44
  • I don't see any code loading a page prior to trying to access the injected object. You need to load some page first, see http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String) – Mikhail Naganov Jan 25 '16 at 21:44

1 Answers1

24

Figured out the problem, so I'll share my insights:

The addJavascriptInterface function applies only if called BEFORE a loadUrl / loadData function.

In my case - I expected addJavascriptInterface to inject a JS bridge, but I never reloaded the WebView content, so it was never actively injected.

After reloading the WebView HTML content, the bridge was added as expected.

Daniel
  • 935
  • 2
  • 6
  • 11
  • 1
    You should accept this as your own answer so other folks can find it more easily I just ran into the same thing myself! – davidgyoung Sep 02 '17 at 13:19
  • thanks I found it states this in the docs: https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String) Note that injected objects will not appear in JavaScript until the page is next (re)loaded. – CrandellWS Nov 25 '20 at 16:37