WebView与JS的交互

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、WebView与JS各自的含义

  • WebView在安卓中出现并不少见,尤其是需要访问网页的时候,如在APP上点击链接
  • JS就是编写前端页面的代码,也就是网页的UI内容
    像之前刚接触安卓的时候,没少看到安卓与JS交互写的一些方法代码,当时都是应付性的学习理解一下,并没有深入的学习和理解,所以今天趁着再一次学习, 把自己学的一些微小的见解写在博客上,方便后续学习。

二、WebView与JS的交互方式

大家如果想深入学习,可以看这一篇博客,内容更加具体,且下面图片出自该处
图片来源
注:AndroidJS的交互是可以通过本地文件和远程url的形式,而本文是采用Andorid调用本地JS代码说明;实际情况时,Android更多的是调用远程JS代码,即将加载的JS代码路径改成url即可

1.Android调用JS方法(2种方式)

:因为webViewAndroid的控件之一,所以这样写成AndroidJS的交互,而webview算是它们二者交互的桥梁。

  • 第一种方式:WebView.loadUrl()
 webView.loadUrl("javascript:callJS()")//当前是加载本地资源
  • 第二种方式:WebView.evaluateJavascript()(比第一种更加高效)
// 只需要将第一种方法的loadUrl()换成下面该方法即可
    mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            //此处为 js 返回的结果
        }
    });
}

两种加载方式对比:
在这里插入图片描述

  1. 步骤1:编写本地的html文件javascript.html
    在这里插入图片描述
    javascript.html内容如下:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"> //注意结尾后面不需要斜杠 /
            <title>CXJ</title>

        //JS代码
        <script>
            function callJS(){
            alert("Android调用了JS的callJS方法");
            }
        </script>
    </head>
</html>
  1. 步骤2:布局文件:
 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">
    
    <Button
        android:text="点击我"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button"/>
        
    <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webview"/>

</LinearLayout>
  1. 步骤3:编写关键代码
 //1.3先加载JS代码   规定格式:file:///android_asset/文件名.html
webView.loadUrl("file:///android_asset/javascript.html");

注意:file:///android_asset/文件名.html 是加载本地JS文件的规定格式

    //方法名要对应javascript.html文件里面的 callJS()函数
   webView.loadUrl("javascript:callJS()");

完整的代码:

public class MainActivity extends AppCompatActivity {

    WebView webView;
    Button button;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        button=findViewById(R.id.button);

        //1.开始设置web View相关设置
        WebSettings webSettings=webView.getSettings();
        //1.1允许与JS发生交互
        webSettings.setJavaScriptEnabled(true);
        //1.2允许设置JS弹窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        //1.3先加载JS代码   规定格式:file:///android_asset/文件名.html
        webView.loadUrl("file:///android_asset/javascript.html");

        //2.点击事件
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                webView.post(new Runnable() {
                    @Override
                    public void run() {
                    //第一种方式加载
                        //方法名要对应 callJS()
//                        webView.loadUrl("javascript:callJS()");

                     //第二种方式加载
//                        webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
//                            @Override
//                            public void onReceiveValue(String s) {
//                                Log.d("TAG", "js返回的结果: "+s);
//                            }
//                        });

                       //兼容上下版本更改的方式加载
                        // Android版本变量
                        final int version = Build.VERSION.SDK_INT;
                        // 因为该方法在 Android 4.4 版本才可使用,所以使用时需进行版本判断
                        if (version < 18) {
                            webView.loadUrl("javascript:callJS()");
                        } else {
                        webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
                            @Override
                            public void onReceiveValue(String s) {
                                Log.d("TAG", "js返回的结果: "+s);
                            }
                        });
                        }
                    }
                });
            }
        });

        //webView只是载体,内容的渲染需要使用webViewChromeClient类去实现  设置响应JS的Alert()函数
        webView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
                builder.setTitle("Alert");
                builder.setMessage(message);
                builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        result.confirm();
                    }
                });
                builder.setCancelable(false);
                builder.create().show();
                return true;
            }
        });
    }
}

2.JS调用Android方法(3种方式)

第一种方式:WebView.addJavascriptInterface()
第二种方式:WebViewClient.shouldOverrideUrlLoading ()
第三种方式:WebChromeClient.addJavascriptInterface()
在这里插入图片描述

第一种方式WebView.addJavascriptInterface()的实现步骤
  1. 步骤1:编写给JS调用的安卓方法类AndroidToJs
/**
 1. 定义给JS调用的安卓方法
 */
public class AndroidToJs extends Object{
    //定义给JS调用的安卓方法——且必须加上JavascriptInterface
    @JavascriptInterface
    public void hello(String msg){
        System.out.println("JS调用安卓的Hello方法");
    }
}
  1. 步骤2:将本地JS文件格式放到src/main/assets文件夹里
    在这里插入图片描述
    javascript2.html内容如下
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>CXJ</title>
    <script>
         function callAndroid(){
        // 由于对象映射,所以调用test对象等于调用Android映射的对象
            test.hello("js调用了android中的hello方法");
         }
      </script>
</head>
<body>
     //点击按钮则调用callAndroid函数   这一段代码是在JS界面设置好的,不需要在安卓的布局里面添加Button控件
     <button type="button" id="button1" onclick="callAndroid()"></button>
</body>
</html>
  1. 步骤3:在Android里通过WebView设置Android类与JS代码的映射
    关键代码:
 //2.通过addJavascriptInterface将Java映射到JS对象  参数1:javascript对象名  参数2:Java对象名
webView.addJavascriptInterface(new AndroidToJs(),"test");

注:参数1:javascript对象名(提供给JS调用的类名) 参数2:javascript2.html里面的对象
在这里插入图片描述
完整的代码:

public class JSUseAndroid extends AppCompatActivity {
    WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jsuse_android);

        webView = findViewById(R.id.webview);


        //1.开始设置web View相关设置
        WebSettings webSettings=webView.getSettings();
        //1.1允许与JS发生交互
        webSettings.setJavaScriptEnabled(true);

        //2.通过addJavascriptInterface将Java映射到JS对象  参数1:javascript对象名  参数2:Java对象名
        webView.addJavascriptInterface(new AndroidToJs(),"test");

        //3.加载JS代码
        webView.loadUrl("file:///android_asset/javascript2.html");
    }
}

效果展示:
在这里插入图片描述

第二种方式WebViewClient.shouldOverrideUrlLoading ()的实现步骤

原理Android通过 WebViewClient的回调方法shouldOverrideUrlLoading ()拦截 url并解析该 url 的协议,如果检测到是预先约定好的协议,就调用相应方法。

  1. 步骤1:在JS约定所需要的Url协议JS代码:javascript.html
    在这里插入图片描述
  2. 步骤2:在Android通过WebViewClient复写shouldOverrideUrlLoading()
    关键代码:
//3.复写WebViewClient类的shouldOverrideUrlLoading方法
webView.setWebViewClient(new WebViewClient(){
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        //3.1根据协议的参数,判断是否是所需要的url格式
        //TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数)  "js://webview?arg1=111&arg2=222"
        Uri uri=Uri.parse(url);
        //3.2如果协议等于预先约定的js协议,则往下解析参数
        if (uri.getScheme().equals("js")){
            //3.3如果authority=预先约定好的webview,则表示都符合约定
            if (uri.getAuthority().equals("webview")){
                System.out.println("js调用了Android的方法");

                //后续需要
                HashMap<String,String> params=new HashMap<>();
                Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中
            }
            return true;
        }
        return super.shouldOverrideUrlLoading(view, url);
    }
});

uri.getScheme()对应的是约定协议约定的url协议为:js://webview?arg1=111&arg2=222js 部分 ,而 uri.getAuthority()对应的是webview
完整的代码:

public class JSUseAndroid2 extends AppCompatActivity {
    WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jsuse_android2);

        webView = findViewById(R.id.webview);

        //1.开始设置web View相关设置
        WebSettings webSettings=webView.getSettings();
        //1.1允许与JS发生交互
        webSettings.setJavaScriptEnabled(true);

        //2.加载JS代码
        webView.loadUrl("file:///android_asset/javascript3.html");

        //3.复写WebViewClient类的shouldOverrideUrlLoading方法
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //3.1根据协议的参数,判断是否是所需要的url格式
                //TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数)  "js://webview?arg1=111&arg2=222"
                Uri uri=Uri.parse(url);
                //3.2如果协议等于预先约定的js协议,则往下解析参数
                if (uri.getScheme().equals("js")){
                    //3.3如果authority=预先约定好的webview,则表示都符合约定
                    if (uri.getAuthority().equals("webview")){
                        System.out.println("js调用了Android的方法");

                        //后续需要
                        HashMap<String,String> params=new HashMap<>();
                        Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中
                    }
                    return true;
                }
                return super.shouldOverrideUrlLoading(view, url);
            }
        });
    }
}

效果展示:
在这里插入图片描述

第三种方式WebChromeClient的实现步骤

有三种形式

  • WebChromeClient.onJsAlert()
  • WebChromeClient.onJsConfirm()
  • WebChromeClient.onJsPrompt()
    在这里插入图片描述
  1. 步骤1:在JS约定所需要的Url协议JS代码:javascript.html
    在这里插入图片描述
  2. 步骤2:在Android通过WebChromeClient复写onJsPrompt()
    关键代码:
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    //3.1根据协议的参数,判断是否是所需要的url格式
    //TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数)  "js://webview?arg1=111&arg2=222"
    Uri uri=Uri.parse(message);//TODO 这样传入的是promt()的内容
    //3.2如果协议等于预先约定的js协议,则往下解析参数
    if (uri.getScheme().equals("js")){
        //3.3如果authority=预先约定好的webview,则表示都符合约定
        if (uri.getAuthority().equals("demo")){
            System.out.println("js调用了Android的方法");

            //后续需要
            HashMap<String,String> params=new HashMap<>();
            Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中

            //参数result:代表消息框的返回值(输入值)
            result.confirm("js调用Android方法成功啦");
        }
        return true;
    }
    return super.onJsPrompt(view, url, message, defaultValue, result);
}

完整代码:

public class JSuseAndroid3 extends AppCompatActivity {
    WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jsuse_android3);

        webView = findViewById(R.id.webview);

        //1.开始设置web View相关设置
        WebSettings webSettings=webView.getSettings();
        //1.1允许与JS发生交互
        webSettings.setJavaScriptEnabled(true);
        //1.2 允许设置JS弹窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        //2.加载JS代码
        webView.loadUrl("file:///android_asset/javascript4.html");

        //3.复写
        webView.setWebChromeClient(new WebChromeClient(){
            //拦截输入框  参数message:代表promt()的内容(不是url)   参数result:代表输入框的返回值
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                //3.1根据协议的参数,判断是否是所需要的url格式
                //TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数)  "js://webview?arg1=111&arg2=222"
                Uri uri=Uri.parse(message);//TODO 这样传入的是promt()的内容
                //3.2如果协议等于预先约定的js协议,则往下解析参数
                if (uri.getScheme().equals("js")){
                    //3.3如果authority=预先约定好的webview,则表示都符合约定
                    if (uri.getAuthority().equals("demo")){
                        System.out.println("js调用了Android的方法");

                        //后续需要
                        HashMap<String,String> params=new HashMap<>();
                        Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中

                        //参数result:代表消息框的返回值(输入值)
                        result.confirm("js调用Android方法成功啦");
                    }
                    return true;
                }
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }

            //拦截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);
            }
        });

    }
}

效果图:
在这里插入图片描述

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值