1.目的
在WebView控件中,如果頁面中調(diào)用了javascript腳本console.log 方法,就調(diào)用一個Java方法.
2.默認(rèn)實(shí)現(xiàn)方法
在Android的WebView控件中,有一個setChromeClient(WebChromeClient)方法,
此方法的參數(shù)是WebChromeClient對象,通過重載此對象中的onConsoleMessage方法就
可以達(dá)到此目的.看代碼:
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才有的方法,第二個方法是舊版本的.
第二個方法已經(jīng)不推薦使用了,但是在舊版本的android中,仍然需要此方法.所以最好兩個方法都實(shí)現(xiàn).
3.問題
默認(rèn)的實(shí)現(xiàn)在某些版本的手機(jī)中不好使,onConsoleMessage方法死活不被調(diào)用
4.解決方案
使用WebView的addJavascriptInterface方法:
// 首先,定一個類,叫什么名稱都可以,但是里面的方法名必須與 // Javascript的console中的方法名對應(yīng) private class Console{ private static final String TAG="[WebView]"; public void log(String msg){ Log.i(TAG,msg); } // 還可以添加其他的方法,比如: warn,assert等等 } // 然后,為WebView添加對應(yīng)的接口 webView.addJavascriptInterface(new Console, "console");
這個解決方案有一個不好的地方,就是輸出的內(nèi)容沒有onConsoleMessage方法那么詳細(xì),比如行號,就沒法輸出.
所以,我們應(yīng)該在onConsoleMessage好使的時候使用onConsoleMessage,不好使的時候在使用我們自定義的方式.
那么,如何來判斷onConsoleMessage是否好使呢? 我們可以在程序初始化的時候,先在WebView中運(yùn)行一下console.log,
如果onConsoleMessage運(yùn)行了,就添加一個標(biāo)記,表示默認(rèn)的實(shí)現(xiàn)是好使的.
@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(); // 先執(zhí)行console.log,測試是否調(diào)用了onConsoleMessage webView.loadUrl("javascript:console.log('testConsoleMessage')"); if (((TestConsoleMessageWebChromeClient)webChromeClient).isConsoleMessageOK()){ // 這里額外使用了一個新的類 TestConsoleMessageWebChromeClient // 如果不適用TestConsoleMessageWebChromeClient,就需要在 // DefaultWebChromeClient中添加標(biāo)記字段 consoleMessageOK, // 這樣如果方法onConsoleMessage好使,那么每次都給consoleMessageOK賦值, // 這個有些多余,也影響性能. webChromeClient = new DefualtWebChromeClient(); }else{ // onConsoleMessage不好使,就使用這種方式,第二個參數(shù)值必須是"console" webView.addJavascriptInterface(new Console(), "console"); } webView.loadUrl("http://www.baidu.com"); return super.onCreateView(inflater, container, savedInstanceState); } // 當(dāng)默認(rèn)的onConsoleMessage不好使的時候使用的類 private class Console { private static final String TAG = "[WebView]"; public void log(String msg) { Log.i(TAG, msg); } // 這里還可以添加其他方法console對象中有的方法,比如 assert } // 默認(rèn) 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是否調(diào)用的類 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; } }