Hi Dave, Thanks for the help.
I can call ContentViewCore#evaluateJavaScript() inside Test#myFunction -- what I'd like to know is if there is any way to pass a JavaScript function through the bridge -- (or some representative reference to that function)?
For example, consider a common idiom in JavaScript APIs where you pass a callback function as a parameter:
/**
* @param value {String} a value
* @param callback {Function} a JavaScript function
*/
function echo(value, callback) {
// echo value back
callback(value);
}
If I wanted to create this same interface on the Java side so that it is implemented in Java, but can be called from JavaScript -- I can't seem to resolve how to pass a JS function (second param).
public class EchoChamber {
@JavascriptInterface
public void echo(String value, Object callback) {
// this does not work, callback is always null
}
}
contentViewCore.addJavascriptInterface(new EchoChamber(), "echo");
I could have a named function in JavaScript and then call ContentViewCore#evaluateJavaScript
/**
* Named JS function for echo callback
* @param {String} the echoed value
*/
function echoCallback(value) {
console.log("echo callback: " + value);
}
public class EchoChamber {
private ContentViewCore core;
public EchoChamber(ContentViewCore core) { this.core = core; }
@JavascriptInterface
public void echo(String value) {
core.evaluateJavaScript("echoCallback('" + value + "');");
}
}
That seems to work, but it forces a certain API idiom that won't allow passing of functions -- callback functions always need to be pre-defined in the JavaScript. The Android Issue I linked to indicated that JavaScript functions used to get serialized into a java.lang.String representation, and then one could turn around and execute that via ContentViewCore#evaluateJavaScript(), but this does not seem to be the case with Chromium. Anytime I pass a JavaScript function as an argument it becomes null in Java-land.
Even if it did work, it still poses a problem whereby async code could be interleaved -- there doesn't seem to be any representation of an internal stack. For example:
// javascript named callback function
function myJsCallback(val) {
console.log('callback returned: ' + val);
}
// call a Java function that is asynchronous and will callback to myJsCallback
window.callAsyncJavaFunction('hello 1');
// call a Java function that is asynchronous and will callback to myJsCallback
window.callAsyncJavaFunction('hello 2');
If you execute this code, there's no relation between the initial call into Java, and the return callback. They could return as "hello 1" -> "hello 2" or vice-versa
Is there any way around this -- or am I just thinking about it all wrong?
Thanks!
Davis