写 Android 通过 webView 与 js 交互
转载自 https://www.jianshu.com/p/345f4d8a5cfa
目录

1. 交互方式总结
Android 与 JS 通过 WebView 互相调用方法,实际上是:
- Android 去调用 JS 的代码
- JS 去调用 Android 的代码
二者沟通的桥梁是 WebView
对于 Android 调用 JS 代码的方法有 2 种:
- 通过
WebView
的 loadUrl()
- 通过
WebView
的 evaluateJavascript()
对于 JS 调用 Android 代码的方法有 3 种:
- 通过
WebView
的 addJavascriptInterface()
进行对象映射 - 通过
WebViewClient
的 shouldOverrideUrlLoading ()
方法回调拦截 url - 通过
WebChromeClient
的 onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回调拦截 JS 对话框 alert()
、confirm()
、prompt()
消息
2. 具体分析
2.1 Android 通过 WebView 调用 JS
对于 Android 调用 JS 代码的方法有 2 种:
- 通过
WebView
的 loadUrl()
- 通过
WebView
的 evaluateJavascript()
方式 1:通过 WebView
的 loadUrl()
- 实例介绍:点击 Android 按钮,即调用 WebView JS(文本名为
javascript
)中 callJS() - 具体使用:
步骤 1:将需要调用的 JS 代码以.html 格式放到 src/main/assets 文件夹里
- 为了方便展示,本文是采用 Andorid 调用本地 JS 代码说明;
- 实际情况时,Android 更多的是调用远程 JS 代码,即将加载的 JS 代码路径改成 url 即可
需要加载 JS 代码:javascript.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| // 文本名:javascript <!DOCTYPE html> <html>
<head> <meta charset="utf-8"> <title>Carson_Ho</title> // JS代码 <script>
function callJS(){ alert("Android调用了JS的callJS方法"); } </script>
</head>
</html>
|
步骤 2:在 Android 里通过 WebView 设置调用 JS 代码
Android 代码:MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| public class MainActivity extends AppCompatActivity {
WebView mWebView; Button button;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
mWebView =(WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.loadUrl("file:///android_asset/javascript.html");
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mWebView.post(new Runnable() { @Override public void run() {
mWebView.loadUrl("javascript:callJS()"); } }); } });
mWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this); b.setTitle("Alert"); b.setMessage(message); b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.confirm(); } }); b.setCancelable(false); b.create().show(); return true; }
});
} }
|

特别注意:JS 代码调用一定要在 onPageFinished() 回调之后才能调用,否则不会调用。
onPageFinished()
属于 WebViewClient 类的方法,主要在页面加载结束时调用
方式 2:通过 WebView
的 evaluateJavascript()
优点:该方法比第一种方法效率更高、使用更简洁。
- 因为该方法的执行不会使页面刷新,而第一种方法(loadUrl )的执行则会。
- Android 4.4 后才可使用
1 2 3 4 5 6 7 8
| mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { } }); }
|
2.1.2 方法对比

2.1.3 使用建议
两种方法混合使用,即 Android 4.4 以下使用方法 1,Android 4.4 以上方法 2
1 2 3 4 5 6 7 8 9 10 11 12 13
| final int version = Build.VERSION.SDK_INT;
if (version < 18) { mWebView.loadUrl("javascript:callJS()"); } else { mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { } }); }
|
2.2 JS 通过 WebView 调用 Android 代码
对于 JS 调用 Android 代码的方法有 3 种:
- 通过
WebView
的 addJavascriptInterface()
进行对象映射 - 通过
WebViewClient
的 shouldOverrideUrlLoading ()
方法回调拦截 url - 通过
WebChromeClient
的 onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回调拦截 JS 对话框 alert()
、confirm()
、prompt()
消息
2.2.1 方法分析
方式 1:通过 WebView
的 addJavascriptInterface()
进行对象映射
步骤 1:定义一个与 JS 对象映射关系的 Android 类:AndroidtoJs
1 2 3 4 5 6 7 8 9 10
| public class AndroidtoJs extends Object {
@JavascriptInterface public void hello(String msg) { System.out.println("JS调用了Android的hello方法"); } }
|
步骤 2:将需要调用的 JS 代码以.html 格式放到 src/main/assets 文件夹里
需要加载 JS 代码:javascript.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Carson</title> <script> function callAndroid(){ test.hello("js调用了android中的hello方法"); } </script> </head> <body> //点击按钮则调用callAndroid函数 <button type="button" id="button1" onclick="callAndroid()"></button> </body> </html>
|
步骤 3:在 Android 里通过 WebView 设置 Android 类与 JS 代码的映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new AndroidtoJs(), "test");
mWebView.loadUrl("file:///android_asset/javascript.html");
|

特点
仅将 Android 对象和 JS 对象映射即可
方式 2:通过 WebViewClient
的方法 shouldOverrideUrlLoading ()
回调拦截 url
- Android 通过
WebViewClient
的回调方法 shouldOverrideUrlLoading ()
拦截 url - 解析该 url 的协议
- 如果检测到是预先约定好的协议,就调用相应方法
即 JS 需要调用 Android 的方法
- 具体使用:
步骤 1:在 JS 约定所需要的 Url 协议
JS 代码:javascript.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <!DOCTYPE html> <html>
<head> <meta charset="utf-8"> <title>Carson_Ho</title> <script> function callAndroid(){ document.location = "js://webview?arg1=111&arg2=222"; } </script> </head>
<!-- 点击按钮则调用callAndroid()方法 --> <body> <button type="button" id="button1" onclick="callAndroid()">点击调用Android代码</button> </body> </html>
|
当该 JS 通过 Android 的 mWebView.loadUrl("file:///android_asset/javascript.html")
加载后,就会回调 shouldOverrideUrlLoading ()
,接下来继续看步骤 2:
步骤 2:在 Android 通过 WebViewClient 复写 shouldOverrideUrlLoading ()
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.loadUrl("file:///android_asset/javascript.html");
mWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
Uri uri = Uri.parse(url); if ( uri.getScheme().equals("js")) {
if (uri.getAuthority().equals("webview")) {
System.out.println("js调用了Android的方法"); HashMap<String, String> params = new HashMap<>(); Set<String> collection = uri.getQueryParameterNames();
}
return true; } return super.shouldOverrideUrlLoading(view, url); } } ); } }
|
特点
- 优点:不存在方式 1 的漏洞;
- 缺点:JS 获取 Android 方法的返回值复杂。
如果 JS 想要得到 Android 方法的返回值,只能通过 WebView 的 loadUrl ()
去执行 JS 方法把返回值传递回去,相关的代码如下:
1 2 3 4 5 6 7
| mWebView.loadUrl("javascript:returnResult(" + result + ")");
function returnResult(result){ alert("result is" + result); }
|
方式 3:通过 WebChromeClient
的 onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回调拦截 JS 对话框 alert()
、confirm()
、prompt()
消息
在 JS 中,有三个常用的对话框方法:

方式 3 的原理:Android 通过 WebChromeClient 的 onJsAlert ()、onJsConfirm ()、onJsPrompt()方法回调分别拦截 JS 对话框
(即上述三个方法),得到他们的消息内容,然后解析即可。
下面的例子将用拦截 JS 的输入框(即 prompt()方法)说明 :
常用的拦截是:拦截 JS 的输入框(即 prompt()方法)
因为只有 prompt()可以返回任意类型的值,操作最全面方便、更加灵活;而 alert()对话框没有返回值;confirm()对话框只能返回两种状态(确定 / 取消)两个
步骤 1:加载 JS 代码,如下:
javascript.html
以.html 格式放到 src/main/assets 文件夹
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Carson_Ho</title> <script> function clickprompt(){ var result=prompt("js://demo?arg1=111&arg2=222"); alert("demo " + result); }
</script> </head>
<body> <button type="button" id="button1" onclick="clickprompt()">点击调用Android代码</button> </body> </html>
|
当使用 mWebView.loadUrl("file:///android_asset/javascript.html")
加载了上述 JS 代码后,就会触发回调 onJsPrompt()
,具体如下:
- 如果是拦截警告框(即
alert()
),则触发回调 onJsAlert()
; - 如果是拦截确认框(即
confirm()
),则触发回调 onJsConfirm()
;
步骤 2:在 Android 通过 WebChromeClient 复写 onJsPrompt()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.loadUrl("file:///android_asset/javascript.html");
mWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
Uri uri = Uri.parse(message); if ( uri.getScheme().equals("js")) {
if (uri.getAuthority().equals("webview")) {
System.out.println("js调用了Android的方法"); HashMap<String, String> params = new HashMap<>(); Set<String> collection = uri.getQueryParameterNames();
result.confirm("js调用了Android的方法成功啦"); } return true; } return super.onJsPrompt(view, url, message, defaultValue, result); }
@Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); }
@Override public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { return super.onJsConfirm(view, url, message, result); } } );
}
}
|
2.2.2 三种方式的对比 & 使用场景

3. 总结
- 本文主要对 Android 通过 WebView 与 JS 的交互方式进行了全面介绍
