Android WebView控件捕獲用戶輸入的信息
WebView可所謂是Android中最強大的控件之一,無所不能。
于是有這么一個需求,用戶在app之中內(nèi)嵌的WebView中輸入帳號密碼的時候,App需要捕獲已經(jīng)輸入的帳號密碼。
當(dāng)用戶輸入帳號密碼,一般情況下會進行頁面轉(zhuǎn)跳,在頁面轉(zhuǎn)跳之前執(zhí)行js腳本,通過js腳本來獲取這個帳號密碼的value值。要先獲取各個元素的class值,需要解析整個html頁面,那么我們可以重寫 onLoadResource 這個方法,代碼如下:
webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return false; } @Override public void onLoadResource(WebView view, String url) { getHtml(); Log.e("log-->", "onLoadResource-->>" + url); } @Override public void onPageFinished(WebView view, String url) { } });
上面這個方法在加載頁面資源時會調(diào)用,每一個資源(比如圖片)的加載都會調(diào)用一次。那么我們可以在這個方法里面執(zhí)行注入的js腳本
先執(zhí)行addJavascriptInterface方法,將一個java對象綁定到一個js對象中,代碼如下:
public class JavaScriptInterface { String mPasswrod; String mUsername; @JavascriptInterface public void getHTML(final String html) { if (!TextUtils.isEmpty(html)) { saveWebViewUserData.saveUserDataWebView(webview, html); } } @JavascriptInterface public void save_password(final String password) { if (!TextUtils.isEmpty(password)){ LogUtils.e("received from js. password = " + password); this.mPasswrod = password; checkData(mUsername, mPasswrod); } } @JavascriptInterface public void save_username(final String username) { if (!TextUtils.isEmpty(username)) { LogUtils.e("received from js. username = " + username); this.mUsername = username; checkData(mUsername, mPasswrod); } } } webview.addJavascriptInterface(new JavaScriptInterface(), "android"); private void getHtml() { webview.loadUrl("javascript:window.android.getHTML('<html>'+document.body.innerHTML+'</html>');"); }
那么下面這句話執(zhí)行完的結(jié)果將會返回到JavaScriptInterface中g(shù)etHTML方法里面。也就是說通過綁定,js代碼調(diào)用了java代碼,并將整個html作為返回值返回,執(zhí)行的是saveWebViewUserData.saveUserDataWebView(webview, html);
得到了包含class的html之后,就需要依次分析了,通常來說,一般輸入帳號密碼的頁面都含有 type=”password” 字樣。先判斷這個html頁面是否含有這個字樣,如果有,那么可能就是登錄頁面。
再判斷這個頁面的id,或者是classname是否包含password啦,pwd啦,或者什么其他和密碼有關(guān)的了,這個元素肯定就是密碼框了,再過濾掉頁面中其他的button,hidden,submit,checkbox等等,剩下的那一個肯定就是用戶名了;過濾代碼如下:(這里使用jsoup解析html獲取各個document,循環(huán)遍歷剔除不需要的元素)
public void saveUserDataWebView(WebView webView, String html) { Document document = Jsoup.parse(html); Elements elements = document.select("input"); boolean isContainsPassword = false; for (Element element : elements) { String type = element.attr("type"); if ("password".equals(type)) { isContainsPassword = true; break; } } if (!isContainsPassword) { return; } for (Element element : elements) { String className = element.className(); String type = element.attr("type"); webView.post(new Runnable() { @Override public void run() { LogUtils.e("this element id is = " + element.attr("id") + " type = " + type); String id = element.attr("id"); if (filterData(type, id)) { int handType = handleType(type); if (handType == NONE) { handType = handleId(id); if (handType == NONE) { handleClassName(className); } } switch (handType) { case PASSWORD: if (id==null){ }else { savePasswordById(id, webView); } break; case USERNAME: if (id==null){ }else { saveUsernameById(id, webView); } break; case NONE: break; } } } }); } } private int handleClassName(String className) { if (className == null) { return ERROR; } if (className.contains("password")) { return PASSWORD; } if (className.contains("captcha")) { return ERROR; } return USERNAME; } private boolean filterData(String type, String id) { if ("captcha".equals(type)) { return false; } else if ("login_vcode".equals(type)) { return false; } else if ("button".equals(type)) { return false; } else if ("hidden".equals(type)) { return false; } else if ("submit".equals(type)) { return false; } else if ("checkbox".equals(type)) { return false; } else if ("captcha".equals(id)) { return false; } else if ("inp_ChkCode".equals(id)) { return false; } else { return true; } } private int handleId(String id) { if (id == null) { return NONE; } if (id.contains("captcha")) { return ERROR; } if (id.contains("password")) { return PASSWORD; } if (id.contains("Phone")) { return USERNAME; } if (id.contains("username")) { return USERNAME; } if (id.contains("code")) { return ERROR; } return USERNAME; } private int handleType(String type) { if (type == null) { return NONE; } if (type.contains("tel")) { return ERROR; } if (type.contains("pwd")) { return PASSWORD; } if (type.contains("password")) { return PASSWORD; } return NONE; }
將他們倆的class id記錄下來,再次通過js代碼獲取到頁面的value值,調(diào)用java代碼保存下來。代碼如下:
private void saveUsernameById(String id, WebView webView) { webView.loadUrl("javascript:window.android.save_username(document.getElementById('" + id + "').value)"); } private void savePasswordById(String id, WebView webView) { webView.loadUrl("javascript:window.android.save_password(document.getElementById('" + id + "').value)"); }
經(jīng)過上面簡單的處理,已經(jīng)大致可以獲取到用戶輸入的帳號密碼了,經(jīng)過測試,簡單的頁面中的帳號密碼是可以獲取到的,其他復(fù)雜的(如密碼在轉(zhuǎn)跳時清空了,又傳值到其他地方進行運算的)需要再根據(jù)不同的方案來對付了。
轉(zhuǎn)跳前先獲取整個頁面的html,用jsoup獲取頁面的所有class name,遍歷各個節(jié)點,剔除無用內(nèi)容(驗證碼按鈕等),判斷密碼框在哪,剩下的可能就是帳號了,執(zhí)行js代碼獲取value值。
以上就是本文的全部內(nèi)容,希望大家喜歡。
- Android高仿微信支付密碼輸入控件
- Android自定義控件通用驗證碼輸入框的實現(xiàn)
- Android如何禁止向EditText控件中輸入內(nèi)容詳解
- Android用戶輸入自動提示控件AutoCompleteTextView使用方法
- Android 帶清除功能的輸入框控件實例詳解
- Android開發(fā)中給EditText控件添加TextWatcher監(jiān)聽實現(xiàn)對輸入字?jǐn)?shù)的限制(推薦)
- Android帶清除功能的輸入框控件EditTextWithDel
- Android輸入框控件ClearEditText實現(xiàn)清除功能
- Android實現(xiàn)EditText控件禁止輸入內(nèi)容的方法(附測試demo)
- Android自定義view實現(xiàn)輸入控件
相關(guān)文章
Android EdText編輯框禁止輸入表情符號(使用正則表達式)
這篇文章主要介紹了Android EdText編輯框禁止輸入表情符號使用正則表達式,需要的朋友可以參考下2017-06-06Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用詳解
這篇文章主要給大家介紹了關(guān)于Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用的相關(guān)資料,文中通過圖文及示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09在Ubuntu下搭建Android開發(fā)環(huán)境
對一個程序猿來說,裝好系統(tǒng)之后的第一件事,一定是搭建開發(fā)環(huán)境,已經(jīng)安裝各種開發(fā)工具,以便之后能方便順利地進行程序的開發(fā)。簡單的介紹下在Ubuntu環(huán)境下搭建Android開發(fā)環(huán)境,雖然基本上和在Windows下沒有太大差別,但有些細節(jié)上還是很值得注意的。2014-07-07SwipeLayout框架實現(xiàn)側(cè)拉刪除編輯功能
這篇文章主要為大家詳細介紹了SwipeLayout框架實現(xiàn)側(cè)拉刪除編輯功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08