1. 程式人生 > >Android Webview Js互動遇到的坑!!!

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

最近研究了一下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和魚吃肉兩位大神的技術支援。