Android WebView控件捕獲用戶輸入的信息
WebView可所謂是Android中最強(qiáng)大的控件之一,無所不能。
于是有這么一個需求,用戶在app之中內(nèi)嵌的WebView中輸入帳號密碼的時候,App需要捕獲已經(jīng)輸入的帳號密碼。
當(dāng)用戶輸入帳號密碼,一般情況下會進(jìn)行頁面轉(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ìn)行運(yùn)算的)需要再根據(jù)不同的方案來對付了。
轉(zhuǎn)跳前先獲取整個頁面的html,用jsoup獲取頁面的所有class name,遍歷各個節(jié)點(diǎn),剔除無用內(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編輯框禁止輸入表情符號(使用正則表達(dá)式)
這篇文章主要介紹了Android EdText編輯框禁止輸入表情符號使用正則表達(dá)式,需要的朋友可以參考下2017-06-06
Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用詳解
這篇文章主要給大家介紹了關(guān)于Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用的相關(guān)資料,文中通過圖文及示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09
在Ubuntu下搭建Android開發(fā)環(huán)境
對一個程序猿來說,裝好系統(tǒng)之后的第一件事,一定是搭建開發(fā)環(huán)境,已經(jīng)安裝各種開發(fā)工具,以便之后能方便順利地進(jìn)行程序的開發(fā)。簡單的介紹下在Ubuntu環(huán)境下搭建Android開發(fā)環(huán)境,雖然基本上和在Windows下沒有太大差別,但有些細(xì)節(jié)上還是很值得注意的。2014-07-07
SwipeLayout框架實現(xiàn)側(cè)拉刪除編輯功能
這篇文章主要為大家詳細(xì)介紹了SwipeLayout框架實現(xiàn)側(cè)拉刪除編輯功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08

