Asynchronous JavaScript calls from Android WebView

I am creating a hybrid Android app with WebView that interacts with an annotated device JavaScriptInterface

From WebView:

webView.addJavascriptInterface(someService, "someService");

      

Service implementation:

@JavascriptInterface
public void someMethod() {
    //do some business logic..
}

      

The problem is that from JavaScript I run it like this:

function callSomeMethod() {
    someService.someMethod()
};

      

This call is synchronous, and he would like something to run asynchronously:

function callSomeMethod(callback) {
    someService.someMethod(function(result) {
        if (result == 'success')
            callback();
    })
};

      

It is preferable to use a promise:

function callSomeMethod() {
    return someService.someMethod()
    //someMethod returns promise
};

      

Does Android WebView have support for JavaScript code to run asynchronously?

+6


source to share


2 answers


It only depends on you. You just need to return immediately from the injected method, but be able to call the JS code when the execution is complete. Something like this (note that this is only a rough sketch):

private WebView mWebView;
private final Object mLock = new Object();
private String mJsCallbackCode;

@JavascriptInterface
public void someMethod(String jsCallbackCode) {
    synchronized (mLock) {
        mJsCallbackCode = jsCallbackCode;
    }
    // Start some business logic asynchronously, and return back here immediately.
    return;
}

public void onBusinessLogicCompleted(bool success) {
    String jsCallbackCode;
    synchronized (mLock) {
        jsCallbackCode = mJsCallbackCode;
    }
    mWebView.loadUrl("javascript:" + jsCallbackCode + "(" + success + ");void(0);");
}

      

And in JavaScript, you use it like this:

function callSomeMethod(callback) {
    window._someMethodCallback = callback;
    someService.someMethod(
        '(function(success){' +
        '    if (success) window._someMethodCallback();' +
        '    delete window._someMethodCallback;' +
        '})'
    );
};    

      



So the idea is that you are passing the JS code that you need to call as a string (because you cannot pass a real JS object). This code will be called in the global context.

Blocking in Java is necessary because methods called from JS run on a dedicated thread, not on the application's UI thread.

Note that in the M preview, the WebView has added an API for postMessage

allowing asynchronous messages to be posted between Java and JS code.

+5


source


Do you guys know any other (updated) way to do this?



0


source







All Articles