編輯:關於Android編程
WebView可所謂是Android中最強大的控件之一,無所不能。
於是有這麼一個需求,用戶在app之中內嵌的WebView中輸入帳號密碼的時候,App需要捕獲已經輸入的帳號密碼。
當用戶輸入帳號密碼,一般情況下會進行頁面轉跳,在頁面轉跳之前執行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) {
}
});
上面這個方法在加載頁面資源時會調用,每一個資源(比如圖片)的加載都會調用一次。那麼我們可以在這個方法裡面執行注入的js腳本
先執行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>');");
}
那麼下面這句話執行完的結果將會返回到JavaScriptInterface中getHTML方法裡面。也就是說通過綁定,js代碼調用了java代碼,並將整個html作為返回值返回,執行的是saveWebViewUserData.saveUserDataWebView(webview, html);
得到了包含class的html之後,就需要依次分析了,通常來說,一般輸入帳號密碼的頁面都含有 type=”password” 字樣。先判斷這個html頁面是否含有這個字樣,如果有,那麼可能就是登錄頁面。
再判斷這個頁面的id,或者是classname是否包含password啦,pwd啦,或者什麼其他和密碼有關的了,這個元素肯定就是密碼框了,再過濾掉頁面中其他的button,hidden,submit,checkbox等等,剩下的那一個肯定就是用戶名了;過濾代碼如下:(這裡使用jsoup解析html獲取各個document,循環遍歷剔除不需要的元素)
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值,調用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)");
}
經過上面簡單的處理,已經大致可以獲取到用戶輸入的帳號密碼了,經過測試,簡單的頁面中的帳號密碼是可以獲取到的,其他復雜的(如密碼在轉跳時清空了,又傳值到其他地方進行運算的)需要再根據不同的方案來對付了。
轉跳前先獲取整個頁面的html,用jsoup獲取頁面的所有class name,遍歷各個節點,剔除無用內容(驗證碼按鈕等),判斷密碼框在哪,剩下的可能就是帳號了,執行js代碼獲取value值。
以上就是本文的全部內容,希望大家喜歡。
Android Studio Share Project On Github
在Android Studio上將項目導入Github上: Enable Version Control Integration... 2.選擇Git,點擊
android動畫Animation
首先我們要知道一共有哪幾種動畫,這個面試有可能被問哦^_^。 變換動畫(透明度、縮放、平移、旋轉)、逐幀動畫、布局動畫和屬性動畫一、變換動畫我們可以通過XML文件設置動畫
自定義SwipeLayout實現側滑菜單
先看 SwipeLayout的效果圖圖太多了,我這只上傳一張,想看 listview和GridView效果的,和想看源碼的 —> GitHub怎麼實現後
android-----滑動沖突解決案例
之前的幾篇博客,我測試了View事件分發機制中的一些知識點,我們理解事件分發機制的目的就是為了能夠更好了知道View中事件的傳遞過程進而能夠對於滑動沖突有針對性的解決措施