ericwlange / AndroidJSCore

AndroidJSCore allows Android developers to use JavaScript natively in their apps.
468 stars 78 forks source link

is there a way to call JS function, and also JS function can call native function in remote html ? #13

Closed caprice closed 8 years ago

caprice commented 8 years ago

As title mentioned, I would like to use this library to implement the functionality similarly as below ,

  1. Java call js function with return value in html

    webView.evaluateJavascript(call, new ValueCallback() { @Override public void onReceiveValue(String value) {

       }
    });
  2. Js function in html call java API:

    function callPhone(number){ var result = window.control.callPhone(number) console.log(result); alert(result); }

Can it both work for these two features? If yes, how can i use it ? Thanks.

ericwlange commented 8 years ago

Yes and No.

The first thing to note is that JavaScriptCore is just that. It is the JavaScript engine of WebKit. It is not a full-blown browser or WebView. So your JS function in html won't work because you are attempting to use three objects that do not exist: window, console, and alert. Those objects are part of the browser, and are not native to JavaScript.

However, leaving aside that piece, the rest of it can be done. You can make calls from Java to JavaScript and have JavaScript return a value. For example:

JSContext context = new JSContext();
JSObject myJSFunction = new JSObject(
    context,
    "function_name",
    new String[]{"x","y"}, // array of parameter names
    "return x+y;" // body of JS function
);

JSValue value = myJSFunction.callAsFunction(null, new JSValue[]{ 4, 5 });
// value will be 9

You can also write functions in Java and make them available to JavaScript:

public interface IExposedToJS {
    public Integer factorial(Integer x);
}
public class FactorialObject extends JSObject
implements IExposedToJS {
    public FactorialObject(JSContext ctx) {
        super(ctx,IExposedToJS.class);
    }
    @Override
    public Integer factorial(Integer x) {
        int factorial = 1;
        for (; x > 1; x--) {
               factorial *= x;
        }
        return factorial;
    }
}

context.property("myJavaFunctions", new FactorialObject(context));
JSValue value = context.evaluateScript("myJavaFunctions.factorial(10);")
// value will be (10!)
caprice commented 8 years ago

Very pity for that. Still very thanks for your detailed explanations. I am developing an android app, in which some UI pages we intend to use html5 in place of native. One problem we faced and have to stride across, there are interactions with native in h5 as I mentioned above two examples. In fact, they are both supported in build-in webview in android, but it's too inflexible to use and has more limitations. At last, IOS team tell me that they can do it use JavaScriptCore very conveniently, so I searched your wondering library here. I saw other guys post similar questions in IOS. FYI, http://stackoverflow.com/questions/19664206/access-the-javascriptcore-engine-of-a-uiwebview. Maybe, you can implement it future 😊

ericwlange commented 8 years ago

As it happens, the next version that I am working on is, in fact, a full implementation of WebKit with the kind of functionality you are requesting. But I am quite a ways away from having it working yet.

jebai0521 commented 8 years ago

i have the same problem, i want use the library to work with webview.

jebai0521 commented 8 years ago

@ericwlange how does jscontext work with webview

ericwlange commented 8 years ago

It doesn't, unfortunately.

AndroidJSCore is an isolated JavaScript environment that is not designed to interact with WebViews. Technically, they aren't even the same implementation of JavaScript. AndroidJSCore uses WebKit's JavaScriptCore engine, while WebViews (on Android, anyway) use Chromium's V8. So there is no practical way to get them to interact at the library level.

However, this is an eventual goal of mine. There are two ways to do this. The preferred method would be if I can figure out how to tap into the V8 engine that is already preloaded on Android devices. The advantage is you get WebViews for free and the footprint of the SDK would be tiny. The downside comes from versioning. You are completely dependent on which version of libwebcore happens to be on the device. To do this, I will need to rewrite the entire C++ backend to interact with V8 instead of JavaScriptCore and hope that there is enough consistency in APIs so that I can leave the Java side largely unchanged.

The other method is to include the WebKit implementation of WebCore. This, at some level, is easier to do as I can see how to achieve it. I've already laid the groundwork. But the challenges are that the size of the library will balloon and if you want the resulting WebView to actually render (as opposed to work in the background), there is a lot of work to do there.

It would help if you could describe your use case. That would help me understand which path to pursue.

On Wed, Jun 15, 2016 at 8:35 AM, Chen Ming notifications@github.com wrote:

@ericwlange https://github.com/ericwlange how does jscontext work with webview

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ericwlange/AndroidJSCore/issues/13#issuecomment-226076656, or mute the thread https://github.com/notifications/unsubscribe/ABIuZMzP60mW2TK7GDZFFE3tD28HhQ96ks5qL2wWgaJpZM4HpEQz .

ericwlange commented 8 years ago

Closing this issue as it is outside the scope of AndroidJSCore. I am toying with a new project that may achieve this, but it would be separate from this.