經過WebView的loadUrl()javascript
先寫一個html,很簡單的一個代碼,alert顯示。html
android_load_js.htmljava
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Android調用 JS 代碼demo</title> // JS代碼 <script> // Android須要調用的方法 function callJS(){ alert("Android調用了JS的callJS方法"); } </script> </head> </html>
在Activity中android
mWebSettings = mWebview.getSettings(); //與JS交互開關 mWebSettings.setJavaScriptEnabled(true); //設置容許JS彈窗 mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); mWebview.loadUrl("file:///android_asset/android_load_js.html"); //在這我用了一個TextView 點擊事件中去調用JS中的方法 beginLoading.setOnClickListener(new View.OnClickListener() { [@Override](https://my.oschina.net/u/1162528) public void onClick(View view) { //執行JS方法 mWebview.loadUrl("javascript:callJS()"); } }); mWebview.setWebChromeClient(new WebChromeClient() { //獲取網站標題 [@Override](https://my.oschina.net/u/1162528) public void onReceivedTitle(WebView view, String title) { System.out.println("標題在這裏"); mtitle.setText(title); } //獲取加載進度 [@Override](https://my.oschina.net/u/1162528) public void onProgressChanged(WebView view, int newProgress) { if (newProgress < 100) { String progress = newProgress + "%"; loading.setText(progress); } else if (newProgress == 100) { String progress = newProgress + "%"; loading.setText(progress); } } //因爲設置了彈窗檢驗調用結果,因此須要支持js對話框 //webview只是載體,內容的渲染須要使用webviewChromClient類去實現 //經過設置WebChromeClient對象處理JavaScript的對話框 //設置響應js 的Alert()函數 [@Override](https://my.oschina.net/u/1162528) public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { AlertDialog.Builder b = new AlertDialog.Builder(TestActivity.this); b.setTitle("Alert"); b.setMessage(message); b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { [@Override](https://my.oschina.net/u/1162528) public void onClick(DialogInterface dialog, int which) { result.confirm(); } }); b.setCancelable(false); b.create().show(); return true; } });
經過WebView的evaluateJavascript()web
該方法比第一種方法效率更高,由於該方法的執行不會使頁面刷新,而第一種方法(loadUrl)的執行則會。該方法在Android 4.4 後纔可以使用,該方法在主線程執行ide
//將上面webView.loadUrl("javascript:callJS()")替換爲 mWebview.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { //此處爲 js 返回的結果 } });
能夠作一下兼容:函數
if (Build.VERSION.SDK_INT > 18) { mWebview.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { //此處爲 js 返回的結果 } }); } else { mWebview.loadUrl("javascript:callJS()"); }
經過WebView的addJavaScriptInterface()進行對象映射測試
html網站
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>DEMO</title> <script> function callAndroid(){ // 因爲對象映射,因此調用test對象等於調用Android映射的對象 test.showLog("js調用了android中的hello方法"); } </script> </head> <body> //點擊按鈕則調用callAndroid函數 <button type="button" id="button1" onclick="callAndroid()" text="Android"></button> </body> </html>
映射的代碼ui
package org.professor.procartoon.temp; import android.webkit.JavascriptInterface; import org.professor.procartoon.utils.LogUtils; /** * Created by Caipeng on 2018.02.06. */ public class JSObject { /** * 定義JS須要調用的方法被JS調用的方法必須加入@JavascriptInterface註解 */ @JavascriptInterface public void showLog(String text) { LogUtils.i(text); } }
在Activity中的測試代碼
mWebSettings.setJavaScriptEnabled(true); mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); //經過addJavascriptInterface()將Java對象映射到JS對象 //參數1:Javascript對象名 //參數2:Java對象名 mWebview.addJavascriptInterface(new JSObject(),"test"); mWebview.loadUrl("file:///android_asset/android_load_js.html");
經過WebViewClient的ShouldOverrideUrlLoading() 方法進行回調攔截
Android經過 WebViewClient 的回調方法shouldOverrideUrlLoading ()攔截 url,解析該 url 的協議,若是檢測到是預先約定好的協議,就調用Android相應的方法。
html Document
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>DEMO</title> <script> function callAndroid(){ //協議org://professor?arg1=com&arg2=test document.location = "org://professor?arg1=111&arg2=222"; } </script> </head> <body> //點擊按鈕則調用callAndroid函數 <button type="button" id="button1" onclick="callAndroid()">CallAndroid</button> </body> </html>
JAVA代碼
@Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { //通常根據scheme(協議格式) & authority(協議名)判斷(前兩個參數) Uri uri = Uri.parse(request.getUrl().toString()); if (uri.getScheme().equals("org")) { if (uri.getAuthority().equals("professor")) { LogUtils.i(uri.getQueryParameter("arg1")); } return true; } return super.shouldOverrideUrlLoading(view, request); }
備註
JS獲取Android方法的返回值複雜。 若是JS想要獲得Android方法的返回值,只能經過 WebView 的loadUrl ()去執行 JS 方法把返回值傳遞回去,相關的代碼以下:
//Android原生調用js mWebView.loadUrl("javascript:returnResult(" + result + ")"); //須要在html中接收 function returnResult(result){ alert("result is" + result); }
經過WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調攔截JS對話框alert()、confirm()、prompt() 消息
首先介紹下JS中的alert()、confirm()、prompt()三個方法
原理:Android經過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調分別攔截JS對話框 (即上面的三個方法),獲得他們的消息內容,而後解析便可。
經常使用的攔截是:攔截 JS的輸入框(即prompt()方法)。由於只有prompt()能夠返回任意類型的值,操做最全面方便、更加靈活;而alert()對話框沒有返回值;confirm()對話框只能返回兩種狀態(肯定 / 取消)兩個值。
html代碼
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>DEMO</title> <script> function callAndroid(){ //document.location = "org://professor?arg1=111&arg2=222"; var result=prompt("org://professor?arg1=111&arg2=222"); alert("demo " + result); } </script> </head> <body> //點擊按鈕則調用callAndroid函數 <button type="button" id="button1" onclick="callAndroid()">CallAndroid</button> </body> </html>
JAVA代碼
@Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { //通常根據scheme(協議格式) & authority(協議名)判斷(前兩個參數) Uri uri = Uri.parse(url); if (uri.getScheme().equals("org")) { if (uri.getAuthority().equals("professor")) { LogUtils.i(uri.getQueryParameter("arg1")); //參數result:表明消息框的返回值(輸入值) result.confirm("js調用了Android的方法成功啦"); } return true; } return super.onJsPrompt(view, url, message, defaultValue, result); }
結語
由上能夠比較,根據第三種方式,即:經過WebChromeClient的方法攔截比較靈活一些