当前位置: 移动技术网 > IT编程>移动开发>Android > Android和js、H5进行交互数据(面试必问)

Android和js、H5进行交互数据(面试必问)

2018年12月27日  | 移动技术网IT编程  | 我要评论

教师借款25万,包卜nba直播,中国联通积分商城

android和h5、js进行交互调用

android开发过程中,我们或多或少都会用到webview,使用webview来展示一些经常变动的界面更加方便简单,
也已于维护。另一方面hybrid app开发现在用的也越来越多了。其中native和h5之间的交互更是必不可少的。
具体android中是如何和h5交互的?或者说android中是如何和js交互的。

1 webview加载页面

我们都知道在android中是通过webview来加载html页面的。根据html文件所在的位置不同写法也不同。

例如:加载assets文件夹下的test,html页面

mwebview.loadurl("file:///android_asset/test.html")

例如:加载网页

mwebview.loadurl("https://www.baidu.com")

如果只是这样调用webview.loadurl 加载的话,那么当你点击页面中的链接的时候,页面将会在你手机默认的上打开。那如果想要在页面在app内中打开的话,那么就得设置serwebviewclient:

mwebview.setwebviewclient(new webviewclient() {
        @override
        public boolean shouldoverrideurlloading(webview view, string url) {
                //我们可以在这里拦截特定的rl请求,然后进行自己要的操作
                if (url.equals("file:///android_asset/test2.html")) {
                    log.e(tag, "shouldoverrideurlloading: " + url);
                    startactivity(new intent(mainactivity.this,main2activity.class));
                    return true;
                } else {
                //这里我们自己重新加载新的url页面,防止点击链接跳转到系统浏览器
                    mwebview.loadurl(url);
                    return true;
                }
            }
        }
    });

重写activity的onbackpressed方法,使得返回按钮不会关闭当前页面,而是返回webview上一个历史页面。

@override
    public void onbackpressed() {
        if (webview.cangoback()) {
            //返回上一个页
            webview.goback();
            return ;
        }
        super.onbackpressed();
    }

二、给webview添加加载新页面的进度条。

开启和关闭进度条

webview.setwebviewclient(new webviewclient() {

      //重写页面打开和结束的监听。打开时弹出菊花,关闭时隐藏菊花
      /**
       * 界面打开的回调
       */
      @override
      public void onpagestarted(webview view, string url, bitmap favicon) {
          if (progressdialog != null && progressdialog.isshowing()) {
              progressdialog.dismiss();
          }
          //弹出菊花
          progressdialog = new progressdialog(jsactivity.this);
          progressdialog.settitle("提示");
          progressdialog.setmessage("软软正在拼命加载……");
          progressdialog.show();

      }

      /**
       * 界面打开完毕的回调
       */
      @override
      public void onpagefinished(webview view, string url) {
          //隐藏菊花:不为空,正在显示。才隐藏关闭
          if (progressdialog != null && progressdialog.isshowing()) {
              progressdialog.dismiss();
          }
      }

  });

让进度条显示页面加载进度:

//设置进度条
        //webchromeclient与webviewclient的区别
        //webviewclient处理偏界面的操作:打开新界面,界面打开,界面打开结束
        //webchromeclient处理偏js的操作
        webview.setwebchromeclient(new webchromeclient() {
            /**
             * 进度改变的回调
             * webview:就是本身
             * newprogress:即将要显示的进度
             */
            @override
            public void onprogresschanged(webview view, int newprogress) {
                if (progressdialog != null && progressdialog.isshowing())
                    progressdialog.setmessage("软软正在拼命加载……" + newprogress + "%");
            }

三、android本地通过java调用html页面中的javascript方法

想要调用js方法那么就必须让webview支持js的代码。

//首先设置webview支持js代码
webview.getsettings().setjavascriptenabled(true);

若调用的js方法没有返回值,则可以直接调用mwebview.loadurl(“javascript:do());其中do是js中的方法;
若有返回值时我们可以调用mwebview,evalutejavascript方法;

@targetapi(build.version_codes.kitkat)
    public void onsum(view view){
        webview.evaluatejavascript("sum(1,2)", new valuecallback() {
            @override
            public void onreceivevalue(string value) {
                toast.maketext(getapplicationcontext(),
                        "相加结果:"+value, toast.length_short).show();
            }
        });
    }

    public void ondoing(view view){
        string msg = "测试";
        webview.loadurl("javascript:showinfofromjava('"+msg+"')");
    }

对应的js方法

    function sum(a,b){
    return a+b;
    }

    function showinfofromjava(){
    document.getelementbyid("p").innerhtml="java成功调的js方法";
    }

四、js调用android本地java方法

在android 4.2以上可以直接使用@javascriptinterface注解来声明,下面是在一个本地java方法

public void addjavascriptinterface(object object, string name);

1 object参数:在object对象里面添加我们想要在js里面调用的android方法,下面的代码中我们调用了showtoast方法
2 name参数:这里的name就是我们可以在js里面调用的对象名称,对应下面代码中的jstext

对应的js代码

function jsjava(){
        //调用java的方法,顶级对象,java方法
        //可以直接访问jstest,这是因为jstest挂载到js的window对象下了
        jstest.showtoast("我是被js执行的android代码");
    }

对应的java代码:

//java与js回调,自定义方法
        //1.java调用js
        //2.js调用java
        //首先java暴露接口,供js调用
        /**
         * obj:暴露的要调用的对象
         * interfacename:对象的映射名称 ,object的对象名,在js中可以直接调用
         * 在html的js中:jstest.showtoast(msg)
         * 可以直接访问jstest,这是因为jstest挂载到js的window对象下了
         */
        webview.addjavascriptinterface(new object() {
            //定义要调用的方法
            //msg由js调用的时候传递
            @javascriptinterface
            public void showtoast(string msg) {
                toast.maketext(getapplicationcontext(),
                        msg, toast.length_short).show();
            }
        }, "jstest");

五、重绘alert 、confirm和prompt的弹出效果,并把用户具体操作结果回调给js
alert弹窗:
这里写图片描述
重绘confirm弹窗:
这里写图片描述
重绘prompt弹窗:
这里写图片描述

具体代码:

/**
             * webview加载html中有alert()执行的时候,会回调这个方法
             * url:当前webview显示的url
             * message:alert的参数值
             * jsresult:java将结果回传到js中
             */
            @targetapi(build.version_codes.jelly_bean_mr1)
            @override
            public boolean onjsalert(webview view, string url, string message, final jsresult result) {
                alertdialog.builder builder = new alertdialog.builder(jsactivity.this);
                builder.settitle("提示:看到这个,说明java成功重写了js的alert方法");
                builder.setmessage(message);//这个message就是alert传递过来的值
                builder.setpositivebutton("确定", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理确定按钮,且通过jsresult传递,告诉js点击的是确定按钮
                        result.confirm();
                    }
                });
                builder.show();
                //自己处理
                result.cancel();
                return true;
            }

            /**
             * webview加载html中有confirm执行的时候,会回调这个方法
             * url:当前webview显示的url
             * message:alert的参数值
             * jsresult:java将结果回传到js中
             */
            @override
            public boolean onjsconfirm(webview view, string url, string message, final jsresult result) {
                alertdialog.builder builder = new alertdialog.builder(jsactivity.this);
                builder.settitle("提示:看到这个,说明java成功重写了js的confirm方法");
                builder.setmessage(message);//这个message就是alert传递过来的值
                builder.setpositivebutton("确定", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理确定按钮,且通过jsresult传递,告诉js点击的是确定按钮
                        result.confirm();
                    }
                });
                builder.setnegativebutton("取消", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理取消按钮,且通过jsresult传递,告诉js点击的是取消按钮
                        result.cancel();

                    }
                });
                builder.show();
                //自己处理
                result.cancel();
                return true;
            }

            /**
             * webview加载html中有prompt()执行的时候,会回调这个方法
             * url:当前webview显示的url
             * message:alert的参数值
             *defaultvalue就是prompt的第二个参数值,输入框的默认值
             * jspromptresult:java将结果重新回传到js中
             */
            @override
            public boolean onjsprompt(webview view, string url, string message, string defaultvalue,
                                      final jspromptresult result) {
                alertdialog.builder builder = new alertdialog.builder(jsactivity.this);
                builder.settitle("提示:看到这个,说明java成功重写了js的prompt方法");
                builder.setmessage(message);//这个message就是alert传递过来的值
                //添加一个edittext
                final edittext edittext = new edittext(jsactivity.this);
                edittext.settext(defaultvalue);//这个就是prompt 输入框的默认值
                //添加到对话框
                builder.setview(edittext);
                builder.setpositivebutton("确定", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //获取edittext的新输入的值
                        string newvalue = edittext.gettext().tostring().trim();
                        //处理确定按钮了,且过jsresult传递,告诉js点击的是确定按钮(参数就是输入框新输入的值,我们需要回传到js中)
                        result.confirm(newvalue);
                    }
                });
                builder.setnegativebutton("取消", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理取消按钮,且过jsresult传递,告诉js点击的是取消按钮
                        result.cancel();

                    }
                });
                builder.show();
                //自己处理
                result.cancel();
                return true;
            }
        });

效果图:
这里写图片描述

界面上方是两个按钮,下方是一个webview控件,开启页面自动加载url,这里为了方便学习,
我已经写了一个html文件放置在了asset文件中,通过 file:///android_asset/test.html 来进行加载。
webview成功加载页面后,会出现四个新的按钮,点击不同的按钮,会产生不同的效果

asset文件夹下面的test.html文件

<meta charset="utf-8" />
<title></title>
<script>

    function jsalert(){
        var r = alert("我是alert的提示框");
        document.getelementbyid("p").innerhtml="java成功调的js的alert方法";
    }

    function jsconfirm(){
      var r = confirm("我是confirm的弹出框");
      if (r == true)
      {
        document.getelementbyid("p").innerhtml="用户点击了确认按钮";
      }else{
        document.getelementbyid("p").innerhtml="用户点击了取消按钮";
      }
    }
    function jsprompt(){
        //第一个参数是提示
        //第二个参数是默认值
        var r = prompt("请输入姓名:","小明同学");
        if (r != null)
        {
         document.getelementbyid("p").innerhtml="用户输入的姓名为:"+r;
        }else{
         document.getelementbyid("p").innerhtml="用户点击了取消按钮";
        }

    }
    function jsjava(){
        //调用java的方法,顶级对象,java方法
        //可以直接访问jstest,这是因为jstest挂载到js的window对象下了
        jstest.showtoast("我是被js执行的android代码");
    }

    function sum(a,b){
    return a+b;
    }

    function showinfofromjava(){
    document.getelementbyid("p").innerhtml="js方法成功被java调用";
    }

    </script>

界面成功初始化

调用jsalert方法
调用jsconfirm方法
调用jsprompt方法
调用jsjava方法

具体的java代码

public class jsactivity extends appcompatactivity {

    //assets下的文件的test.html所在的绝对路径
    private static final string default_url = "file:///android_asset/test.html";

    private webview webview;

    private progressdialog progressdialog;//加载界面的菊花

    @override
    protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_js);
        initview();
        initwebview();
    }

    /**
     * 初始化控件
     */
    private void initview() {
        webview = (webview) findviewbyid(r.id.webview);
        webview.loadurl(default_url);
    }

    /**
     * 初始化webview
     */
    private void initwebview() {

        //首先设置webview支持js代码
        webview.getsettings().setjavascriptenabled(true);

        //webview自己处理超链接(webview的监听器非常多,封装一个特殊的监听类来处理)
        webview.setwebviewclient(new webviewclient() {

            /**
             * 当打开超链接的时候,回调的方法
             * webview:自己本身webview
             * url:即将打开的url
             */
            @override
            public boolean shouldoverrideurlloading(webview view, string url) {
                //自己处理新的url
                webview.loadurl(url);
                //true就是自己处理
                return true;
            }

            //重写页面打开和结束的监听。打开时弹出菊花
            /**
             * 界面打开的回调
             */
            @override
            public void onpagestarted(webview view, string url, bitmap favicon) {
                if (progressdialog != null && progressdialog.isshowing()) {
                    progressdialog.dismiss();
                }
                //弹出菊花
                progressdialog = new progressdialog(jsactivity.this);
                progressdialog.settitle("提示");
                progressdialog.setmessage("软软正在拼命加载……");
                progressdialog.show();

            }

            /**
             * 重写页面打开和结束的监听。打开时弹出菊花,关闭时隐藏菊花
             * 界面打开完毕的回调
             */
            @override
            public void onpagefinished(webview view, string url) {
                //隐藏菊花:不为空,正在显示。才隐藏
                if (progressdialog != null && progressdialog.isshowing()) {
                    progressdialog.dismiss();
                }
            }

        });

        //设置进度条
        //webchromeclient与webviewclient的区别
        //webviewclient处理偏界面的操作:打开新界面,界面打开,界面打开结束
        //webchromeclient处理偏js的操作
        webview.setwebchromeclient(new webchromeclient() {
            /**
             * 进度改变的回调
             * webview:就是本身
             * newprogress:即将要显示的进度
             */
            @override
            public void onprogresschanged(webview view, int newprogress) {
                if (progressdialog != null && progressdialog.isshowing())
                    progressdialog.setmessage("软软正在拼命加载……" + newprogress + "%");
            }

            /**
             * 重写alert、confirm和prompt的弹出效果,并把用户操作的结果回调给js
             */
            /**
             * webview加载html中有alert()执行的时候,会回调这个方法
             * url:当前webview显示的url
             * message:alert的参数值
             * jsresult:java将结果回传到js中
             */
            @override
            public boolean onjsalert(webview view, string url, string message, final jsresult result) {
                alertdialog.builder builder = new alertdialog.builder(jsactivity.this);
                builder.settitle("提示:看到这个,说明java成功重写了js的alert方法");
                builder.setmessage(message);//这个message就是alert传递过来的值
                builder.setpositivebutton("确定", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理确定按钮了,且通过jsresult传递,告诉js点击的是确定按钮
                        result.confirm();
                    }
                });
                builder.setoncancellistener(new dialoginterface.oncancellistener() {
                    @override
                    public void oncancel(dialoginterface dialog) {
                        //防止用户点击对话框外围,再次点击按钮页面无响应
                        result.cancel();
                    }
                });
                builder.show();
                //自己处理
                return true;
            }

            /**
             * webview加载html中有confirm执行的时候,会回调这个方法
             * url:当前webview显示的url
             * message:alert的参数值
             * jsresult:java将结果回传到js中
             */
            @override
            public boolean onjsconfirm(webview view, string url, string message, final jsresult result) {
                alertdialog.builder builder = new alertdialog.builder(jsactivity.this);
                builder.settitle("提示:" +
                        "看到这个,说明java成功重写了js的confirm方法");
                builder.setmessage(message);//这个message就是alert传递过来的值
                builder.setpositivebutton("确定", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理确定按钮了,且通过jsresult传递,告诉js点击的是确定按钮
                        result.confirm();
                    }
                });
                builder.setnegativebutton("取消", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理取消按钮,且通过jsresult传递,告诉js点击的是取消按钮
                        result.cancel();

                    }
                });
                builder.setoncancellistener(new dialoginterface.oncancellistener() {
                    @override
                    public void oncancel(dialoginterface dialog) {
                        //防止用户点击对话框外围,再次点击按钮页面无反应
                        result.cancel();
                    }
                });
                builder.show();
                //自己处理
                return true;
            }

            /**
             * webview加载html中有prompt()执行的时候,会回调这个方法
             * url:当前webview显示的url
             * message:alert的参数值
             *defaultvalue就是prompt的第二个参数值,输入框的默认值
             * jspromptresult:java将结果重新回传到js中
             */
            @override
            public boolean onjsprompt(webview view, string url, string message, string defaultvalue,
                                      final jspromptresult result) {
                alertdialog.builder builder = new alertdialog.builder(jsactivity.this);
                builder.settitle("提示:看到这个,说明java成功重写了js的prompt方法");
                builder.setmessage(message);//这个message就是alert传递过来的值
                //添加一个edittext
                final edittext edittext = new edittext(jsactivity.this);
                edittext.settext(defaultvalue);//这个就是prompt 输入框的默认值
                //添加到对话框
                builder.setview(edittext);
                builder.setpositivebutton("确定", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //获取edittext的新输入的值
                        string newvalue = edittext.gettext().tostring().trim();
                        //处理确定按钮了,且过jsresult传递,告诉js点击的是确定按钮(参数就是输入框新输入的值,我们需要回传到js中)
                        result.confirm(newvalue);
                    }
                });
                builder.setnegativebutton("取消", new onclicklistener() {

                    @override
                    public void onclick(dialoginterface dialog, int which) {
                        //处理取消按钮,且过jsresult传递,告诉js点击的是取消按钮
                        result.cancel();

                    }
                });
                builder.setoncancellistener(new dialoginterface.oncancellistener() {
                    @override
                    public void oncancel(dialoginterface dialog) {
                        //防止用户点击对话框外围,再次点击按钮页面无反应
                        result.cancel();
                    }
                });
                builder.show();
                //自己处理
                return true;
            }
        });

        //java与js回调,自定义方法
        //1.java调用js
        //2.js调用java
        //首先java暴露接口,供js调用
        /**
         * obj:暴露的要调用的对象
         * interfacename:对象的映射名称 ,object的对象名,在js中可以直接调用
         * 在html的js中:jstest.showtoast(msg)
         * 可以直接访问jstest,这是因为jstest挂载到js的window对象下了
         */
        webview.addjavascriptinterface(new object() {
            //定义要调用的方法
            //msg由js调用的时候传递
            @javascriptinterface
            public void showtoast(string msg) {
                toast.maketext(getapplicationcontext(),
                        msg, toast.length_short).show();
            }
        }, "jstest");

    }

    @targetapi(build.version_codes.kitkat)
    public void onsum(view view){
        webview.evaluatejavascript("sum(1,2)", new valuecallback() {
            @override
            public void onreceivevalue(string value) {
                toast.maketext(getapplicationcontext(),
                        "相加结果:"+value, toast.length_short).show();
            }
        });
    }

    public void ondoing(view view){
        string msg = "测试";
        webview.loadurl("javascript:showinfofromjava('"+msg+"')");
    }


    @override
    public void onbackpressed() {
        if (webview.cangoback()) {
            //返回上一个页
            webview.goback();
            return ;
        }
        super.onbackpressed();
    }

}

布局文件activity_js.xml



    



代码过程描述的废话我就不多说了,注释写的算是比较仔细了,另外再强调两点需要注意的地方:

1、不要忘记通过setjavascriptenabled(true)设置webview支持js代码

2、在使用addjavascriptinterface方法添加挂载对象时,要注意在android4.2之后需要给对象方法加上@javascriptinterface注解。

3、重绘alert、confirm和prompt的弹出效果之后,在对话框结束之后一定要调用result.confirm()或者result.cancel()两个方法中的一个

,否则会出现后续再次点击html页面按钮,页面无响应的情况

项目地址:https://github.com/afinalstone/webviewandjs-master

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网