首页 文章

Android在WebView中调用JavaScript函数

提问于
浏览
206

我试图在 android webview 中运行的 html 页面中调用一些 javascript 函数 . 非常简单的代码试图在下面做什么 - 从Android应用程序,调用带有测试消息的 javascript 函数,该函数在Android应用程序中调用java函数,通过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 class

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();
    }
}

我花了很多时间在谷歌上搜索我可能做错了什么 . 我发现的所有例子都使用这种方法 . 这里有人看错了吗?

Edit:html 中有几个其他外部 javascript 文件被引用和使用,它们可能是问题吗?

6 回答

  • 171

    是的,你有语法错误 . 如果要在logcat中获取Javascript错误和打印语句,则必须在WebChromeClient中实现 onConsoleMessage(ConsoleMessage cm) 方法 . 它提供了完整的堆栈跟踪,如Web控制台(Inspect元素) . 这是方法 .

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

    实现后,您将在logcat上获得Javascript错误并打印语句( console.log ) .

  • 17

    我弄清楚问题是什么:在testEcho()参数中缺少引号 . 这就是我接到工作的方式:

    myWebView.loadUrl("javascript:testEcho('Hello World!')");
    
  • 31

    修改@Ilya_Gazman的答案

    private void callJavaScript(WebView view, String methodName, Object...params){
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("javascript:try{");
            stringBuilder.append(methodName);
            stringBuilder.append("(");
            String separator = "";
            for (Object param : params) {               
                stringBuilder.append(separator);
                separator = ",";
                if(param instanceof String){
                    stringBuilder.append("'");
                }
                    stringBuilder.append(param);
                if(param instanceof String){
                    stringBuilder.append("'");
                }
    
            }
            stringBuilder.append(")}catch(error){console.error(error.message);}");
            final String call = stringBuilder.toString();
            Log.i(TAG, "callJavaScript: call="+call);
    
    
            view.loadUrl(call);
        }
    

    将正确创建JS调用,例如

    callJavaScript(mBrowser, "alert", "abc", "def");
    //javascript:try{alert('abc','def')}catch(error){console.error(error.message);}
    callJavaScript(mBrowser, "alert", 1, true, "abc");
    //javascript:try{alert(1,true,'abc')}catch(error){console.error(error.message);}
    

    请注意,对象将无法正确传递 - 但您可以在作为参数传递之前对它们进行序列化 .

    此外,我已经改变了错误的位置,我已将其转移到控制台日志,可以通过以下方式收听:

    webView.setWebChromeClient(new CustomWebChromeClient());
    

    和客户

    class CustomWebChromeClient extends WebChromeClient {
        private static final String TAG = "CustomWebChromeClient";
    
        @Override
        public boolean onConsoleMessage(ConsoleMessage cm) {
            Log.d(TAG, String.format("%s @ %d: %s", cm.message(),
                    cm.lineNumber(), cm.sourceId()));
            return true;
        }
    }
    
  • 89

    从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();");
        }
    
  • 17
    public void run(final String scriptSrc) { 
            webView.post(new Runnable() {
                @Override
                public void run() { 
                    webView.loadUrl("javascript:" + scriptSrc); 
                }
            }); 
        }
    
  • 11

    我创建了一个很好的包装来调用JavaScript方法;它还显示日志中的JavaScript错误:

    private void callJavaScript(String methodName, Object...params){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("javascript:try{");
        stringBuilder.append(methodName);
        stringBuilder.append("(");
        for (int i = 0; i < params.length; i++) {
            Object param = params[i];
            if(param instanceof String){
                stringBuilder.append("'");
                stringBuilder.append(param);
                stringBuilder.append("'");
            }
            if(i < params.length - 1){
                stringBuilder.append(",");
            }
        }
        stringBuilder.append(")}catch(error){Android.onError(error.message);}");
        webView.loadUrl(stringBuilder.toString());
    }
    

    你也需要添加它:

    private class WebViewInterface{
    
        @JavascriptInterface
        public void onError(String error){
            throw new Error(error);
        }
    }
    

    并将此界面添加到您的webview:

    webView.getSettings().setJavaScriptEnabled(true);
    webView.addJavascriptInterface(new WebViewInterface(), "AndroidErrorReporter");
    

相关问题