webview与js通信踩坑以及返回键处理与清空浏览历史操作

最近在做webview与js通信,遇到一些坑,记录一下

1.webview与js方法交互

首先,webview与js确定一个类名,作为通信的依据,比如"android",webview设置

webSettings.setJavaScriptEnabled(true) 表示让WebView支持调用Js;
 webView.addJavascriptInterface(new AndroidtoJs(this), "android");

js调用android方法

写用于让js调用的方法,比如

 public class AndroidtoJs extends Object
    {
        Activity activity;

        public AndroidtoJs(Activity activity)
        {
            this.activity = activity;
        }

        // 定义JS需要调用的方法
        // 被JS调用的方法必须加入@JavascriptInterface注解
        @JavascriptInterface
        public void getimg(String bean)
        {
            Log.e("acntiontype", bean);
            Gson gson = new Gson();
            GetImageBean imageBean = new GetImageBean();
            try
            {
                imageBean = gson.fromJson(bean, GetImageBean.class);

            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            methodtype = imageBean.getMethodtype();
            if (imageBean.getMethodtype().equals("1"))
            {//照片
                runOnUiThread(new Runnable()
                {

                    @Override
                    public void run()
                    {
                    //选择相册或相机的对话框
                        showSignaturePopWindow();
                    }
                });


            }
        }
    }

js调用app的方法名getimg,传入参数,webview会根据参数,进行相应的操作,
坑1:在js调用android定义的方法中,操作UI,会报 java.lang.IllegalStateException: Calling View methods on another thread than the UI thread.at 异常,这个主要是Android的相关View和控件不是线程安全的,所以将js调用我们的代码放在UI线程中

 runOnUiThread(new Runnable()
                {

                    @Override
                    public void run()
                    {
                        showSignaturePopWindow();
                    }
                });

js代码里边,可以写
android.getimg(bean)之类的,来调用android方法

android调用js方法

app调用js方法名setImg(String name)

 webView.loadUrl("javascript:setImg(" + result + ")");

注:网上有资料说,调用js带参数的方法,参数要用单引号,比如

//在android调用js有参的函数的时候参数要加单引号
                webView.loadUrl("javascript:message('" + name + "')");

我发现没加好像也可以,为保险起见,还是加上,跟后台调试调试
坑2:如果传的参数是图片的base64,在网页不显示的话,可以在base64之前加上"data:image/jpeg;base64,"

android调用js方法获取返回值

4.4以上版本

webView.evaluateJavascript("javascript:jsMethod()", new ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String value) {
                            //value即为js返回值
                        }
                    });

4.4以下版本
通过loadUrl调用js的alert方法,然后在android端监听alert弹出

webView.loadUrl("javascript:alert(jsMethod())");
 public class MyWebChromeClient extends WebChromeClient
    {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result)
        {
            Log.i(TAG, "onJsAlert: " + message);
            if (message.contains("false"))
            {
                showBackDialog();
                //message即为返回值
                result.confirm();
                return true;
            }
    /* //true,拦截JavaScript的弹窗。如果拦截了,不会出现弹窗。
            return super.onJsAlert(view, url, message, result);
       
     
        }

        @Override
        public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
        {
            Log.i(TAG, "onJsConfirm: " + message);
            return super.onJsConfirm(view, url, message, result);
        }

        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
        {
            Log.i(TAG, "onJsPrompt: " + message);
            return super.onJsPrompt(view, url, message, defaultValue, result);
        }

        @Override
        public void onReceivedTitle(WebView view, String title)
        {
            super.onReceivedTitle(view, title);
        }
    }

我没有找到在android中判断调用的js是否存在的方法,就是用了try catch,在异常中处理方法不存在的逻辑

返回键处理

有的时候,在网页中操作,跳转到其他网页,按返回键,应该一层一层返回到首页,如果已经是首页了,点击返回,应该跳出该页面,在返回事件中,通过webView.canGoBack()来判断,通过 webView.goBack();返回

 if (webView.canGoBack())
                {
                    webView.goBack();
                }
                else
                {
                super.onBackPressed();
                }

切换url,清空浏览历史

如果webview中,需要根据需要切换url,不清空之前浏览的历史的话,会返回到之前url的页面,清空历史,就在WebViewClient的onPageFinished中进行

 //是否切换url,如果切换了,清空历史
    private boolean isReloadData = false;
	.....
	webView.clearHistory();
                        webView.clearCache(true);
                        isReloadData = true;
                        webView.loadUrl(url);
                        ...
 @Override
        public void onPageFinished(WebView view, String url)
        {   //重载url以后,清空历史,设置为初始值,如果一直清空,canGoBack()会一直返回false
            if(isReloadData){
                view.clearHistory();
            }
            isReloadData = false;
          
        }

这里加一个isReloadData判断的原因,是只有在切换url的时候,把之前的历史清空,其他的不进行操作,加载url,然后点击页面中的一些操作,跳转到其他url,如果把之前的都清空了,canGoBack()会一直返回false,就没办法返回到首页
参考文章
Android和H5交互一篇就够了
在加载下一个WebView之前,如何清除以前的WebView内容
WebView调用js方法获取返回值的完美解决方案
混合开发-Android 判断 js 方法是否存在
Android WebView 不支持 H5 input type=“file” 解决方法
WebView中JS调用Android Method 遇到的坑整理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章