1. 程式人生 > >Android WebView 詳解

Android WebView 詳解

本文記錄 AndroidWebView 控制元件的相關使用,不斷完善中…

主要包括:

  • 基本屬性的配置
  • WebView 快取相關內容
  • JavaJs 的互動
  • WebView 開啟本地應用(支付寶等)
  • 載入網路連結,本地 sd 卡路徑,assert 目錄路徑的方法
  • WebView 支援下載等其它一些內容

基本配置彙總

彙總的記錄一下 WebView 的配置方法,重要的屬性後面會展開說明。

@SuppressLint("SetJavaScriptEnabled")
public static void initWebViewSettings(WebView mWebView) {
    //支援獲取手勢焦點
mWebView.requestFocusFromTouch(); // 觸覺反饋,暫時沒發現用處在哪裡 mWebView.setHapticFeedbackEnabled(false); WebSettings settings = mWebView.getSettings(); // 支援外掛 settings.setPluginState(WebSettings.PluginState.ON); // 允許js互動 settings.setJavaScriptEnabled(true); // 設定WebView是否可以由 JavaScript 自動開啟視窗,預設為 false
// 通常與 JavaScript 的 window.open() 配合使用。 settings.setJavaScriptCanOpenWindowsAutomatically(true); // 允許中文編碼 settings.setDefaultTextEncodingName("UTF-8"); // 使用大檢視,設定適應螢幕 settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); // 支援多視窗 settings.setSupportMultipleWindows(true
); // 隱藏自帶縮放按鈕 settings.setBuiltInZoomControls(false); // 支援縮放 settings.setSupportZoom(true); // 設定可訪問檔案 settings.setAllowFileAccess(true); // 當WebView呼叫requestFocus時為WebView設定節點 settings.setNeedInitialFocus(true); //支援自動載入圖片 settings.setLoadsImagesAutomatically(true); // 指定WebView的頁面佈局顯示形式,呼叫該方法會引起頁面重繪。 // NORMAL,SINGLE_COLUMN 過時, NARROW_COLUMNS 過時 ,TEXT_AUTOSIZING settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); // 從Lollipop(5.0)開始WebView預設不允許混合模式,https當中不能載入http資源,需要設定開啟 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } }

WebView 快取

清除快取,true 表示清除磁碟快取,這個方法是全域性的,也就是說會清除掉整個應用所有的 網頁快取。

mWebView.clearCache(true);

清除歷史記錄

mWebView.clearHistory();

網上有介紹說,設定快取的目錄,清除快取時刪除掉快取檔案,但是使用下面的方法設定快取路徑後,發現檔案並沒有快取到指定的目錄,不知道是怎麼回事?求指教

快取模式 描述
LOAD_DEFAULT 預設的快取使用模式。在進行頁面前進或後退的操作時,如果快取可用並未過期就優先載入快取,否則從網路上載入資料。這樣可以減少頁面的網路請求次數。
LOAD_CACHE_ELSE_NETWORK 只要快取可用就載入快取,哪怕它們已經過期失效。如果快取不可用就從網路上載入資料。
LOAD_NO_CACHE 不載入快取,只從網路載入資料。
LOAD_CACHE_ONLY 不從網路載入資料,只從快取載入資料。
private static void initWebViewCache(WebView mWebView) {

    String cachePath = new File(Environment.getExternalStorageDirectory()
            , "webCache").getAbsolutePath();

    WebSettings settings = mWebView.getSettings();
    settings.setAppCacheEnabled(true);
    settings.setAppCachePath(cachePath);
    settings.setDatabaseEnabled(true);
    // 過時
    settings.setDatabasePath(cachePath);
    // 開啟dom快取
    settings.setDomStorageEnabled(true);
    // 載入模式
    settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
    // 快取最大值,過時
    settings.setAppCacheMaxSize(1000 * 1024);
}

載入 Url

載入網路路徑,headers 不是必選的

Map<String,String> headers = new HashMap<>();
headers.put("auth","110");
mWebView.loadUrl("https://www.baidu.com/",headers);

載入 assert 路徑

// WebViewUtil.java
public static String getAssertUrl(String fileUrl) {
    return "file:///android_asset/" + fileUrl;
}

mWebView.loadUrl(WebViewUtil.getAssertUrl("index.html"));

載入 sd 卡路徑

// WebViewUtil.java
public static String getSdUrl(String fileUrl) {
    return "file://" + Environment.getExternalStorageDirectory() + "/" + fileUrl;
}

mWebView.loadUrl(WebViewUtil.getSdUrl("index.html"));    

Js 呼叫 Java

JavaJs 互動需要定義一個帶有 @JavascriptInterface 註解方法的物件,如下:

public class JsBridge {

    @JavascriptInterface
    public void toast(String msg) {
        ToastUtils.show(msg);
    }

    @JavascriptInterface
    public void log(String msg) {
        Log.e(TAG, msg);
    }
}

使用 JsBridge 連線 JavaJs,使用 mWebView.addJavascriptInterface(obj, name); 方法。

  • obj:帶有 JavascriptInterface 註解方法的物件例項。
  • name:一個標誌符,js 將會使用該標誌來呼叫 java 層的方法。
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JsBridge(), "android");

在新增呼叫介面時,我們添加了一個標記,如上面程式碼中新增的是 android,它相當於呼叫介面物件的一個別名,因此在 js 中呼叫 java 方法時,只需要使用 window 物件,如下:

window.android.log('test js invoke java method');

Java 呼叫 Js

使用 java 呼叫 js 方法相對簡單,假如在 js 中應該宣告如下 function

<script>
// 有參無返回值
    function funcParam(param){
        alert(param+"");
    }

    // 有參有返回值
    function newFunc(param1,param2,param3){
        alert((param1 +  param2) + " " + param3);
        return param3;
    }
</script>

java 層呼叫時只需 loadUrl("Javascript:js方法名()) 即可,但是 Android 4.4 之後在呼叫 js 方法時可以獲取返回值,寫一個方法相容一下

public static final String JS_FUNC_PREFIX = "javascript:";

public void invokeJs(String jsFunc, final ValueCallback<String> callback) {
    if (!jsFunc.startsWith(JS_FUNC_PREFIX)) {
        jsFunc = JS_FUNC_PREFIX + jsFunc;
    }
    // api 19
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        mWebView.evaluateJavascript(jsFunc, callback);
    } else {
        mWebView.loadUrl(jsFunc);
    }
}

在與 js 進行引數傳遞時,基本資料型別可以直接傳遞,字串型別要使用引號包含,而且直接拼接字串不太好,因此寫一個簡化構建 js 方法,自動按順序進行引數的拼接。

// 建立一個 js 方法
public static String generateJsFunc(String funcName, Object... params) {
    StringBuilder sb = new StringBuilder(funcName).append("(");
    for (int i = 0; i < params.length; i++) {
        if (params[i] != null) {
            if (params[i] instanceof String) {
                sb.append("'").append(params[i]).append("'");
            } else {
                sb.append(params[i]);
            }
            if (i != params.length - 1) {
                sb.append(",");
            }
        }
    }
    sb.append(")");
    return sb.toString();
}

簡單呼叫

// 呼叫有參有返回值的方法
String jsFunc = JsBridge.generateJsFunc("newFunc", "str", 100, 100);
mJsBridge.invokeJs(jsFunc, new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        Log.e(TAG, "value = " + value);
    }
});

// 呼叫有參無返回值方法
String funcParam = JsBridge.generateJsFunc("funcParam", 100);
mJsBridge.invokeJs(funcParam, null);

攔截 Url 開啟應用(支付寶)

主要原理是由於某些應用會暴露一些頁面出來供別的 app 喚起,因此我們只需要攔截這種 Url,然後使用 intent 開啟即可,下面以支付寶為例說明:

前端使用支付寶進行支付時,需要開啟手機支付寶客戶端,斷點看到支付寶會載入一個 schemealipays 的url,連結中配置了支付的相關資訊,客戶端要做的就是攔截該 Url,使用 intent 開啟支付寶。

html 載入網頁之前會先走 shouldOverrideUrlLoading() 方法,此時截斷不使用 webView 載入,而是使用 intent 開啟,此方法不僅適用支付寶,也適用開啟其他應用。

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // 如果不使用 intent 覆蓋載入這個連結,就走原來
        if (!shouldOverrideIntentUrl(getContext(), url)) {
            view.loadUrl(url, Api.makeHttpHeaders(getContext()));
        }
        return true;
    }
});


private boolean shouldOverrideIntentUrl(Context context, String url) {
    Uri uri = Uri.parse(url);
    if (uri.getScheme().equals("alipays")) {
        try {
            Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
            intent.addCategory(Intent.CATEGORY_BROWSABLE);
            intent.setComponent(null);
            intent.setSelector(null);
            context.startActivity(intent);
            return true;
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return false;
        }
    }
    return false;
}

支援下載連結

當網頁中載入一個下載的連結,如 http://xxx.apk 這種連結,會走 shouldOverrideUrlLoading() 方法,但是,它是無法載入一個網頁的,結果就是沒有任何反應,此時需要設定 DownloadListener,需要下載的連結會進入監聽,你可以在監聽中自己進行網路下載儲存到檔案,下面我使用直接開啟瀏覽器的方式,更簡單一些。

public static void setDefDownloadListener(final WebView webView) {
    webView.setDownloadListener(new DownloadListener() {
        @Override
        public void onDownloadStart(String url, String userAgent,
                                    String contentDisposition,
                                    String mimetype,
                                    long contentLength) {
            //去下載
            Intent intent = new Intent(Intent.ACTION_VIEW);
            String downLoadUrl = url;
            if (!downLoadUrl.contains("http://")) {
                downLoadUrl = "http://" + downLoadUrl;
            }
            intent.setData(Uri.parse(downLoadUrl));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            webView.getContext().startActivity(intent);
        }
    });
}

WebChromeClient

WebView 預設是無法彈出 alert() 的,需要設定 WebChromeClient

mWebView.setWebChromeClient(new WebChromeClient());

todo

更多內容補充中 …

相關推薦

Android WebView之檔案下載

1、佈局檔案activity_main.xml:線性佈局,TextView顯示頁面標題,WebView顯示頁面。 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

(轉)最全面的Android Webview

原地址:http://blog.csdn.net/carson_ho/article/details/52693322 前言 現在很多App裡都內建了Web網頁(Hyprid App),比如說很多電商平臺,淘寶、京東、聚划算等等,如下圖  那麼這種該如何實現呢

Android WebView

本文記錄 Android 中 WebView 控制元件的相關使用,不斷完善中…主要包括:基本屬性的配置 WebView 快取相關內容 Java 與 Js 的互動 WebView 開啟本地應用(支付寶等) 載入網路連結,本地 sd 卡路徑,assert 目錄路徑的

android WebView,常見漏洞和安全原始碼(上)

  這篇部落格主要來介紹 WebView 的相關使用方法,常見的幾個漏洞,開發中可能遇到的坑和最後解決相應漏洞的原始碼,以及針對該原始碼的解析。   由於部落格內容長度,這次將分為上下兩篇,上篇詳解 WebView 的使用,下篇講述 WebView 的漏洞和

Android:最全面的 Webview

前言 現在很多App裡都內建了Web網頁(Hyprid App),比如說很多電商平臺,淘寶、京東、聚划算等等,如下圖 那麼這種該如何實現呢?其實這是Android裡一個叫WebView的元件實現的。今天我將全面介紹WebView的常用用法。

Android開發:最全面、最易懂的Webview

現在很多App裡都內建了Web網頁(Hyprid App),比如說很多電商平臺,淘寶、京東、聚划算等等,如下圖 京東首頁.jpg 那麼這種該如何實現呢?其實這是Android裡一個叫WebView的元件實現的。今天我將全面介紹WebView的常用用法。 目錄 文章目錄 1. 簡介

webViewAndroid互動

具體原理:  Android通過 WebViewClient 的回撥方法shouldOverrideUrlLoading ()攔截 url解析該 url 的協議如果檢測到是預先約定好的協議,就呼叫相應方法  即JS需要呼叫Android的方法 具體使用: 步驟1:在JS約定所需要的Url協議

WebView及使用說明;(android外殼專案總結版)

最近做了一個關於webview寫安卓的殼,套HTML5的應用,雖然整個寫下來後,到了目前的進度,程式碼量不多,共有1000多行,但是整個殼的設計思想和實現思路還是當初查了很久的。所以寫下來,以備後續檢視和分享。 這個webview的殼目前實現的功能我將從三方面說明並總結。

WebView與簡單Android與H5互調

為什麼要學習Android與H5互調? 微信,QQ空間等大量軟體都內嵌了H5,不得不說是一種趨勢。Android與H5互調可以讓我們的實現混合開發,至於混合開發就是在一個App中內嵌一個輕量級的瀏覽器,一部分原生的功能改為Html 5來開發。  優勢:使用H5實現的功能能夠在不升級App的情況下動態更

WebView與簡單實現Android與H5互調

本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 為什麼要學習Android與H5互調? 微信,QQ空間等大量軟體都內嵌了H5,不得不說是一種趨勢。Android與H5互調可以讓我們的實現混合開發,至於混合開發就是在一個App中內嵌

android -------- WIFI

mov 取ip地址 fico alt b- else if 無線網 pan PC 今天簡單的來聊一下安卓開發中的Wifi,一些常用的基礎,主要分為兩部分: 1:WiFi的信息 2:WiFi的搜索和連接 現在app大多都需要從網絡上獲得數據。所以訪問網絡是在

Android Permission

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android ViewModel

1. ViewModel概述 2. 實現一個ViewModel 3. ViewModel的生命週期 4. 在fragments之間共享資料 5. ViewModel替換Loaders 6. 附加資源 1.

Android LiveData

官方文件翻譯 1.LiveData概述 1.1 使用LiveData的優點 1.2 使用LiveData物件 1.2.1 建立LiveData物件 1.2.2 觀察LiveData物件

Android Lifecycle(一)

官方文件翻譯 使用生命週期感知元件處理生命週期 Lifecycle Event State LifecycleOwner 實現一個自定義的LifecycleOwner 生命週期感

Android Animation

關於動畫的實現,Android提供了Animation,在Android SDK介紹了2種Animation模式: 1. Tween Animation:通過對場景裡的物件不斷做影象變換(平移、縮放、旋轉)產生動畫效果,即是一種漸變動畫; 2. Frame Animation:

Android開發之onTouch和onClick

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android UI之顏色資源的使用

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android開發--ContentProvider/Cursor的使用

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android Activity

生命週期 如上圖所示,Activity生命週期很簡單共七個生命週期函式,oncreate(),onrestart(),onstart(),onresume(),onpause(),onstop(),ondestroy(); 下面舉兩個例子來說明Activity生命週期函式呼叫關係。