原生+H5开发之:js交互【location方式】

1. 交互方式总结

1Android与JS通过WebView互相调用方法,实际上是:

  • Android去调用JS的代码
  • JS去调用Android的代码
    二者沟通的桥梁是WebView

    对于Android调用JS代码的方法有2种: 
    1. 通过WebViewloadUrl() 
    2. 通过WebViewevaluateJavascript()

    对于JS调用Android代码的方法有3种: 
    1. 通过WebViewaddJavascriptInterface()进行对象映射 
    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;
            }

    这种方式的优点就是不存在漏洞,并且稳定

posted @ 2018-04-11 09:22  环球移动团队  阅读(1350)  评论(0编辑  收藏  举报