WebView(H5)调用Android端代码

WebView调用Android代码

做好战斗准备,其实也不复杂

情景再现:
运营的H5页面上有个按钮,叫“立即参加”,当用户点击按钮的时候,App上要弹一个吐司出来。

一、通过WebView的addJavascriptInterface ()方式进行映射

1.准备工作
定义我们将来要响应js代码的类

/**
 * 与h5交互的共同类
 */
public class ForJs {
    //添加注解,不添加注解方法不能够被js调用
  //注意方法名称,提供给js的时候也一定要匹配
    @JavascriptInterface
    public void fromAndroid(){
        //我们具体要执行的逻辑,本例只是弹一个吐司
        ToastUtil.showToast("这个是android里的方法");
    }
 // 同上,只是一个有参,一个无参而已
    @JavascriptInterface
    public void fromAndroid(String msg){
        //我们具体要执行的逻辑,本例只是弹一个吐司
        ToastUtil.showToast("msg");
    }
}

至此,准备工作就已经结束。
2.使用

  • android端代码
        //如果只需要让js调用android代码,这几行就够了
        WebSettings settings = mWebView.getSettings();
        settings.setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(new ForJs(), "testMall");

参数说明:
1、我们定义的与H5交互的java类
2、java类在H5中映射的对象名称
H5中的js在调用我们的方法的时候,必须知道的是:
映射对象的名称,即示例中的testMall
映射对象提供的方法名称,即示例中的ForJs类中的fromAndroid()
H5中的关键代码
注意这部分代码并不需要我们Android端人员编写,但是却需要我们Android端人员的配合

//js中的点击方法调用,调用的是Android端的无参方法

重复一下注意事项:

Androdi端提供给js调用的方法名称要准确无误的告诉前端人员
Js中映射的Java对象名称,要准确无误的告诉Android端人员

一定要看

这种使用方式看起来很简单,但是却有一个致命漏洞:
https://www.jianshu.com/p/3a345d27cd42

二、通过WebViewClinet的shouldOverrideUrlLoading()方法拦截url

  • 拦截该Url
  • 解析Url协议()//新的API可以直接获取到uri
  • 按照约定调用Android端的方法
    1.Android端代码
 mWebView.loadUrl("file:///android_asset/test.html");
        WebSettings settings = mWebView.getSettings();
        settings.setJavaScriptEnabled(true);
        mWebView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                //请求方式
                String method = request.getMethod();
                //请求头
                Map requestHeaders = request.getRequestHeaders();
                //uri,给里面有各种我们需要的东西,只需要get即可
                Uri uri = request.getUrl();
                String host = uri.getHost();
                String authority = uri.getAuthority();
                // TODO: 2018/12/15 判断,如果符合约定,即执行Android提供好的方法,最后记得return true
              //模拟微信封杀抖音链接
                if (authority.contains("douyin")){
                    ToastUtil.showToast("不要看抖音,微信不够丰富吗");
                    return true;
                }
                return super.shouldOverrideUrlLoading(view, request);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //如果使用这个方法,那么需要自己手动获取uri,其实与上面并无本质区别
                Uri uri = Uri.parse(url);
                return super.shouldOverrideUrlLoading(view, url);
            }
        });

至此,Android端代码完成
2.H5端代码
注意这部分代码并不需要我们Android端人员编写,但是却需要我们Android端人员与H5端人员协商好协议约定

//js中的点击方法调用

与第一种方法比起来,这种写法双方写起来都比较随意。除了Url的协议约定外,别的没有需要注意事项。尤其H5端,其实只是重定向了一个网页而已。
换句话说,在本示例中,如果我们直接在webView中加载
https://www.douyin.com/,也会触发我们的Android中的方法,即拦截逻辑。

更重要的是,第二种方式没有第一种方式那种致命漏洞。即利用shouldOverrideUrlLoading方法不存在漏洞

缺点:难以获得返回值,如果想要获得返回值,那么就利用Android端调用Js的方法webView的loadUrl(restul),将Android端的返回值result当做参数传递给js。

Android端示例代码:

 WebSettings settings = mWebView.getSettings();
        settings.setJavaScriptEnabled(true);
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                Uri uri = request.getUrl();
                String authority = uri.getAuthority();
                //模拟代码
                if (authority.contains("douyin")) {
                    String result = "这是Android端执行完成之后的结果";
//获取android端的结果后调用js中的方法,把result当参数传递给js
mWebView.loadUrl("javascript:callJsFromAndroid("+result+")");
                    return true;
                }
                return super.shouldOverrideUrlLoading(view, request);
            }
        });

        //注意,本示例之所以加此行代码,是为了能弹出js框,具体要看实际需求
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.loadUrl("file:///android_asset/test.html");

H5端示例代码



三、通过WebChromeClient的alert()、prompt()、confirm()方法回调js对应的对话框

我在https://www.jianshu.com/p/22265f5c5d78中详细介绍了Android端响应这三种js弹框的方式,如果不熟悉的请先了解一下。一般来将,我们使用的最多的是prompt()方法,因为这个有任意类型的返回值,请看示例代码

Android端代码

  WebSettings settings = mWebView.getSettings();
        settings.setJavaScriptEnabled(true);
        //本行代码添加只是为了让网页在app内打开
        mWebView.setWebViewClient(new WebViewClient());
        
        mWebView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                //message即是js弹框中的内容
                //解析message,按照约定处理逻辑
                if (TextUtils.equals(message,"douyin")) {
                    // android端的处理逻辑
                    ToastUtil.showToast("你们怎么都那么好看又有钱");
                    return true;
                }
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
        });
        mWebView.loadUrl("file:///android_asset/test.html");

H5端示例代码

//js中的点击方法调用

三种使用方式的对比

1.比较简单,但存在致命漏洞
2.需要双方约定协议,但不存在漏洞
3.与方式2很相似,只是拦截对象不同,也不存在漏洞

写在最后
这些交互方式各有特点,而且并不难以理解,个人认为都应该掌握。

你可能感兴趣的:(WebView(H5)调用Android端代码)