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'");
}
}
//實驗請開啟網路連線許可權
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的方法