Android WebView詳解(一):相關API介紹

相關API 介紹

下面主要介紹一下下面幾個APIcss

  • WebView
  • WebSettings
  • WebViewClient
  • WebChromeClient

WebView

  • 基本APIhtml

    // 獲取當前頁面的URL
      public String getUrl();
    
      // 獲取當前頁面的原始URL(重定向後可能當前url不一樣)
      // 就是http headers的Referer參數,loadUrl時爲null
      public String getOriginalUrl();
    
      // 獲取當前頁面的標題
      public String getTitle();
    
      // 獲取當前頁面的favicon
      public Bitmap getFavicon();
    
      // 獲取當前頁面的加載進度
      public int getProgress();
    
      // 通知WebView內核網絡狀態
      // 用於設置JS屬性`window.navigator.isOnline`和產生HTML5事件`online/offline`
      public void setNetworkAvailable(boolean networkUp)
    
      // 設置初始縮放比例
      public void setInitialScale(int scaleInPercent);
  • 加載網頁相關APIandroid

    // 加載URL指定的網頁
      public void loadUrl(String url);
    
      // 攜帶http headers加載URL指定的網頁
      public void loadUrl(String url, Map<String, String> additionalHttpHeaders);
    
      // 使用POST請求加載指定的網頁
      public void postUrl(String url, byte[] postData);
    
      // 從新加載當前網頁
      public void reload();
    
      // 加載內容
      public void loadData(String data, String mimeType, String encoding);
    
      // 使用baseUrl加載內容
      public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl);
  • JavaScript 相關web

    // 注入Javascript對象
      public void addJavascriptInterface(Object object, String name);
    
      // 移除已注入的Javascript對象,下次加載或刷新頁面時生效
      public void removeJavascriptInterface(String name);
    
      // 對傳入的JS表達式求值,經過resultCallback返回結果
      // 此函數添加於API19,必須在UI線程中調用,回調也將在UI線程
      public void evaluateJavascript(String script, ValueCallback<String> resultCallback)
  • 導航相關ajax

    // 複製一份BackForwardList
      public WebBackForwardList copyBackForwardList();
    
      // 是否可後退
      public boolean canGoBack();
    
      // 是否可前進
      public boolean canGoForward();
    
      // 是否可前進/後退steps頁,大於0表示前進小於0表示後退
      public boolean canGoBackOrForward(int steps);
    
      // 後退一頁
      public void goBack();
    
      // 前進一頁
      public void goForward();
    
      // 前進/後退steps頁,大於0表示前進小於0表示後退
      public void goBackOrForward(int steps);
    
      // 清除當前webview訪問的歷史記錄
      public void clearHistory();
  • 網頁查找相關算法

    // 設置網頁查找結果回調
      public void setFindListener(FindListener listener);
    
      // 異步執行查找網頁內包含的字符串並設置高亮,查找結果會回調.
      public void findAllAsync (String find);
    
      // 查找下一個匹配的字符串
      public void findNext (boolean forward);
    
      // 清除網頁查找的高亮匹配字符串
      public void clearMatches();
  • 保存網頁/翻頁/縮放數據庫

    // 保存網頁(.html)到指定文件
      public void saveWebArchive(String filename);
    
      // 保存網頁(.html)到文件
      public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback);
    
      // 上翻一頁,即向上滾動WebView高度的一半
      public void pageUp(boolean top);
    
      // 下翻一頁,即向下滾動WebView高度的一半
      public void pageDown(boolean bottom);
    
      // 縮放
      public void zoomBy(float factor);
    
      // 放大
      public boolean zoomIn();
    
      // 縮放
      public boolean zoomOut();
  • others緩存

    // 清除網頁緩存,因爲內核緩存是全局的所以這個方法不只僅針對webview而是針對整個應用程序
      public void clearCache(boolean includeDiskFiles);
    
      // 清除自動完成填充的表單數據
      public void clearFormData();
    
      // 清除SSL偏好
      public void clearSslPreferences();
    
      // 查詢文檔中是否有圖片,查詢結果將被髮送到msg.getTarget()
      // 若是包含圖片,msg.arg1 爲1,不然爲0
      public void documentHasImages(Message msg);
    
      // 請求最近輕叩(tapped)的 錨點/圖像 元素的URL,查詢結果將被髮送到msg.getTarget()
      // msg.getData()中的url是錨點的href屬性,title是錨點的文本,src是圖像的src
      public void requestFocusNodeHref(Message msg);
    
      // 請求最近觸摸(touched)的 圖像元素的URL,查詢結果將被髮送到msg.getTarget()
    
      // msg.getData()中的url是圖像連接
      public void requestImageRef(Message msg) 
    
    
      // 清除證書請求偏好,添加於API21
      // 在WebView收到`android.security.STORAGE_CHANGED` Intent時會自動清除
      public static void clearClientCertPreferences(Runnable onCleared)
    
      // 開啓網頁內容(js,css,html...)調試模式,添加於API19
      public static void setWebContentsDebuggingEnabled(boolean enabled)

WebSetting

在android中專門經過WebSettings來設置WebView的一些屬性、狀態等。在建立WebView時, // 系統有一個默認的設置,咱們可以經過WebView.getSettings來獲得這個設置: // WebSettings和WebView都在同一個生命週期中存在。當WebView被銷燬後。假設再使用WebSettings,則會拋出異常。安全

WebSettings settings = web.getSettings();

// 存儲(storage)
// 啓用HTML5 DOM storage API,默認值 false
settings.setDomStorageEnabled(true); 
// 啓用Web SQL Database API,這個設置會影響同一進程內的全部WebView,默認值 false
// 此API已不推薦使用,參考:https://www.w3.org/TR/webdatabase/
settings.setDatabaseEnabled(true);  
// 啓用Application Caches API,必需設置有效的緩存路徑才能生效,默認值 false
// 此API已廢棄,參考:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Using_the_application_cache
settings.setAppCacheEnabled(true); 
settings.setAppCachePath(context.getCacheDir().getAbsolutePath());

// 定位(location)
settings.setGeolocationEnabled(true);

// 是否保存表單數據
settings.setSaveFormData(true);
// 是否當webview調用requestFocus時爲頁面的某個元素設置焦點,默認值 true
settings.setNeedInitialFocus(true);  

// 是否支持viewport屬性,默認值 false
// 頁面經過`<meta name="viewport" ... />`自適應手機屏幕
settings.setUseWideViewPort(true);
// 是否使用overview mode加載頁面,默認值 false
// 當頁面寬度大於WebView寬度時,縮小使頁面寬度等於WebView寬度
settings.setLoadWithOverviewMode(true);
// 佈局算法
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);

// 是否支持Javascript,默認值false
settings.setJavaScriptEnabled(true); 
// 是否支持多窗口,默認值false
settings.setSupportMultipleWindows(false);
// 是否可用Javascript(window.open)打開窗口,默認值 false
settings.setJavaScriptCanOpenWindowsAutomatically(false);

// 資源訪問
settings.setAllowContentAccess(true); // 是否可訪問Content Provider的資源,默認值 true
settings.setAllowFileAccess(true);    // 是否可訪問本地文件,默認值 true
// 是否容許經過file url加載的Javascript讀取本地文件,默認值 false
settings.setAllowFileAccessFromFileURLs(false);  
// 是否容許經過file url加載的Javascript讀取所有資源(包括文件,http,https),默認值 false
settings.setAllowUniversalAccessFromFileURLs(false);

// 資源加載
settings.setLoadsImagesAutomatically(true); // 是否自動加載圖片
settings.setBlockNetworkImage(false);       // 禁止加載網絡圖片
settings.setBlockNetworkLoads(false);       // 禁止加載全部網絡資源

// 縮放(zoom)
settings.setSupportZoom(true);          // 是否支持縮放
settings.setBuiltInZoomControls(false); // 是否使用內置縮放機制
settings.setDisplayZoomControls(true);  // 是否顯示內置縮放控件

// 默認文本編碼,默認值 "UTF-8"
settings.setDefaultTextEncodingName("UTF-8");
settings.setDefaultFontSize(16);        // 默認文字尺寸,默認值16,取值範圍1-72
settings.setDefaultFixedFontSize(16);   // 默認等寬字體尺寸,默認值16
settings.setMinimumFontSize(8);         // 最小文字尺寸,默認值 8
settings.setMinimumLogicalFontSize(8);  // 最小文字邏輯尺寸,默認值 8
settings.setTextZoom(100);              // 文字縮放百分比,默認值 100

// 字體
settings.setStandardFontFamily("sans-serif");   // 標準字體,默認值 "sans-serif"
settings.setSerifFontFamily("serif");           // 襯線字體,默認值 "serif"
settings.setSansSerifFontFamily("sans-serif");  // 無襯線字體,默認值 "sans-serif"
settings.setFixedFontFamily("monospace");       // 等寬字體,默認值 "monospace"
settings.setCursiveFontFamily("cursive");       // 手寫體(草書),默認值 "cursive"
settings.setFantasyFontFamily("fantasy");       // 幻想體,默認值 "fantasy"


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    // 用戶是否須要經過手勢播放媒體(不會自動播放),默認值 true
    settings.setMediaPlaybackRequiresUserGesture(true);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // 5.0以上容許加載http和https混合的頁面(5.0如下默認容許,5.0+默認禁止)
    settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    // 是否在離開屏幕時光柵化(會增長內存消耗),默認值 false
    settings.setOffscreenPreRaster(false);
}

if (isNetworkConnected(context)) {
    // 根據cache-control決定是否從網絡上取數據
    settings.setCacheMode(WebSettings.LOAD_DEFAULT);
} else {
    // 沒網,離線加載,優先加載緩存(即便已通過期)
    settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}

// deprecated
settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
settings.setDatabasePath(context.getDir("database", Context.MODE_PRIVATE).getPath());
settings.setGeolocationDatabasePath(context.getFilesDir().getPath());
  • 通常調整爲如下默認設置服務器

    WebSettings settings = web.getSettings();
      // 緩存(cache)
      settings.setAppCacheEnabled(true);      // 默認值 false
      settings.setAppCachePath(context.getCacheDir().getAbsolutePath());
    
      // 存儲(storage)
      settings.setDomStorageEnabled(true);    // 默認值 false
      settings.setDatabaseEnabled(true);      // 默認值 false 
    
      // 是否支持viewport屬性,默認值 false
      // 頁面經過`<meta name="viewport" ... />`自適應手機屏幕
      settings.setUseWideViewPort(true);
      // 是否使用overview mode加載頁面,默認值 false
      // 當頁面寬度大於WebView寬度時,縮小使頁面寬度等於WebView寬度
      settings.setLoadWithOverviewMode(true);
    
      // 是否支持Javascript,默認值false
      settings.setJavaScriptEnabled(true);    
    
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          // 5.0以上容許加載http和https混合的頁面(5.0如下默認容許,5.0+默認禁止)
          settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
      } 
    
      if (isNetworkConnected(context)) {
          // 根據cache-control決定是否從網絡上取數據
          settings.setCacheMode(WebSettings.LOAD_DEFAULT);
      } else {
          // 沒網,離線加載,優先加載緩存(即便已通過期)
          settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
      }

WebViewClient

WebViewClient主要幫助WebView處理各類通知、請求事件的

// 攔截頁面加載,返回true表示宿主app攔截並處理了該url,不然返回false由當前WebView處理
// 此方法在API24被廢棄,不處理POST請求
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    return false;
}

// 攔截頁面加載,返回true表示宿主app攔截並處理了該url,不然返回false由當前WebView處理
// 此方法添加於API24,不處理POST請求,可攔截處理子frame的非http請求
@TargetApi(Build.VERSION_CODES.N)
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}

// 此方法廢棄於API21,調用於非UI線程
// 攔截資源請求並返回響應數據,返回null時WebView將繼續加載資源
// 注意:API21如下的AJAX請求會走onLoadResource,沒法經過此方法攔截
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    return null;
}

// 此方法添加於API21,調用於非UI線程
// 攔截資源請求並返回數據,返回null時WebView將繼續加載資源
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    return shouldInterceptRequest(view, request.getUrl().toString());
}

// 頁面(url)開始加載
public void onPageStarted(WebView view, String url, Bitmap favicon) {
}

// 頁面(url)完成加載
public void onPageFinished(WebView view, String url) {
}

// 將要加載資源(url)
public void onLoadResource(WebView view, String url) {
}

// 這個回調添加於API23,僅用於主框架的導航
// 通知應用導航到以前頁面時,其遺留的WebView內容將再也不被繪製。
// 這個回調能夠用來決定哪些WebView可見內容能被安全地回收,以確保不顯示陳舊的內容
// 它最先被調用,以此保證WebView.onDraw不會繪製任何以前頁面的內容,隨後繪製背景色或須要加載的新內容。
// 當HTTP響應body已經開始加載並體如今DOM上將在隨後的繪製中可見時,這個方法會被調用。
// 這個回調發生在文檔加載的早期,所以它的資源(css,和圖像)可能不可用。
// 若是須要更細粒度的視圖更新,查看 postVisualStateCallback(long, WebView.VisualStateCallback).
// 請注意這上邊的全部條件也支持 postVisualStateCallback(long ,WebView.VisualStateCallback)
public void onPageCommitVisible(WebView view, String url) {
}

// 此方法廢棄於API23
// 主框架加載資源時出錯
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
}

// 此方法添加於API23
// 加載資源時出錯,一般意味着鏈接不到服務器
// 因爲全部資源加載錯誤都會調用此方法,因此此方法應儘可能邏輯簡單
@TargetApi(Build.VERSION_CODES.M)
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
    if (request.isForMainFrame()) {
        onReceivedError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString());
    }
}

// 此方法添加於API23
// 在加載資源(iframe,image,js,css,ajax...)時收到了 HTTP 錯誤(狀態碼>=400)
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
}


// 是否從新提交表單,默認不重發
public void onFormResubmission(WebView view, Message dontResend, Message resend) {
    dontResend.sendToTarget();
}

// 通知應用能夠將當前的url存儲在數據庫中,意味着當前的訪問url已經生效並被記錄在內核當中。
// 此方法在網頁加載過程當中只會被調用一次,網頁前進後退並不會回調這個函數。
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
}

// 加載資源時發生了一個SSL錯誤,應用必需響應(繼續請求或取消請求)
// 處理決策可能被緩存用於後續的請求,默認行爲是取消請求
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    handler.cancel();
}

// 此方法添加於API21,在UI線程被調用
// 處理SSL客戶端證書請求,必要的話可顯示一個UI來提供KEY。
// 有三種響應方式:proceed()/cancel()/ignore(),默認行爲是取消請求
// 若是調用proceed()或cancel(),Webview 將在內存中保存響應結果且對相同的"host:port"不會再次調用 onReceivedClientCertRequest
// 多數狀況下,可經過KeyChain.choosePrivateKeyAlias啓動一個Activity供用戶選擇合適的私鑰
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
    request.cancel();
}

// 處理HTTP認證請求,默認行爲是取消請求
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
    handler.cancel();
}

// 通知應用有個已受權帳號自動登錄了
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
}
// 給應用一個機會處理按鍵事件
// 若是返回true,WebView不處理該事件,不然WebView會一直處理,默認返回false
public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
    return false;
}

// 處理未被WebView消費的按鍵事件
// WebView老是消費按鍵事件,除非是系統按鍵或shouldOverrideKeyEvent返回true
// 此方法在按鍵事件分派時被異步調用
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
    super.onUnhandledKeyEvent(view, event);
}

// 通知應用頁面縮放係數變化
public void onScaleChanged(WebView view, float oldScale, float newScale) {
}

WebChromeClient

WebChromeClient是輔助WebView處理Javascript的對話框,網站圖標,網站title,加載進度等

// 得到全部訪問歷史項目的列表,用於連接着色。
public void getVisitedHistory(ValueCallback<String[]> callback) {
}

// <video /> 控件在未播放時,會展現爲一張海報圖,HTML中可經過它的'poster'屬性來指定。
// 若是未指定'poster'屬性,則經過此方法提供一個默認的海報圖。
public Bitmap getDefaultVideoPoster() {
    return null;
}

// 當全屏的視頻正在緩衝時,此方法返回一個佔位視圖(好比旋轉的菊花)。
public View getVideoLoadingProgressView() {
    return null;
}

// 接收當前頁面的加載進度
public void onProgressChanged(WebView view, int newProgress) {
}

// 接收文檔標題
public void onReceivedTitle(WebView view, String title) {
}

// 接收圖標(favicon)
public void onReceivedIcon(WebView view, Bitmap icon) {
}

// Android中處理Touch Icon的方案
// http://droidyue.com/blog/2015/01/18/deal-with-touch-icon-in-android/index.html
public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed) {
}

// 通知應用當前頁進入了全屏模式,此時應用必須顯示一個包含網頁內容的自定義View
public void onShowCustomView(View view, CustomViewCallback callback) {
}

// 通知應用當前頁退出了全屏模式,此時應用必須隱藏以前顯示的自定義View
public void onHideCustomView() {
}


// 顯示一個alert對話框
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
    return false;
}

// 顯示一個confirm對話框
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
    return false;
}

// 顯示一個prompt對話框
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    return false;
}

// 顯示一個對話框讓用戶選擇是否離開當前頁面
public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
    return false;
}


// 指定源的網頁內容在沒有設置權限狀態下嘗試使用地理位置API。
// 從API24開始,此方法只爲安全的源(https)調用,非安全的源會被自動拒絕
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
}

// 當前一個調用 onGeolocationPermissionsShowPrompt() 取消時,隱藏相關的UI。
public void onGeolocationPermissionsHidePrompt() {
}

// 通知應用打開新窗口
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
    return false;
}

// 通知應用關閉窗口
public void onCloseWindow(WebView window) {
}

// 請求獲取取焦點
public void onRequestFocus(WebView view) {
}

// 通知應用網頁內容申請訪問指定資源的權限(該權限未被受權或拒絕)
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void onPermissionRequest(PermissionRequest request) {
    request.deny();
}

// 通知應用權限的申請被取消,隱藏相關的UI。
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void onPermissionRequestCanceled(PermissionRequest request) {
}

// 爲'<input type="file" />'顯示文件選擇器,返回false使用默認處理
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
    return false;
}

// 接收JavaScript控制檯消息
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
    return false;
}

Demo

package org.professor.procartoon.temp;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;

import org.professor.procartoon.R;

/**
 * Created by Caipeng on 2018.02.01.
 */
public class TestActivity extends AppCompatActivity {

    private WebView mWebview;
    private WebSettings mWebSettings;
    private TextView beginLoading, endLoading, loading, mtitle;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.about_by);
        initView();


    }

    private void initView() {
        mWebview = findViewById(R.id.webView1);
        beginLoading = findViewById(R.id.text_beginLoading);
        endLoading = findViewById(R.id.text_endLoading);
        loading = findViewById(R.id.text_Loading);
        mtitle = findViewById(R.id.title);
        mWebSettings = mWebview.getSettings();
        mWebview.loadUrl("https://my.oschina.net/u/1433837/blog");

        //設置WebChromeClient類
        mWebview.setWebChromeClient(new WebChromeClient() {
            //獲取網站標題
            @Override
            public void onReceivedTitle(WebView view, String title) {
                System.out.println("標題在這裏");
                mtitle.setText(title);
            }

            //獲取加載進度
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                if (newProgress < 100) {
                    String progress = newProgress + "%";
                    loading.setText(progress);
                } else if (newProgress == 100) {
                    String progress = newProgress + "%";
                    loading.setText(progress);
                }
            }
        });

        //設置WebViewClient類
        mWebview.setWebViewClient(new WebViewClient() {
            //設置加載前的函數
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                System.out.println("開始加載了");
                beginLoading.setText("開始加載了");
            }

            //設置結束加載函數
            @Override
            public void onPageFinished(WebView view, String url) {
                endLoading.setText("結束加載了");
            }
        });
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebview.canGoBack()) {
            mWebview.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    //銷燬Webview
    @Override
    protected void onDestroy() {
        if (mWebview != null) {
            mWebview.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            mWebview.clearHistory();
            ((ViewGroup) mWebview.getParent()).removeView(mWebview);
            mWebview.destroy();
            mWebview = null;
        }
        super.onDestroy();
    }
}
相關文章
相關標籤/搜索