我可以在Android(v2.2及更高版本)上从Java同步运行javascript吗?

我可以在Android(v2.2及更高版本)上从Java同步运行javascript吗?,javascript,android,Javascript,Android,我试图在我的Java android应用程序中运行一些javascript,但我需要它同步运行。WebView无法完成此操作,因为loadUrl和loadData没有返回类型。事实上,我在iOS的UIWebView上寻找的东西与此相当: - (NSString)stringByEvaluatingJavaScriptFromString:(NSString)script 我试着用Rhino,但它对我来说太慢了 谢谢 是的,但您必须使用。我相信它是同步的,但是,正如您正确指出的,无法从调用返回值

我试图在我的Java android应用程序中运行一些javascript,但我需要它同步运行。WebView无法完成此操作,因为loadUrl和loadData没有返回类型。事实上,我在iOS的UIWebView上寻找的东西与此相当:

- (NSString)stringByEvaluatingJavaScriptFromString:(NSString)script
我试着用Rhino,但它对我来说太慢了


谢谢

是的,但您必须使用。

我相信它是同步的,但是,正如您正确指出的,无法从调用返回值。丹提到了一个解决方案

首先,创建这样一个简单的类(假设返回类型是字符串):

保持此类的简单性和封装性非常重要,因为如果您从可能不可信的源加载HTML,它可能会给应用程序带来安全漏洞。也就是说,不要试图简单地传入您的活动并直接在其上使用Javascript调用方法

然后执行您想要的Javascript,给它一个回调实例来存储结果:

 WebView webView = // ... get this from somewhere
 MyCallback callback = new MyCallback();
 webView.addJavaScriptInterface(callback, "callback");
 webView.loadURL("javascript:callback.setReturnValue(someFunction())");
 System.out.println("return value is " + callback.getReturnValue());

老问题,但我看没有答案。我是这样做的(但是要小心在这里阻塞UI线程(Kotlin)

然后运行如下操作:

webview.syncJsCall(
  """
    (function() {
      console.log("hello world");
      MyApp.finished();
   })()
  """.trimIndent()
)

“我正在尝试从Java运行一些javascript…”从技术上讲,is语句是不正确的。我将措辞更改为更精确。不幸的是,这不起作用。loadURL不同步,因此当loadURL返回时,回调的结果尚未设置。这是@brindy答案的子集,但并不真正满足我的需要,因为出于我的目的,因为我需要整个调用是同步的nous java->js->java,比如stringByEvaluatingJavaScriptFromString:在ios中,除了我们的答案之外,没有其他API可以使用。
class MyWebView @JvmOverloads constructor(
  context: Context,
  attrs: AttributeSet? = null,
  defStyle: Int = 0
): WebView(context, attrs, defStyle) {

  private val lock = ReentrantLock()
  private val condition = lock.newCondition()

  private inner class MyJsInterface {
    @JavascriptInterface
    fun finished() {
      lock.withLock {
        // Do stuff (Not the UI thread)
        condition.signalAll()
      }
    }
  }

  private val jsInterface = MyJsInterface()

  fun syncJsCall(js: String) {
    lock.withLock {
      loadUrl("javascript:$js")
      condition.await()
    }
  }

  init {
    options.javascriptEnabled = true
    addJavascriptInterface(jsInterface, "MyApp")
  }
}
webview.syncJsCall(
  """
    (function() {
      console.log("hello world");
      MyApp.finished();
   })()
  """.trimIndent()
)