diff --git a/jsbridge/src/main/java/com/apkfuns/jsbridge/JBCallbackImpl.java b/jsbridge/src/main/java/com/apkfuns/jsbridge/JBCallbackImpl.java index 905dbbe..2b0d900 100644 --- a/jsbridge/src/main/java/com/apkfuns/jsbridge/JBCallbackImpl.java +++ b/jsbridge/src/main/java/com/apkfuns/jsbridge/JBCallbackImpl.java @@ -1,5 +1,6 @@ package com.apkfuns.jsbridge; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; @@ -47,10 +48,29 @@ public void apply(Object... args) { mHandler.post(new Runnable() { @Override public void run() { - if (method.getModule().mWebView instanceof WebView) { - ((WebView) method.getModule().mWebView).loadUrl(builder.toString()); - } else if (method.getModule().mWebView instanceof IWebView) { - ((IWebView) method.getModule().mWebView).loadUrl(builder.toString()); + // Issue #34: an asynchronous callback.apply (for example + // after a network request finishes) loses its result + // because loadUrl("javascript:...") is unreliable on + // modern WebView when called outside of an active JS + // event. evaluateJavascript was added in API 19 for + // exactly this case so prefer it when available. + Object webView = method.getModule().mWebView; + if (webView instanceof WebView) { + WebView wv = (WebView) webView; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // Strip the leading "javascript:" prefix that + // loadUrl required, evaluateJavascript wants + // raw script. + String js = builder.toString(); + if (js.startsWith("javascript:")) { + js = js.substring("javascript:".length()); + } + wv.evaluateJavascript(js, null); + } else { + wv.loadUrl(builder.toString()); + } + } else if (webView instanceof IWebView) { + ((IWebView) webView).loadUrl(builder.toString()); } } });