Android Webview Js交互遇到的坑!!!

来源:互联网 发布:qq输入法 linux 编辑:程序博客网 时间:2024/06/06 01:11

最近研究了一下webview的js交互问题,遇到了各种坑。现在就遇到的坑进行讲解一下,避免其他盆友遇到同样的坑不知所挫。

1.需求:修改html中控件内容的值,如登录界面的用户名与密码自动输入问题。

初始解决方法:通过webview设置webviewClient,并重新onpagefinished()方法,该方法在页面加载完成后会调用,进行js注入还必须设置支持javascript脚本webView.getSettings().setJavaScriptEnabled(true);

出现的问题:页面刷新后,先加载正常登录页面,最后跳到修改了后只显示修改内容的空白页;其他布局,内容消失。

结果:未达到需求。

改进方法:在调用htmll的代码的时候,需要写个方法,并且需要再次调用该方法。例:在webviewClient设置中重新onpagefinished()方法并添加如下代码更改Html端的控件值。

  new Handler().postDelayed(new Runnable() {
                                            @Override
                                             public void run() {
                                                 webView.loadUrl("javascript:function setJsAcion(){document.getElementById('u').value='13800138000'; 
document.getElementById('p').value='13800138000'}");
                                                 webView.loadUrl("javascript:setJsAcion()");
                                             }
                                         }, 500);
运行效果:


2.需求:通过对html的拦截,实现数据收集。
1).添加js接口
  webView.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj");
注:第一个参数是java类,用于js交互的类 java_obj是用于js交互的别名,在js中交互用到。
2).重写webViewclient中的方法。
//用于处理https请求用到的证书处理,不设置默认handler.cancel()。
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    // TODO Auto-generated method stub
    // handler.cancel();// Android默认的处理方式 super方法包含该方法导致部分手机无法访问页面
    handler.proceed();// 接受所有网站的证书
    // handleMessage(Message msg);// 进行其他处理
}
@Override
// 在开始加载网页时会回调
 public void onPageStarted(WebView view, String url, Bitmap favicon) {
      super.onPageStarted(view, url, favicon);
       }
 // 拦截 url 跳转,在里边添加点击链接跳转或者操作
 @Override
   public boolean shouldOverrideUrlLoading(WebView view, String url) {
     view.loadUrl(url);//用webveiw加载
     return true;//返回true表示点击页面内容可跳转,否则点击页面点击事件无反应
}
  @Override
   public void onPageFinished(WebView view, String url) {
                new Handler().postDelayed(new Runnable() {//进行延时处理 
                                             @Override
                                             public void run() {
                                                 webView.loadUrl("javascript:function setJsAcion(){document.getElementById('u').value='13800138000'; //注入js代码
document.getElementById('p').value='13800138000'}");//获取控件并赋值
                                                 webView.loadUrl("javascript:setJsAcion()");//注入的js函数或方法再次调用 重要:直接html js赋值有问题
                                             }
                                         }, 500);
                                         // 获取页面内容并通过showSource方法回传
                                         view.loadUrl("javascript:window.java_obj.showSource("
                                                 + "document.getElementsByTagName('html')[0].innerHTML);");


                                         // 获取解析<meta name="share-description" content="获取到的值">并通过showDescription方法回传
                                         view.loadUrl("javascript:window.java_obj.showDescription("
                                                 + "document.querySelector('meta[name=\"share-description\"]').getAttribute('content')"
                                                 + ");");
  // 获取解析<meta name="iframe" body="获取到的值">并通过showJs()方法回传  注:可以加个延时同上,因为有些时候存在页面未加载完就调用了该onpagefinished()方法
                                         view.loadUrl("javascript:window.java_obj.showJs(document.getElementById('MainContent')" +    //可能出现加载的iframe框架内的数据有延时情况,建议加延迟
                                           ".contentWindow.document.getElementsByTagName('body')[0].innerHTML);");
super.onPageFinished(view, url);
                                     }
//js交互接口类 用于拦截webview内容
  public final class InJavaScriptLocalObj {
        @JavascriptInterface
        public void showSource(final String html) {
            Log.e(TAG, "htmlshowsource: " + html);
            System.out.println("====>htmlshowsource===" + html);
        }


        @JavascriptInterface
        public void showDescription(String str) {
            System.out.println("====>htmlshowdescription==" + str);
            Log.e(TAG, "htmlshowdescription: " + str);
        }


        @JavascriptInterface
        public void showJs(String str) {
            Log.e(TAG, "htmlshowjs: " + str);
            System.out.println("====>htmlshowjs==" + str);
        }
        public void Tz(String str){
            Log.e(TAG, "htmlshowTz"+"进入tz" +str);
            webView.loadUrl("javascript:document.getElementById('CreditCardNo').value='9999'");
        }
    }

//实验请打开网络连接权限


全部demo代码附上
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "msg";

    private static String BaseUrl  ="https://ui.ptlogin2.qq.com/cgi-bin/login?style=9&appid=522005705&daid=4&s_url=https%3A%2F%2Fw.mail.qq.com%2Fcgi-bin%2Flogin%3Fvt%3Dpassport%26vm%3Dwsk%26delegate_url%3D%26f%3Dxhtml%26target%3D&hln_css=http%3A%2F%2Fmail.qq.com%2Fzh_CN%2Fhtmledition%2Fimages%2Flogo%2Fqqmail%2Fqqmail_logo_default_200h.png&low_login=1&hln_autologin=%E8%AE%B0%E4%BD%8F%E7%99%BB%E5%BD%95%E7%8A%B6%E6%80%81&pt_no_onekey=1";

    private static String BaseUrl1 = "https://ui.ptlogin2.qq.com/cgi-bin/login?style=9&appid=522005705&daid=4&s_url=https%3A%2F%2Fw.mail.qq.com%2Fcgi-bin%2Flogin%3Fvt%3Dpassport%26vm%3Dwsk%26delegate_url%3D%26f%3Dxhtml%26target%3D&hln_css=http%3A%2F%2Fmail.qq.com%2Fzh_CN%2Fhtmledition%2Fimages%2Flogo%2Fqqmail%2Fqqmail_logo_default_200h.png&low_login=1&hln_autologin=%E8%AE%B0%E4%BD%8F%E7%99%BB%E5%BD%95%E7%8A%B6%E6%80%81&pt_no_onekey=1";

    private WebView webView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = findViewById(R.id.webView);
        initWebView();
        webView.loadUrl(BaseUrl);
    }




    private void initWebView() {
        // 设置WebView属性,能够执行Javascript脚本
//        webView.getSettings().setJavaScriptEnabled(true);
//        webView.setWebChromeClient(new WebChromeClient());
////          wvAboutUs.setLayerType(View.LAYER_TYPE_HARDWARE, null);
////          wvAboutUs.getSettings().setLoadWithOverviewMode(true);
//        webView.getSettings().setBuiltInZoomControls(false);
//        webView.getSettings().setUseWideViewPort(true);
//        webView.getSettings().setLoadWithOverviewMode(true);
//        webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
//        webView.setBackgroundColor(0);
        // 开启JavaScript支持
        webView.getSettings().setJavaScriptEnabled(true);
//        webView.loadUrl("https://pbsz.ebank.cmbchina.com/CmbBank_GenShell/UI/GenShellPC/Login/Login.aspx");


        webView.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj");


        // 设置WebView是否支持使用屏幕控件或手势进行缩放,默认是true,支持缩放
        webView.getSettings().setSupportZoom(true);


        webView.setWebChromeClient(new WebChromeClient());


        // 设置WebView是否使用其内置的变焦机制,该机制集合屏幕缩放控件使用,默认是false,不使用内置变焦机制。
        webView.getSettings().setBuiltInZoomControls(true);


        // 设置是否开启DOM存储API权限,默认false,未开启,设置为true,WebView能够使用DOM storage API
        webView.getSettings().setDomStorageEnabled(true);


        // 触摸焦点起作用.如果不设置,则在点击网页文本输入框时,不能弹出软键盘及不响应其他的一些事件。
        webView.requestFocus();


        // 设置此属性,可任意比例缩放,设置webview推荐使用的窗口
        webView.getSettings().setUseWideViewPort(true);


        // 设置webview加载的页面的模式,缩放至屏幕的大小
        webView.getSettings().setLoadWithOverviewMode(true);


        webView.setWebViewClient(new WebViewClient() {
                                     @Override
                                     public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                                         // TODO Auto-generated method stub
                                         // handler.cancel();// Android默认的处理方式 super方法包含该方法导致部分手机无法访问页面
                                         handler.proceed();// 接受所有网站的证书
                                         // handleMessage(Message msg);// 进行其他处理
                                     }


                                     @Override
                                     public void onPageStarted(WebView view, String url, Bitmap favicon) {
                                         // 在开始加载网页时会回调
//                                         view.loadUrl("javascript:document.getElementById('CreditCardNo').value='2222222';");
//                                         view.loadUrl("javascript:window.java_obj.Tz()");
                                         super.onPageStarted(view, url, favicon);
                                     }
                                     @Override
                                     public boolean shouldOverrideUrlLoading(WebView view, String url) {
                                         // 拦截 url 跳转,在里边添加点击链接跳转或者操作
                                          view.loadUrl(url);
                                          return true;
//                                         if (url.startsWith("iframe")) {
////                                             view.loadUrl("javascript:window.java_obj.showJs(document.getElementById('MainContent')" +
////                                                     ".contentWindow.document.getElementsByTagName('body')[0].innerHTML);");
//                                             return false;
//                                         } else {
//                                              return super.shouldOverrideUrlLoading(view, url);
//                                         }
                                     }


                                     @Override
                                     public void onPageFinished(WebView view, String url) {




                                        //加这句代码可以在谷歌浏览器调试H5代码 需要翻墙
//                                         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//                                             webView.setWebContentsDebuggingEnabled(true);
//                                         }
                                         // 在结束加载网页时会回调(function(){**这里是需要执行JS代码**})()
//                                         view.loadUrl("javascript:(function(){document.getElementById('CreditCardNo').value='6202222';})()");
//                                         Log.e(TAG, "onPageFinished: " + url);
//                                         view.loadUrl("javascript:document.getElementById('CreditCardNo').value='32343';");
//                                         view.loadUrl("javascript:document.getElementById('u').value='323263262';");
//                                         view.reload();
//                                         webView.loadUrl("javascript:document.getElementById('u').value='6202222';");
//                                         new Handler().postDelayed(new Runnable() {
//
//                                             @Override
//                                             public void run() {
////                                                 webView.loadUrl("javascript:function setJsAcion(){var privateForm=document.getElementById(\"privateForm\").value=\"ejia\"}");
////                                                 webView.loadUrl("javascript:setJsAcion()");
//                                                 webView.loadUrl("javascript:setJs(){var input=document.getElementById('u').value='6202222'}");
//                                             }}, 500);


                                         new Handler().postDelayed(new Runnable() {


                                             @Override
                                             public void run() {
                                                 webView.loadUrl("javascript:function setJsAcion(){document.getElementById('u').value='13800138000'; document.getElementById('p').value='13800138000'}");
                                                 webView.loadUrl("javascript:setJsAcion()");
                                             }
                                         }, 500);
                                         // 获取页面内容
                                         view.loadUrl("javascript:window.java_obj.showSource("
                                                 + "document.getElementsByTagName('html')[0].innerHTML);");


                                         // 获取解析<meta name="share-description" content="获取到的值">
                                         view.loadUrl("javascript:window.java_obj.showDescription("
                                                 + "document.querySelector('meta[name=\"share-description\"]').getAttribute('content')"
                                                 + ");");
//                                         if (url.contains("CreditCardNo")) {
//                                         view.loadUrl("javascript:window.java_obj.Tz()");
//
//                                         }


                                         // 获取解析<meta name="iframe" body="获取到的值">
                                         view.loadUrl("javascript:window.java_obj.showJs(document.getElementById('MainContent')" +
                                                 ".contentWindow.document.getElementsByTagName('body')[0].innerHTML);");


                                         super.onPageFinished(view, url);
                                     }




                                     @Override
                                     public void onReceivedError(WebView view, int errorCode,
                                                                 String description, String failingUrl) {
                                         // 加载错误的时候会回调,在其中可做错误处理,比如再请求加载一次,或者提示404的错误页面
                                         super.onReceivedError(view, errorCode, description, failingUrl);
                                     }


                                     @Override
                                     public WebResourceResponse shouldInterceptRequest(WebView view,
                                                                                       WebResourceRequest request) {
                                         // 在每一次请求资源时,都会通过这个函数来回调
                                         return super.shouldInterceptRequest(view, request);
                                     }
                                 }
        );
    }


    public final class InJavaScriptLocalObj {
        @JavascriptInterface
        public void showSource(final String html) {
            Log.e(TAG, "htmlshowsource: " + html);
            System.out.println("====>htmlshowsource===" + html);
        }


        @JavascriptInterface
        public void showDescription(String str) {
            System.out.println("====>htmlshowdescription==" + str);
            Log.e(TAG, "htmlshowdescription: " + str);
        }


        @JavascriptInterface
        public void showJs(String str) {
            Log.e(TAG, "htmlshowjs: " + str);
            System.out.println("====>htmlshowjs==" + str);
        }
        public void Tz(String str){
            Log.e(TAG, "htmlshowTz"+"进入tz" +str);
            webView.loadUrl("javascript:document.getElementById('CreditCardNo').value='9999'");
        }
    }

拦截截图:js调用android的方法 


最后感谢【武汉-5】cokus和鱼吃肉两位大神的技术支持。
原创粉丝点击