-
Notifications
You must be signed in to change notification settings - Fork 13
Android: Communication
Here we describe some subtleties of the implementation of Transit for Android.
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().
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);") 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 )