WebView控件中的onConsoleMessage方法不被调用

1.目的

在WebView控件中,若是页面中调用了javascript脚本console.log 方法,就调用一个Java方法.javascript

 

2.默认实现方法

在Android的WebView控件中,有一个setChromeClient(WebChromeClient)方法,java

此方法的参数是WebChromeClient对象,经过重载此对象中的onConsoleMessage方法就android

能够达到此目的.看代码:web

WebView webView = new WebView();
webView.setWebChromeClient(new DefaultWebChromeClient);

// 以上代码放在在Activity或则Fragment中的onCreate方法中

private class DefualtWebChromeClient extends WebChromeClient {
    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        String message = consoleMessage.message();
        int lineNumber = consoleMessage.lineNumber();
        String sourceID = consoleMessage.sourceId();
        String messageLevel = consoleMessage.message();

        Log.i("[WebView]", String.format("[%s] sourceID: %s lineNumber: %n message: %s",
                messageLevel, sourceID, lineNumber, message));

        return super.onConsoleMessage(consoleMessage);
    }

    @Override
    public void onConsoleMessage(String message, int lineNumber, String sourceID) {
        Log.i("[WebView]", String.format("sourceID: %s lineNumber: %n message: %s", sourceID,
                lineNumber, message));
        super.onConsoleMessage(message, lineNumber, sourceID);
    }
}

第一个方法onConsoleMessage(ConsoleMessage consoleMessage)是新版本的android才有的方法,第二个方法是旧版本的.ide

第二个方法已经不推荐使用了,可是在旧版本的android中,仍然须要此方法.因此最好两个方法都实现.性能

 

3.问题

默认的实如今某些版本的手机中很差使,onConsoleMessage方法死活不被调用测试

 

4.解决方案

使用WebView的addJavascriptInterface方法:this

// 首先,定一个类,叫什么名称均可以,可是里面的方法名必须与
// Javascript的console中的方法名对应
private class Console{
    private static final String TAG="[WebView]";
    public void log(String msg){
        Log.i(TAG,msg);
    }
	// 还能够添加其余的方法,好比: warn,assert等等
}

// 而后,为WebView添加对应的接口
webView.addJavascriptInterface(new Console, "console");

 

这个解决方案有一个很差的地方,就是输出的内容没有onConsoleMessage方法那么详细,好比行号,就无法输出.code

因此,咱们应该在onConsoleMessage好使的时候使用onConsoleMessage,很差使的时候在使用咱们自定义的方式.orm

那么,如何来判断onConsoleMessage是否好使呢? 咱们能够在程序初始化的时候,先在WebView中运行一下console.log,

若是onConsoleMessage运行了,就添加一个标记,表示默认的实现是好使的.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // 这些代码也能够放到onCreate方法中
	
    this.webView = (WebView) layout.findViewById(R.id.webview);
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    
    // Set WebChromeClient
    WebChromeClient webChromeClient = new TestConsoleMessageWebChromeClient();
	// 先执行console.log,测试是否调用了onConsoleMessage
    webView.loadUrl("javascript:console.log('testConsoleMessage')");
	
    if (((TestConsoleMessageWebChromeClient)webChromeClient).isConsoleMessageOK()){
	    // 这里额外使用了一个新的类 TestConsoleMessageWebChromeClient
		// 若是不适用TestConsoleMessageWebChromeClient,就须要在
		// DefaultWebChromeClient中添加标记字段 consoleMessageOK,
		// 这样若是方法onConsoleMessage好使,那么每次都给consoleMessageOK赋值,
		// 这个有些多余,也影响性能.
        webChromeClient = new DefualtWebChromeClient();
    }else{
	    // onConsoleMessage很差使,就使用这种方式,第二个参数值必须是"console"
        webView.addJavascriptInterface(new Console(), "console");
    }
    
    webView.loadUrl("http://www.baidu.com");

    return super.onCreateView(inflater, container, savedInstanceState);
}

// 当默认的onConsoleMessage很差使的时候使用的类
private class Console {
    private static final String TAG = "[WebView]";

    public void log(String msg) {
        Log.i(TAG, msg);
    }
	// 这里还能够添加其余方法console对象中有的方法,好比 assert
}

// 默认
private class DefualtWebChromeClient extends WebChromeClient {
    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        String message = consoleMessage.message();
        int lineNumber = consoleMessage.lineNumber();
        String sourceID = consoleMessage.sourceId();
        String messageLevel = consoleMessage.message();

        Log.i("[WebView]", String.format("[%s] sourceID: %s lineNumber: %n message: %s",
                messageLevel, sourceID, lineNumber, message));

        return super.onConsoleMessage(consoleMessage);
    }

    @Override
    public void onConsoleMessage(String message, int lineNumber, String sourceID) {
        Log.i("[WebView]", String.format("sourceID: %s lineNumber: %n message: %s", sourceID,
                lineNumber, message));
        super.onConsoleMessage(message, lineNumber, sourceID);
    }
}

// 用于测试onConsoleMessage是否调用的类
private class TestConsoleMessageWebChromeClient extends WebChromeClient {
    private boolean consoleMessageOK = false;

    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        this.consoleMessageOK = true;
        return super.onConsoleMessage(consoleMessage);
    }

    @Override
    public void onConsoleMessage(String message, int lineNumber, String sourceID) {
        this.consoleMessageOK = true;
        super.onConsoleMessage(message, lineNumber, sourceID);
    }

    public boolean isConsoleMessageOK() {
        return this.consoleMessageOK;
    }
}
相关文章
相关标签/搜索