Skip to content

Android: Communication

sirlantis edited this page Feb 12, 2013 · 2 revisions

Here we describe some subtleties of the implementation of Transit for Android.

Blocking call into JavaScript

Problem: Android's WebView doesn't have a function like iOS's WebView stringByEvaluatingJavaScriptFromString. It only supports webView.loadUrl("javascript:...) which doesn't return a value.

Solution: Call loadUrl and wait (block) for JavaScript to post the result back to us (to a JavascriptInterface method for example). Implemented by transit.poll().

Reentrancy

Problem: When JavaScript calls into Java another call to webView.loadUrl() won't be executed until the current call into Java returns. We can't block a second time here!

Solution: If JavaScript invokes function a() and a wants to evaluate something via the JavaScript runtime, a() has to return the job for JavaScript to execute instead of the regular return-value. The JavaScript runtime has to expect and handle this.

TransitNativeFunction f = transit.registerCallable(new TransitCallable() {
  @Override
  public Object evaluate(TransitProxy thisArg, TransitProxy... arguments) {
    int integer = arguments[0].getIntegerValue();

    if (integer > 0) {
      return integer + context.eval("window.nativeFunction(@)", integer - 1);
    } else {
      return 0;
    }
  }
});

transit.eval("window.nativeFunction = @", f);
TransitProxy result = transit.eval("@ + window.nativeFuncition(@)", 2, 1);
assert(result.getIntegerValue() == 3);

![Sequence Diagram](http://www.websequencediagrams.com/cgi-bin/cdraw?s=modern-blue&m= title Communication between Java and JavaScript , App->Transit.java: eval("2 %2B window.nativeFuncition(1)") Transit.java->Transit.js: javascript:loadUrl("javascript:transit.poll()") Transit.js->Transit.java: ["POLL"] Transit.java->Transit.js: ["EVAL", "2 %2B window.nativeFunction(1)"] note right of Transit.js: eval(2 %2B window.nativeFunction(1)) Transit.js->Transit.java: ["INVOKE", { nativeId: 42, thisArg: null, args: [1] ] Transit.java->App: nativeFunction(null, TransitProxy(1)) App->Transit.java: eval("window.nativeFuncition(0)") Transit.java->Transit.js: ["EVAL", "window.nativeFunction(0)"] note right of Transit.js: eval(window.nativeFunction(0)) Transit.js->Transit.java: ["INVOKE", { nativeId: 42, thisArg: null, args: [0] ] Transit.java->App: nativeFunction(null, TransitProxy(0)) App->Transit.java: return 0 Transit.java->Transit.js: ["RETURN", 0] note right of Transit.js: window.nativeFunction(0) -> 0 Transit.js->Transit.java: ["RETURN", 0] Transit.java->App: return 0 note left of App: 1 %2B 0 -> 1 App->Transit.java: return 1 Transit.java->Transit.js: ["RETURN", 1] note right of Transit.js: window.nativeFunction(1) -> 1 note right of Transit.js: 2 %2B window.nativeFunction(1) -> 3 Transit.js->Transit.java: ["RETURN", 3] Transit.java->Transit.js: ["RETURN", null] Transit.java->App: return 3 )

Clone this wiki locally