Android-WebView詳解

WebSettings

WebSettings webSettings = mWebView.getSettings();
webview.requestFocusFromTouch();//支持獲取手勢焦點,輸入用戶名、密碼或其他
setJavaScriptEnabled(true);//支持js
setPluginsEnabled(true);//支持插件 
webSettings.setRenderPriority(RenderPriority.HIGH);//提高渲染的優先級設置自適應屏幕,兩者合用
setUseWideViewPort(true);//將圖片調整到適合webview的大小
setLoadWithOverviewMode(true);// 縮放至屏幕的大小
setSupportZoom(true);//支持縮放,默認爲true。是下面那個的前提。
setBuiltInZoomControls(true);//設置內置的縮放控件。//若上面是false,則該WebView不可縮放,這個不管設置什麼都不能縮放。
setDisplayZoomControls(false);//隱藏原生的縮放控件setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);//支持內容重新佈局 supportMultipleWindows();//多窗口 
setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//關閉webview中緩存 
setAllowFileAccess(true);//設置可以訪問文件 
setNeedInitialFocus(true);//當webview調用requestFocus時爲webview設置節點setJavaScriptCanOpenWindowsAutomatically(true);//支持通過JS打開新窗口 setLoadsImagesAutomatically(true);//支持自動加載圖片
setDefaultTextEncodingName("utf-8");//設置編碼格式

關於緩存
緩存模式
LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據
LOAD_DEFAULT: (默認)根據cache-control決定是否從網絡上取數據。
LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據.
LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。

  • 結合使用(離線加載):
    if (NetStatusUtil.isConnected(getApplicationContext())) {
            webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
    //根據cache-control決定是否從網絡上取數據。
    }else {
           webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    //沒網,則從本地獲取,即離線加載
    }
    webSettings.setDomStorageEnabled(true);// 開啓 DOM storage API 功能webSettings.setDatabaseEnabled(true);//開啓 database storage API 功能
    webSettings.setAppCacheEnabled(true);//開啓 Application Caches 功能
    String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
    webSettings.setAppCachePath(cacheDirPath);//設置  Application Caches 緩存目錄
    **注意:**每個 Application 只調用一次 WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()
    加載方式
    **加載一個網頁:**
    webView.loadUrl("[http://www.google.com/](http://www.google.com/)");
    **加載apk包中的一個html頁面**
    webView.loadUrl("file:///android_asset/test.html");
    **加載手機本地的一個html頁面的方法:**
    webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
    WebViewClient
    **WebViewClient就是幫助WebView處理各種通知、請求事件的。**
    打開網頁時不調用系統瀏覽器, 而是在本WebView中顯示:
    mWebView.setWebViewClient(new WebViewClient(){
    @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
              view.loadUrl(url);returntrue;
            }
    });
    

     

  • WebViewClient方法

WebViewClient mWebViewClient =new WebViewClient(){
    shouldOverrideUrlLoading(WebView view,String url)  最常用的,比如上面的。
//在網頁上的所有加載都經過這個方法,這個函數我們可以做很多操作。
//比如獲取url,查看url.contains(“add”),進行添加操作    
shouldOverrideKeyEvent(WebView view, KeyEvent event)
//重寫此方法才能夠處理在瀏覽器中的按鍵事件。    
onPageStarted(WebView view,String url, Bitmap favicon)
//這個事件就是開始載入頁面調用的,我們可以設定一個loading的頁面,告訴用戶程序在等待網絡響應。    
onPageFinished(WebView view,String url)
//在頁面加載結束時調用。同樣道理,我們可以關閉loading 條,切換程序動作。    onLoadResource(WebView view,String url)// 在加載頁面資源時會調用,每一個資源(比如圖片)的加載都會調用一次。    
onReceivedError(WebView view, int errorCode,String description,String failingUrl)
// (報告錯誤信息)    
doUpdateVisitedHistory(WebView view,String url, boolean isReload)
//(更新歷史記錄)    
onFormResubmission(WebView view, Message dontResend, Message resend)
//(應用程序重新請求網頁數據)    
onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler,String host,String realm)
//(獲取返回信息授權請求)    
onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
//重寫此方法可以讓webview處理https請求。    
onScaleChanged(WebView view, float oldScale, float newScale)
// (WebView發生改變時調用)    
onUnhandledKeyEvent(WebView view, KeyEvent event)
//(Key事件未被加載時調用)
}
**將上面定義的WebViewClient設置給WebView:**
webView.setWebViewClient(mWebViewClient);

WebChromeClient

**WebChromeClient是輔助WebView處理Javascript的對話框,網站圖標,網站title,加載進度等 :**
方法中的代碼都是由Android端自己處理。
WebChromeClient mWebChromeClient =new WebChromeClient() {
//獲得網頁的加載進度,顯示在右上角的TextView控件中
@Override public void onProgressChanged(WebView view,int newProgress) 
{
if (newProgress <100) {
            String progress = newProgress +"%";        
}else {        
}    
}
//獲取Web頁中的title用來設置自己界面中的title
//當加載出錯的時候,比如無網絡,這時onReceiveTitle中獲取的標題爲 找不到該網頁,
//因此建議當觸發onReceiveError時,不要使用獲取到的title
@Override public void onReceivedTitle(WebView view, String title) {
        MainActivity.this.setTitle(title);
}
@Override public void onReceivedIcon(WebView view, Bitmap icon) {
//    
}
@Override public boolean onCreateWindow(WebView view,boolean isDialog,boolean isUserGesture, Message resultMsg) {
//return true;    
}
@Override public void onCloseWindow(WebView window) {    
}
//處理alert彈出框,html 彈框的一種方式
@OverridepublicbooleanonJsAlert(WebView view, String url, String message, JsResult result) {
//return true;    
}
//處理confirm彈出框
@Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult            result) {//returntrue;    }//處理prompt彈出框@OverridepublicbooleanonJsConfirm(WebView view, String url, String message, JsResult result) {//returntrue;
}
};
**同樣,將上面定義的WebChromeClient設置給WebView:**
webView.setWebChromeClient(mWebChromeClient);
調用JS代碼
WebSettings webSettings = mWebView .getSettings();  
webSettings.setJavaScriptEnabled(true);  mWebView.addJavascriptInterface(newInsertObj(),"jsObj");
**上面這是前提!!!**
然後實現上面的類,這個類提供了四個方法,註釋的非常清楚。
class Insert Object ends Object {
//給html提供的方法,js中可以通過:var str = window.jsObj.HtmlcallJava(); 獲取到
@Javascript Interface public String HtmlcallJava()
 {
return"Html call Java";   
 }
//給html提供的有參函數 : window.jsObj.HtmlcallJava2("IT-homer blog"
);
@Javascript Interface public String HtmlcallJava2(final String param) {
return"Html call Java : " + param;    
}
//Html給我們提供的函數
@Javascript Interface public void JavacallHtml() {        
runOnUiThread(new Runnable() {
@Override public void run() {
//這裏是調用方法                
mWebView.loadUrl("javascript: showFromHtml()");                
Toast.makeText(Html5Activity.this,"clickBtn", Toast.LENGTH_SHORT).show();
            }
        });
    }
//Html給我們提供的有參函數
@JavascriptInterfacepublicvoidJavacallHtml2(final String param) 
{
        runOnUiThread(new Runnable() {
                @Override public void run() {
                mWebView.loadUrl("javascript: showFromHtml2('IT-homer blog')"); 
               Toast.makeText(Html5Activity.this,"clickBtn2", Toast.LENGTH_SHORT).show();
                }
        });
    }
}

Android 調用js有個漏洞:
http://blog.csdn.net/leehong2005/article/details/11808557
WebView的方法
前進、後退
goBack()//後退goForward()//前進goBackOrForward(intsteps)//以當前的index爲起始點前進或者後退到歷史記錄中指定的steps, 如果steps爲負數則爲後退,正數則爲前進canGoForward()//是否可以前進canGoBack()//是否可以後退
清除緩存數據:
clearCache(true);//清除網頁訪問留下的緩存,由於內核緩存是全局的因此這個方法不僅僅針對webview而是針對整個應用程序.clearHistory()//清除當前webview訪問的歷史記錄,只會webview訪問歷史記錄裏的所有記錄除了當前訪問記錄.clearFormData()//這個api僅僅清除自動完成填充的表單數據,並不會清除WebView存儲到本地的數據。
WebView的狀態:
onResume()//激活WebView爲活躍狀態,能正常執行網頁的響應onPause()//當頁面被失去焦點被切換到後臺不可見狀態,需要執行onPause動過, onPause動作通知內核暫停所有的動作,比如DOM的解析、plugin的執行、JavaScript執行。pauseTimers()//當應用程序被切換到後臺我們使用了webview, 這個方法不僅僅針對當前的webview而是全局的全應用程序的webview,它會暫停所有webview的layout,parsing,javascripttimer。降低CPU功耗。resumeTimers()//恢復pauseTimers時的動作。destroy()//銷燬,關閉了Activity時,音樂或視頻,還在播放。就必須銷燬。
但是注意:
webview調用destory時,webview仍綁定在Activity上.這是由於自定義webview構建時傳入了該Activity的context對象,因此需要先從父容器中移除webview,然後再銷燬webview:
rootLayout.removeView(webView);webView.destroy();
判斷WebView是否已經滾動到頁面底端 或者 頂端:
getScrollY() //方法返回的是當前可見區域的頂端距整個頁面頂端的距離,也就是當前內容滾動的距離.
getHeight()或者getBottom() //方法都返回當前WebView這個容器的高度
getContentHeight()返回的是整個html的高度,但並不等同於當前整個頁面的高度,因爲WebView有縮放功能,所以當前整個頁面的高度實際上應該是原始html的高度再乘上縮放比例.因此,更正後的結果,準確的判斷方法應該是:
if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {//已經處於底端 }if(webView.getScrollY() ==0){//處於頂端
}
避免WebView內存泄露的一些方式
1.可以將 Webview 的 Activity 新起一個進程,結束的時候直接System.exit(0);退出當前進程;
啓動新進程,主要代碼: AndroidManifest.xml 配置文件代碼如下
在新進程中啓動 Activity ,裏面傳了 一個 Url:
Intent intent =newIntent("com.lyl.boon.ui.activity.htmlactivity");Bundle bundle =newBundle(); bundle.putString("url", gankDataEntity.getUrl()); intent.putExtra("bundle",bundle);
startActivity(intent);
然後在 Html5Activity 的onDestory() 最後加上 System.exit(0); 殺死當前進程。
2.不能在xml中定義 Webview ,而是在需要的時候創建,並且Context使用 getApplicationgContext(),如下代碼:
LinearLayout.LayoutParamsparams =new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); mWebView =new WebView(getApplicationContext()); mWebView.setLayoutParams(params);
mLayout.addView(mWebView);

3.在 Activity 銷燬的時候,可以先讓 WebView 加載null內容,然後移除 WebView,再銷燬 WebView,最後置空。
代碼如下:
@OverrideprotectedvoidonDestroy() {if (mWebView !=null) { mWebView.loadDataWithBaseURL(null,"","text/html","utf-8",null); mWebView.clearHistory(); ((ViewGroup) mWebView.getParent()).removeView(mWebView); mWebView.destroy(); mWebView =null; }super.onDestroy();
}
返回鍵
返回上一次瀏覽的頁面
public booleanonKeyDown(int keyCode, KeyEventevent) {if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) { mWebView.goBack();returntrue; }return super.onKeyDown(keyCode,event);
}
有一個非常不錯的 Html5Activity 加載類帖出來:

public class Html5Activity extends AppCompatActivity { 
private String mUrl;
private LinearLayout mLayout;
private WebView mWebView;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);        
setContentView(R.layout.activity_web);      
 Bundle bundle = getIntent().getBundleExtra("bundle");        
mUrl = bundle.getString("url");        
Log.d("Url:", mUrl);        
mLayout = (LinearLayout) findViewById(R.id.web_layout);        
LinearLayout.LayoutParams params =new 
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);        
mWebView =new WebView(getApplicationContext());        
mWebView.setLayoutParams(params);        
mLayout.addView(mWebView);       
WebSettings mWebSettings = mWebView.getSettings();        
mWebSettings.setSupportZoom(true);        
mWebSettings.setLoadWithOverviewMode(true);        
mWebSettings.setUseWideViewPort(true);        
mWebSettings.setDefaultTextEncodingName("utf-8");        
mWebSettings.setLoadsImagesAutomatically(true);
//調用JS方法.安卓版本大於17,加上註解 @JavascriptInterface        
mWebSettings.setJavaScriptEnabled(true);        
saveData(mWebSettings);        
newWin(mWebSettings);        
mWebView.setWebChromeClient(webChromeClient);        
mWebView.setWebViewClient(webViewClient);        
mWebView.loadUrl(mUrl);    
}
/**    * 多窗口的問題    */
private void newWin(WebSettings mWebSettings) {
    //html中的_bank標籤就是新建窗口打開,有時會打不開,需要加以下
    //然後 複寫 WebChromeClient的onCreateWindow方法        
    mWebSettings.setSupportMultipleWindows(true);        
    mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
}
/**    * HTML5數據存儲    */
private void saveData(WebSettings mWebSettings) {
    //有時候網頁需要自己保存一些關鍵數據,Android WebView 需要自己設置        
    mWebSettings.setDomStorageEnabled(true);        
    mWebSettings.setDatabaseEnabled(true);        
    mWebSettings.setAppCacheEnabled(true);

}

....

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章