我试图调用一些javascript函数坐在运行在一个android webview内的html页面。下面的代码尝试做的很简单——从android应用程序,调用一个带有测试消息的javascript函数,该函数反过来调用一个java函数返回android应用程序,通过toast显示测试消息。

javascript函数如下所示:

function testEcho(message){
     window.JSInterface.doEchoTest(message);
}

从WebView,我已经尝试调用javascript如下方式,运气不好:

myWebView.loadUrl("javascript:testEcho(Hello World!)");
mWebView.loadUrl("javascript:(function () { " + "testEcho(Hello World!);" + "})()");

我在WebView上启用了javascript

myWebView.getSettings().setJavaScriptEnabled(true);
// register class containing methods to be exposed to JavaScript
myWebView.addJavascriptInterface(myJSInterface, "JSInterface"); 

这里是Java类

public class JSInterface{

private WebView mAppView;
public JSInterface  (WebView appView) {
        this.mAppView = appView;
    }

    public void doEchoTest(String echo){
        Toast toast = Toast.makeText(mAppView.getContext(), echo, Toast.LENGTH_SHORT);
        toast.show();
    }
}

我花了很多时间在谷歌上搜索,看看我哪里做错了。我找到的所有示例都使用了这种方法。有人发现问题了吗?

编辑:有其他几个外部javascript文件被引用和使用的html,他们会是问题吗?


当前回答

下面是一个从WebView上的资产加载js脚本的例子。 把脚本放到文件中有助于阅读 我在onPageFinished中加载脚本,因为我需要访问脚本中的一些DOM元素(能够访问它应该被加载,否则它将为空)。根据脚本的用途,我们可以更早地加载它

资产/ myjsfile.js

document.getElementById("abc").innerText = "def"
document.getElementById("abc").onclick = function() {
    document.getElementById("abc").innerText = "abc"
}

WebViewActivity

webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient() {
   
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)

        val script = readTextFromAsset("myjsfile.js")
        view.loadUrl("javascript: $script")
    }
}

fun readTextFromAsset(context: Context, fileName: String): String {
    return context.assets.open(fileName).bufferedReader().use { it.readText() 
}

其他回答

从kitkat开始使用evaluateJavascript方法代替loadUrl来调用javascript函数,如下所示

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        webView.evaluateJavascript("enable();", null);
    } else {
        webView.loadUrl("javascript:enable();");
    }

下面是一个从WebView上的资产加载js脚本的例子。 把脚本放到文件中有助于阅读 我在onPageFinished中加载脚本,因为我需要访问脚本中的一些DOM元素(能够访问它应该被加载,否则它将为空)。根据脚本的用途,我们可以更早地加载它

资产/ myjsfile.js

document.getElementById("abc").innerText = "def"
document.getElementById("abc").onclick = function() {
    document.getElementById("abc").innerText = "abc"
}

WebViewActivity

webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient() {
   
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)

        val script = readTextFromAsset("myjsfile.js")
        view.loadUrl("javascript: $script")
    }
}

fun readTextFromAsset(context: Context, fileName: String): String {
    return context.assets.open(fileName).bufferedReader().use { it.readText() 
}

我发现了问题所在:testEcho()参数中缺少引号。我是这样接到工作电话的:

myWebView.loadUrl("javascript:testEcho('Hello World!')");
public void run(final String scriptSrc) { 
        webView.post(new Runnable() {
            @Override
            public void run() { 
                webView.loadUrl("javascript:" + scriptSrc); 
            }
        }); 
    }

是的,你有语法错误。如果你想在你的logcat中得到你的Javascript错误和打印语句,你必须在WebChromeClient中实现onConsoleMessage(ConsoleMessage cm)方法。它提供了完整的堆栈跟踪,如Web console(Inspect元素)。这是方法。

public boolean onConsoleMessage(ConsoleMessage cm) 
    {
        Log.d("Message", cm.message() + " -- From line "
                             + cm.lineNumber() + " of "
                             + cm.sourceId() );
        return true;
    }

实现后,你会得到你的Javascript错误和打印语句(console.log)在你的logcat。