webview總結
一.webview載入白屏或者載入表格介面無法顯示
什麼都別管,先把這坨設定丟上去
pullToRefreshWebView.getSettings().setBlockNetworkImage(false); pullToRefreshWebView.getSettings().setJavaScriptEnabled(true); pullToRefreshWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); pullToRefreshWebView.setHorizontalScrollBarEnabled(false); pullToRefreshWebView.setHorizontalScrollbarOverlay(false); pullToRefreshWebView.getSettings().setBuiltInZoomControls(true); pullToRefreshWebView.getSettings().setUseWideViewPort(true); pullToRefreshWebView.getSettings().setLoadWithOverviewMode(true); pullToRefreshWebView.getSettings().setSavePassword(false); pullToRefreshWebView.getSettings().setSupportZoom(false); pullToRefreshWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); pullToRefreshWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); pullToRefreshWebView.getSettings().setAppCacheEnabled(true); pullToRefreshWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); pullToRefreshWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); pullToRefreshWebView.getSettings().setAllowFileAccess(true); pullToRefreshWebView.getSettings().setSaveFormData(false); pullToRefreshWebView.getSettings().setLoadsImagesAutomatically(true); pullToRefreshWebView.getSettings().setDomStorageEnabled(true);
二.webview與JS的互動
1. 呼叫js的方法,前提設定.setJavaScriptEnabled(true); 必須的
兩種方式:第一種通過webview.loadurl(),第二種mWebView.evaluateJavascript(); 兩種方法卻別在於第一種會重新整理介面,第二種只能在4.4以後使用,並且可以獲取JS的返回值! loadurl()具體使用
String open_id = SpUtils.getString(this, Constant.OPEN_ID, ""); String userNmae = SpUtils.getString(this, Constant.USER_NAME, ""); String userHead = SpUtils.getString(this, Constant.USER_HEAD, ""); userinf_Url = "javascript:appLogin('" + open_id + "'," + "'" + userHead + "','" + userNmae + "')";
appLogin是JS的方法名,open_id ,userHead ,userNmae 是相關引數! 也就是將整個方法拼接成一個字串 然後再webview載入完畢之後再去呼叫,pagefinished方法!
@Override public void onPageFinished(WebView view, String url) { web.post(new Runnable() { @Override public void run() { web.loadUrl(userinf_Url); } }); }
在某些動態獲取值的時候,在移動端處理完資料之後需要再次傳遞,重新載入一次webview.reload()接可以再次呼叫方法! 也就是loadurl方法在呼叫JS方法的時候每次都需要重新整理介面 方法二此方法需要注意只有在4.4以上才能使用 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { mWebView.evaluateJavascript("javascript:appLogin()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { LoginBean loginBean =MyApplicaytion,getInstance,gson.fromJson(value,LoginBean.class); //這個地方處理返回值 } });
}
載入本地html呼叫本地方法就不在介紹,網上很多!
3.JS呼叫本地方法
通過WebView的addJavascriptInterface()進行物件對映
1.定義一個與JS物件有對映關係的Android類:AndroidtoJs
public class AndroidtoJs extends Object { // 定義JS需要呼叫的方法 // 被JS呼叫的方法必須加入@JavascriptInterface註解 @JavascriptInterface public void login() { //此方法就直接跳轉到 購買成功的介面,同時還有另外一個方法判斷是否需要關閉當前的介面 if (!Application.iwxapi.isWXAppInstalled()) { Toast.makeText(MainActivity.this, "請先安裝微信", Toast.LENGTH_SHORT).show(); } else { final SendAuth.Req req = new SendAuth.Req(); req.scope = "snsapi_userinfo"; req.state = "wechat_sdk_demo_test"; Application.iwxapi.sendReq(req); } } @JavascriptInterface public String toString() { return "androids";//JS端通過該引數呼叫方法 } }
載入本地js方法, html檔案放在assets下
mWebView.loadUrl("file:///android_asset/htmls_two.html"); way ="javascript:wxjswap"+"('"+url+"')";
JS端程式碼
function 方法名(){ // 由於物件對映,所以呼叫test物件等於呼叫Android對映的物件 androids.login(); //注意此處定義的Androids和移動端定義的要一樣 }
上訴互動方是僅僅是在專案中使用到的!更多方式參考這篇文章
https://www.jianshu.com/p/345f4d8a5cfa三webciew廣告攔截
webview載入介面的時候會出現很多小廣告,有運營商的也有一些亂七八糟的!最簡單最暴力的方式就是隻要不是我們專案域
名下的統統攔截!
具體方式如下:
首先定義一個數組
<string-array name="legal_domain"> <item>skin.se.360.cn</item> <item>m.gooooal.com</item> </string-array>
把專案更中用到的所有域名全部寫上去!是全部包括圖片啥的,如果有一個用到的域名沒有寫上去可能會導致介面載入不出 來,也可以在通過檢視載入的所有域名來看有沒有被漏掉的! 攔截工具類
public class ADFilterTool { /** * 正則表示式 */ private static String PATTERN = " "; static { initPattern(); } /** * 初始化pattern */ private static void initPattern() { PATTERN = getPatternStr(); } /** * 判斷url的域名是否合法 * <p> * 域名是否合法:自己專案中使用的域名,為合法域名;其它域名皆為不合法域名,進行遮蔽 * * @param url * @return */ public static boolean hasNotAd(String url) { if (TextUtils.isEmpty(url)) { LogUtils.e("攔截判斷裡面獲取到的是空的"); return false; } if (TextUtils.isEmpty(PATTERN)) { initPattern(); } if (Pattern.matches(PATTERN, url)) { return true; } return false; } /** * 拼接正則表示式 * * @return */ private static String getPatternStr() { String[] adUrls = Application.getInstance().getResources().getStringArray(R.array.legal_domain); if (null != adUrls && adUrls.length > 0) { StringBuffer sb = new StringBuffer("^(https|http)://.*("); for (String a : adUrls) { if (null != a && a.length() > 0) { sb.append(a).append("|"); } } return sb.substring(0, sb.length() - 1) + ").*"; } return null; } }
hasNotAd方法裡面可以看到所有載入的域名,當然也可以通過webview的shouldInterceptRequest()方法
具體使用在webview的shouldInterceptRequest方法呼叫
@Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if (ADFilterTool.hasNotAd(url)) { return super.shouldInterceptRequest(view, url); } else { return new WebResourceResponse(null, null, null); } }
上訴方法完美的解決了專案當中的廣告頁面!
四:webview重定向,以及地址中包含alipay,weixin等敏感欄位時無法載入介面的處理方法!
我自己的專案中有些直接出現了alipays,weixin 有些則是alipayqr等相關字眼,載入的地址中包含這些欄位時Webview就會無
法載入!,解決方案就是通過重定向到瀏覽器當中去開啟這些介面!
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { LogUtils.e("跳轉連結:" + url); String newUrl = ""; if (url.contains("alipayqr")){ newUrl = url.replace("alipayqr", "alipays"); } LogUtils.e("修改後的跳轉連結" + newUrl); if(newUrl.startsWith("alipays://")|| url.contains("weixin://") ){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); if (url.contains("weixin://")){ intent.setData(Uri.parse(url)); }else { intent.setData(Uri.parse(newUrl)); } try { startActivity(intent); }catch (Exception e){ ToasUtils.showToast("充值失敗,請聯絡客服"); } return true; } return super.shouldOverrideUrlLoading(view, url); }
五。webview自定義報錯介面
載入頁面出錯的時候webview原生報錯很醜,有些情況下還會出現域名當這些資訊我們不想直接向客戶展示的時候就需要自
定義報錯介面!
onReceivedError();通過這個方法來進行處理
@TargetApi(Build.VERSION_CODES.M) @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { view.removeAllViews(); Log.e("log","報錯拉"); rlError.setVisibility(View.VISIBLE);//自定義的報錯介面 view.loadUrl("about:blank"); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return; } Log.e("log","報錯拉"); rlError.setVisibility(View.VISIBLE); view.removeAllViews(); view.loadUrl("about:blank"); }
注意如果不加上view.loadUrl("about:blank");這行程式碼的話,webview的原生報錯介面很多情況下還是會一閃而過!