Search code examples
javascriptandroidv8rhinoj2v8

Android Javascript Engine; Need to replace WebView with Rhino, J2V8, etc


We are trying to replace our webview and html with a layout file and a javascript engine of some sort. There is a TON of javascript that must be called and we have a rather large JavaScriptInterface that will need to be accessable by the JS engine. I have been trying out Rhino and J2V8 but cannot figure out a way to give javascript access to a full class of methods or an annotation that works similarly to how you annotate methods for WebView.

If anyone has any insight, it would be much appreciated!

Thanks, Jon


Solution

  • AFAIK there is no "out-of-the-box" solution for this for JSV8.

    But have a look at following example:

    public class V8ConsoleBridge implements JavaVoidCallback {
        @Override
        public void invoke(V8Object receiver, V8Array parameters) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < parameters.length(); ++i) {
                if (i > 0) {
                    sb.append(", ");
                }
                Object object = parameters.get(i);
                if (object instanceof V8Object) {
                    V8Object v8Object = (V8Object) object;
                    sb.append(v8Object.toString());
                    v8Object.release();
                } else {
                    sb.append(object);
                }
            }
            Log.i("goebl-v8", sb.toString());
        }
    
        public static void register(V8 v8) {
            V8ConsoleBridge console = new V8ConsoleBridge();
            V8Object v8Console = new V8Object(v8);
            v8.add("console", v8Console);
            v8Console.registerJavaMethod(console, "debug");
            v8Console.registerJavaMethod(console, "log");
            v8Console.registerJavaMethod(console, "info");
            v8Console.registerJavaMethod(console, "warn");
            v8Console.registerJavaMethod(console, "error");
            v8Console.release();
        }
    }
    

    This is a hardcoded bridge for a JS console object to access Android logging system.

    You could write generic code to

    • scan a class you want to expose in JavaScript, much like JavaScript-Interface for WebView, even with annotations like @JavascriptInterface to only include certain members
    • write generic code for the invoke which actually invokes members of the receiver class by using Java reflection.

    Of course it would be great if J2V8 had this useful code, because it might be used by many projects. When you have a solid solution, create a pull request so I can use it too :-)

    If you don't mind wading deep in source code, you might find it useful to check out NativeScript. They provide a generic way to access all Java classes known at compile time in JavaScript, which is internally done via reflection. Well, I've heard that they do it this way, I actually didn't read the source code of NativeScript. In NativeScript, you don't have to create bridges, it's done magically by the build- and runtime-system. Maybe the source inspires you to port the ideas to J2V8.