Android WebView使用,Http/Https,硬體加速等相關細節詳解
概述
在應用的開發過程中,經常遇到需要經常變化的頁面,一般針對這種頁面,我們會用WebView
來實現.如隱私條款等等.並且隨著 hybrid
的興起,webview
將會更加常用.
loadDataWithBaseURL 與 loadData
loadData
//方法原型
loadData(String data, String mimeType, String encoding)
loadData
用於載入一段html
文字,這個和loadUrl
是有區別的,
loadUrl
是根據一個url
來載入一個網頁,他們各有利弊,
參考:WebView到底該使用loadUrl還是loadData
其中loadData
使用 #、%、\、?
四種字元易出現問題.
%
會報找不到頁面錯誤,頁面全是亂碼。亂碼樣式見符件。
#
會讓你的goBack
失效,但canGoBack
是可以使用的。於是就會產生返回按鈕生效,但不能返回的情況。
\
會被當做轉義字元.
如果出現亂碼問題,需要將encoding
引數設定為utf-8
.
mimeType
,指定mineType
型別,如text/html; charset=utf-8
loadDataWithBaseURL
//方法原型
public void loadDataWithBaseURL(String baseUrl, String data,
String mimeType, String encoding, String failUrl) {
}
public void loadData(String data, String mimeType, String encoding) {
}
public void loadUrl(String url) {
}
public void loadUrl(String url,Map<Stirng,String> extraHeaders) {
}
loadDataWithBaseURL
可以指定相對根路徑,也可以指定歷史Url
。
baseUrl
相對根路徑,常見於WebView
中的超連結或者是image
元素,如使用絕對路徑傳""
即可。
比如, 我們的data
String body ="示例:這裡有個img標籤,地址是相對路徑<img src='/uploads/allimg/130923/1FP02V7-0.png' />";
如果baseUrl
沒有指定為網站域名,那麼這張圖片將顯示不出來。
常用屬性
通過mWebView.getSettings()拿到WebView的設定.
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//支援通過JS開啟新視窗
mWebView.getSettings().setSupportZoom(true);//設定是否支援縮放
mWebView.getSettings().setBuiltInZoomControls(true);//設定是否顯示縮放工具
webview.getSettings().setDisplayZoomControls(false);//設定縮放控制元件隱藏
/**http://stackoverflow.com/questions/5448841/what-do-setusewideviewport-and-setloadwithoverviewmode-precisely-do*/
webview.getSettings().setLoadWithOverviewMode(true);// loads the WebView completely zoomed out
webview.getSettings().setUseWideViewPort(true); //makes the Webview have a normal viewport (such as a normal desktop browser), while when false the webview will have a viewport constrained to its own dimensions (so if the webview is 50px*50px the viewport will be the same size)
webview.getSettings().setAllowFileAccess(true); // 允許訪問檔案
mWebView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);//一般很少會用到這個,用WebView元件顯示普通網頁時一般會出現橫向滾動條,這樣會導致頁面檢視起來非常不方便。//LayoutAlgorithm是一個列舉,用來控制html的佈局,總共有三種類型://NORMAL:正常顯示,沒有渲染變化。//SINGLE_COLUMN:把所有內容放到WebView元件等寬的一列中。//NARROW_COLUMNS:可能的話,使所有列的寬度不超過螢幕寬度。
mWebView.getSettings().setDefaultFontSize(18);//設定預設的字型大小,預設為16,有效值區間在1-72之間。
//若要考慮相容3.0以下版本則:
/**http://jingyan.baidu.com/article/48b37f8d0b918e1a646488ec.html*/
if(android.os.Build.VERSION.SDK_INT>=11){
this.getSettings().setDisplayZoomControls(false);
}else{
this.setZoomControlHide(this);
}
//Android 3.0(11) 以下使用以下方法:
//利用java的反射機制
public void setZoomControlHide(View view) {
try {
Class webview = Class.forName("android.webkit.WebView");
Method method = webview.getMethod("getZoomButtonsController");
zoomController = (ZoomButtonsController) method.invoke(this, null);
} catch (Exception e) {
e.printStackTrace();
}
}
-WebView
連結在WebView
內部開啟,而非呼叫系統瀏覽器的方法.
重寫
shouldOverrideUrlLoading
,並且return true
;
WebViewClient與WebChromeClient
WebViewClient
主要幫助WebView
處理各種通知、請求事件的,比如:
onLoadResource
onPageStart
onPageFinish
onReceiveError //錯誤,可以在此顯示一個錯誤頁面
onReceivedHttpAuthRequest
WebChromeClient
主要輔助WebView
處理Javascript
的對話方塊、網站圖示、網站title、載入進度等,比如:
onCloseWindow//關閉WebView
onCreateWindow()
onJsAlert //WebView上alert無效,需要定製WebChromeClient處理彈出
onJsPrompt
onJsConfirm
onProgressChanged
onReceivedIcon
onReceivedTitle//獲取title
如果你的WebView
只是用來處理一些v
的頁面內容,只用WebViewClient
就行了,如果需要更豐富的處理效果,比如JS、進度條等,就要用到WebChromeClient
比如,我們想要在webview
中相應Email
,tel
的Intent
,我們繼承WebViewClient
並重寫shouldOverrideUrlLoading
方法
public abstract class WebClient extends android.webkit.WebViewClient {
private final WeakReference<Context> contextWeakReference;
public WebClient(Context context) {
contextWeakReference = new WeakReference<>(context);
}
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("mailto:") || url.startsWith("geo:") || url.startsWith("tel:")) {
final Context context = contextWeakReference.get();
if (context != null) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(intent);
view.reload();
}
} else {
reloadUrl(view, url);
}
return true;
}
public abstract void reloadUrl(WebView view, String url);
}
onPageFinished:
onReceivedTitle()
方法在goback()
之後無效。
這時,我們可以使用onPageFinished(WebView view, String url)
方法來實現返回及時重新整理標題
WebView mWebView = (WebView) findViewById(R.id.mwebview);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
setTitle(view.getTitle());
}
});
處理https請求
android 預設是不處理https請求的,請求https會顯示空白。
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
//default
// handler.cancel();
// handler.handleMessage(null);
}
});
cookies 和歷史紀錄
比如在某些場景中,我們的使用者在客戶端 登入了,要在 網頁中也保持登入狀態,則可以使用cookies
來實現,不過需要伺服器端配合完成.
//cookies清理
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
CookieManager.getInstance().removeSessionCookie();
//清理cache 和歷史記錄
webView.clearCache(true);
webView.clearHistory();
檔案下載
我們都知道WebView
中 有這麼一個方法
// 方法原型
public void setDownloadListener(DownloadListener listener){}
那麼我們只需要自定義一個DownloadListener
即可
public class WebViewDownLoadListener implements DownloadListener {
@Override public void onDownloadStart(String url, String userAgent, String contentDisposition,
String mimetype, long contentLength) {
// 引數含義: url :檔案現在連結
// userAgent : 使用者瀏覽器代理
// contentDisposition : 檔案描述符
// mimetype : 檔案的型別
// contentLength : 檔案的長度
}
}
硬體加速
Android自帶的WebView非常的雞肋,比如不能開啟pdf,播放視屏也只能開啟硬體加速才能支援,但是這裡也存在著 問題,比如,在某些機型上會崩潰
這裡的做法是在 onPageStart
中關閉硬體加速,在onPageFinish
中開啟硬體加速
HTTP/HTTPS混合
在應用全面適配https
後發現 某些圖片不再顯示了,通過抓包工具發現,是 Https
頁面中包含了 Http
的 圖片連結。使用混合模式即可。
//http,https 混合使用
// http://developer.android.com/reference/android/webkit/WebSettings.html#setMixedContentMode(int)
if (Build.VERSION.SDK_INT >= 21) {
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}