trev9065
trev9065

Reputation: 3501

Android WebView JavascriptInterface Property

Hey I am working with an app that has to interface with some javascript (coffeescript) code. The code JS code looks something like this:

$(".content").on "click", ".feedback", ->
      window.webkit.foo.bar.message("hello")
      false

So I need to add a javascript interface to my WebView like:

 webView.addJavascriptInterface(new Window(), "window");
 ...
 class Window {
   @JavascriptInterface
   public Webkit webkit() {
     return new Webkit();
   }
   class Webkit {
     @JavascriptInterface
     public Foo foo() {
 ...

I am running into two problems here, first it appears you can't add properties to the global window object. And second when I change my interface name to something else, I can't seem to figure out how to add properties rather than methods.

I can get it to work in a way like this:

  webkit().foo().bar().message("hello")

Has anyone done anything like this?

Thanks!

Upvotes: 1

Views: 5248

Answers (1)

Mikhail Naganov
Mikhail Naganov

Reputation: 6871

The window object in browsers (and in WebView) already has a window property, which points back to the same object. Try evaluating this in your JavaScript debugger console:

> window.window === window
< true

So trying to inject a Java object with a name "window" would produce confusing results and may break code, since you will likely break this invariant.

And it is also true that Java Bridge only exposes function objects through properties, it doesn't support exposing getters or setters. Though, you can overcome that with a bit of JavaScript magic by defining getters and setters yourself. You will need to expose getter and setter methods on your injected object and then assign them to be property getter setters with JavaScript.

So, in Java you name method differently, e.g.:

webView.addJavascriptInterface(new Window(), "myWindow");

class Window {
  @JavascriptInterface
  public Webkit getWebkit() {
    return new Webkit();
  }
  ...

And then after you have loaded the page, you can execute JavaScript code like this:

Object.defineProperty(myWindow, 'webkit', { get: myWindow.getWebkit });

Then both calling getWebkit() and accessing webkit on myWindow will mean the same thing.

Upvotes: 5

Related Questions