文章分两块,js调用andorid代码,android代码调用js

参考的博文http://blog.csdn.net/carson_ho/article/details/64904691

这也许是功能最强大的Android与Javascript交互开源库

前提 打开js交互 webview.getSetting().setJavaScriptEnable(true);

一:android调用js代码

说明:主要有两种方式,

方式1: 4.4系统以前
//需要另外开启线程mWebView.post(new Runnable() {//                    @Override                    public void run() {                  // 调用javascript的callJS()方法   ,,用于4.4以下,缺点:该方法会使页面再次刷新,且无法获取返回值                        mWebView.loadUrl("javascript:callJS()");                    }                });
方式2: 4.4系统以上
//4.4以上可用,优点:不会使页面再次刷新,且可以获取返回值                    mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback() {                        @Override                        public void onReceiveValue(String value) {                            //此处为 js 返回的结果                        }                    });

综合使用:

if(Build.VERSION.SDK_INT<19){                    mWebView.post(new Runnable() {//                    @Override                    public void run() {                  // 调用javascript的callJS()方法   ,,用于4.4以下,缺点:该方法会使页面再次刷新,且无法获取返回值                        mWebView.loadUrl("javascript:callJS()");                    }                });                }else{                  //4.4以上可用,优点:不会使页面再次刷新,且可以获取返回值                    mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback() {                        @Override                        public void onReceiveValue(String value) {                            //此处为 js 返回的结果                        }                    });                }

二,js调用android代码

一: 通过addJavascriptInterface 接口

通过webView.addJavascriptInterface(new JsObject(), "injectedObject");接口

参考博文

4.2版本以前,我们一般是这么做的
//随便创建一个类class JsObject {      //新建一个js要调用的方法      public String toString() { return "injectedObject"; }   }   //将该类的对象注入到js代码中 webView.addJavascriptInterface(new JsObject(), "injectedObject");
  • [ 该方式有个致命漏洞,就是当js端得到我们注入的类对象的时候,可以通过类对象得到Java.lang.Runtime类,这样js就可以通过adb命令修改前端程序,比如文件修改等]
  • 关于漏洞分析请看这篇文章
  • js一般的攻击代码
function execute(cmdArgs)  {      // 步骤1:遍历 window 对象    // 目的是为了找到包含 getClass ()的对象    // 因为Android映射的JS对象也在window中,所以肯定会遍历到    for (var obj in window) {          if ("getClass" in window[obj]) {        // 步骤2:利用反射调用forName()得到Runtime类对象            alert(obj);                      return  window[obj].getClass().forName("java.lang.Runtime")        // 步骤3:以后,就可以调用静态方法来执行一些命令,比如访问文件的命令getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);  // 从执行命令后返回的输入流中得到字符串,有很严重暴露隐私的危险。// 如执行完访问文件的命令之后,就可以得到文件名的信息了。        }      }  }  
4.2版本后:google修复了该漏动,虽有注入的类对象都必须添加@JavascriptInterface 注解,以代码只有该类的注解方法可以被js调用
webview.getSetting().setJavaScriptEnable(true);  class JsObject {  //js要调用的方法必须添加注解    @JavascriptInterface      public String toString() { return "injectedObject"; }   }   webView.addJavascriptInterface(new JsObject(), "injectedObject");  
二.使用:

注意: 以下下代码必须要在loadurl前调用,也就是说需要先注入,再加载网页,否者无效

 注入该对象,第二个参数则是js中要用的该对象的变量名 mWebView.addJavascriptInterface(new AndoridJs(), "test");//AndroidtoJS类对象映射到js的test对象

html代码

        Carson    //点击按钮则调用callAndroid函数

二:通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url(无方式一存在的漏洞)

示例html
               Carson_Ho                
调用 :注意要和html上的沟通协议一样
// 复写WebViewClient类的shouldOverrideUrlLoading方法mWebView.setWebViewClient(new WebViewClient() {                                      @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")) {                                                 //  步骤3:                                                  // 执行JS所需要调用的逻辑                                                  System.out.println("js调用了Android的方法");                                                  // 可以在协议上带有参数并传递到Android上                                                  HashMap params = new HashMap<>();                                                  Set collection = uri.getQueryParameterNames();                                              }                                              return true;                                          }                                          return super.shouldOverrideUrlLoading(view, url);                                      }                                  }        );

++该方式缺点:JS获取Android方法的返回值复杂。若要返回给js值,就必须再通过andorid调用js的方法传递参数过去++

方式二 通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息

  1. 说明:
  2. 常用的拦截是:拦截 JS的输入框(即prompt()方法)
    因为只有prompt()可以返回任意类型的值,操作最全面方便、更加灵活;而alert()对话框没有返回值;confirm()对话框只能返回两种状态(确定 / 取消)两个值
html示例:
               Carson_Ho                
使用:
// 设置允许JS弹窗        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 先加载JS代码        // 格式规定为:file:///android_asset/文件名.html        mWebView.loadUrl("file:///android_asset/javascript.html");        mWebView.setWebChromeClient(new WebChromeClient() {                                        // 拦截输入框(原理同方式2)                                        // 参数message:代表promt()的内容(不是url)                                        // 参数result:代表输入框的返回值                                        @Override                                        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {                                            // 根据协议的参数,判断是否是所需要的url(原理同方式2)                                            // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)                                            //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)                                            Uri uri = Uri.parse(message);                                            // 如果url的协议 = 预先约定的 js 协议                                            // 就解析往下解析参数                                            if ( uri.getScheme().equals("js")) {                                                // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议                                                // 所以拦截url,下面JS开始调用Android需要的方法                                                if (uri.getAuthority().equals("webview")) {                                                    //                                                    // 执行JS所需要调用的逻辑                                                    System.out.println("js调用了Android的方法");                                                    // 可以在协议上带有参数并传递到Android上                                                    HashMap params = new HashMap<>();                                                    Set collection = uri.getQueryParameterNames();                                                    //参数result:代表消息框的返回值(输入值)                                           //注意记得把弹窗消费掉,否者下个页面可能会被卡住         result.confirm("js调用了Android的方法成功啦");                                                }                                                return true;                                            }                                            return super.onJsPrompt(view, url, message, defaultValue, result);                                        }// 通过alert()和confirm()拦截的原理相同,此处不作过多讲述                                        // 拦截JS的警告框                                        @Override                                        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {                                            return super.onJsAlert(view, url, message, result);                                        }                                        // 拦截JS的确认框                                        @Override                                        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {                                            return super.onJsConfirm(view, url, message, result);                                        }                                    }        );            }

更多相关文章

  1. Android(安卓)顶部灰条标题栏不显示的方法
  2. android事件处理总结--dispatchTouchEvent【转】
  3. Android(安卓)LayoutInflater.inflate()方法参数详解
  4. android的触摸机制
  5. Android短信彩信收发流程(应用层)
  6. Android中Service的生命周期
  7. 简单音乐播放实例的实现,Android(安卓)Service AIDL 远程调用服
  8. [Android(安卓)机制] 使用Ksoap2访问webservie,设置timeout时间
  9. android 蓝牙模块相关的一些知识了解

随机推荐

  1. android:layout_gravity和android:gravit
  2. android:layout_gravity和android:gravit
  3. android:layout_gravity和android:gravit
  4. android中线程进程模型
  5. android:layout_gravity和android:gravit
  6. android:layout_gravity和android:gravit
  7. android之常用知识点(一)
  8. Android真响应式架构——Model层设计
  9. android:layout_gravity和android:gravit
  10. 学习培训Android软件工程师之不归路