接外包,有相关需求的可以联系我:Telegram | Email

通过WebChromeClient复写onJsPrompt来调用andriod代码

该文章创建(更新)于06/6/2020,请注意文章的时效性!

文章目录[隐藏]

感觉这个和通过复写shouldOverrideUrlLoading来调用andriod代码有相似之处,但发现了有趣的一点是它在触发后可以把Android的一个数据给返回到JS代码之处;

代码

布局

HTML

在src/main/下创建一个文件夹assets,里面添加一个index.html文件,内容如下;

<html>
<head>
    <meta charset="utf-8">
    <title>emperinter</title>

    <script>

    function clickprompt(){
            var name,password;
            name = document.getElementById("n").value;
            document.getElementById("gn").innerHTML = name;

            password = document.getElementById("p").value;
            document.getElementById("gp").innerHTML = password;

            var data = "js://demo?arg1=" + name + "&arg=" + password + "&arg3=test&fuck=fuck";
            document.getElementById("toandroid").innerHTML = data;

            // 调用prompt(),result为Android传来的值
            var result=prompt(data);
            alert("demo " + result);

            document.getElementById("info").innerHTML = result;
        }

      </script>
</head>


<body>
<div align="center">
    name:<input id="n">
    <br/>
    password:<input id="p">
    <p id="info">Android 传进来的值</p>
    get_name:<p style="color:red;" id="gn">get_name</p>
    get_password:<p style="color:red" id="gp">get_password</p>
    <p id="toandroid">传给Android的一套js数据</p>
    <!-- 点击按钮则调用clickprompt()  -->
    <button style="font-size:32px;" type="button" onclick="clickprompt()">点击调用Android代码</button>
    <p></p>
</div>

</body>
</html>

MainActivity

注意这里的Uri参数是message!

public class MainActivity extends AppCompatActivity {
    WebView mwebview;
    TextView mtxt0;
    TextView mtxt1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mwebview = (WebView) findViewById(R.id.MainWeb);
        mtxt0 = (TextView) findViewById(R.id.MainTxt0);
        mtxt1 = (TextView) findViewById(R.id.MainTxt1);

        WebSettings websettings = mwebview.getSettings();

        // 允许 WebView 加载 JS 代码
        websettings.setJavaScriptEnabled(true);
        // 允许 JS 弹窗
        websettings.setJavaScriptCanOpenWindowsAutomatically(true);

        try {
            mwebview.loadUrl("file:///android_asset/index.html");
            Log.e("LoadUrl:", "Successful !");
        }catch (Exception ex) {
            Log.e("LoadUrl:", "wrong !");
        }

        mwebview.setWebChromeClient(new WebChromeClient(){
            //拦截输入框(原理同复写shouldOverrideUrlLoading)
            //参数message:代表prompt()的内容(不是url)
            //参数result:代表输入框的返回值
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result){
                //根据协议的参数,判段是否所需要的url
                //一般根据schema(协议格式) & authority(协议名)判断(前两个参数)
                //假定传入进来的 rul = "js://demo?arg1=111&arg2=222" (同时也是约定好需要拦截的)

                Uri uri = Uri.parse(message);
                // 如果url的协议 = 预先约定的js协议
                // 就往下解析参数

                if(uri.getScheme().equals("js")){
                    //如果 authority = 预先约定协议里的webview,即代表都符合约定的协议
                    //所以拦截rul,下面JS开始调用Android需要的方法
                    if(uri.getAuthority().equals("demo")){

                        //参数result:代表消息框的返回值(输入值),这里的参数会传递给JS里面去;
                        result.confirm("从Android向JS返回的数据");

                        Set<String> collection = uri.getQueryParameterNames();
                        Iterator<String> it = collection.iterator();
                        String txt0 = uri.getQueryParameter(it.next());
                        String txt1 = uri.getQueryParameter(it.next());

                        mtxt0.setText(txt0);
                        Log.e("arg1",txt0);
                        mtxt1.setText(txt1);
                        Log.e("arg2",txt1);
////                      测试传参
                        Log.e("test:",uri.getQueryParameter(it.next()));
                        Log.e("fuck:",uri.getQueryParameter(it.next()));


                    }
                    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的确认框
//            public boolean onJsConfirm(WebView view,String url,String message,JsResult result){
//                return  super.onJsConfirm(view,url,message,result);
//            }
        });
    }
}

运行截图


要不赞赏一下?

微信
支付宝
PayPal
Bitcoin

版权声明 | Copyright

除非特别说明,本博客所有作品均采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。转载请注明转自-
https://www.emperinter.info/2020/06/06/onjsprompt-on-android-webview/


要不聊聊?

我相信你准备留下的内容是经过思考的!【勾选防爬虫,未勾选无法留言】

*

*



YouTube | B站

微信公众号

优惠码

阿里云国际版20美元
Vultr10美元
搬瓦工 | Bandwagon应该有折扣吧?
Just My SocksJMS9272283 【注意手动复制去跳转】
域名 | namesiloemperinter(1美元)
币安 币安