原生+H5开发之:js交互【location方式】
1. 交互方式总结
1Android与JS通过WebView互相调用方法,实际上是:
- Android去调用JS的代码
- JS去调用Android的代码
二者沟通的桥梁是WebView
对于Android调用JS代码的方法有2种:
1. 通过WebView
的loadUrl()
2. 通过WebView
的evaluateJavascript()
对于JS调用Android代码的方法有3种:
1. 通过WebView
的addJavascriptInterface()
进行对象映射
2. 通过WebViewClient
的shouldOverrideUrlLoading ()
方法回调拦截 url
3. 通过WebChromeClient
的onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回调拦截JS对话框alert()
、confirm()
、prompt()
消息 -
2.1 Android通过WebView调用 JS 代码
-
mWebView =(WebView) findViewById(R.id.webview); mWebView.loadUrl("file:///android_asset/javascript.html");
LocationActivity.this.webView.post(() -> LocationActivity.this.webView.evaluateJavascript( "javascript:locationDidChange('" + LocationActivity.this.locationString + "')", value -> { // 此处为 js 返回的结果 }));
2.2 JS通过WebView调用 Android 代码
-
方式2:通过
WebViewClient
的方法shouldOverrideUrlLoading ()
回调拦截 url -
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Carson_Ho</title> <script> function callAndroid(){ /*约定的url协议为:js://webview?arg1=111&arg2=222*/ document.location = "js://webview?arg1=111&arg2=222"; } </script> </head> <!-- 点击按钮则调用callAndroid()方法 --> <body> <button type="button" id="button1" onclick="callAndroid()">点击调用Android代码</button> </body> </html>
private class MyWebViewClient extends WebViewClient { @TargetApi(21) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return this.shouldOverrideUrlLoading(view, request.getUrl().toString()); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // 步骤2:根据协议的参数,判断是否是所需要的url // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数) // 假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的) Uri uri = Uri.parse(url); // 如果url的协议 = 预先约定的 js 协议 // 就解析往下解析参数 if (uri.getScheme().equals("js")) { // 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议 // 所以拦截url,下面JS开始调用Android需要的方法 if (uri.getAuthority().equals("webview")) { Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + uri.getQueryParameter("tel"))); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); LocationActivity.this.startActivity(intent); } else if (uri.getAuthority().equals("location")) { LocationActivity.this.webView.post(() -> LocationActivity.this.webView.evaluateJavascript( "javascript:locationDidChange('" + LocationActivity.this.locationString + "')", value -> { // 此处为 js 返回的结果 })); } else if (uri.getAuthority().equals("toast")) { Toast.makeText(LocationActivity.this, uri.getQueryParameter("info"), Toast.LENGTH_SHORT).show(); } else if (uri.getAuthority().equals("takePhoto")) { photoIdent = uri.getQueryParameter("ident"); openPopupWindow(); } else if (uri.getAuthority().equals("takeVideo")) { /***************************** 录制视频 ***********************************/ EventBus.getDefault().post(new VideoIdentEvent(uri.getQueryParameter("ident"))); Intent intent = new Intent(LocationActivity.this, VideoActivity.class); intent.putExtra(VideoActivity.VIDEO_IDENT, uri.getQueryParameter("ident")); startActivity(intent); } else if (uri.getAuthority().equals("playVideo")) { /***************************** 播放视频 ***********************************/ startActivity(new Intent(LocationActivity.this, VideoPlayerActivity.class).putExtra("path", uri.getQueryParameter("path"))); } else if (uri.getAuthority().equals("takeAudio")) { /******************************** 录制音频 ********************************/ dialogShow(uri.getQueryParameter("ident")); } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "userLogin")) { /******************************** 登录 ********************************/ String username = uri.getQueryParameter("username"); if (TextUtils.isEmpty(username)) { return true; } JPushInterface.setAlias(LocationActivity.this, username.hashCode(), username); String account = uri.getQueryParameter("yx_username"); String password = uri.getQueryParameter("yx_password"); chatFragment.startImLogin(username, account, password); } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "userLogout")) { /******************************** 退出 ********************************/ chatFragment.logout(); finish(); } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "playAudio")) { /***************************** 播放视频 ***********************************/ MediaActivity.start(LocationActivity.this, uri.getQueryParameter("path")); } return true; } return false; }
这种方式的优点就是不存在漏洞,并且稳定