交互實現的前提 —— WebView容許執行JSjavascript
WebSettings settings = myWebView.getSettings(); settings.setJavaScriptEnabled(true);
調用方式:html
/** 注意參數的傳遞須要符合JS的語法,用單引號或者反斜槓轉義 */ String js = "javascript:javaCallJS(\"Java called JS.\")";
此時注意,javascript 這個詞不能存在大寫的狀態,不然在低版本的Android手機上(Android 4.4版本如下)是無反應的,由於Android 4.4版本如下的手機的WebView內核是WebKit,Android 4.4版本之後WebView的內核爲Chromium。java
實現JS調用Java也比較簡單,一般只須要如下幾步。android
提供JavaScript調用的交互接口web
public class MainActivity extends Activity { @SuppressLint("JavascriptInterface") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); .... /** 添加交互接口 */ myWebView.addJavascriptInterface(new JsInteration(), "control");
.... }
/** 聲明交互接口及具體的回調方法 */ public class JsInteration { @JavascriptInterface public void toastMessage(String message) { Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); } } }
網頁端調用交互接口安全
function toastMessage(message) { window.control.toastMessage(message) }
沒有設置WebChromeClient的緣由,須要在webView設置WebChromeClient().ide
myWebView.setWebChromeClient(new WebChromeClient() {});
網頁的js代碼沒有加載,就調用了js方法。解決方法是在網頁加載完成以後調用js方法或者限制用戶在頁面加載完成以前不容許調用JS的事件,下面的代碼是在網頁加載完成後調用JS方法的實例:函數
myWebView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); //在這裏執行你想調用的js函數 } });
若是隻在Android 4.2版本及以上的手機存在這個問題,4.2版本一下不存在這個問題,那麼就是系統處於安全限制的問題了。經過查閱Android文檔發現:oop
Caution: If you’ve set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.post
中文大意爲
警告:若是你的APP的tagSdk level是17或者是更高,你必需要在暴露給網頁可調用的方法(這個方法必須是公開的)加上@JavascriptInterface註釋。若是你不這樣作的話,在4.2以之後的平臺上,網頁沒法訪問到你的方法。
E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546): at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546): at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546): at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546): at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546): at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546): at android.os.HandlerThread.run(HandlerThread.java:61)
此問題出現的緣由是:在js調用後的Java回調線程並非主線程。如打印日誌可驗證
ThreadInfo=Thread[WebViewCoreThread,5,main]
解決上述的異常,將webview操做放在主線程中便可。
webView.post(new Runnable() { @Override public void run() { webView.loadUrl(YOUR_URL). } });
JavaScript和Java的交互是在子線程上面進行的
由於JavaScript和Java交互是在子線程上面進行的,因此若是須要UI方面的修改操做,或者執行其餘的操做,必需要考慮到線程安全的問題。這個在上面的 疑問解答4有所體現出來。
爲什麼Android4.2版本以後須要使用@JavascriptInterface來進行註解
在JELLY_BEAN_MAR1以前JS的注入存在很大的漏洞,此漏洞會致使經過頁面能夠直接操做Android Native Application。並且隨着Android版本的不斷提升,對WebView的要求也是逐漸嚴格的,這樣減小了對Android的安全存在的威脅。
連接: Android 4.2版本如下使用WebView組件addJavascriptInterface方法存在JS漏洞